Is it ever Ok to have a 'strong' reference for a delegate? - objective-c

I have a class that retrieves JSON from a URL and returns the data via the protocol/delegate pattern.
MRDelegateClass.h
#import <Foundation/Foundation.h>
#protocol MRDelegateClassProtocol
#optional
- (void)dataRetrieved:(NSDictionary *)json;
- (void)dataFailed:(NSError *)error;
#end
#interface MRDelegateClass : NSObject
#property (strong) id <MRDelegateClassProtocol> delegate;
- (void)getJSONData;
#end
Note that I'm using strong for my delegate property. More about that later...
I am trying to write a 'wrapper' class that implements getJSONData in a block-based format.
MRBlockWrapperClassForDelegate.h
#import <Foundation/Foundation.h>
typedef void(^SuccessBlock)(NSDictionary *json);
typedef void(^ErrorBlock)(NSError *error);
#interface MRBlockWrapperClassForDelegate : NSObject
+ (void)getJSONWithSuccess:(SuccessBlock)success orError:(ErrorBlock)error;
#end
MRBlockWrapperClassForDelegate.m
#import "MRBlockWrapperClassForDelegate.h"
#import "MRDelegateClass.h"
#interface DelegateBlock:NSObject <MRDelegateClassProtocol>
#property (nonatomic, copy) SuccessBlock successBlock;
#property (nonatomic, copy) ErrorBlock errorBlock;
#end
#implementation DelegateBlock
- (id)initWithSuccessBlock:(SuccessBlock)aSuccessBlock andErrorBlock:(ErrorBlock)aErrorBlock {
self = [super init];
if (self) {
_successBlock = aSuccessBlock;
_errorBlock = aErrorBlock;
}
return self;
}
#pragma mark - <MRDelegateClass> protocols
- (void)dataRetrieved:(NSDictionary *)json {
self.successBlock(json);
}
- (void)dataFailed:(NSError *)error {
self.errorBlock(error);
}
#end
// main class
#interface MRBlockWrapperClassForDelegate()
#end
#implementation MRBlockWrapperClassForDelegate
+ (void)getJSONWithSuccess:(SuccessBlock)success orError:(ErrorBlock)error {
MRDelegateClass *delegateClassInstance = [MRDelegateClass new];
DelegateBlock *delegateBlock = [[DelegateBlock alloc] initWithSuccessBlock:success andErrorBlock:error];
delegateClassInstance.delegate = delegateBlock; // set the delegate as the new delegate block
[delegateClassInstance getJSONData];
}
#end
I've come to the objective-c world relatively recently (only lived in ARC times, and still coming to terms with blocks) and admittedly my understanding of memory management is on the slimmer side of things.
This code seems to work fine, but only if I have my delegate as strong. I understand that my delegate should be weak to avoid potential retain-cycles. Looking in instruments, I find that allocations do not continue to grow with continued calls. However, I believe 'best practice' is to have weak delegates.
Questions
Q1) is it ever 'ok' to have strong delegates
Q2) how could I implement the block-based wrapper leaving the delegate of the underlying class as weak delegate (ie. prevent the *delegateBlock from being deallocated before it receives the protocol methods)?

