When to retain a "delegate" - objective-c

I know that in Objective-C you should never retain your delegates because it may cause a retain-cycle, however, how do you know the difference between a delegate and a non-delegate object ? Can't it be said that just sending a message to any object is delegating work to that object ?

A delegate in Objective-C has a fairly well established definition. They're typically used in classes that are already implemented, but have some options for customization.
For example, the UIApplicationDelegate is used to implement application specific behavior so that you don't have to subclass UIApplication. This helps to minimize boilerplate code.
Also, delegate objects are usually kept around using the delegate property. I would argue that any object that isn't the delegate property, isn't a delegate object. The delegate objects are usually used to act on behalf of the regular object.
I hope this helps, your question was quite open-ended.

Related

confusion over Objective-c views, delegates, and outlets

I am trying to teach myself objective-c, but coming from a Python/Java background, it is proving very difficult. I tried to post a bunch of points I am confused on, but it was marked as too vague, so I'll break it into sections.
First, every example of a delegate and outlet I've found uses cocoa view code to get the idea across. Unfortunately, I don't yet understand enough of the code to grasp the example's point. So, can anyone provide a more basic example of a delegate? My understanding is that it is a way of subclassing; how is this better than traditional subclassing? Why does every cocoa project automatically include appDelegate.m? Can delegates be used for other purposes, not just GUI stuff?
Okay, I think I see. So a delegate is a class that conforms to the protocol of some other class. A protocol is simply a list of methods and variables that have to (or can, if set to optional) be implemented in the delegate class. To make a delegate, you have to use the #interface keyword, then the name of your delegate, then (in < > signs) the protocol name? So if class c1 wants to set itself up as a delegate of class c, class c must first specify a protocol, right? You would then be able to implement everything in c's protocol in c1:
#interface c1;
I feel like I'm missing some bits there, but hopefully I have the concepts right. :) This also explains the mysterious less- and greater-than signs; they declare what interface the delegate implements.
Outlets are similarly always tied to view code. They seem to be some kind of inter-object messaging system. Is that right? Again, an example of a basic outlet that is not mixed in with complex GUI statements would be great.
So outlets are never needed? I know that IBOutlet and IBAction are not needed except for use with Interface Builder, but I thought outlets were more general than that? The docs seemed to indicate that they are not even specifically for interfaces, but could be used for anything.
Thanks in advance for any help.
Update: Delegates don't have to conform to protocols. Protocols just make it easier to require some classes to have methods. It allows you to know for certain an object one has set as a delegate implements a certain method so you can call it safely, and allows the compiler to verify that method is indeed implemented (if you declare a delegate instance variable as id<SomeProtocol> delegate, the compiler will give a warning or error if you try to set delegate to an object of a class that doesn't conform to SomeProtocol.
Protocols help ensure safety, but they're not strictly necessary. A class can have a delegate (or multiple!), and they don't have to conform to any protocols at all.
As for outlets, no, they're specifically and only used with Interface Builder. The IBOutlet and IBAction keywords have no effect on code (they're even stripped out before compile time) - they're only markers for Interface Builder to look for so it knows which properties and methods should be accessible within the interface. The term 'outlet' is a direct reference to something marked as an IBOutlet, and is really not used in any other context that I can tell.
Again, it's okay if you don't understand this right away. Think it over a bit, and at some point, it'll just 'click'. I was caught up on delegates for a long time, just like this, before one day, I realized that delegates really aren't any special. They're regular objects referenced by other objects - it's just that this design pattern has a special name (delegation), and these objects are only called delegates. They could just as easily be called gyros or falafels, and the net effect would be the same. :P
You don't need to name an object delegate for it to be a delegate; it's just a convention.
About delegates: the first thing to understand, and this got me for a while until I had the proper "Aha!" moment, is that there is nothing special about a "delegate". The word "delegate" is just a title for a type of object that another class depends on, very often for content or decision-making. A developer will use a delegate when they don't want to (or can't) tie one of their classes to another class by name - it's an Object-Oriented way of decoupling and making classes more generic.
Now, very often, classes will require delegates to have specific methods they rely on, and one way to ensure that is with a protocol (more commonly known as an interface in Java). Protocols define a list of methods; classes "conform" to a protocol if they declare they do in their interface (e.g. #interface IFObject : NSObject <SomeProtocol> { ... }) and if they implement all the methods they're required to. Protocols can have optional methods as well.
This model is used often with view controllers, views, and the GUI in general because many AppKit and UIKit classes are written to be as generic as possible. NSTableView, for instance, implements the most basic behavior it can possibly implement without requiring any implementation-specific information; for the rest, it relies on other objects, ones that conform to the NSTableViewDelegate and NSTableViewDataSource protocols. Any object can conform to the protocols, as long as they implement the right methods (and in this case, a controller class will usually implement methods from both protocols, but it doesn't have to be so). In fact, one easy way to understand this topic better is to take a look at NSTableView - it's got a delegate property and a dataSource property, but in effect, they're no different. delegate could be called monkeyButt, and the concept would still work. The key is to not treat delegates as a black box - there's nothing special about them.
Delegates can be also used for non-GUI purposes; one concrete example, as you mention, is the app delegate. NSApplication sends a delegate notifications to let it know when the application has been launched (among other things), so it can set up shop. Again, any object can be a delegate to any other object, for any purpose. It's simply a convention.
Briefly about outlets: as others have mentioned, outlets are simply connections between an interface defined in an XIB and your code. They're a way of letting Xcode link up the interface to the appropriate elements so that when your application loads the interface file, it can load up the right pieces of code or execute them.
They're generally an easier way of setting up an interface - they're not strictly necessary (you can create an interface programmatically, without using an XIB file), but if you do decide to go the XIB route, they're how you relate your interface to your code.
A delegate is an object that is delegated some task by an object it declares itself the delegate of. Let's say an object does some task and then needs to notify the object that "owns" it, so to speak. In order to allow the object to work under any conditions, it cannot be allowed to know what type of object it should contact, so we set its delegate and adhere to its protocol. Setting the object's delegate is like saying "Here's the object I want you to use contact with the messages declared in your protocol. I promise the object actually implements the methods in the protocol." For example, you might see this.
#protocol SpriteDelegateProtocol
#required
- (void) projectionMatrix;
#optional
- (void) animation:(int)animationIndex willCompleteFrameNumber:(int)frame forSprite:(id)sender;
#end
#interface Sprite
#property (nonatomic, assign) id<SpriteDelegateProtocol> delegate;
#end
The interface for our sprite object declares that it has a property called a delegate, which is of type id. It can be any object, but it must adhere to the protocol in the triangle brackets. If it says it adheres to the protocol, it has to implement the methods declared under the #required and can implement the ones listed under the #optional. It's up to us to determine whether or not our delegate actually implements the optional methods using something like respondsToSelector:. We might even store the return value if we had a lot of methods to do that for.
The application delegate is special in that it is the delegate to our UIApplication object. It receives messages on application state, such as applicationDidEnterBackground:. You can see what methods are in the protocol adhered to by our application delegate here.
Delegates can be used with any object. Any object can say it has a delegate property to set, and that it must have the following methods as shown above. The protocol is essentially a portable interface that can be used to tell another object what we need it to implement so that we can call said methods to delegate some portion of functionality out to it. We can notify our delegate when a task has completed, ask it to give us information (typically called a data source instead of a delegate so that they can be different objects if you want) or ask it whether or not we should do some task at all.
An outlet is a way of connecting a view instantiated in a NIB or storyboard to a property in its controller. So, if you place a UIViewController into your main storyboard and change its class to MyGreatControllerSubclass then proceed to place a button in that controller's view, you might want to hook that button up to an "outlet" (property) in the controller's interface so that you can access the button from the controller later.
No delegates are not a way of subclassing. I also came from Java and have been doing O-C for almost 5 years now.
Delegates generally conform to Protocols, which are the equivalent of Interfaces. What's great about that is it leaves you a lot of flexibility in how you implement the things that are covered by the delegate. So for instance, you will see that Table Views can be implemented by extending UITableViewController or implementing the delegate. That way, if you have a composed view where a user is selecting items from one table and putting them into another, you can do a single controller and have it perform the delegation for both views.
The best way to think about delegates is as examples of message/event oriented callbacks. Have you ever heard the saying that what makes a Framework different from ordinary programming is, with a Framework, it tells you what it wants you to do to ensure the results you seek? That is what delegation is. I was doing a Collection View last night and could not get the edit menu to come up. Just provide delegation of three methods, know nothing about how the menu is invoked, where the Long Press gesture handler is, etc.
Note that Delegates are the glue that makes Dependency Injection unneeded in the O-C world. I prefer them.
Delegates are the common design pattern (http://en.wikipedia.org/wiki/Delegation_pattern), they are not objective-c specific.
Outlets make possibly the binding of Controller and View (GUI). May be you know the MVC paradigm (model-view-controller)? So you build your GUI (the View from MVC) with Interface Builder and bind the elements of this GUI such as Buttons, Text fields and so on to your Obj-C code (the Controller from MVC) using outlets.
Take a look at this post: Conforming Objective-C’s Protocols in C# Codes
Don't worry about the word "C#" in the title, you could just ignore that part. The main part of this post talks about protocols and delegates in Objective-C. This might be helpful.

Methods required to be implemented when subclassing in Objective C

I am new at programming in general (though I have had a C class many, many years ago) and am learning Objective-C for programming on the iPhone. I have what I think is a simple question, but after looking for a while (days, off and on) I can't find the answer that I'm looking for explicitly.
I know that when subclassing an Objective-C class I should implement the initialize method along with the deallocate method (unless using ARC for the latter, if I am correct?). The questions are:
Are these the only two to worry about, or will other classes potentially have additional methods that can be required to be implemented?
If other classes might have methods that I am required to implement when subclassing them, where is that documentation typically found? (I don't seem to see that in the Apple framework docs, though that kind of information is there for protocols it appears)
Thanks for your help!
Technically, you are not required to implement even the init and dealloc if the inherited versions are sufficient. Also, ARC does not free you from having to write dealloc in all cases (but it certainly covers the overwhelming majority). For example, if you allocate memory for your object using malloc, you need to free it in the dealloc.
When you add instance variables to your class, you need to initialize them. Typically, you do that in a designated initializer. Again, if you do not to initialize anything, you do not have to code your own initializer; same goes for deinitializer.
The only case when you need to implement a method is when you adopt a protocol with one or more methods marked #requried. These methods are marked in the protocol reference. For example, tableView:cellForRowAtIndexPath: and tableView:numberOfRowsInSection: are marked with the "required method" tag in Apple's documentation.
No methods are required when subclassing an NSObject (or any of their subclasses, such as UIViewController, UIView, etc. etc.).
If you create a new, let's say UIViewController, it's generally a good idea to keep the methods you find in the newly created file as a guideline/template, but you're not really required to keep any of the methods. The super class will always call the methods on itself.
Be aware, though, some methods you have to call super, like viewWillAppear, etc.

How to manage unsafe_unretained ivars/properties?

I started objective-c and iOS a couple of weeks ago (worth bearing in mind), and I apologise in advance for the awful diagram!!
The above diagram shows the structure of my calls to a webservice. Thin arrows denote an object creating another object, whereas thick arrows denote an object holding a strong (retained) reference to the pointed-to object.
I believe that this contains what is called a "circular reference" and will create problems when it comes to deallocating the objects.
I understand that the easy answer would be to replace some of the strong references to weak ones, which I'd love to do, except my project is also targeting iOS 3.2 (not my decision - I can't really change this fact!). So, I think I'm right in saying that I have to use __unsafe_unretained instead, but I'm quite worried about the fact that these won't auto-zero, as I'll end up with EXC_BAD_ACCESS problems when objects get deallocated...
So my problem is firstly that I have circular references. To solve, I would have to use __unsafe_unretained, which leads to my second problem: How to correctly manage these?
A question that might be related is: How does NSURLConnection manage it's strong references? I have heard from various sources that it retains its delegate? So...if I retain an NSURLConnection, (and am also its delegate) and it retains me, this would also be a circular reference, no? How does it get around my problem?
Any advice is very welcome!
Regards,
Nick
When a parent has a reference to a child object, it should use a strong reference. When a child has a reference to it's parent object, it should use a weak reference, aka unsafe_unretained.
By convention, delegate relationships in iOS are usually weak references, so you'll find that most delegate properties on Apple's own classes are declared as unsafe_unretained.
So your controller retains the services that it is using, but the services only weakly link back to the controller. That way, if the controller is released, the whole lot can be safely disposed of without any circular references.
The danger with this is that if the web service is doing some long-running task, and the controller gets released before it has finished, the service is left with a dangling pointer to it's now-deallocated delegate. If it tries to send a message to the delegate, such as "I have finished" it will crash.
There are a few approaches to help solve this (they aren't mutually exclusive - you should try to do them all whenever possible):
1) Always set the delegate properties of your services to nil in your controller's dealloc method. This ensures that when the controller is released, the delegate references to it are set to nil (sort of a crude, manual equivalent of what ARC's weak references do automatically).
2) When creating your own service classes that have delegates, make them retain their delegate while they are running and then release the delegate when they are done. That way the delegate object can't get deallocated while the service is still sending it messages, but it will still get released once the service has finished (NSTimer's and NSURLConnections both work this way - they retain their delegate while they are running and release it when they are done).
3) Try not to have long-running services owned by something transient like a view controller. Consider creating singleton objects (shared static object instances) that own your services, that way the service can do it's job in the background regardless of what's going on in the view layer. The controller can still call the service, but doesn't own it - the service is owned by a static object that will exist for the duration that the app is running, and so there's no risk of leaks or premature releases. The service can communicate with the controller via NSNotifications instead of delegate calls, so there is no need for it to have a reference to an object that may vanish. NSNotifications are a great way to communicate between multiple classes without creating circular references.
All of your questions and concerns are correct, and this problem with the previous use of assign (now better named __unsafe_unretained) is why Apple developed auto-zeroing for weak. But we've dealt reasonably safely with assign delegates for many years, so as you suspect, there are ways to do it.
First, as a matter of practice, you should always clear yourself as the delegate when your release an object you were delegate for. Pre-ARC, this was traditionally done in dealloc:
- (void)dealloc {
[tableView_ setDelegate:nil];
[tableView_ release];
tableView_ = nil;
}
You should still include that setDelegate:nil in your dealloc if delegate is __unsafe_unretained. This will address the most common form of the problem (when the delegate is deallocated before the delegating object).
Regarding NSURLConnection, you are also correct that it retains its delegate. This is ok because it has a lifespan typically much shorter than its delegate (versus a table view delegate which almost always has the same lifespan as the table view). See " How to work around/handle delegation EXC_BAD_ACCESS errors? Obj C " for more discussion on this in a pre-ARC context (the same concepts apply in the new world of strong/weak).

