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.
Related
I need to call a method and pass an object from my custom UITableViewClass implementation to my UITableViewController class. I realize creating an instance of the tableViewController in the custom tableViewCell and calling tableViewController's method is a bad practice.
What is the proper way of doing this?
Two magical concepts in Objective-C are Delegation and Notifications.
Delegation allows you to have your controller hook into a weak object referenced in the cell, which avoids a retain cycle, while still allowing you to send messages to it.
Notifications allow your Cell to broadcast a general notification to any classes that are active and listening for it.
Pick one, and whichever is easiest, stick with it. The two are basically equal in this situation.
Having a reference of the tableController inside the cell is indeed Bad practice
You could fix this by implementing a special #protocol for your UITableViewClass
And add a delegate method to it, and then implment the method inside UITableViewController, and since your UITableViewClass delegate is your UITableViewController, then you would call it like
in your UITableViewClass.m
[delegate someMethod:data];
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.
i have been working on moving one of my apps away from the "shared appdelegate" process which seems to be frowned up, despite its over whelming use. i have been attempting to setup protocol methods for what i want to do but am having zero luck. my question is, can you even have lets say a single viewcontroller send delegate requests to multiple classes? from what im finding out it doesn't seem like you can. which doesn't make sense because i thought that was the whole point of delegates and protocols with mvc. now just to clarify, i know you can have a single viewcontroller act as the delegate for multiple other viewcontrollers. but that's not what i am asking. for a simple example, lets say you have apples flip-utility template. the "done" button just calls a delegate method to the mainvc to dismiss it. now lets say we added a new class called...
#interface NewClass : NSObject <TheOtherDelegate>
and it had a delegate method...
- (void)doSomething
{
NSLog(#"The Delegate did something...");
}
can we have a button on the flipsideviewcontroller, that we wanted to call that delegate method, but still keep the "done" button call to the delegate method on the mainviewcontroller that dismisses it?
that being said, i put together a quicky project just to see if it would work and it doesn't. i came across an "answer" that says you have to instantiate the class first you want to be the delegate...
NewClass *myDelegate = [NewClass alloc] init]
[fillInMethodHere setDelegate:myDelegate];
not sure why it got a correct answer check, because needless to say it doesn't work. is there something i am missing? i scoured ib to see if there is some "delegate" connection somewhere but i couldn't find anything.
on a side note, as i was working in my working project, i read a suggestion about removing the #import and adding #class. again, that broke all kinds of things. the strange thing is before doing that, what i had so far was working and building fine. when i removed the new #class and un-commented the #import. xcode all of a sudden gave me an error "cannot find protocol deceleration for..." but yet, it worked seconds earlier. i would up having to remove the protocol code and re-add it for it to work again. very starge.
any help would be appreciated. everything iv read in docs, google, stack, etc that say something should work, don't in an actual project.
A "delegate" isn't some fancy object. It's simply a synthesized property of type id called delegate. If you wanted to, you could have an arbitrary number of properties that all conformed to the same protocol. Then when you wanted to issue a callback, you would just address all of them:
[self.mydelegateA doSomething];
[self.mydelegateB doSomething];
etc.
You could also have an NSMutableArray property that you could add objects to, and then use [self.myMutableArrayOfDelegates makeObjectsPerformSelector:#selector(doSomething)].
Finally, there's always the route of NSNotificationCenter (not to be confused with push notifications) is a class that provides an inter-object messaging system. Many objects can register for a message that any other object can send.
Please see the Apple's documentation for more information. Click Here.
Regardless of the fact that this is OS X documentation, it's still quite good at explaining things visually: click here.
Here's an example of simply changing the name of the delegate property: click here
And here's an example of adding another protocol and a second delegate: click here
Finally, here's an example that builds on the previous two and has a third delegate that also conforms to the same protocol: click here
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.
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.