Q1 - Yes. As you point out yourself having delegate properties being weak is a recommendation to help avoid retain cycles. So there is nothing wrong per se with having a strong delegate, but if the clients of your class expect it to be weak you may cause them surprises. The better approach is to keep the delegate weak and for the server side (the class with the delegate property) to keep a strong reference internally for those periods it needs one. As #Scott points out Apple documents doing this for NSURLConnection. Of course that approach doesn't solve your issue - where you want the server to retain the delegate for you...
Q2 - Looked at from the client side the problem is how to keep a delegate alive as long as a server with a weak reference to it requires it. There is a standard solution to this problem called associated objects. In brief the Objective-C runtime essentially allows a key-collection of objects to be associated with another object, along with an association policy which states how long that association should last. To use this mechanism you just need to pick your own unique key, which is of type void * - i.e. an address. The following code outline shows how to use this using NSOpenPanel as an example:
#import <objc/runtime.h> // import associated object functions
static char myUniqueKey; // the address of this variable is going to be unique
NSOpenPanel *panel = [NSOpenPanel openPanel];
MyOpenPanelDelegate *myDelegate = [MyOpenPanelDelegate new];
// associate the delegate with the panel so it lives just as long as the panel itself
objc_setAssociatedObject(panel, &myUniqueKey, myDelegate, OBJC_ASSOCIATION_RETAIN);
// assign as the panel delegate
[panel setDelegate:myDelegate];
The association policy OBJC_ASSOCIATION_RETAIN will retain the passed in object (myDelegate) for as long as the object it is associated with (panel) and then release it.
Adopting this solution avoids making the delegate property itself strong and allows the client to control whether the delegate is retained. If you are also implementing the server you can of course provide a method to do this, maybe associatedDelegate:?, to avoid the client needing to define the key and call objc_setAssociatedObject itself. (Or you can add it to an existing class using a category.)
HTH.

