I have a view controller with 3 sliders. I only have 1 function that needs to be called every time a slider value changes - a value change in any one of the 3 sliders should cause call to that function.
How do i do that?
If I try to use outlets then I am only able to link only one UISlider.
You can simply connect the Value changed event of all sliders to the same IBAction:
If you want to connect them as outlets (which is something entirely different) you will have to use an IBOutletCollection:
If I try to use outlets then I am only able to link one UISlider.
You need to connect the slider to a target and action, not an outlet. The target is the object that will receive a message when the slider changes, and the action is the message that will be sent to the target. An outlet, on the other hand, is a reference to some object; for example, if you connect a slider to an outlet in your view controller, the view controller will then have a reference to the slider that it can use to send messages to the slider.
Related
I'm trying a storyboard-free approach, and attempted the following:
I created a FooView.xib to hold my layout. It has a few buttons and labels.
I created a FooView.swift to hold a FooView subclass of UIView. At the moment, it doesn't really do anything.
I created FooViewController.swift to manage my FooView instances. I call it to create FooViews as follows:
init() {
super.init(nibName: "FooView", bundle: nil)
}
I set the File Owner of FooView.xib to the FooView class
I set the custom class of the FooView view as FooView
I dragged some #IBAction outputs from the IB to the FooView implementation
When my actions fire, I get a runtime exception: "unrecognized selector sent to instance" that references the FooViewController(!). I double checked the File Owner and all the outputs, all references look correct.
It acts like it ignores the File Owner with respect to the event dispatch.
(It feels like I'm fighting the framework and really am expected to implement all my outputs/actions inside the controller, but from an architectural purity perspective (to enhance testing) I was leaning towards hiding the xib control details and making a more opaque view that didn't directly expose its inner controls to the controller, but instead had a protocol/delegate kind of contract.)
I have a sneaky suspicion that if I moved all the xib-loading logic into the UIView implementation that things would work, but that feels like a larger adventure. Is there an easy way to set up my FooView subclass to receive the events?
Another thing you could use is set the First Responder as the target for your action. Although you won't get the nice neat indicator in XCode that you IBAction is connected, it will pass the message to the first class in the responder chain that implements that method.
To set it up in interface builder, click on First Responder and open the Attributes inspector. Add your method to the User Defined list as someAction: (don't forget the colon). Then you can connect your button to the first responder and that method will be an available option for you to connect it.
Lastly you declare your IBAction just like normal in the view class you want to implement it.
I have created a custom view (Quantity View) with nib file in Swift. I have created some IBOutlets & IBActions (for buttons, labels etc.) in my custom view.
I tried to use this custom view (Quantity View) by assigning class name to a UIView in my storyboard.
It's showing me all the IBOutlets & IBActions in the Connections Inspector, as shown in this screenshot: .
I just want to show only delegate for the Custom view.
Possible Answer:
I thought I can use the -viewWithTag to get the views instead of Outlets.
But, I want to know if it's possible with having Outlets also or if there is much better way to do this?
What are the other possible ways (optimum) to handle this situation?
You can also consider the following solution:
You can take the subviews of your QuantityViews(custom view) and you can identify the specific views by its frame origin.
Note : you should know the customview subviews frame
Its not possible to hide IBOutlets from storyboard if you declare the class members as IBs (IBOutlets or IBActions).
The IBOutlets or the IBActions are just indicators to the interface builder so that it can show the names on it when you try to bind them it actually calls the setValue: forKey: method to set the view's reference to the IBOutlet property.
Now if you try to access an subview from the file's owner class without any IBoutlets you need to have a pointer to point it, so for that either you can get the reference using ObjectID which is assigned to the subview by the interface builder or you can get it using the viewWithTag: method.
The ObjectID you need to find all time when you add or replace a subview from the view, so better and convenient approach is to use tag property of UIView class.
So my conclusion to this problem is to access the views using the viewWithTag method you mentioned earlier.
I think your way is correct. But sometimes Xcode doesn't work correctly.
The following makes the IBOutlets and IBActions reappear and work properly:
Clean project your project in Xcode.
Quit Xcode completely.
Delete all contents of ~/Library/Developer/Xcode/DerivedData/.
Restart MacOS just in case.
I hope you will resolve that :)
I am writing code for a tip calculator in Xcode using swift. I am reading a book and was instructed to connect the slider to the calculateTip method. I am trying to figure out what connecting the action will do. Does this simply mean that every time the slider is moved the calculateTip method will be called?
This particular connection means that you assign an action to the slider: In this case your calculateTip method. By default the slider sends a message to this method, when its value has changed. This connection can also be done programmatically, but Xcode makes that easier for you.
So to answer your question: yes. Anytime the slider is moved the calculateTip method is called. But take a look on the sliders continuousproperty to decide whether this method should be called when the user stops dragging the slider, or — as the name suggests — to send continuous messages.
Yes, it depends which action you choose exactly, but if you select the ValueChanged action then yes, it will call that method every time the slider moves.
Where should I customise my IBOutlets?
Say I have created a button with interface builder, created an IBOutlet for it and I would want to change a property during runtime (ex: background color or localized title).
I would think of adding it to the viewDidLoad method, but outlets aren't yet created.
I remember having nil outlets in viewDidLoad, but I might be wrong.
If I move it viewWillAppear, the code will be executed every time the view controller's view appears.
Is there any better place for my IBOutlet related code, so it's only executed once?
Obviously I can do just about any customization using only the interface builder and making use of the User defined runtime attributes or localized stroryboards, but I don't like that since it's much more tedious to change later.
From the Doc
Its clearly says about the Views loaded into the memory in the -viewDidLoad() delegate itself.
I would think of adding it to the viewDidLoad method, but outlets
aren't yet created.
It is a false statement, Because you only get the viewDidLoad: message after IBOutlets are created. So you can safely do any customization in viewDidLoad:
Let’s say you have a Button you want to customise. You put the button at the place where you want it to be and then open the “Identity Inspector” on the right.
There is a textfield for “Custom Class”:
I usually create a subclass of UIButton / NSButton (depending on iOS or OSX) and edit the behaviour, drawing methods and functionality in this class file. Then just add the name of this class in this textfield. Voila!
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.)