I am making a custom keyboard that has a search bar. In order for a user to be able to interact with it, they must be able to:
1- Input text with individual letter buttons.
2- Tap the search button.
As for number 1, I have working IBActions that are called at every button press. For example, here's the action for the letter "m":
#IBAction func mPressed(button: UIButton) {
searchBar.text! += "m"
}
However, the search button IBAction will not call:
#IBAction func searchPressed(button: UIButton) {
print("searchPressed")
}
When I connect the search button in storyboard to the "mPressed" action, that action is called. But when I reconnect it back to the "searchPressed" function above, it doesn't work again.
I have also made sure that I correctly connected the button to the action.
The search action is connected to the search button
The 'm' action is connected to the 'm' button
Thanks!
In your screenshot search button connected to method searchButtonPressed, but in code you have method searchPressed.
Delete connection to searchButtonPressed and reconnect to searchPressed and it will work.
Related
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.
When I create two UIBarButtonItem's on a UINavigationItem in Storyboard in Swift 5, using XCode 10.2.1, the buttons get enabled correctly and can be clicked, but the IBAction associated never gets triggered when I click on them.
I have two IBAction methods called saveButtonPressed and cancelButtonPressed, and also have both the cancel button and save button hooked up with an Unwind seque action to another ViewController, which has the unwindToPeriodicalList(sender:) method. I can set up the connection fine, it shows up when I Ctrl+Drag from the buttons to the Exit button on the overarching VC. I also have the prepare(for seque:) method defined in the VC that contains the buttons. Nothing seems wrong until I go to click these buttons and nothing happens. The seque back to the originating VC doesn't happen, nor do the methods saveButtonPressed or cancelButtonPressed methods get called. I've redone these IBAction connections what seems like 100 times, under different circumstances, and nothing seems to work. I've followed tutorial after tutorial and nothing has fixed it. Any ideas?
#IBAction func cancelButtonPressed(_ sender: Any) {
os_log("cancelButtonPressed() called", log: OSLog.default, type: .debug)
}
#IBAction func saveButtonPressed(_ sender: Any) {
os_log("saveButtonPressed() called", log: OSLog.default, type: .debug)
}
No error messages in the logs, nor the os_log messages that tell me saveButtonPressed or cancelButtonPressed were triggered. Yes, I have the debugger output set to All Output and not just one type.
İ have created a custom raised button in tabbarviewcontroller. Already added a custom action on button for selectedindex = 2.
Problem I am facing first time button clicked is working fine shows second tabbar item and perform action but if I re-clicked button again it won’t show tabbar item view. To check button status I use print command and its printing that button clicked.
Tabbarviewcontroller —> tabbarİtem 2 —> webview
As it stays on webview controller but On re-click of button İ need it come backs(navigates) to tabbarİtem 2.(refresh view as navigatecontroller performs back button). Behind the custom button - tabbarbar item for item2 (link able) is working but not on button.
#objc func buttonAction(sender: UIButton!) {
print("clicked button")
selectedIndex = 2 //// button click to open tabbar item 2
}
Short: In Swift/iOS, when does the "Done" (which was previously "Edit") nav bar button trigger when getting out of the UITableViewController "Edit" mode? When the user presses "Done" I'd like to enable a "+" button in my UINavigationItem bar so the user can once-again add rows by migrating to another view controller.
Longer: When a UITableViewController is showing below a UINavigationItem nav bar, there is an "Edit" button which turns into "Done" after it's clicked to enable deletes & move/drags. Works great when this button is enabled via uncommenting code in viewDidLoad() generated as part of the UITableViewController class:
self.navigationItem.leftBarButtonItem = self.editButtonItem
I've got my move/drags & deletes working fine, but I want to appropriately disable my "+" button (addBarButton, used for navigating to another view controller to add a new row) while the user is in the Edit mode. I'd then like to re-enable addBarButton after the user has clicked "Done" (which turns back into "Edit").
It looks like disabling addBarButton during the func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) is correct. If I read Apple's docs right, this is triggered when user presses Edit in the nav bar. What I don't know is what is triggered when the user presses "Done" (the button formerly labeled "Edit"). If I enable my addBarButton "+" button after the func tableView with moveRowAt, this enables addBarButton before the user has pressed "Done".
The Apple doc I'm referencing is at:
https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/TableView_iPhone/ManageReorderRow/ManageReorderRow.html#//apple_ref/doc/uid/TP40007451-CH11-SW1
Apologies if I'm missing something obvious. Thx
The answer is right in the description for the UIViewController editButtonItem documentation:
If one of the custom views of the navigationItem property is set to the returned object, the associated navigation bar displays an Edit button if isEditing is false and a Done button if isEditing is true. The default button action invokes the setEditing(_:animated:) method.
The last sentence is the key. You should override the setEditing(_:animated:) method in your table view controller subclass. Be sure you call the super implementation and then perform whatever custom action you want based on whether the controller is entering or exiting editing mode.
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
if (editing) {
// User tapped the Edit button, do what you need
} else {
// User tapped the Done button, do what you need
}
}
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.