Repercussions of Reassigning Delegates - iphone

I'm looking to find out what the effects are (if any) of assigning a delegate multiple times? Is it bad practice to assign a delegate inside viewWillAppear considering I do not assign the delegate to another viewController?
It is just a simple custom delegate for one of my classes. I need the delegate in one view of my tabBar, but not in the other. And since I've been assigning it in viewWillAppear, and viewWillAppear gets called every time you change tabs, I was just wondering if there were some unwanted effects.

No, in the case you describe there should be no problem. But it depends on what your code does when the delegate is assigned. If it's a simple property assignment with no custom implementation of the 'setter' method for the property, then you have no issue. But if you wrote your own 'setter' method for the property and the implementation performs other actions, then it is possible that those other actions could be an issue.
Either way, you may wish to consider moving the assignment to the viewDidLoad method. As if iOS 6 this will only be called once. Under iOS 5 or earlier it could be called more than once but viewDidUnload will be called as well in such cases.

Related

What is meaning of calling superview's viewwillappear?

-(void)viewwillAppear
{
[super viewwillAppear:animated];
}
What does mean of calling [super viewwillAppear:animated] and what happen if we not call it?
By using super you are calling the base class version of the method. You will see similar call in init, dealloc, viewDidLoad etc. methods. The reason is in base class's implementation something important may be carried out without which the derived class will not work properly. When you have overridden the method in derived class, you will need to make a call to the base version by using super.
The only situation you will not call base class's method by using super is when you know that you don't need the tasks carried out by base class, in other words you are overriding completely. This is not the situation with viewWillAppear:animated or viewDidLoad etc. So we always call super in these cases.
Apple's documentation for viewWillAppear: just says:
If you override this method, you must call super at some point in your implementation.
It will probably lead to some unexpected behavior if you don't call it. Note that 'at some point' means you don't have to call it first.
The reference clearly states
This method is called before the
receiver’s view is about to be
displayed onscreen and before any
animations are configured for showing
the view. You can override this method
to perform custom tasks associated
with presenting the view. For example,
you might use this method to change
the orientation or style of the status
bar to coordinate with the orientation
or style of the view being presented.
If you override this method, you must
call super at some point in your
implementation.

UITextView with multiple delegates?

I have a UITextView that points to the File's Owner as its delegate, and I have a number of the delegate functions implemented. However, I would also like to point to a second object (in this case a TextExpander object, http://www.freshblocks.com/tutorials/how-to-add-textexpander-touch-sdk-to-iphone-apps/) also as a delegate. How might this be possible? As far as I know there can only be one delegate in objective-c.
I don't know the specific of TextExpander but he delegate design pattern assumes one and only one delegate. You can't have two delegates for one object.
There are ways around this. You could designate one of the delegates as the primary delegate and implement all the methods in this class. That class could then simple call the secondary delegate for the required methods. This is the simplest approach but does result in the primary delegate becoming tightly coupled with the secondary delegate.
Another approach would be to resolve the messages dynamically and use message forwarding. You would still require the a primary/secondary delegate pattern, but instead of the primary delegate needing to implement all the methods it would simply pass all messages it doesn't respond to onto the secondary delegate. This approach means that the secondary delegate can change by adding/removing additional delegate methods without having to change the primary delegate. The key method is - (id)forwardingTargetForSelector:(SEL)sel. See Objective-C Message Forwarding for a good explanation.
It seems that they solve this in step 5, by setting [textExpander setNextDelegate:self]; before setting the textExpander object as the "primary" delegate of the view.
I don't have the code myself so I haven't tried it, though, and their documentation is... well not.
Just for information: Delegates are not an Objective-C feature, but a design pattern using though Cocoa/Cocoa-touch.
Delegate pattern allow only one object to be notified of the changes of another. The solution to have an intermediate delegate object could be an easy way of doing things.
If you want to keep your code clean and reduce the coupling you might use another pattern known as KVO (Key Value Observing). Apple provides a good guide on how to use it.
In KVO a single object, that needs to be KVC (Key Value Coding) compliant, can notify multiple objects without even knowing about it. It uses an intermediate notifier object (singleton for you application).
Check the Apple doc on KVC + KVO and you shall be able to do what you want.
I have a class with the protocol NSXMLParserDelegate implemented. I call this ParserHelper. I parse a lot of XML which happen to have some tags in all of them and i have about 20 parsers (one for each type of XML), and i didnt want to implement it over and over again.
So, I subclassed my ParserHelper class 20 times, adding in each subclass the required tags/behaviours like CaseAParser, CaseBParser and so on...
I just implement the delegate methods i needed and called it on the superclass once i'm done with the method.
I assume it works on every delegate.
This way, all you need is to make your class a subclass of SMTEDelegateController and implement the methods you need, remembering to call the [super whatEverMethod:andParameters] at the end of your functions and you should be good to go.

How do I have a class communicate to it's view controller that something has happened

