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.
Related
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 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!
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.
I'm trying to show a search bar above a table with a list of recent searches that will swap to matching search results once someone enters a search term.
I want to set a custom class MySearchViewController to be the delegate for doing the search and managing the display of search results back to the table so that I can separate the code and not have conditional statements in the default controller.
I've found a bunch of examples that describe how to do this in code but I can't figure out how to do it using Interface Builder.
I've tried dragging a new viewcontroller into my xib and setting the custom class to MySearchViewController and then dragging outlets from the SearchDisplayController as hinted at here: http://goo.gl/RgmwG
I've also tried dragging an Object into the objects column and changing this class to MySearchViewController.
But I feeling completely lost and really just trying things randomly. I'm guessing that I also need to create a property/IBOutlet for the SearchDisplayController somewhere but again lost.
If anyone has a reference to how to go about this I'd be so happy!
Like most problems, it seems pretty obvious in retrospect.
Add an 'object' placeholder in interface builder (orange cube).
Change the objects custom class to the class you want to be the delegate - e.g. MySearchViewController
Remove the default outlets from the standard SearchDisplayContoller to connect with the MySearchViewController object (see screenshot)
Make sure that the new delegate has an outlet to a parent view (in my case View)
Make sure that the delegate class is initiated from somewhere
// I did this from the parent ViewConroller, but probably better from the main app delegate?
#property (strong, nonatomic) IBOutlet MSSearchViewController *searchViewController;
Hope this helps someone else who was also stuck!
In many iOS books and tutorials they demonstrate how in interface builder you can basically turn a UIView into a UIControl and have it inherit new higher level functionality to respond to clicks and behave like button for example. This is done simply by changing the class type in interface builder of a selected UIView.
This is often done to dismiss the keyboard when someone touches on the "background" or main view of a given view controller. Once a UIView's class is changed to a UIControl you just assign connect a new IBAction for when a TouchUpInside event occurs for example.
Now I understand this concept but it seams like a weird Xcode hack. The reason is, I don't see how I could accomplish the same thing programatically. Let me explain: If I create an instance of a UIView in code and I want it to behave like a UIControl how would I tell this UIView instance that I want it to inherit from UIControl. Now keep in mind I don't actually want to subclass UIControl because that would be jumping through more hoops and I don't think that is what Interface Builder is doing when you change that class type, or is it? Also, keep in mind UIControl is meant to be an abstract class and not to be used directly otherwise I would probably just do that.
Ultimately my question is, is there an equivalent way to accomplish the same thing in pure code and have a UIView become a UIControl such that I can assign the higher level events to it?
I hope this makes sense, if not I can elaborate.
UIControl inherits from UIView, so if you wanted to do this programmatically, you would just create an instance of UIControl instead. So if you were creating a view controller's view programmatically, for instance, you could do something like:
- (void)loadView
{
CGRect viewSize = /* some appropriate default size */
UIControl* myControlView = [[UIControl alloc] initWithFrame:viewSize];
// configure your control (e.g., set events, etc)
[self setView:myControlView];
[myControlView release]; // omit this line if using ARC
}
I created xib file. then new Objective c class file inherits from
UIView. i set xib class Objective c class, in interface builder and
then change super class of Objective c class to UIControl.