Possible deallocation of UIKit object on the non-main queue - objective-c

I've faced several times in public APIs the following code style:
#interface UITextField (SomeFunctionalitySupport)
- (void) someMethod {
#weakify(self)
dispatch_async(someConcurrentQueue, ^{
#strongify(self)
self.text = #"Some text"
})
}
#end
Given that UITextField is UIKit object it should be deallocated on the main queue. As I understand, weakify/strongify macros are just a neat way to not declare __weak and __strong local variables manually and perform conditional check on the strong one.
But __strong increments reference counting, right? So, until the block completes we'll have one more strong reference. And block runs on the non-main queue. What if during execution of the block the strong reference became the last one? Logically, self'd be deallocated upon completion of the block. But this wouldn't happen on the main queue which could cause significant problems.
Was API creators wrong or I'm missing something?

self will not be deallocated while the block is running, because it holds a strong reference on it.
It will be deallocated after the block execution finished, because in your case it is the last strong reference. Who should care about this, since no one else has a strong reference on it?

Related

How to enforce using `-retainCount` method and `-dealloc` selector under ARC?

Under ARC, compiler will forbid using any method or selector of -retainCount, -retain, -dealloc, -release, and -autorelease.
But sometimes I want to know the retain counts at runtime, or using method swizzling to swap the -dealloc method of NSObject to do something.
Is it possible to suppress (or bypass) the compiler complaining just a couple of lines of code? I don't want to modify ARC environment for whole project or whole file. I think preprocessor can do it, but how?
Additions:
Thanks guys to give me a lesson about the use of -retainCount. But I wonder whether it is possible to enforce invoking/using those forbidden methods/selectors.
I know Instruments is a powerful tool to do this job. But I am still curious about those question.
Why do I want to use -retainCount:
When using block, if you don't specify a __weak identifier on the outside variables, the block will automatically retain those outside objects in the block after the block is copied into the heap. So you need to use a weak self to avoid retain cycle, for example:
__weak typeof(self) weakSelf = self;
self.completionBlock = ^{
[weakSelf doSomething];
};
However, it will still cause retain cycle when you only use instance variables in the copied block (YES, although you didn't use any keyword self in the block).
For example, under Non-ARC:
// Current self's retain count is 1
NSLog(#"self retainCount: %d", [self retainCount]);
// Create a completion block
CompletionBlock completionBlock = ^{
// Using instance vaiable in the block will strongly retain the `self` object after copying this block into heap.
[_delegate doSomething];
};
// Current self's retain count is still 1
NSLog(#"self retainCount: %d", [self retainCount]);
// This will cuase retain cycle after copying the block.
self.completionBlock = completionBlock;
// Current self's retain count is 2 now.
NSLog(#"self retainCount: %d", [self retainCount]);
Without using -retainCount before/after the copied block code, I don't think this retain cycle caused by using instance variables in the completion block will be discovered easily.
Why do I want to use -dealloc:
I want to know whether I can use method swizzling to monitor which object will be deallocated by logging messages on the Xcode console when the -dealloc is invoked. I want to replace the original implementation of -dealloc of NSObject.
That's not recommened at all, I dont know your intentions but they dont sound very safe.
The use of retainCount is not recommended.
From AppleDocs:
This method is of no value in debugging memory management issues.
Because any number of framework objects may have retained an object in
order to hold references to it, while at the same time autorelease
pools may be holding any number of deferred releases on an object, it
is very unlikely that you can get useful information from this method
And, if there's any doubt, check this link:
http://whentouseretaincount.com/
Whatever you are trying to do, please dont.
For future references, I'm going to add some linsk to help you understand the process of how memory works in iOS. Even if you use ARC, this is a must know (remember that ARC is NOT a garbage collector)
Beginning ARC in iOS 5 Tutorial Part 1
Understand memory management under ARC
Memory Management Tutorial for iOS
Advance Memory Managment
And, of course, once you understand how memory works is time to learn how to profile it with instruments:
Instruments User Guide
Agreed 100% with the other commenters about the fact that you do not want to use -retainCount. To your other question, however, about -dealloc:
You also do not want to swizzle -dealloc. If you think you want to swizzle it, you don't understand how it works. There are a lot of optimizations going on there; you can't just mess with it. But, as #bbum hints at, you can easily get notifications when objects are deallocated, and this can be very useful.
You attach an associated object to the thing you want to watch. When the thing you want to watch goes away, so does the associated object, and you can override its dealloc to perform whatever action you want. Obviously you need to be a little careful, because you're in the middle of a dealloc, but you can generally do most anything you'd need to here. Most importantly for many cases, you can put a breakpoint here or add a logging statement, so you can see where the object was released. Here's a simple example.
With ARC
const char kWatcherKey;
#interface Watcher : NSObject
#end
#import <objc/runtime.h>
#implementation Watcher
- (void)dealloc {
NSLog(#"HEY! The thing I was watching is going away!");
}
#end
NSObject *something = [NSObject new];
objc_setAssociatedObject(something, &kWatcherKey, [Watcher new],
OBJC_ASSOCIATION_RETAIN);
Without ARC
const char kWatcherKey;
#interface Watcher : NSObject
- (void)lastRetainDone;
#end
#import <objc/runtime.h>
// turn off ARC!
#implementation Watcher
{
BOOL noMoreRetainsAllowed;
}
- (void)lastRetainDone {
noMoreRetainsAllowed = YES;
}
- (id) retain {
if (noMoreRetainsAllowed) abort();
return [super retain];
}
- (void)dealloc {
NSLog(#"HEY! The thing I was watching is going away!");
[super dealloc];
}
#end
...
NSObject *something = [NSObject new];
Watcher *watcher = [Watcher new];
objc_setAssociatedObject(something, &kWatcherKey, watcher,
OBJC_ASSOCIATION_RETAIN);
[watcher lastRetainDone];
[watcher release];
Now, when something goes away, -[Watcher dealloc] will fire and log for you. Very easy. Completely supported and documented.
EDIT:
Without using -retainCount before/after the copied block code, I don't think this retain cycle caused by using instance variables in the completion block will be discovered easily.
You are somewhat correct here, but there are two lessons to be learned, and neither is to use retainCount (which won't actually help you in this case anyway because retainCount can very often be something you don't expect).
The first lesson is: Do not allow any warnings in ObjC code. The situation you're describing will generally create a compiler warning in recent versions of clang. So it's actually quite easy to discover in many cases. The way you've separated it into multiple assignments, the compiler may miss it, but the lesson there is to change your coding style to help the compiler help you.
The second lesson is: don't access ivars directly outside of init and dealloc. This is one of the many little surprises that can cause. Use accessors.

Why the retain cycle warning not thrown?

I use Xcode 5 and have some code
#interface Controller {
__weak IBOutlet UIView *someView;
}
#implementation Controller {
- (void)doSomething
{
[UIView animateWithDuration:0.5 animations:^{
someView.hidden = YES;
}];
}
- (void)doSomething1
{
[UIView animateWithDuration:0.5 animations:^{
[self doSomething];
}];
}
Why the retain cycle warning not thrown there? Should I use weak references on self every time I use self in blocks?
Also I enabled Implicit retain of self within blocks warning and it gave me 100 warnings with advice to write self->ivar.prop (not ivar.prop) in blocks. Should I do so after that warning is disabled by default?
Why the retain cycle warning not thrown there?
The block retains you, but you don't retain the block. It'll be destroyed after animation is complete. So, no cycles.
Should I use weak references on self every time I use self in blocks?
If your block doesn't get destroyed automatically (e.g. a recurring timer), then you should.
Should I do so after that warning is disabled by default?
Depends upon the context. Again, if your blocks live for a long time, you might want to declare non-retained weakSelf.
But basically you're fine if your blocks don't get saved somewhere.
See also How do I avoid capturing self in blocks when implementing an API?
This is not a retain cycle. This is two methods calling each other in a loop. A retain cycle happens when two object instances have strong (retained) references to each other that are never broken, and those two objects remain in memory unnecessarily.
Example with code: Retain cycle in ARC
Should I use weak references on self every time I use self in blocks?
Absolutely not. Blocks retain captured object pointers for a reason -- to keep the objects alive until so that they'll still be there when the block is run. If there is no retain cycle and there is no other thing keeping a reference to the object pointed to by self, it could be deallocated before the block is run (asynchronously, for example).

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

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

Xcode/Cocoa: "object.property = value" sporadically failing? Can anyone explain this?

I'm writing a project where a very straightforward assignment is sporadically failing. Fascinated with this result and curious to see what y'all make of it.
I've got a project with a large data set, and I'm creating and display a modal window to present some details about a new class instance. So I've got a window with a custom window controller class, with the following code:
MyWindowController.h:
#import <DataModel.h>
#interface MyWindowController : NSWindowController
#property (nonatomic, weak) FooClass *fooInstance;
#end
MyWindowController.m:
#implementation MyWindowController
#synthesize fooInstance = _fooInstance;
-(void) init {
self = [super init];
if (self) {
self.fooInstance = [FooClass new];
}
return self;
}
#end
Totally cookie-cutter, right? But when I first added the form and ran it a bunch of times, the assignment failed over and over again. self.fooInstance kept coming back as nil. I even confirmed that the FooClass initializer was running (stepped right through it) and returning a non-null pointer to a valid FooClass instance. And yet, after the assignment line, self.fooInstance remained null.
I ran it a bunch of times, watching this same result over and over again. Then, I replaced just the assignment statement with this:
FooClass *foo = [FooClass new];
self.fooInstance = foo;
...and the assignment suddenly started working, and it's run consistently ever since. Even when I reverted the code back to self.fooInstance = [FooClass new], it's worked perfectly.
I couldn't believe it... until I saw it happen AGAIN, in the same project, while banging out the same type of window for a different class.
I don't understand what's happening. The self.fooInstance accessors are totally #synthesized; there is no code running in the background that might be futzing with the class (it's a single-threaded modal window); and there's nothing bound to the class. It just... doesn't work. It's like the code for the window classes doesn't run right until it's run a few times to break it in.
What in the world is happening? Does anyone even hazard a guess that might explain this behavior?
I recommend taking a read through Mike Ash's explanation of weak pointers. This section is the relevant bit:
Weak References
First, what is a weak reference? Simply put, a weak
reference is a reference (pointer, in Objective-C land) to an object
which does not participate in keeping that object alive. For example,
using memory management, this setter creates a weak reference to the
new object:
- (void)setFoo: (id)newFoo
{
_foo = newFoo;
}
Because the setter does not use retain, the reference does not keep the new object alive. It will stay alive as long as it's retained
by other references, of course. But once those go away, the object
will be deallocated even if _foo still points to it.
OK, that explains the first part, but why does the second part work?
Well, when you write an instance variable like:
FooClass *foo = //assignment
The compiler says to itself "it's a really good idea to keep this thing around, (at least til the function goes out of scope under ARC), and it turns it into this:
__strong FooClass *foo = //assignment
That means whatever I assigned is retained, and therefore, because at least one object owns it, I can assign it to my weak instance variable.

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.