How to connect UIButton to action using only interface builder - ios

At the moment I am setting up my buttons for my keyboard with the following code:
func setupButtons() {
for subview in self.view.subviews {
if subview.isKindOfClass(UIButton) {
setupButton(subview as! UIButton)
}
}
}
func setupButton(btn: UIButton) {
btn.addTarget(self, action: #selector(KeyboardViewController.keyPressed(_:)), forControlEvents: .TouchUpInside)
}
But is there anyway I can skip this and all the target inside the layout builder so I can save a little bit of time looping through buttons on each keyboard view?

Sure, there are two ways to connect objects to Interface Builder, through outlets and actions.
class ViewController: UIViewController {
#IBOutlet weak var doStuffButton: UIButton!
#IBAction func doStuff(sender: UIButton) {
//do stuff
}
}
After adding that code look in interface builder and click on the view controller for this class.
Click on the connections inspector
Under outlets you will now see doStuffButton, however over the circle to the right of that, press control and click with your mouse, and drag it over to the button you want to connect it to and release. Setting outlets is NOT required for enabling actions. I just wanted to show this to you as well.
In the same pane you will also see received actions and the doStuff: method. Click and drag in the same way and release on the button. Select which type of event you want to process this action (normal is touch up inside).
Once you're all hooked up it should look like this:
There are many other variations of how to do this, but I thought this would get you a quick start.

If you're trying to ask how to do this without coding anything, just go into the assistant editor view of Xcode and Ctrl-drag from your button to the controllers class file. Then when the pop up displays, change outlet to action and give it a method name. This creates the IBAction method for you.
But in reality, the way you are doing it now with the for loop is far better. Especially if you have many buttons.

Related

How to hook up "Pop Up Button" event handler on selection update?

I added a "Pop Up Button" from XCode Object Library, and wanted to hook it up with event handler that handles menu item selection update (for app's language selection).
The button is already created in *.xib file, and what kind of function should I create to hook up with button events?
I created a IBAction handler like this:
#IBOutlet weak var languageSettingButton: UIButton!
#IBAction func onLanguageSelected() {
// handling selection
// ...
}
But dragging the selector to this IBAction function did not work. What kind of selector function is it expecting? How do I hook it up?
My usage with two menu options regarding two app languages:
The Pop Up Button:
Update:
Followed #Charles Srstka's comment:
The IBAction func needs to have a sender param:
#IBAction func onLanguageSelected(_ sender: Any?) {
}
However the interesting thing is, we are able to hook up the entire button with the IBAction func, but not the menu item's selector, what should we do with the selector here? does it need to be hooked up with a function too?
Finally figured out the solution:
Based on Charles' comment, in view controller file, add a selection handler with sender param:
#IBAction func onSelectionUpdate(_ sender: Any?) {
// add logic here
}
In the pop up button's menu item's selector hook, drag it all the way to "File's owner", after dragging, a small menu will show available IBAction functions, choose the one we just created.

UIButton never fires off code in Action

I have the following screen:
The X is the image of a UIButton, I have add the appropriate action to the button. Yet when I click on the button it never fires off the code in the action.
Here is some code:
#IBAction func CloseProfilePage(sender: AnyObject) {
self.removeAnimate();
}
This is the code that is used to launch the view controller seen:
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let selectedAppointment = self.dayDatasource!.appointmentAtIndex(indexPath.item);
let profilePageViewController = ProfilePageViewController.init(withAppointment: selectedAppointment);
profilePageViewController.view.frame = self.view.frame
self.view.addSubview(profilePageViewController.view)
profilePageViewController.didMoveToParentViewController(self)
}
The button is definitely connected in the xib to the action:
When I check in the view hierachy, there isn't anything else on top of the button that would prevent the button but registering clicks. I'm assuming here that the imageView in the UIButton is clickable as its part of the button iteself.
The X in the image is not an image view I added, it is the image view that comes with the UIButton. With that said I've also resorted to the following:
self.profilePageClosePopUpButton.imageView?.userInteractionEnabled = true;
Still the button remains unclickable. Where am I going wrong?
It pains me to say this but I'm only writing a solution here just in case someone in the future struggles with the same issue and maybe this post could help them.
In the view, seen in the image below, I had some how unintentionally switched off User Interaction Enabled in interface builder. Because this was off, all other children didn't have interaction enabled on them and hence why the button was not clickable...
Moral of the story is, check your parent views and make sure their user interaction is enabled as well.

