I have a nib that has a button that I would like the relevant controller to have access to. But right now the owner is a generic NSViewController, and inside AppDelegate I assign the nib to the controller like:
[browseViewController initWithNibName:#"BrowseView" bundle:[NSBundle mainBundle]];
But is it possible within the nib file to assign a button's referencing outlet generically? In other words, to give the outlet a name and point it to File's Owner, and then if/when the nib is connected to the controller if that controller has an outlet with the same name it just works?
The File Owner has to have the certain outlet and/or the action when you connect it in IB. Even if you could connect it to an outlet that does not exist, an exception will be raised when the nib is being loaded. I you want to check it make an outlet, connect it to an object, save the nib, delete the outlet from the object and run the application. NSUnknownKeyException will be raised.
The easiest way would be to use a common superclass of your controller. If the controllers cannot be derived from the common ancestor, the only workaround I see is to make a protocol where you define your outlet properties and actions. Make an object that conforms to the protocol
MyObject: NSObject < MyNibProtocol >
now use this object in the nib to connect the outlets and actions.
However, the properties and methods cannot be optional, you have to implement them.
Related
I have a subclassed NSCollectionView that is created in Interface Builder and is bound to an array.
I need to implement some of the delegate classes from NSCollectionViewDelegate but I'm kind of stumped as to what class to designate as the delegate.
Do I just create a random NSObject and designate it as the delegate? Do I create an NSViewController and designate that as the delegate—but if so, since the Collection View isn't being created programmatically, how do I tie the NSViewController to the Collection View?
Any pointer to a good document that would explain stuff like this in Mac app architectural decisions would be a great bonus.
It is common, but not mandatory, to make a view controller also be the delegate of the underlying view object. However, you can also make a new class as you suggest and use that. If that works for your overall architecture, do that.
What kind of object is the File's Owner of the NIB? Most often, a NIB should be loaded and owned by either an NSWindowController or NSViewController (or subclass of one of those). That controller would typically be responsible for everything in the NIB, so it would be the delegate.
If it makes sense, you might put the collection view into a NIB all its own. You'd create a subclass of NSViewController to load and own the NIB and set the class of the File's Owner placeholder in the NIB to that class. You'd connect the view outlet of File's Owner to the collection view and the delegate outlet of the collection view to File's Owner.
I have UIScrollView added to the main window of the app with IB.
What I want is that view to subclass UICustomScrollView instead of UIScrollView. To do that I choose the UIScrollView and then I change Custom class to UICustomScrollView in identity inspector. I have put some NSLog messages in init method of UICustomScrollView. When I run the app UICustomScrollView seem like it is not used because NSLog messages in init are not printed.
What I miss here ?
Here's what the UIView Class Reference has to say about initWithFrame::
If you use Interface Builder to design your interface, this method is not called when your view objects are subsequently loaded from the nib file. Objects in a nib file are reconstituted and then initialized using their initWithCoder: method, which modifies the attributes of the view to match the attributes stored in the nib file.
If your NSLog is only in initWithFrame, it won't be called if the view is loaded from a nib.
What is meant by "File's Owner"? The XIB interface says it's UIApplication, but why is it named so? Which file does it own? I understand MVC to some extent, but I never heard of "File's Owner". What does it have to do with the controller of the application?
File's Owner is a proxy for the object that's specified as the owner when the .xib is loaded. Usually, it's the object that's actually loading the .xib. In any case, it's important to realize that File's Owner represents some object that's external to the objects in the .xib file, and as such it's basically the way that objects inside the .xib are connected to something outside the .xib and vice versa.
This all has very little to do with MVC and a lot to do with how Interface Builder works. Typically, you add IBOutlet properties and IBAction methods to the object that will load a .xib (such as an application delegate or a view controller). Then, using IB, you connect objects inside the .xib to the File's Owner proxy, and you set File's Owner as the target of your controls (choosing the appropriate action for the control).
In my application I have a single nib file. The File's Owner is a NSViewController and insider there is just a vertical slider that I want to bind to a property in one of my classes. (I don't have any other nib files since it is a status bar application, so I don't have a window). The nib is loaded runtime to create a custom view for a NSMenuItem.
The problem is that I want to use an object controller to do the binding but I'm not sure what is the content of the object controller. How can I access from the nib to an arbitrary class in my project?
In the examples I have seen, usually the object controller uses the File's Owner to access the class (and the property for the binding) setting the Content Object binding to the File's Owner. But in my case from the File's Owner I do not have access to the class.
Any pointer?
Ok this works for me. It is enough subclassing NSViewController and sets the new subclass as the File's Owner. Now it is possible to use a Controller Object to bind through the File's Owner.
If you use XCode 4 you can Control-drag from the slider to the .h file (AppController.h?), and you will get the option to generate an outlet or an action. If you want to create an action, caused by sliding the slider, you should select action. The generated method will be called whenever the slider is changed. If you want the slider value to react to an event (or a changed instance variable in your program), set it to 'outlet'.
Hope that helps, let me know if you were really looking for something else :-)
I am just trying to get my head around MVC in Objective C and IOS but am having a problem I'm hoping someone can help me with.
I have created a custom view (created as a child UIView in a XIB) that uses a simple delegate protocol for requesting information from its delegate in drawRect. I have a view Controller that implementes the protocol and is connected to the view through interface builder.
The custom view also has a few properties that I want to set on startup.
The problem I have is working out how the controller is supposed to access the view to set these properties as it doesn't appear to have direct access to it. Also the properties don't seem to be visible in interface builder inspector as I would expect unlike the delegate property I added.
Initially I thought I could do something like
[self.view setViewIntProperty:10]
But that would be calling the main XIB view and my custom view is actually a child of this view so I need someway to get that specific child view to I can initialise it from the controller in viewDidLoad.
Hopefully that is clear. I'm sure this should be easy and I've missed something simple but can't see how this should normally work.
You can just create another property on your view controller of type MyCustomView*.
Declare that property as an IBOutlet and you wire that up in IB.
Then in your view controller you can use that property to access that custom view.
Your custom view's properties (as opposed to its outlets) can only be set in code unless you create an IB plugin for it.
Your other subviews can be accessed easily if you create an outlet for each of them in your controller. The view outlet is there as the primary view of that view controller. There is nothing preventing you creating additional outlets to other views/controls. Yu would just need to subclass the view controller and add the outlets as needed. Just remember to set the class name of the controller (in Interface Builder) to that of your custom subclass. That will expose the available outlets for you to connect.
You'd still need to create an Interface Builder plugin if you want to make your control's custom properties available in IB's inspector palette. Unless you plan to reuse it frequently in other applications or make it available to others, it's probably easiest just to set the properties in your source code.
Example for setting corner radius of your custom subview (subclass of UIButton in my case) from xib.
Create a property like this
#property (nonatomic, assign) IBInspectable CGFloat cornerRadius;
Override setter in your custom view's implementation file.
-(void)setCornerRadius:(CGFloat)cornerRadius
{
self.layer.cornerRadius = cornerRadius;
}
Drag your view in xib and change its class to your custom class.
Magic... You will see the custom properties appearing in attribute inspector like this.