It entirely depends on the architecture of your objects.
When people use weak delegates, it's because the delegate is usually some kind of "parent" object, which retains the thing that has the delegate (let's call the "delegator"). Why does it have to be a parent object? It doesn't have to be; however, in most use cases it turns out to be the most convenient pattern. Since the delegate is a parent object that retains the delegator, the delegator can't retain the delegate or it will have a retain cycle, so it holds a weak reference to the delegate.
However, that is not the only use situation. Take, for example, UIAlertView and UIActionSheet in iOS. The usual way that they are used is: inside a function, create an alert view with a message and add buttons to it, set its delegate, perform any other customization, call -show on it, and then forget it (it is not stored anywhere). It's a kind of "fire and forget" kind of mechanism. Once you show it, you don't need to retain it or anything and it will still be displayed on screen. It's possible in some cases you might want to store the alert view around so you can programmatically dismiss it, but that is rare; in the vast majority of use cases, you simply show and forget it, and just handle any delegate calls.
So in this case, the proper style would be a strong delegate, because 1) the parent object does not retain the alert view, so there is no issue with a retain cycle, and 2) the delegate needs to be kept around, so that when some button is pressed on the alert view, someone will be around to respond to it. Now, a lot of times, #2 isn't a problem because the delegate (parent object) is some kind of view controller or something that is otherwise retained by something else. But this is not always the case. For example, I can simply have a method that is not part of any view controller, which anyone can call to show an alert view, and if the user presses Yes, uploads something to the server. Since it's not part of any controller, it likely is not retained by anything. But it needs to stay around long enough until the alert view is done. So ideally the alert view should have a strong reference to it.
But as I've mentioned before, this is not always what you want for an alert view; sometimes you want to keep it around and dismiss it programmatically. In this case, you want a weak delegate or it will cause a retain cycle. So should an alert view have a strong or weak delegate? Well, the caller should decide! In some situations the caller wants strong; in others the caller wants weak. But how is this possible? The alert view delegate is declared by the alert view class, and must be declared as either strong or weak.
Fortunately, there is a solution that does let the caller decide -- a blocks-based callback. In a blocks-based API, the block essentially becomes the delegate; but the block is not the parent object. Usually the block is created in the calling class and captures self so that it can perform actions on the "parent object". The delegator (alert view in this case) always has a strong reference to the block. However, the block may have a strong or weak reference to the parent object, depending on how the block is written in the calling code (to capture a weak reference to the parent object, don't use self directly in the block, and instead, create a weak version of self outside the block, and let the block use that instead). In this way, the calling code fully controls whether the delegator has a strong or weak reference to it.

You are correct in that delegates are usually weakly referenced. However, there are use cases where a strong reference is preferred, or even necessary. Apple uses this in NSURLConnection:
During a download the connection maintains a strong reference to the delegate. It releases that strong reference when the connection finishes loading, fails, or is canceled.
An NSURLConnection instance can only be used once. After it finishes (either with failure or success), it releases the delegate, and since the delegate is readonly, it can't be (safely) reused.
You can do something similar. In your dataRetrieved and dataFailed methods, set your delegate to nil. You probably don't need to make your delegate readonly if you want to reuse your object, but you will have to assign your delegate again.

As other said it's about architecture. But I'll walk you through it with several examples:
Retry upon failure
Suppose you've made a URLSession, and are waiting for a network call you made through a viewController, sometimes it doesn't matter if it failed, but at other times it does. e.g. you're app is sending a message to another user, then you close that viewcontroller and somehow that network request fails. Do you want it to retry again? If so then that viewController has to remain in memory, so it can resubmit the request again.
Writing to disk
Another case would be when a request succeeds you may want to write something to the disk, so even after the viewcontroller has its UI updated you might still want to sync your local database with the server.
Large background tasks
The original use case for NSURLSession was to power background network task execution, large file downloads and things of that nature. You need something in memory to handle the finalization of those tasks to indicate execution is complete and the OS can sleep the app.
Associating the lifecycle of downloading large files to a certain view is a bad idea…it needs to be tied to some more stable/persistent e.g. the session itself…
Normally if I’m going to use the delegate based system rather than URLSession’s newer block-based API, I have a helper object that encapsulates all the logic necessary to handle failure and success cases that I may require that way, I don’t have to rely on a heavy VC to do the dirty works
This is answer was entirely written thanks to a conversation I had with MattS

Related

NSWindowController subclass will not release in ARC

I'm encountering a strange situation with NSWindowController. I want the window controller to be released but it will not. It doesn't seem to be following my expectations for ARC behavior.
I've created a simple window controller subclass, PlainWindowController. Its interface and implementation are empty:
#import <Cocoa/Cocoa.h>
#interface PlainWindowController : NSWindowController
#end
#implementation PlainWindowController
#end
I created with it a default windowController xib named PlainWindowController.xib, which has a window with delegate and windowController connections already set.
In a test, I've written this code:
PlainWindowController *strongWindowController = [[PlainWindowController alloc] initWithWindowNibName:#"PlainWindowController"];
__weak PlainWindowController *weakWindowController = strongWindowController;
[strongWindowController showWindow:nil];
strongWindowController = nil;
STAssertNil(weakWindowController, #"The window controller should have been deleted, wasn't");
When this test runs, the weak reference is not nil.
If I leave out the showWindow it is nil. If I use init instead of initWithWindowNibName, it is nil.
Does anyone know what's going on here? Thank you in advance for any guidance.
There’s no guarantee that an object under ARC hasn’t been added to the autorelease pool, in which case it won’t be freed until the end of the current event.
In your case, I strongly suspect somewhere within initWithWindowNibName: the controller gets retained and autoreleased.
If you really want to ensure your object is being freed, just subclass the -dealloc method and add an NSLog to it or break on it.
You generally shouldn't harbor "expectations" about when objects are deallocated if they've ever been passed to other code which you don't control.
Cocoa might have retained and then autoreleased the controller. Cocoa may retain the window controllers of any windows which are showing.
In general, when it comes to Cocoa memory management, you are supposed to make sure your own code follows the rules (which ARC largely does for you) and you should assume that other code follows the rules, but you can't assume that other code doesn't retain objects beyond where your interest ends. You should basically not care about what the other code is doing with respect to memory management.
If you really want to know what's happening, run your app under the Allocations instrument and explore the retain/release/autorelease history of your object after the point where you expected it to have been deallocated.
I had a similar issue when first using ARC. I unfortunately don't remember the details as this was more than a year ago. I eventually tracked it down as a circular retain problem using Instruments to monitor retain values, although not without losing a lot of hair.
I think the actual problem was with the delegate which I fixed with #property (unsafe_unretained) id delegate;
I ran into a similar issue yesterday with an ARC based project - a NSWindowController subclass would not deallocate, nor did -dealloc fire. I worked with Zombies, Allocations to no avail. The problem was very simple. There was a subclassed control within the window, and in that controls subclass .h header file a property was defined as:
#property id delegate;
correcting it to
#property (nonatomic, weak) id delegate;
fixed the issue.

Do strong objects get destroyed on segue?

I have a iPhone app with a table view and an add button in the navigation bar. The table view has a custom NSObject that holds it's data called dataBase. dataBase is a (strong, nonatomic) #property of this table view. The table view has a public method that allows new data to be added to dataBase. On clicking the add button there is a segue to a new view that lets you set the same of the new cell. On hitting a save button another segue is used to call the public method adding the information to dataBase. However, the original dataBase object is gone when this second segue is called, meaning that there is only ever one item in dataBase. Is this to be expected with segues? In order to keep the object alive do I need to pass the object itself around?
Sorry if this is a very noob question, I'm new to iOS programming and reference counting memory management.
This has nothing to do with a segue, so don't confuse the issue for yourself.
The basic deal with reference counted objects is that as long as there is at least one reference to the object, it will not be deallocated. However, once the reference count reaches zero, the object will be deallocated.
So, if you want an object to be kept "alive" then you need to keep a reference to it in some way. If you expect your database to be around for the life of the program, the usual pattern is to use a "singleton" object. This can be accomplished in many ways. A simple way is to mimic the common singleton pattern:
#interface Database : NSObject
+ (Database*)sharedInstance;
// other stuff for your class
#end
#implementation Database
+ (Database*)sharedInstance {
static Database *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[Foo alloc] init];
// Any other initialization necessary...
});
return instance;
}
#end
The dispatch_once stuff ensures correctness for multi-threaded applications (which all iOS apps should be).
Now, when you need your "shared" Database object...
Database *database = [Database sharedInstance];
The dispatch_once code, in addition to making it thread-safe, will make sure the creation code runs exactly once. The static object inside the function will keep a reference to the object, so it will never be deallocated... and live for the entire life of the program.
This is one common pattern for dealing with this situation, but there are many others. The key is that if you want an object to live, you have to keep a reference to it. Pass it to each view controller, or keep it in a "common" place, or archive it to disk when not needed, and re-hydrate it later when it is needed... lots of ways to do it...

