Should I call [super awakeFromNib]? - objective-c

If i implement my own version of awakeFromNib, should I call [super awakeFromNib] at the end of my method?

awakeFromNib for UIKit (iOS):
You must call the super implementation of awakeFromNib to give parent classes the opportunity to perform any additional initialization they require. Although the default implementation of this method does nothing, many UIKit classes provide non-empty implementations. You may call the super implementation at any point during your own awakeFromNib method.
awakeFromNib for AppKit (Mac):
(not true anymore, if using OS X 10.6 or higher)
You should call the super implementation of awakeFromNib only if you know for certain that your superclass provides an implementation. Because the Application Kit does not provide a default implementation of the awakeFromNib method, calling super results in an exception if the parent class does not implement it. Classes whose immediate parent class is NSObject or NSView do not need to call the super implementation. For any other classes, you can use the instancesRespondToSelector: class method of NSObject to determine if the parent class responds to awakeFromNib and call the method if it does.

The documentation covers that perfectly.
If you meant to ask about Cocoa Touch, you're not so lucky: The UIKit documentation doesn't answer the question definitively anywhere that I could find. Best I can suggest would be to follow the same rules as in Cocoa.

Yes you should.
I implemented drag and drop and everything was working until I added my own awakeFromNib then the drag and drop function whichTypeToProcess never got called.
It wasn't till I added [super awakeFromNib]; as the last statement in my own awakeFromNib that the drag and drop function whichTypeToProcess was being called again and drag and drop started working again.
FYI - This was in a MacOSX application.

Related

Objective C: init and awakeFromNib

I've recently studied some Cocoa based open source projects. I saw that a lot of programs have all initializing code in awakeFromNib and rarely use the designated initializer. I am used to do it that way:
in the overridden designated initializer: do all non-Nib stuff
in awakeFromNib: do all Nib-related stuff
Is this approach wrong?
Yes, it's correct, all nib-related stuff should be done in awakeFromNib method. At the moment when it's called you already have initialized and loaded view from nib, so you already may configure and use it.
As concerned to initializers, please, check this question: iOS: UIView subclass init or initWithFrame:?
The designated initializer is the one that all the other initializers must call. UIView and subclasses are a little unusual in that they've actually got two such initializers: -initWithFrame: and -initWithCoder:, depending on how the view is created. You should override -initWithFrame: if you're instantiating the view in code, and -initWithCoder: if you're loading it from a nib. Or, you could put your code in third method and override both those initializers such that they call your third method. In fact, that's often the recommended strategy.

On iOS and Cocoa Touch, should we assume we should always send "super" the same message?

In iOS and Cocoa Touch, sometimes it seems we can get by without calling super, such as:
-(void) viewDidAppear:(BOOL)animated {
// nothing weird if the following is not called:
// [super viewDidAppear: animated]
// but the docs says we should call it
}
and I think with drawRect, we usually won't send super that same message, unless the super is doing some drawing of its own. Is it true that we should always send super the same message just to be safe in Cocoa Touch and iOS, and are there cases, then, not not send super the same message?
There's no general rule, it always depends on the class you're subclassing and method you're overriding. NSObject is the root of the class hierarchy in (modern) Objective-C and obviously it doesn't implement most of the methods you see and use, so always calling super wouldn't make sense as a general rule.
You just have to check the documentation for each method separately.
You can't say this in general. Only one thing is sure: call super if you want the functionality that the method being overridden does, and don't call it if you don't.

What invokes viewDidLoad when subclassing UIViewController?

Trying to get my head around protocols and delegates when extending it further into the UIKit framework's implementation.
From my understanding of this stackoverflow post a delegate method will usually have Did, Should & Will in it's name.
Based on this, I would assume that - (void)viewDidLoad; declared in UIViewController.h is a delegate method, but of what and from where?
I've looked at UIViewController's header file and it only adhere's to the NSCoding protocol which is a dead end. UIViewController's superclass UIResponder is also a dead end as far as I can see.
I've used viewDidLoad as an example here but this could apply to any of the Did, Should & Will methods in UIViewController.
Is this simply one of those cases that is an exception to the guidelines or am I missing something?
"did", "should", and "will" are words usually used to describe when a method is called, whether it is asking if it "should" do something", giving you a hook to run code before something "will" happen, or as a callback when something "did" happen. these words are usually used in delegate and callback methods.
viewDidLoad is called when your .nib file has been loaded into memory, and your IBOutlets have been instantiated and hooked up, and are ready for configuration. you don't need to worry about calling it yourself if you intend to subclass UIViewController, if that's what you're wondering.

