After Swift 3.0 Migration, UIButtons no longer working in iOS 8.2 Simulators

Hey everyone,


I migrated my code to Swift 3.0 and I find that it works on iOS 10 Simulator and actual devices.

However, it broke UIButton clicks when I try to run it on iOS 8.2 simulators.


I am getting this error: "EXC_BAD_ACCESS (code=1, address= ... )" message upon a UIButton press.


This is what I am using for my addTarget:

button.addTarget(UIApplication.shared.windows , action: #selector(ViewController.onClick(_:)), for: UIControlEvents.touchDown)


OnClick is a function within ViewController that accepts sender inputs (usually in the form of UIButton presses)


Any help or hints would be greatly appreciated !


Thanks

Accepted Reply

Given that the

BUTTON(…)
function takes an action as a parameter, why not have it take a target as well? It’s called the target-action pattern for a reason (-:

The other option is to pass in nil for the target, which will send the action down the responder chain.

Passing in a window list is just weird.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Replies

Setting the target of an action to

UIApplication.shared.windows
is really weird. What are you expecting this code to do?

btw I did manage to reproduce your crash, but I’d like to understand what you’re trying to do before offering any concrete advice.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi Eskimo,


Thanks for responding. Just checked this forum again and saw your response.


I wanted a generic UIButton constructor in another swift file which I could instantiate in my ViewController swift file. Within my VIewController swift file, I have an OnClick function that processes the UIButton input via button tag. In order for my UIButton constructor to add itself to the calling class or to connect itself to the OnClick function, I decided to pass in the UIApplication.shared.windows parameter.


This worked well in Swift 2.0 and it still works in Swift 3.0 (iOS10). The issue here is it gives a bad pointer access when attempting to run on iOS8.2 (and possibly earlier) simulators.


Let me know if my explanation was not clear or if there's a better way of setting UIButtons programmatically in general in Swift that would work in iOS8.2.


Best regards,


eigen

Alas, I don’t really understand your explanation. Can you post some code snippets?

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi Eskimo,


From GUI.swift, I am trying to create a generic button instantiator in one file (GUI.swift) that I can create in another file (ViewController.swift).

The issue is: "EXC_BAD_ACCESS (code=1, address= ... )" whenever I tap a button instantiated the way its done below:


File#1: GUI.swift


func BUTTON (_ view : UIView, tag : TAG, text : String, font : UIFont, textColor : UIColor, bgColor : UIColor, rect : CGRect, selector : Selector) {

let button = UIButton(type: UIButtonType.custom) as UIButton

button.tag = getTag(tag)

button.frame = rect

button.titleLabel?.textAlignment = NSTextAlignment.center

button.titleLabel!.font = font

button.setTitle(text, for: UIControlState())

button.setTitle(text, for: UIControlState.highlighted)

button.setTitleColor(textColor, for: UIControlState())

button.setTitleColor(textColor, for: UIControlState.highlighted)

button.addTarget(UIApplication.shared.windows , action: selector, for: UIControlEvents.touchDown)

button.backgroundColor = bgColor

view.addSubview(button)

}


func LABEL { ... }

func TEXTFIELD { ... }

...


File #2: ViewController.swift


...


//Create a button in ViewController.swift

BUTTON ( self.view, tag: 1, text: "text goes here", font: ..., textColor: ..., UIColor: ..., bgColor: ..., CGRect: ... , selector: #selector(ViewController.onClick(_:)) )


...


//onClick Function

func onClick (_ b : UIButton) {

switch b.tag {

case 1:

//Do Something when BUTTON with tag = 1 is pressed.

break

default: break

}

}


...


Hope this clears up some things.

This works in iOS10 but not in iOS 8.2 when written in Swift 3.0, however in Swift 2.0 (before migrating to 3.0) it worked for 8.2 perfectly.


Thanks again for taking the time to responding to my post!

Regards,

eigen

Given that the

BUTTON(…)
function takes an action as a parameter, why not have it take a target as well? It’s called the target-action pattern for a reason (-:

The other option is to pass in nil for the target, which will send the action down the responder chain.

Passing in a window list is just weird.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Setting the button target to NIL did the trick !

That window list was a weird thing to pass into a button target. Never really questioned it because it worked all these years.


Thanks a lot for taking the time in helping me debug my code Eskimo! Greatly appreciated!


Regards,

eigen