viewDidLoad vs appDelegate methods

I persist to be a little confused about when to put something in a viewController and when to put it inside an AppDelegate, and if it is ok to reference viewController methods from the AppDelegate (i know you can but that doesn't mean it is encouraged).
Really, I wouldn't be confused if it weren't for all this multi-tasking stuff that seems to complicate the concepts for me. First, if anyone knows of a good, thorough and easy to read overview of how to deal with multitasking, I'd love to know.
Here's the deal: there are things I need my app to do when it loads, whether loading fresh or loading from the background. Stuff like perform a network reachability test, setup the interface based on data received from the internet, and this or that.
One of my main questions relates to how the viewcontroller's view interacts with background states. If the app resumes from the background and the view is immediately present without loading, then I assume it is still in memory and I have verified that viewDidLoad was not called with a basic NSLog. So, is it safe to say that any and all objects retained by my viewcontroller (like the data models and all subviews) are thus still in memory? If not, what's the best practice discovering which objects need to be re-loaded, what are still there, etc?
I think it's safe to assume that the standard memory management rules apply, even in a multi-tasking environment. That means that your controller, and anything you've got a reference to in your controller should still be valid until either:
You explicitly deallocate your controller/objects
Your app terminates
It seems like your assumption is that the system is going to mess with your objects behind your back, which (I hope) can't happen. Those methods are there in the app delegate in case you want to explicitly do anything when those particular events occur.
Regarding the viewDidLoad question, you could implement viewDidUnload or check the isViewLoaded method to make sure your view wasn't unloaded due to a low memory condition or otherwise. More on this in the UIViewController documentation.
One way to approach this problem is with lazily-loaded properties. In your .h file:
#interface YourViewController : NSObject
#property (nonatomic, retain) NSArray *exampleObject;
#end
And in your .m file:
#implementation YourViewController
#synthesize exampleObject = _exampleObject;
- (NSArray *)exampleObject {
// reload only if necessary
if (!_exampleObject) {
_exampleObject = [[NSArray alloc] init];
// do whatever other setup you need to
}
return _exampleObject;
}
#end

What are NSManagedObjectContext best practices?

I'm working with a Navigation Controller based iOS app. There are multiple tableView screens that pull and save data from a Core Data persistent store. Most of the data for the different table views comes from NSFetchedResultsController instances or NSFetchRequests.
The app works as intended but I have been getting a few random crashes and glitches that seem to be related to Core Data. For example sometimes when I save the context the app will crash but not always. Another thing I've been seeing is the very first tableView doesn't always update the reflect the data that was modified in it's detail view.
Currently I'm passing around a single Managed Object Context that was created in the app delegate to each of the different view controllers by setting the context property of the view controller just before I push it onto the navigation stack.
This seems like a clunky, hacky way of getting the job done. Is there a better design pattern to use?
I noticed in one of the WWDC sessions using delegation but I've never used creating my own delegates before and haven't been able to puzzle it out of the WWDC session.
Thanks.
=)
Use singleton NSManagedObjectContext for all Controllers isn't a best practice.
Each Controller should have your own Context to manage specific, sometimes atomic, operations at document store.
Think if you can edit a NSManagedObject attached to Controller that pass the same Context to other Controller that will select another instance to delete or edit.. you can lost the controll about modified states.
When you create a view controller, you pass it a context. You pass an
existing context, or (in a situation where you want the new controller
to manage a discrete set of edits) a new context that you create for
it. It’s typically the responsibility of the application delegate to
create a context to pass to the first view controller that’s
displayed.
http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/CoreDataSnippets/Articles/stack.html
1)
Use a singleton for your CoreData setup (NSPesistentStoreCoordinator, NSManagedObjectModel & NSManagedObjectContext). You can use this singleton to execute the fetch requests you created in your Models and to add or delete Entities to your Context.
2)
Delegates are not that hard. Following is a sample:
#class SomeClass
#protocol SomeClassDelegate <NSObject> //Implements the NSObject protocol
- (void) someClassInstance:(SomeClass *)obj givesAStringObject:(NSString *)theString;
- (BOOL) someClassInstanceWantsToKnowABooleanValue:(SomeClass *)obj //Call to delegate to get a boolean value
#optional
- (NSString *) thisMethodIsOptional;
#end
#interface SomeClass : NSObject {
id<SomeClassDelegate> delegate;
//Other instance variables omitted.
}
#property (assign) id<SomeClassDelegate> delegate;
#end
#implementation SomeClass
#synthesize delegate;
- (void) someMethodThatShouldNotifyTheDelegate {
NSString *hello = #"Hello";
if (self.delegate != nil && [self.delegate respondsToSelector:#selector(someClassInstance:givesAStringObject:)]) {
[self.delegate someClassInstance:self givesAStringObject:hello];
}
}
#end
Option 1 could be something like this, you will have to setup the variables in the init of the object (and implement the singleton ofcourse):
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface CoreDataUtility : NSObject {
#private
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
}
+ (CoreDataUtility *)sharedCoreDataUtility;
- (NSEntityDescription *) entityDesctiptionForName:(NSString *)name;
- (NSMutableArray *) executeRequest:(NSFetchRequest *)request;
- (id) getInsertedObjectForEntity:(NSString *)entity;
- (void) deleteAllObjects:(NSString *) entityName;
- (void) deleteManagedObject:(NSManagedObject *)object;
- (void) saveContext;
#end
Currently I'm passing around a single Managed Object Context that was
created in the app delegate to each of the different view
controllers...This seems like a clunky, hacky way of getting the job
done. Is there a better design pattern to use?
There's nothing particularly special about a managed object context in this respect, it's just another object that your view controller may need to do its job. Whenever you're setting up an object to perform a task, there are at least three strategies that you can use:
Give the object everything it needs to get the job done.
Give the object a helper that it can use to make decisions or get additional information.
Build enough knowledge about other parts of the application into the object that it can go get the information it needs.
What you're doing right now sounds like the first strategy, and I'd argue that it's often the best because it makes your view controllers more flexible, less dependant on other parts of the app. By providing the MOC to your view controllers, you leave open the possibility that you might someday use that same view controller with a different context.
Jayallengator makes the helpful observation that every managed object has a reference to its context, and if you're passing around specific managed objects you don't also need to pass along the context. I'd take that a step further: if you're passing specific managed objects to your view controller, the view controller often won't need to know about the context at all. For example, you might keep Game objects in your data store, but a GameBoardViewController will probably only care about the one Game that's being played, and can use that object's interface to get any related objects (Player, Level, etc.). Perhaps these observations can help you streamline your code.
The second strategy is delegation. You'll usually use a protocol when you use delegation, so that your object knows what messages it can send its helper without knowing anything else about the helper. Delegation is a way to introduce a necessary dependency into your code in a limited, well-defined way. For example, UITableView knows that it can send any of the messages defined in the UITableViewDelegate protocol to its delegate, but it doesn't need to know anything else about the delegate. The delegate could be a view controller, or it could be some other kind of object; the table doesn't care. The table's delegate and data source are often the same object, but they don't have to be; again, the table doesn't care.
The third strategy is to use global variables or shared objects (which is what people usually mean when they talk about singletons). Having a shared object that you can access from anywhere in your code is certainly easy, and you don't have that "klunky" extra line of code that configures your object, but it generally means that you're locking your view controllers in to using that shared object and no other. It's a lot like gluing a hammer to your hand because you know for certain that that hammer is the tool you need. Works great for pounding nails, but it can be painful if you later discover that you'd like to use the same hand for driving screws or eating dinner.
The singleton approach seems to be best-practice, but another trick I found useful was that in cases where you're passing a NSManagedObject from one view controller to the next anyway (usually as an instance variable), you don't need to also pass the NSManagedObjectContext since you can get the context from the object you passed in by invoking [myManagedObject managedObjectContext]. This can be a handy shortcut when there's maybe only one or two methods where you need the context and you don't want the overhead of creating yet another NSManagedObjectContext ivar/property.

Under what conditions can the object at an address change? (obj-c)

I have a controller with a delegate.
#interface MyConversionController : NSObject {
id <ConversionDelegate> _delegate;
}
#property (assign) id delegate;
#end
#implementation
#synthesize delegate = _delegate;
#end
I'm getting Unrecognized selector sent to instance 0x36c4a0 errors. I've set a breakpoint on the -(void)setDelegate(id)delegate method so I can observe objects that are passed into my MyConversionController class. My setDelegate method is called twice, the first time is an object at the address 0x36c4a0 that I know conforms to the <ConversionDelegate> protocol. The second time this method is called another object is passed in that also conforms to the protocol. When the time comes to start calling methods on the delegate the method calls are sent to the first object (0x36c4a0) which is now some other kind of object (usually a CFString or __NSFastEnumerationEnumerator if that makes a difference).
Does anyone know why this could be happening?
After running malloc_history I see that the first address, the one that's giving me trouble, is allocated and freed a number of times before I get to it. The second object is just allocated once. Under what conditions would the pointers be reused like this?
You might want to use malloc_history to find the callstack of the object at that address. Do the following in the terminal while your process is running:
malloc_history <pid> 0x36c4a0 # insert the address in question for the 2nd arg
You'll also need to enable MallocStackLogging (thanks to Kubi's comment below on this).
This may help you understand where the object at that address is being allocated.
Also, you've marked the delegate as assign, not retain, however, I think this is appropriate for delegates. That said, if it was autoreleased somewhere else, that memory may be being reused.
Are you possibly autoreleasing the delegate and assigning it? Something like:
delegate = [[[ConversionDelegateClass alloc] init] autorelease];
controller.delegate = delegate
If so, the delegate will be released in the next autopool release since nothing is retaining it and that memory location will be available for re-use.
The problem is that the the delegate was being prematurely deallocated. The reason this was so difficult to debug was that the deallocation occured in code I had written a long time ago, and the program would quit before the issues would occur. Writing the new sliver of code kept the program open for just long enough for other classes to start sending messages to the deallocated object.
Solution: I ran the code with the the Zombie module in Instruments. Wish I had done this a few days ago, I fixed the code within 30 seconds of looking at the output from Instruments.