Can't link a bar button to an #IBAction in superclass - ios

I have a number of view controllers, each with their own menu button (a UIBarButton, added in the storyboard). Now I want to link all these up to a single #IBAction function in their superclass (the superclass is the same for all the view controllers with that menubutton).
Now I have linked up #IBOutlets to a superclass before, but it doesn't seem to work with #IBActions, even though the function isn't private, and it definitely is part of the superclass (I am refactoring, previously it was an #IBAction in each class, which only did menuButtonTap() (calling the method in the superclass).
Any ideas?

I have solved the problem by manually creating an #IBAction on the superclass, and giving them the same name as the ones I create in the subclasses. Then I deleted the ones in the subclasses. This leaves a 'dangling reference' from the storyboard, according to Xcode, but I know it's there.

Although this still does not work as of Xcode 9.4 for general purpose UIViewController (but your workaround still does work 👍🏻), please note that it works as expected for UITableViewCell templates in storyboard.
If some of your template cells in storyboard share the same base class containing #IBOutlet properties, you will be able to link them to every template cell instance as you usually do:
Then Xcode will show a popup for telling in which prototype cell the link is "backed":
I'm not sure why this second step is necessary though, since you designate a specific component from within a given prototype cell

You can do it like you do when adding an action to a UITabbar button from subview class.
Assuming btn is a UIBarButtonItem,
[btn setTarget:self.superview];
[btn setAction:#selector(menuButtonTap:)]

Are you using __unused keyword by any chance? If you do the IBAction won't show up in storyboard(I am using Xcode 6.3.2)
- (IBAction)actionBack:(__unused id)sender;
vs
- (IBAction)actionBack:(id)sender;
To make it show up and selectable removed the __unsused keyword.

Related

How to set up #IBAction to target a UIView subclass

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.

Hide Outlets from Connections Inspector for Custom View

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 :)

How to show subclass of UIControl in View Controller

I would like to be able to interact with the UIControl I have made, and therefore want it in my ViewController.
What I tried
I subclassed UIControl (1).
Then I added a UIView to my View Controller and assigned it the new class (2).
But in Interface Builder I am not able to set my outlets to the buttons contained in the new class (1)?!
1:
2:
UIControl's documentation confirms that it is a subclass of UIView, and I should therefore be able to connect the outlets, right?
What am I missing here? :/
Off-course you can't add IBOutlet because buttons what you added to WeekdayControl are in UIViewController, you can't add Outlet to WeekdayControl, buttons only subviews of WeekdayControl, UIViewController is boss here, and you can add outlet only to UIViewController. (Sorry for my English)
Better create you buttons programatically in WeekdayControl.
Must read first:-
You cannot use the UIControl class directly to instantiate controls.
It instead defines the common interface and behavioral structure for
all its subclasses.
The main role of UIControl is to define an interface and base
implementation for preparing action messages and initially dispatching
them to their targets when certain events occur
So, you are doing wrong, if you really need to make a custom view or custom control then you can directly do it by creating a custom UIView and connecting the outlets directly with the view.
I think you missing the objective of subclassing a UIControl, it doesn't give rights to create outlets as it's a subclass of UIView,just read this lines what it is stated in the docs:-
Subclassing Notes
You may want to extend a UIControl subclass for either of two reasons:
To observe or modify the dispatch of action messages to targets for
particular events
To do this, override sendAction:to:forEvent:, evaluate the passed-in
selector, target object, or UIControlEvents bit mask, and proceed as
required.
To provide custom tracking behavior (for example, to change the
highlight appearance)
To do this, override one or all of the following methods:
beginTrackingWithTouch:withEvent:,
continueTrackingWithTouch:withEvent:, endTrackingWithTouch:withEvent:.

Where to customise IBOutlets

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!

Not all UITextFields are calling all delegate methods

I've got a view controller xib file with several views in it. I'm building a wizard-type interface. I'm just doing a simple fade between the views, and I'm already using a navigation controller for the main interface. I'd prefer not to use one for this wizard. Anyway, in the views, each panel has at least a button, some sort of input field (usually a UITextField) and some helper text hard coded in a UILabel.
The problem is that not all the UITextField objects are calling the textFieldDidChange method in the delegate (File's Owner - .m file associated with the xib), but all the UITextField objects ARE calling the textFieldDidBeginEditing method.
Makes no sense to me. I feel like I must be missing something simple in how I set up the screens, but I'll be darned if I can figure it out. Each of the screens all look identical in the property sheets (on the right hand side of Xcode), and everything is wired up correctly in the File's Owner property sheet, both in IBOutlet and IBActions.
Here are some shots of what's going on...
Ideas? Thanks.
Here are links to the screen caps of the vital parts.
(being a new member is making it hard to add all the info I need with screen caps!)
As far as I now, there is no delegate method with the header textFieldDidChange. You have created a method of your own, which is depending on a NSNotification. Make sure all the UITextFields are send the right notification.
There is no such method on a UITextFieldDelegate
You may have confused textViewDidChange, which is a delegate method for a UITextView, but itis passed the UITextView that generated the event, not an NSNotification.
Seems like you want textField:shouldChangeCharactersInRange:replacementString: instead.
This is resolved. I'm a knucklehead. :-)
I was attaching my own notifier/observer and hadn't done so for the last few UITextField objects. Sorry to bother y'all.

Resources