Search code examples
iosswiftnslayoutconstraintuiswitch

Cant get UISwitch constraints to work - swift 4


I'm trying to create a UISwitch programmatically but for some reason I can't get any constraints to work. If I don't use any constraints the UISwitch is created but in the top left corner.

I tried creating the UISwitch by adding in the constraints when declaring my switch and this does move the switch to a different place. However this is a problem as I want to it to be constrained against other items in my view.

class cameraController: UIViewController {

    var switchOnOff: UISwitch {
        let switchOnOff = UISwitch()
        switchOnOff.isOn = false
        switchOnOff.translatesAutoresizingMaskIntoConstraints = false
        switchOnOff.addTarget(self, action: #selector(switchButton(_:)), for: .valueChanged)
        return switchOnOff
    }
}    

extension cameraController{
    @objc func switchButton(_ sender:UISwitch){
        if (sender.isOn == true){
            print("UISwitch state is now ON")
        }
        else{
            print("UISwitch state is now Off")
        }
    }
}

extension cameraController {
    private func setupLayouts() {

        view.addSubview(switchOnOff)

        switchOnOff.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20).isActive = true
        switchOnOff.topAnchor.constraint(equalTo: photosButtonIcon.bottomAnchor, constant: 20).isActive = true

    }
}

I want to be able to add my constraints for the switch into my setupLayouts extension and not when the switch is being declared.

The error I am getting when running the above code is:

Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

I am getting this error on the first line of the constraints in my setupLayouts extension.

Any help would be great.


Solution

  • You need a lazy var to have self inside this block which is a closure , your current code is a computed property which returns a switch for every reference and that causes a crash in constraints as the switch added to view is not the same object as the one you set constraints for

    lazy var switchOnOff: UISwitch = {
        let switchOnOff = UISwitch()
        switchOnOff.isOn = false
        switchOnOff.translatesAutoresizingMaskIntoConstraints = false
        switchOnOff.addTarget(self, action: #selector(switchButton(_:)), for: .valueChanged)
        return switchOnOff
    }()
    

    Then call setupLayouts inside viewDidLoad , btw extension is totally irrelevant to this problem