Do I have to create an instance of a class in order to assign it a delegate?

Sorry for noobness-level of the question.
I saw this answer, where it says
Add something like this to your NSURLConnection delegate
However, the method in question, sendSynchronousRequest:returningResponse:error:, is a class method. If I understand delegate methods correctly, they use a delegate which is specified when the NSURLConnection object is initiated.
So, if I have no instance of the class, a delegate can't be used. Did I understand correctly?
Yes, you are correct. In Cocoa, assigning a delegate requires an instance. In the case of NSURLConnection, its delegate is supposed to be used when making an asynchronous request that is initiated with -initWithRequest:delegate: or +connectionWithRequest:delegate:
Since classes are also objects it could be conceived that they also could have delegates. However, since there is no concept of class variables in Objective-C, a class would have nowhere to store its delegate (it could use a standard C variable in its .m file, though). Anyway, this concept is not used in Cocoa.
Yes delegates are used for handling events when you send your request asynchronously.
While sending synchronous request using +sendSynchronousRequest:returningResponse:error: method delegates are not used - you only get the resulting data and (optionally) server response and error and not aware about intermediate loading events (and remember that calling thread is also blocked while connection is in progress).

Is it bad practice for a delegate to have a reference to the object for which it is the delegate?

I'm using the delegate pattern for one of my objects. My idea is that I will be able to swap the delegate out later for a different delegate implementing a different strategy. I suppose this is just as much the strategy pattern as the delegate pattern.
My question is, is it bad practice for my delegate to have a reference back to the object for which it is the delegate? There are a couple properties of that object that I need to have access to regardless of which delegate/strategy I use. If this is bad form, how should I get access to the properties?
Not necessarily. For example, it's quite common for a "controller"-type object to create data objects and views and make itself the delegate of some of those objects in order to properly control things.
It is not at all bad practice. The delegate pattern allows for a class to have a generic way to talk to any number of objects as long as the implement the same protocol. But the class on which you set the delegate also will usually have a number of public properties or methods that allow you to query or alter what the class is doing, in response to which the class may in turn trigger a number of the delegate calls. So you need a reference of the class to which you are the delegate, in order to tell the object to do something different than it is already, and of course to release it when you are through with it!
This is also why it's important to always have any delegate properties as assign, and not retain, properties. That way when the originating class is released it will actually be released, instead of having delegate objects it is holding onto causing a retain loop that keeps both around.
It's also why whenever you are being released, you should set the delegate reference to nil in anything you may have a delegate reference set. This way a class will not have an invalid delegate reference if the delegate is released before the class that uses a delegate.
Generally a dependency should not have a reference back to the dependent object, as this would be a classical circle reference. To avoid having a back-reference you can supply the needed properties as arguments in a delegate method, or you move the properties themselves into the delegate.
I'd say yes, it's bad practice. The idea behind a delegate is that it's effectively a standalone object that receives messages about the object for which it is the delegate (the "delegator"). The delegator should have a reference to the delegate, not the other way around, otherwise it's not a true delegation relationship anymore.
A preferred way to accomplish what you're asking is to provide the sending object along with whatever message your delegate receives. For example, on your delegate, instead of having a delegator property and then receiving, for example, a didDoSomething:(id)anObject method, you could remove the delegator property and send the message delegator:(id)anObject didDoSomething:(id)anotherObject. This way, you keep the delegate distinct from the delegator, but still get access to the delegator's properties when you need them.
This way also has the advantage of not providing access to the delegator in methods when you don't truly need it; for example, your delegate could have a didDoSomething method that takes no arguments, not even a delegator, and is just used for logging, as well as a delegator:(id)anObject didSomethingElse:(id)anotherObject method that calls some properties on the delegator and is much more involved.
Finally, this method allows you to use the same delegate for multiple delegators, since you don't need to update a delegator property for each delegate object.
For a good example of how this works, take a look at the NSURLConnection documentation, specifically its delegate methods - a lot of them take the form connection:didDoSomething:, where the first argument is the connection calling the delegator. Developers commonly define a single connection delegate for multiple connections, implementing their delegate methods to do different things depending on properties of the NSURLConnection object passed in.