Search code examples
swiftxcodecore-graphics

Core Graphics does not draw certain lines


Overview:
I am trying to draw a stick figure on top of a UILabel (serves as a background), and the "head" draws perfectly. However, nothing else shows up despite changing the "spine" to mimic the head's drawing procedure and changing the UILabel background (to rule out color issues).

The context backtrace lists CGContextSaveGState, CGContextSetLineWidth, CGContextSetLineJoin, CGContextSetLineCap, CGContextSetMiterLimit, CGContextSetFlatness, CGContextAddPath, CGContextDrawPath, CGContextRestoreGState, CGContextSetLineWidth as problematic, each more than once, but no errors occurred.

TLDR: Everything but the head is not drawn and I have no idea why...

Code:

import UIKit
import CoreGraphics
import Foundation

let π:CGFloat = CGFloat(M_PI)

class generateViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {

  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //                                         <OUTLETS & VARIABLES>                                          //
////////////////////////////////////////////////////////////////////////////////////////////////////////////

@IBOutlet var          generateView: UIView!
@IBOutlet weak var      jointPicker: UIPickerView!
@IBOutlet weak var   verticalSlider: UISlider!
@IBOutlet weak var horizontalSlider: UISlider!
@IBOutlet weak var       saveButton: UIButton!
@IBOutlet weak var       undoButton: UIButton!
@IBOutlet weak var      printButton: UIButton!

var jointPickerData: [[String]] = [[String]]()

var   top: Float = 126
var   bot: Float = 574
var right: Float = 1198

  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //                                         <VIEW DID LOAD>                                                //
////////////////////////////////////////////////////////////////////////////////////////////////////////////

override func viewDidLoad() {

    super.viewDidLoad()
     self.jointPicker.delegate   = self
     self.jointPicker.dataSource = self
    jointPickerData = [["Neck","Shoulder","Elbow","Wrist","Spine","Hip","Knee","Ankle"],["Left","Right"]]

    draw(CGRect(x: 0,
                y: Int(top),
            width: Int(right),
           height: Int(top - bot)))

}

override func viewDidAppear(_ animated: Bool) {

    let value = UIInterfaceOrientation.landscapeLeft.rawValue
    UIDevice.current.setValue(value, forKey: "orientation")
    AppUtility.lockOrientation(.landscapeLeft, andRotateTo: .landscapeLeft)

}
override func viewWillDisappear(_ animated: Bool) {

    super.viewWillDisappear(animated)
    // Don't forget to reset when view is being removed
    AppUtility.lockOrientation(.all)

}

override func didReceiveMemoryWarning() {

    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.

}
  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //                                         <PICKER FUNCTIONS>                                             //
////////////////////////////////////////////////////////////////////////////////////////////////////////////

//Number of columns
func numberOfComponents(in: UIPickerView) -> Int {
    return 2
}
//Number of rows
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
    return jointPickerData[component].count
}
//Data to return for the row and column being read
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
    return jointPickerData[component][row]
}
//Catpure the picker view selection
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
    // This method is triggered whenever the user makes a change to the picker selection.
    // The parameter named row and component represents what was selected.
}

  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //                                         <SLIDER FUNCTIONS>                                             //
////////////////////////////////////////////////////////////////////////////////////////////////////////////