i need help understanding a few methods in a view based application

when i create a new view based application a few methods in the implementation file (.h)
i do not understand their purpose and when i look into the developer center its kind of hard to understand because of how its explained.
what purpose do these methods have and what are they used for in plain english.
- (void)loadView
- (void)viewDidLoad
- (void)viewDidUnload
what im guessing the viewdidload is , is that when the view is loaded and anything between the braskets are executed first, but when there are other custom methods created (if that is the purpose of viewdidload) how does it know which method to execute? is the code executed from top to bottom? being that whatever method is listed first is executed?
also i have noticed the word super inside brackets along with other keywords. what is the purpose of super?
thank you!
Well, "super" means Super Class, or the parent class that your current class extends.
#interface MyViewController : UIViewController{}
In the code above, that you can find in some .h files, MyViewController extends UIViewController. So, all the time that you call "super" inside MyViewController, you are calling the UIViewController.
So, when you see the following structure, inside MyViewController...
- (void)viewDidLoad {
[super viewDidLoad];
.
.
.
.
.
}
... it means that when the method "viewDidLoad" is called, it will first call the method from it's super class, to after run it's own code.
if you let the whole viewDidLoad method commented, it means that the parent method will be called automatically, because you are not overwriting it like on the previous example.
To understand what all the methods (loadView, viewDidLoad, viewDidUnload), take a look at the UIViewController Class reference on Apple Developer Connection.
Cheers,
VFN
Your class is a derivative of the system class UIViewController (is a subclass, in Objective C lingo). [super someMethod] means - call this method for the base class (superclass in ObjC lingo).
If you're familiar with C#, super in ObjC means same as base in C#. And the same as super in Java. :)
The system-provided UIViewController class has loading functionality in its loadView method. This method is called by the system, and it does a lot of work. The viewDidLoad method, on the other hand, is defined in the base class but does not do much. Its purpose is that you can override it and provide your own functionality there. Same for viewDidUnload.

In Objective-C, do I redirect a containing instance's method without subclassing it?

In Objective-C, how do you rewire a class's instance method to call a method in another class?
Say a UIView class A contains another UIView class called childA. I want it so that when childA's drawRect is called, a method in class A is invoked without having to subclass childA and do the desired call in its drawRect there. How can this be achieved?
Also, how do I supply a method to childA's draw class dynamically? I know this is probably not a good practice but it would be useful for testing purposes.
To answer your first question about rewiring methods:
You don't want to be doing this on general principle, since it kinda defeats the whole purpose of object-oriented design, but for testing purposes, it can be useful. As long as you're on Leopard, it's not especially difficult, either.
Take a look at the Objective-C 2.0 Runtime Reference, which contains the keys to the kingdom, as it were. Look at the functions class_getInstanceMethod, method_getImplementation, method_getTypeEncoding, and class_addMethod which, in combination, let you change the methods of a class at runtime.
If you're just swizzling one selector for another, method_exchangeImplementations is a useful shortcut.
To answer your second question about supplying a method dynamically, that's as simple as passing a SEL to a method and then calling -performSelector:withObject::
#interface MyView : NSView {
SEL drawingSelector;
id drawingDelegate;
}
#property SEL drawingSelector;
#property id drawingDelegate;
#end
#implementation MyView
- (void)drawRect:(NSRect)rect {
[self.drawingDelegate performSelector:drawingSelector withObject:[NSValue valueWithRect:rect]];
}
#end
For the first issue you raise, it seems like you would set up UIView A as a delegate object of childA and the other UIViews - then they could use delegate methods to call the extra drawing features you wanted in A.
Either that or have each child ask for the superview and if it is of type "A" call the method you are interested in.