Copy UITabBarController logic with default buttons

I want to have three VC's (A, B, C look at picture). And I want each VC to have three same buttons. And when user will press left button it will show A VC, when center button will be pressed - "B" VC will be shown and the same with the last one. Also I don't need view controllers to be created each button press, they have to save their state.
The same functionality has UITabBarController but I dont know how to implement it with buttons.
Can some one help me with my issue or show the right way to accomplish this?
Try this approach:
In your main view, add three overlapping container views.
Add buttons to the main view to switch between views (by bringing them to the front).
Configure the viewControllers however you want. Embed them in a NavigationController if desired.
Add #IBOutlets to the container views.
In the #IBAction for each button, bring the corresponding view to front`
class ViewController: UIViewController {
#IBOutlet weak var containerA: UIView!
#IBOutlet weak var containerB: UIView!
#IBOutlet weak var containerC: UIView!
#IBAction func pressA(sender: UIButton) {
view.bringSubviewToFront(containerA)
}
#IBAction func pressB(sender: UIButton) {
view.bringSubviewToFront(containerB)
}
#IBAction func pressC(sender: UIButton) {
view.bringSubviewToFront(containerC)
}
}
You can achieve it as follows:
Add three buttons on the bottom of the Parent Controller.
Add three Container View's and make their respective separate classes so that your code is modular. Make sure height and width of all the containers are the same and it covers the full view leaving your buttons on the bottom. (Container Views are very easy to manage using storyboards)
Now make three outlets for all the three container views and make three actions for all the respective three buttons.
On button press hide the two container views you dont want to show and unhide the one you want to see.
With this you can get Tab Bar Controller like functionality.
PS: You should not use these kind of approach and one should use tab bar controllers where required.

How to create IBAction from UISegmentControl?

I am dealing with UISegmentControl in my project. I am able to create outlet & outlet collection of UISegmentControl with the help of drag & drop. But not able to create IBAction of Segment Control.
I think I am missing very small thing. Any Idea how should I proceed now?
For more clarity you can refer this screenshot.
Try this code in your controller :
#IBOutlet weak var segmentedControl: UISegmentedControl!
#IBAction func segmentedControl(sender: AnyObject) {
if segmentedControl.selectedSegmentIndex == 1 {
// Do something with the first button
}
else {
// Do something with the second button, etc...
}
}
Then drag it from your code to your segmentedControl
This is same as button actions the only difference is instead of selecting TouchUpInside or other button events you should use "ValueChanged"
UISegmentControll will respond to value changed action
You need to click assitant Navigator in the top corner right hand side to open Implementation file then drag segment control to implementation file after the #implementation directive that will pop the dialog screen.

Is TouchUpOutside the correct control event for events outside of an element?

I'm three days new into swift development, even Xcode for that matter. I've created a UIView called EncounterMenu that appears over my app when i click the menu button. My goal is to have the EncounterMenu UIView close when I do anything outside of it.. This is what I have so far
override func viewDidLoad() {
super.viewDidLoad()
//create a button that spans the width & height of the encounter menu
let btnEncounterMenu = UIButton(type: UIButtonType.System) as UIButton
btnEncounterMenu.frame = CGRectMake(0, 0, EncounterMenu.frame.width, EncounterMenu.frame.height)
//(this is whats not working) If user clicks outside of button, call function "closeEncounter:"
btnEncounterMenu.addTarget(self, action: "closeEncounter:", forControlEvents: .TouchUpOutside)
//Add the button to the EncounterMenu
EncounterMenu.addSubview(btnEncounterMenu)
}
func closeEncounter(sender: UIButton!) {
EncounterMenu.hidden = true;
}
I tried changing it to TouchUpInside and it worked when i clicked inside the EncounterMenu UIView, so I figured it should be as easy as TouchUpOutside?
Any direction to what I'm doing wrong or how I can accomplish what I'm trying to do?
Touch up outside will not work because you need to be pressing on the menu first, then drag your finger outside for that to register. instead, the easiest option for you to do is to create a button that is the entire size of your view, and on that buttons touch down event, fire off close menu. just make sure that this big button is at the very back of the view, and everything else is built on top of it.

Resources