@IBAction func vertical(_ sender: Any){
    if jointPicker.selectedRow(inComponent: 1) == 0 {//left
        if jointPicker.selectedRow(inComponent: 0) == 0 {//lNeck
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 1 {//lShoulder
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 2 {//lElbow
            lElbowYGlobal.lElbowY = Int((verticalSlider.value - 0.5) * 200)

        }
        if jointPicker.selectedRow(inComponent: 0) == 3 {//lWrist
            lWristYGlobal.rWristY = Int((verticalSlider.value - 0.5) * 200)

        }
        if jointPicker.selectedRow(inComponent: 0) == 4 {//lSpine
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 5 {//lHip
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 6 {//lKnee
            lKneeYGlobal.lKneeY = Int((verticalSlider.value - 0.5) * 200)

        }
        if jointPicker.selectedRow(inComponent: 0) == 7 {//lAnkle
            lAnkleYGlobal.lAnkleY = Int((verticalSlider.value - 0.5) * 200)

        }

    }
    if jointPicker.selectedRow(inComponent: 1) == 1 {//right
        if jointPicker.selectedRow(inComponent: 0) == 0 {//rNeck
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 1 {//rShoulder
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 2 {//rElbow
            rElbowYGlobal.rElbowY = Int((verticalSlider.value - 0.5) * 200)

        }
        if jointPicker.selectedRow(inComponent: 0) == 3 {//rWrist
            rWristYGlobal.rWristY = Int((verticalSlider.value - 0.5) * 200)

        }
        if jointPicker.selectedRow(inComponent: 0) == 4 {//rSpine
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 5 {//rHip
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 6 {//rKnee
            rKneeYGlobal.rKneeY = Int((verticalSlider.value - 0.5) * 200)

        }
        if jointPicker.selectedRow(inComponent: 0) == 7 {//rAnkle
            rAnkleYGlobal.rAnkleY = Int((verticalSlider.value - 0.5) * 200)

        }

    }
    generateView.setNeedsDisplay()
    draw(CGRect(x: 0,
                y: Int(top),
            width: Int(right),
           height: Int(top - bot)))
}

@IBAction func horizontal(_ sender: Any) {
    if jointPicker.selectedRow(inComponent: 1) == 0 {//left
        if jointPicker.selectedRow(inComponent: 0) == 0 {//lNeck
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 1 {//lShoulder
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 2 {//lElbow
            lElbowXGlobal.lElbowX = Int((horizontalSlider.value - 0.5) * 200)

        }
        if jointPicker.selectedRow(inComponent: 0) == 3 {//lWrist
            lWristXGlobal.lWristX = Int((horizontalSlider.value - 0.5) * 200)

        }
        if jointPicker.selectedRow(inComponent: 0) == 4 {//lSpine
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 5 {//lHip
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 6 {//lKnee
            lKneeXGlobal.lKneeX = Int((horizontalSlider.value - 0.5) * 200)

        }
        if jointPicker.selectedRow(inComponent: 0) == 7 {//lAnkle
            lAnkleXGlobal.lAnkleX = Int((horizontalSlider.value - 0.5) * 200)

        }

    }
    if jointPicker.selectedRow(inComponent: 1) == 1 {//right
        if jointPicker.selectedRow(inComponent: 0) == 0 {//rNeck
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 1 {//rShoulder
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 2 {//rElbow
            rElbowXGlobal.rElbowX = Int((horizontalSlider.value - 0.5) * 200)

        }
        if jointPicker.selectedRow(inComponent: 0) == 3 {//rWrist
            rWristXGlobal.rWristX = Int((horizontalSlider.value - 0.5) * 200)

        }
        if jointPicker.selectedRow(inComponent: 0) == 4 {//rSpine
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 5 {//rHip
            //nothing yet
        }
        if jointPicker.selectedRow(inComponent: 0) == 6 {//rKnee
            rKneeXGlobal.rKneeX = Int((horizontalSlider.value - 0.5) * 200)

        }
        if jointPicker.selectedRow(inComponent: 0) == 7 {//rAnkle
            rAnkleXGlobal.rAnkleX = Int((horizontalSlider.value - 0.5) * 200)

        }

    }
    generateView.setNeedsDisplay()
    draw(CGRect(x: 0,
                y: Int(top),
            width: Int(right),
           height: Int(top - bot)))
}

func draw(_ rect: CGRect) {

  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //                                              <LINES>                                                   //
////////////////////////////////////////////////////////////////////////////////////////////////////////////
    /*
        aPath.move(to: CGPoint(x:300,
                               y:300 + Int(top)))

     aPath.addLine(to: CGPoint(x:200,
                               y:300 + Int(top)))

     aPath.lineWidth = 10.0

     aPath.close()

     //Apply black color
     UIColor.black.set()
     aPath.stroke()
     //Fill it as well
     //aPath.fill()
     */

  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //                                               <HEAD>                                                   //
////////////////////////////////////////////////////////////////////////////////////////////////////////////

    let circle = UIView(frame: CGRect(x: 560,
                                      y: 10.0 + Double(top),
                                  width: 100.0,
                                 height: 100.0))

    circle.center             = CGPoint(x: 560,
                                        y: 80 + Int(top))
    circle.layer.cornerRadius = 50
    circle.backgroundColor    = UIColor.black
    circle.clipsToBounds      = true

    let circle2 = UIView(frame: CGRect(x: 25.0,
                                       y: 25.0 + Double(top),
                                   width: 90.0,
                                  height: 90.0))

    circle2.center             = circle.center
    circle2.layer.cornerRadius = 45
    circle2.backgroundColor    = UIColor.white
    circle2.clipsToBounds      = true

    /*
     var darkBlur = UIBlurEffect(style: UIBlurEffectStyle.dark)
     var blurView = UIVisualEffectView(effect: darkBlur)

     blurView.frame = circle.bounds

     circle.addSubview(blurView)
 */
    generateView.addSubview(circle)
    generateView.addSubview(circle2)

  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //                                               <SPINE>                                                  //
////////////////////////////////////////////////////////////////////////////////////////////////////////////

    let spine = UIView(frame: CGRect(x: 560,
                                     y: 110 + Double(top),
                                 width: 10,
                                height: 110))
    func spineDraw(){
        spine.center             = CGPoint(x: 560,
                                           y: 165 + Int(top))
        spine.layer.cornerRadius = 5
        spine.backgroundColor    = UIColor.black
        spine.clipsToBounds      = true

        generateView.addSubview(spine)
    }

  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //                                               <ARMS>                                                   //
////////////////////////////////////////////////////////////////////////////////////////////////////////////

    var shoulder = CGPoint(x: 400,
                           y: 120 + Int(top))
    var rElbow = CGPoint(x: 410 + rElbowXGlobal.rElbowX,
                         y: 170 + rElbowYGlobal.rElbowY + Int(top))
    var rWrist = CGPoint(x: 410 + rWristXGlobal.rWristX,
                         y: 195 + rWristYGlobal.rWristY + Int(top))

    let rArm = UIBezierPath()
    rArm.lineWidth = 5

    func rArmDraw() {
        rArm.move(to: shoulder)
        rArm.addLine(to: rElbow)
        rArm.stroke()
        rArm.addLine(to: rWrist)
        rArm.stroke()
        rArm.close()
    }

    var lElbow = CGPoint(x: 390 + lElbowXGlobal.lElbowX,
                         y: 170 + lElbowYGlobal.lElbowY + Int(top))
    var lWrist = CGPoint(x: 390 + lWristXGlobal.lWristX,
                         y: 195 + lWristYGlobal.lWristY + Int(top))

    let lArm = UIBezierPath()
    lArm.lineWidth = 5

    func lArmDraw(){
        lArm.move(to: shoulder)
        lArm.addLine(to: lElbow)
        lArm.stroke()
        lArm.addLine(to: lWrist)
        lArm.stroke()
        lArm.close()
    }

  ////////////////////////////////////////////////////////////////////////////////////////////////////////////
 //                                               <LEGS>                                                   //
////////////////////////////////////////////////////////////////////////////////////////////////////////////

    var hip = CGPoint(x: 400,
                      y: 215 + Int(top))

    var rKnee  = CGPoint(x: 410 + rKneeXGlobal.rKneeX,
                         y: 250 + rKneeYGlobal.rKneeY   + Int(top))
    var rAnkle = CGPoint(x: 410 + rAnkleXGlobal.rAnkleX,
                         y: 270 + rAnkleYGlobal.rAnkleY + Int(top))

    let rLeg = UIBezierPath()
    rLeg.lineWidth = 5

    func rLegDraw(){
        rLeg.move(to: hip)
        rLeg.addLine(to: rKnee)
        rLeg.stroke()
        rLeg.addLine(to: rAnkle)
        rLeg.stroke()
        rLeg.close()
    }

    var lKnee  = CGPoint(x: 390 + lKneeXGlobal.lKneeX,
                         y: 250 + lKneeYGlobal.lKneeY   + Int(top))
    var lAnkle = CGPoint(x: 390 + lAnkleXGlobal.lAnkleX,
                         y: 270 + lAnkleYGlobal.lAnkleY + Int(top))

    let lLeg = UIBezierPath()
    lLeg.lineWidth = 5

    func lLegDraw(){
        lLeg.move(to: hip)
        lLeg.addLine(to: lKnee)
        lLeg.stroke()
        lLeg.addLine(to: lAnkle)
        lLeg.stroke()
        lLeg.close()
    }


    //debug grid
    let path = UIBezierPath()
    for i in 1...10 {
           path.move(to: CGPoint(x: i*100,
                                 y: 0     + Int(top)))
        path.addLine(to: CGPoint(x: i*100,
                                 y: 1000  + Int(top)))
        path.stroke()
           path.move(to: CGPoint(x: 0,
                                 y: i*100 + Int(top)))
        path.addLine(to: CGPoint(x: 2000,
                                 y: i*100 + Int(top)))
    }

//        spineDraw()
//        rArmDraw()
//        lArmDraw()
//        rLegDraw()
//        lLegDraw()
    generateView.setNeedsDisplay()
}

}

If necessary, I can provide the entire backtrace. (I'm too lazy to do that right now)

Thanks in advance!


Solution

  • I solved my own problem eventually by:

    1. Moving the drawing code into its own class
    2. Creating a UIView where the text box was (in the interface builder)
    3. Setting the custom class of said UIView to the new class

    And most importantly:

    1. Removing functions which encapsulate drawing code*

    I have no idea why the functions blocked drawing stuff, all I know is that it just does...

    *example:

    let spine = UIView(frame: CGRect(x: 560,
                                     y: 110 + Double(top),
                                 width: 10,
                                height: 110))
    func spineDraw(){
        spine.center             = CGPoint(x: 560,
                                           y: 165 + Int(top))
        spine.layer.cornerRadius = 5
        spine.backgroundColor    = UIColor.black
        spine.clipsToBounds      = true
    
        generateView.addSubview(spine)
    }
    

    Should be:

    let spine = UIView(frame: CGRect(x: 560,
                                     y: 110 + Double(top),
                                 width: 10,
                                height: 110))
    
        spine.center             = CGPoint(x: 560,
                                           y: 165 + Int(top))
        spine.layer.cornerRadius = 5
        spine.backgroundColor    = UIColor.black
        spine.clipsToBounds      = true
    
        NewView.addSubview(spine)