I have a viewController that's running my game view. The viewController spawns instances of a Dots, which are subclassed from UIView that are added as subviews to the viewController view. Within the dots class I have certain behavior if they are touched (touchesBegan) but I'd also like touching the dots to add to the score which is a property of the viewController, but I can't see any way to communicate that out without ridiculous workarounds. What am I missing here?
Two options (but not the only ones) are NSNotificationCenter and delegate+protocol.
NSNotificationCenter is simpler to implement and use but not ideal in all cases. The viewController would call addObserver to indicate it is interested in some message. The dots would call postNotificationName to send the message to interested objects. Be sure to call removeObserver in the viewController's dealloc.
Delegate+protocol lets you define a more rigid, well-defined, compiler or runtime verifiable interface between objects. For details, see Protocols in the Objective-C Programming Language.
In your case, I think defining a protocol is the better option. The viewController would make itself the delegate of the dot objects. The dot objects would have a delegate property and call the protocol methods through the delegate property.
Why is the score a property of the ViewController in the first place? I can see having a property for the label that displays the score, but the score itself belongs in some kind of model object.
The advantage of this approach is that you could then use Key-Value Observing (KVO), adding your ViewController as an observer of the model object. In fact, this is pretty much what KVO was designed for: an easy way to notify an arbitrary number of observers about a change to a property.
Reference:
Key-Value Coding Protocol Reference
Key-Value Observing Protocol Reference
Model Object Implementation Guide

iPhone Delegates - How to use them correctly

I have 2 or 3 views in my iPhone application where I have various pieces of functionality that use delegates. In all cases the delegates are assigned to "self", responding specifically to that view's actions and interacting with instance variables.
However, if I do something that takes a bit of time with a delegate, and leave the view, obviously it crashes my app as the delegate methods get called on a view I've left.
Typically in my delegate methods I am doing things like interacting with IBOutlets, calling other instance methods, saving data to Core Data etc...
How can I work with delegates better? Is what I'm doing typical, or not?
Thanks for any guidance!
Depends on the use case. If, for example, you've got a UINavigationController that manages a ViewController that use something such as Location Services, when you pop the View Controller off of the stack you're going to want to set the CLLocationManager's delegate to nil. You can do this in the dealloc method.
Can you give a specific example of an issue you're facing?
I've encountered this situation once when dealing with MapKit (race conditions involving delegate callbacks and delegate deallocation). However, in general, I think it's an indication of a bad design decision when your delegate becomes invalidated as a result of race conditions, but I could be wrong.
Typically, the objects that make use of your delegate should exist within the context of the delegate itself. So, for example, the same class that contains various IBOutlets that you want to manage with delegate callbacks should also be the delegate of those IBOutlets. That way, when the class (i.e., the delegate) is deallocated, the IBOutlets are (hopefully) also deallocated, so they won't be making callbacks to anything.
bpapa's right. More generally, if you have a potentially lengthy delegate callback, either make sure that 1) the delegate is an object that won't be deallocated during the lifecycle of the delegator (e.g., UINavigationController managing UIViewControllers) or 2) the delegator's delegate object is set to nil during the delegate's deallocation.
... That last sentence was a mouthful. :)
Your delegates should be declared as
#property (nonatomic, assign) id <MyDelegateProtocol> delegate;
This ensures a weak reference so that when you dealloc the object which has delegate, it only removes the reference and NOT the corresponding object. using (strong) will cause a crash on dealloc.
When calling your delegate, you can check
if (self.delegate && [self.delegate respondsToSelector:#selector(MyDelegateProtocolCallbackMethodName:)] {
[self.delegate MyDelegateProtocolCallbackMethodName:result];]
}
Generally I use delegates for proxy classes which fetch data from a server or edit screens like changing the title of a task in a todo list or editing a model in a database.
The advantage of a delegate is a very clear use case. If you find that multiple parts of your app need to be aware of when an event happens (triggered on 1 screen but perhaps listened for in another), I suggest using NSNotificationCenter to raise notifications, instead of or perhaps in addition to sending a message to your delegate.

tabBar viewControllers in IB: send custom init?

My tabBarController-based app has several tabs. Each has a custom viewController class, the only difference being the way the instance is initialized. Is there a way to make interface builder send the different tabs custom init parameters?
Currently I'm doing the initialisation in viewWillAppear, but for a bunch of reasons it would make sense to do it in IB instead of in the code.
Any suggestions?
thanks,
Kelso
Interface Builder creates an archive of objects that is unarchived when you program executes. You can't really tell IB to call particular methods.
If you need to initialize before viewWillAppear: is called, you can do so in awakeFromNib, which is guaranteed to be called after all objects have been loaded and all outlets have been connected to their targets.
If you want to do initialization even earlier, you can do so by overriding initWithCoder: (see the NSCoding protocol for documentation). I don't know if it is documented anywhere, but that is the designated initialized for objects being decoded from an archive.
In all of the above, you won't be able to receive parameters, but in the code you should be able to access whatever you need with some judicious use of global variables. You can also use [[UIApplication sharedApplication] delegate] to get access to your application delegate object.
I don't think there's any way to change what methods are called by the IB runtime when your nib is loaded. If you described what you were trying to accomplish (i.e. why doing the setup in viewDidAppear doesn't work for you), you might get a suggestion of a better way to handle your initialization.