What's the difference between AnyObject and UIbutton as sender? - ios

When defining an IBAction, there's an option for Anyobject and UIButton, both works, what's the difference?

Yes, both works. The difference is just that by declaring it to a button, you get a typecasted reference as UIButton instead of AnyObject (or id in Objective-C). If you did not do that you will have to do it manually inside the code.
You should prefer leaving it to AnyObject in case the action has some code you would like to call from anywhere else, rather than just the button action.
For example a refresh button, you might have to do a refresh programatically. If you have set your action parameter to UIButton, you have to send an UIButton (but why??? You are doing it programatically, right?). Whereas if it is AnyObject, you can send 'self'. Which will also make you distinguish whether the refresh was done on action or programatically.
Hope that explains.
Sorry for no code. I am not into Swift coding much. Edits are welcome.
EDIT
So, even if it is AnyObject, it does have your UIButton properties. Just type cast it to use them.

If you are only ever going to use the function with a UIButton it is best practice to declare your sender as a UIButton. This saves you a bit of code and it also tells anyone in the future reading your code that you only expect the function to be used with a UIButton.
Using AnyObject or Any will work, but you will need to do an guard let button = sender as? UIButton { return } in order to access it as a button. This way allows you to react differently depending on what the sender actually is, but I don't recommend doing that.

If it's anyObject, then it doesn't have any of UIButton's properties. When you click the button and the IBAction fires, sender contains information about the thing that triggered the action.
For example, for a UIButton, you might want to query the UIButton's text when the IBAction triggers.
However, in a situation where the IBAction is connected to two different UI controls, let's say, a button and a slider, querying the sender when it's of type UIButton (while the triggering UI element is the UISlider) will crash the program. If you have AnyObject, you'll be able to test if the sender is a UIButton or a UISlider, and then do something.
In general, if you don't care about sender, leave it blank, so people reading your code will know that you aren't using sender for anything.

Related

Is there a reason to ever choose sender: Any when creating an #IBAction in Swift?

The sender type is set to Any by default when you use IB/storyboards in Xcode to create an IBAction linking the interface object (e.g. button) with the method in the code file.
Since you are doing this from the interface to the code, Xcode should know by the interface what type of control you are using, for example a UIButton, and so why does it automatically set the sender to the Any type and not to UIButton specifically?
Is there any reason to leave it as Any and not change it to the UIButton type instead at the point of creation? Either when you do it from the interface to the code, or when you create the IBAction in the code first?
Basic example of the code you get when hooking up a button to your view controller, despite control clicking from the button on the interface:
#IBAction func playAgain(_ sender: Any) {}
I think it's an unreasonable default. If your function only applies to a single UI control, then the sender should be as strongly typed as possible.
Technically, you could define a single #IBAction, and bind it to multiple UI controls, of different types. But even in such a case, a more specific type like NSView would be more appropriate than Any.

Button Action using Reactive Cocoa

can anyone say how do i observe for action in Reactive Cocoa for a UIButton or UIControl..
An alternative way is to bind the view to the view model.And observe changes on the Mutable Property.
I tried using below code but none is firing.
self.rollBtn.reactive.trigger(for: .touchUpInside).observeValues {
value in
print(value)
}
EDIT: Actually i am trying to get the sender on button Tap..how can i do that?
You have done nothing wrong in this code snippet - trigger(for:) is one of the ways to get notified in RAC 5.0. It should print () for every press on the button.
Have you linked the button with the view, if you are using Storyboard or Interface Builder? Where did you place this piece of code? Make sure you place it in viewDidLoad or awakeFromNib so that it gets called before the view is presented.
-
EDIT: Actually i am trying to get the sender on button Tap..how can i do that?
As mentioned in the comments, trigger(for:) returns a Signal<(), NoError>. It doesn't include the sender with the value event. You would need to reference the sender manually, e.g.:
button.reactive
.trigger(for: .touchUpInside)
.observeValues { [unowned button] in
_ = button
}

Why is there an option of AnyType when creating a buttons action

When creating a UIBUttons action, the default is AnyType. Why is it default, and why is it an option at all? Shouldn't it just be UIButton?
We can hook any sort of UIControl up to an IBAction method. Additionally, we can hook up UIGestureRecognizers to IBAction methods.
If we do connect multiple things up to this method, it has to take an argument type that works for everything that could possibly be sent in.
So, if we hook up a UIButton and a UIGestureRecognizer to an action, the only thing that works is if the argument it takes is an AnyObject.

Why is my sender.tag coming back as 0 in SWIFT

I have given a UIButton a tag of 1 inside the interface builder attributes section.
I then want to access the tag value of that button once it is pressed, so far I have done this but it is coming back as 0.
#IBAction func attractiveMinus(sender: AnyObject) {
println(sender.tag) //sender.tag comes back as zero.
}
I am not sure if this is the correct way of finding out the tag of a button can somebody please say where i'm going wrong?
thanks
That should work, so I'd double check that you've updated the tag of the right button. Make sure that the updated IB files are being included in the build by wiping your derived data. Sometimes when you make a really small change like that, Xcode will use the previous version of the Storyboard/Xib that it has cached.
Also, since you know the sender is going to be a button, you can use UIButton in place of AnyObject to get the most out of Swift's type safety.

What is the difference between the arguments 'sender' and 'none' for an IBAction in iOS

While creating a new IBAction Method, I have dragged from the Button in the storyboard to my header file as I should. The Popup that appears I have noticed has an arguments dropdown which offers 3 options which are none, sender and sender and event. What is the difference between 'none' and 'sender' and in what situations would each be used?
None
You don't need to know any information about what triggered the action, just that the action was triggered.
Sender
You not only need to know that an action was triggered, but information about what object triggered the action. For instance, if you need to know which button triggered a certain action in order to change its properties.
Sender and event
You need to know the action was triggered, what object triggered this action, and the type of event that triggered the action. For example, if you need to know which button triggered a certain action in order to change its properties, and you will change them differently if they touch down on the button vs touch up vs double-tap vs etc. but you don't want to create a separate action method for each type of event.
Stonz2's answer covers it pretty well.
Some examples where you might want the sender:
Say you have a calculator app, and you have digit buttons and operator buttons. Rather than writing a different IBAction method for every button, you might write a -digitTapped action and an -operatorTapped action.
You could add tag values to each button, and then in your action method, interrogate the sender to see what it's tag is.
Another example would be a slider. You might use the sender parameter to get a pointer to the slider and fetch it's value.
(BTW, by default IB makes the type of the sender be id, which is an anonymous pointer. I usually change the type to be the type of the object that is triggering the action, like UIButton, UISlider, etc.)

Resources