Connect UITableView DataSource/Delegate to base UIViewController class - objective-c

I'm attempting to connect my UITableView's DataSource and Delegate to my ViewController's base class via the storyboard. I Was able to connect my IBActions and IBOutlets easily, but this is proving trickier.
Is the correct method to instantiate the delegate/datasource methods then call the same methods on super?
TIA

Xcode will type-check the objects you attempt to connect. So there are two pre-requisites:
An object of your class must "be present" in the storyboard, which usually involves setting a custom class on a UIViewController in the inspector
The class of your object must declare that it conforms to the correct protocols before you make the connections.
If those two criteria are met, you should be able to ctrl-click on the UITableViewController, and drag from these connections to an object of your class, either in the storyboard or in the list of objects on the left.
EDIT: I have added a picture of setting the delegates via the two-step method of ctrl-clicking the table view, then dragging from the popover to the protocol-conforming view controller. This technique works with both the list view on the left as well as the graphical representations in the workspace.

Related

What object should implement NSCollectionViewDelegate?

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.

StoryBoard handling inherited view controller

I am new to storyboard. I used to make my view using code. I have a question.
I created a view controller
#interface FunctionViewController : UIViewController
And I have use my code to add
a full screen button (alpha : 0.5)
a popup-like view in the middle (not full screen)
Then I created another Viewcontroller
#interface PlayFunctionViewController : FunctionViewController
and add some views on the popup-like view
I want to recreate these stuff by using storyboard.
How can I build these using interface builder and storyboard so that
I don't need to layout the full screen button and the popup-like view in every subclass of FunctionViewController?
You can't inherit the layout of a superclass in a subclass in a storyboard, i.e. if you visually lay out elements in a view controller in a storyboard and connect them to code, subclasses of that view controller, and even other instances of the same class, will have to be laid out individually, and will not automatically be populated or updated.
In other words, in a storyboard, you will have to manually lay out and connect all your interface elements in every individual instance and subclass that you add to the storyboard. This gives you flexibility in that you can reuse multiple instances of the same class throughout your app and lay them out differently, but it does not give you the ability to inherit layouts.
If you want to inherit your layout in subclasses, do your layout programmatically in the viewDidLoad of your superclass, and then all of your subclasses will have those interface elements, even if you design and lay them out in your storyboard (they will not be visible in the storyboard, but they will appear when you build and run your app).
Basically, if you want to have interface elements that are the same in a class and all its subclasses, create them programmatically, and they will exist in all instances and subclass instances, even if you create and design the instances themselves in your storyboard.
You can mix code and storyboard, so you can create some elements in your storyboard, but others that need to be present in all instances and subclasses, in code.
I ran into a similar issue, and though it was time consuming but creating a delegate and reusing it in multiple view controllers was a much better solution. Although that beats the whole point of 'Inheritance'.

What does it mean to delegate to File Owner in my xib file?

I believe that UIView objects can delegate control to views in iOS programming. However, I thought this was already handled by an IBAction associated with an IBOutlet corresponding to the UIView.
In that case, what does it mean to drag a blue line (while pressing Ctrl) from the delegate circle of the UIView in my xib to File Owner?
Isn't the UIView already delegating to my view controller via an IBAction? The code seems to work if I don't specify anything for my UIView's delegate.
"Isn't the UIView already delegating to my view controller via an IBAction? The code seems to work if I don't specify anything for my UIView's delegate".
It looks like you're confusing the idea of the Target-Action Mechanism with delegation. While you could in a way think of target-action as involving “delegation”, it would only be in the most general sense of the word in that it’s the target (generally a controller) that handles and implements the action (the message). However, a Cocoa programmer would probably refrain from explaining the target-action mechanism by using that particular word – delegation – as it would be too easy to confuse it with actual Delegation.
When you “wire up” buttons and controls in the nib file to call IBAction methods in your controller object, that’s just the target-action mechanism at work. As you saw, the code works even if you "don't specify anything for my UIView delegate”, since target-action doesn’t involve delegation (in the Cocoa-sense of the word).
Delegation is generally used as an easier alternative to using subclassing to implement the desired behavior. For example, instead of having to create your own custom subclass of UITableView in order to have it know what data you want it to display, you can simply use the plain UITableView class, set its delegate to a controller class, and have the controller class implement the required/desired designated delegate methods. Using subclassing to accomplish that could potentially get complicated, since when you subclass, you need to have a full understanding of the inheritance chain and how all of the superclasses work.
File's Owner is just a fancy way of disguising the name of the class that the XIB is taking it's references from. When you drag the delegate outlet to your class, it's the equivalent of this line:
[self.myControl setDelegate:self];
When you drag while pressing CNTRL from an IBOutlet or IBAction to a UILabel, UIButton or something else, you are binding events or outlets to your controller.
A delegate sort of a controller that must implement specific functions depending on which type of delegate it is. For example, the UIViewController, which implements the UIViewDelegate protocol, can implement
-(void)viewDidLoad
the YourApplicationDelegate, which implements UIApplicationDelegate must implement
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
So a delegate is just a set of functions which define the behavior of an object, the classes that implement them can change this behavior.

How do I set a property on a custom view instantiated from a XIB

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.

The relationship between UIViewController and UIView

I'm trying to understand how these two are connected. Every time you make a UIViewController does it also automatically come with its own UIView?
Also are these from Cocoa or Objective-C?
UIViewController is a Cocoa Touch class built for the purpose of managing UIViews. It expects to have a view hierarchy, but you don't "automatically" get a view (this is slightly inaccurate; see edit below). Usually you will obtain views by calling initWithNibName on your view controller.
There is some built-in magic in Interface Builder which knows that if File's Owner is a UIViewController (or subclass), there is a property called view. That's about it.
Once you have linked a view controller and a view, the view controller does a fair amount of work for you: it registers as a responder for view touch events, registers for device rotation notifications (and handles them automatically, if you wish), helps you take care of some of the details of animation, and handles low-memory conditions semi-automatically.
Edit: correction—if you don't call initWithNibName or set the view property manually, the view property getter will invoke loadView if view is nil. The default implementation of loadView will see if you've set nibBundle and nibName and attempt to load the view from there (which is why you don't have to call initWithNibName, most of the time), but if those properties aren't set, it will instantiate a UIView object with default values. So technically, yes, it does automatically come with its own UIView, but most of the time that's of little value.
UIViewController doesn't automatically come with a view. You have to make a view in the -loadView method. By default, this loads the view from the nib file you've specified. You can also override this method to make a custom view if you prefer not to use a nib.
Also, the view is not created right when the UIViewController is created. UIViewController uses a technique known as lazy-loading to defer the creation of a view until the view is actually accessed for the first time.