I have been using blocks and familiar with the memory management when using self inside blocks in
Non-ARC environment
But I have two specific questions:
1) I understand I can use __block to avoid the retain cycle a retained block which in turn using self can create, like below:
__block MyClass *blockSelf = self;
self.myBlock = ^{
blockSelf.someProperty = abc;
[blockSelf someMethod];
};
This will avoid the retain cycle for sure but I by doing this I have created a scope for self to be released and eventually deallocated by someone else. So when this happen self is gone and blockSelf is pointing to a garbage value. There can be conditions when the block is executed after the self is deallocated, then the block will crash as it is trying to use deallocated instance. How do we can avoid this condition? How do I check if blockSelf is valid when block executes or stop block from executing when self is deallocated.
2) On the similar lines suppose I use block like below:
__block MyClass *blockSelf = self;
self.myBlock = ^{
[blockSelf someMethod:blockSelf.someProperty];
};
// I am taking someProperty in an method argument
-(void) someMethod:(datatype*)myClassProperty
{
myClassProperty = abc;
}
Now there can be situations where self is not released but someProperty is released before someMethod's execution starts (This could happen when there are multiple threads). Even if I do self.someProperty = nil; when it is release, myClassProperty is not nil and pointing to some garbage, hence when someMethod is executed the first line will lead to crash. How do I avoid this?
This is the same issue as non-zeroing weak references everywhere else in non-ARC code, e.g. delegates etc. (MRC doesn't have zeroing weak references; so these are the only kind of weak reference in MRC. Yet people were still able to write safe code in the pre-ARC days.)
Basically, the solution is that you need a clear map of ownership. Either self is responsible for keeping the block alive; or some other object is responsible for keeping the block alive.
For example, with delegates, usually, a "parent" object is the delegate of a "child" object; in this case the "parent" object is responsible for keeping the "child" object alive, so the "parent" object will outlive the "child" object, thus the back reference can be weak and is safe (because the child object's methods could only possibly be called by the parent object while the parent object is alive).
On the other hand, if you have an asynchronous operation, and the block is given to the operation as a callback, then usually the operation is responsible for holding onto the block. In this case, self would not hold onto the block. And the block would hold a strong reference to self, so that when the operation is done, it can still safely do whatever it is that it needs to do on self. In fact, whatever object self is, it doesn't even need to be retained by whoever uses it, since it is indirectly retained by the asynchronous operation -- it can just be a create, fire, and forget kind of thing.
If you have something where the block is sometimes kept alive by self, and sometimes kept alive by something else, then you should re-think your design. You say "There can be conditions when the block is executed after the self is deallocated"; well, you should describe your whole design and how this can happen. Because usually, for something that is executed asynchronously, self need not hold onto the block.
Your code is really confusing and doesn't make sense. For example, why would you assign to a parameter (myClassProperty)? What's the point of passing an argument when the parameter is going to be overwritten anyway? Why would you name a local variable "myClassProperty"?
What I think you are asking about is accessing a property that can be changed on different threads, and how to deal with the memory management of that. (This question is unrelated to blocks or ARC/MRC. It is equally an issue in ARC.)
The answer is that you need an atomic property. You can make a synchronized property atomic, or implement an atomic property manually if you know how. What an atomic property of object pointer type needs to do is its getter needs to not just return the underlying variable, but also retain and autorelease it, and return the result of that. The retrieval and retaining in the getter occurs in a critical section that is synchronized with a critical section in the setter that includes the release of the old value and retaining of the new. Basically, this synchronization guarantees that the value will not be released in the setter in between retrieving the value and retaining it in the getter. And the value returned from the getter is retained and autoreleased, so it is guaranteed to be alive for the duration of the scope.
Solution for 2)
__block MyClass *blockSelf = self;
self.myBlock = ^{
datatype* p = [blockSelf.someProperty retain];
[blockSelf someMethod:p];
[p release];
};
// I am taking someProperty in an method argument
-(void) someMethod:(datatype*)myClassProperty
{
myClassProperty = abc;
}
For 1) don't know how you use myBlock. If it's used only by self, then all will be fine. And if it's used by some other object, then it's also should have retained reference at self and then there is also all will be fine.
Related
Using self. in blocks causes retain cycles, so I need to create a reference to weakSelf. I understand this
BUT!
If from my block I call a method which uses self", does this too cause a retain cycle? For instance, if I reload a UITableView from a block and in some of my UITableView delegate methods I call self., am I causing a retain cycle? Does that mean I have to pass around this weak reference everywhere? Seems hokey.
I might be misreading your question, but your wording:
If from my block I call a method which uses "self.", does this too cause a retain cycle? For instance if I reload a UITableView from a block and in some of my UITableView delegates I call "self.", I'm causing a retain cycle? That means I have to pass around this weakReference everywhere?
suggests you are misunderstanding what self is. Hopefully if so the following will help and not hinder your understanding...
What is self?
The identifier self is just the name of one of the parameters to your method, it is just passed implicitly rather then explicitly like the other parameters. For example if you have a class:
#implementation MyClass
- (void) someMethod:(NSInteger)value
{
... self ... value
}
#end
then the method is effectively (i.e. bending the facts just a little for clarity):
- (void) someMethod:(NSInteger)value withObject:(MyClass *)self
{
... self ... value
}
When an instance method is called the value passed for the self parameter is a reference to the instance the method should operate on, e.g. the call
MyClass *someInstance = ...
[someInstance someMethod:42];
is effectively a call to:
someMethod:42 withObject:someInstance
Strong reference cycles
An object - which includes both instances of classes and blocks - is kept alive as long as there exists a strong reference to the object.
If an object A holds a strong references, e.g. in an instance variable or property, to an object B, then B will be kept alive at least (there could be other strong references to B) as long as A is alive.
If an object A holds a strong reference to B and B holds one to A then you have a strong reference cycle - each object is keeping the other alive and neither will ever be collected. This could lead to a memory leak - where unused memory is never collected - unless both A and B are meant to live from creation till the end of the program.
Further, you do not create a strong reference cycle simply by having references stored in the local variables and parameters of methods. By their nature such variables, and therefore their contents, are transient and are destroyed when the method returns.
Using self in blocks
using "self." in blocks causes retain cycles so I need to create a reference to weakSelf.
Not quite. When you use self in a block, either directly or indirectly by referencing an instance variable, then the compiler will warn you that you may create a reference cycle.
(Note: There are other ways to create reference cycles, both with and without using blocks, and the compiler will not warn you at all. Managing cycles is just something you need to be aware of.)
You will only actually create a cycle if you store a reference to the block in the object referenced by self. However this is not bad in itself, as long as at some point you break the cycle manually - say by storing nil in the variable referencing the block - the cycle need not be problematic at all.
Finally...
You have nothing per se to worry about with your:
UITableView delegates I call "self."
as that self is just a local parameter to the delegate whose initial value, at some point going back up the call chain, came from you evaluating your weakSelf reference and determining that it was not nil and then calling methods on it.
HTH
First of all: self does NOT cause a retain cycle. This is an urban legend. The incorrectness is obvious: A single reference can never cause a cycle. The usage of self inside a block causes a retain cycle, if the block is directly or indirectly referred by self, too, for example via a property.
To your Q:
If you "call" a method inside the block, the message probably has the receiver self, so you have a usage of self inside the block. For this reason it is captured and retained.
If you really have no usage of self inside the block by neither using self nor using a property of self you do not have a usage of self and it is not captured, therefore not retained. But in this case you can have a dangling pointer or a nil'd reference.
You don't need to worry about references while the block is executing - eventually it finishes doing whatever it does, and all these references go away.
What you need to worry about are the references that are captured when the block is created. These references stay until the block goes away. So if your block has a reference to "self", that reference is there just because the block exists. And if you store that block in a property of self, you have a cycle.
So if you store a block as a property in self, then the block shouldn't capture self. That's easily done by letting it access and capture a weak copy of self. Remember that when the block is executing, the weak copy of self may be nil. Which means the self object has already left our world, and your block might not need to do anything.
Short answer: no, in this situation self is not retained.
Long answer
First of all, retaining self and a reference cycle are not the same thing. Reference cycle is a cycle of strong references between a number of objects: A->B->C->A is a retain cycle.
The general idea is, you want to always guarantee that if you are referencing self in a block, you don't reference this block strongly, and don't reference it through a chain of strong references. In reality, retain cycles can be used purposefully if you are making sure you're breaking the retain cycle under certain conditions. Not that I personally recommend this.
Take a look at documentation on Apple's website. It clearly states that values are captured in blocks, and capturing an object reference retains this object in block.
Basically what this means is that referencing an object in a block increments its retainCount by 1, and when this block gets deallocated, retainCount is decremented by 1.
However, when using a __weak pointer in a block, the retain count is untouched.
Here's an example:
- (void) doSomething {
NSLog(#"%#", self);
}
- (void) callBlock {
__weak typeof(self) weakSelf = self;
dispatch_block_t block = ^{
[weakSelf doSomething];
};
}
When you write [obj method:params] this actually translates into following call:
objc_msgSend(obj, #selector(method:), params). One of the features of Objective-C is that if you call a method on nil pointer, it returns nil. This is guaranteed by the fact that objc_msgSend(nil, #selector(anyselector), ...) always return nil. Note that SEL is just a const char[] under the covers, so it doesn't affect retain counts by any means.
Hence when the block will be executed, if your object was deallocated, the weak weakSelf variable will be nullified, and the block's body will translate into objc_msgSending to zero, which does nothing except of wasting few CPU cycles.
To sum it up, the Objective-C messaging system is implemented in such a way that calling a method does not retain this object or this method or this method's implementation, as it's a simple function call.
Using self. in blocks causes retain cycles, so I need to create a reference to weakSelf. I understand this
BUT!
If from my block I call a method which uses self", does this too cause a retain cycle? For instance, if I reload a UITableView from a block and in some of my UITableView delegate methods I call self., am I causing a retain cycle? Does that mean I have to pass around this weak reference everywhere? Seems hokey.
I might be misreading your question, but your wording:
If from my block I call a method which uses "self.", does this too cause a retain cycle? For instance if I reload a UITableView from a block and in some of my UITableView delegates I call "self.", I'm causing a retain cycle? That means I have to pass around this weakReference everywhere?
suggests you are misunderstanding what self is. Hopefully if so the following will help and not hinder your understanding...
What is self?
The identifier self is just the name of one of the parameters to your method, it is just passed implicitly rather then explicitly like the other parameters. For example if you have a class:
#implementation MyClass
- (void) someMethod:(NSInteger)value
{
... self ... value
}
#end
then the method is effectively (i.e. bending the facts just a little for clarity):
- (void) someMethod:(NSInteger)value withObject:(MyClass *)self
{
... self ... value
}
When an instance method is called the value passed for the self parameter is a reference to the instance the method should operate on, e.g. the call
MyClass *someInstance = ...
[someInstance someMethod:42];
is effectively a call to:
someMethod:42 withObject:someInstance
Strong reference cycles
An object - which includes both instances of classes and blocks - is kept alive as long as there exists a strong reference to the object.
If an object A holds a strong references, e.g. in an instance variable or property, to an object B, then B will be kept alive at least (there could be other strong references to B) as long as A is alive.
If an object A holds a strong reference to B and B holds one to A then you have a strong reference cycle - each object is keeping the other alive and neither will ever be collected. This could lead to a memory leak - where unused memory is never collected - unless both A and B are meant to live from creation till the end of the program.
Further, you do not create a strong reference cycle simply by having references stored in the local variables and parameters of methods. By their nature such variables, and therefore their contents, are transient and are destroyed when the method returns.
Using self in blocks
using "self." in blocks causes retain cycles so I need to create a reference to weakSelf.
Not quite. When you use self in a block, either directly or indirectly by referencing an instance variable, then the compiler will warn you that you may create a reference cycle.
(Note: There are other ways to create reference cycles, both with and without using blocks, and the compiler will not warn you at all. Managing cycles is just something you need to be aware of.)
You will only actually create a cycle if you store a reference to the block in the object referenced by self. However this is not bad in itself, as long as at some point you break the cycle manually - say by storing nil in the variable referencing the block - the cycle need not be problematic at all.
Finally...
You have nothing per se to worry about with your:
UITableView delegates I call "self."
as that self is just a local parameter to the delegate whose initial value, at some point going back up the call chain, came from you evaluating your weakSelf reference and determining that it was not nil and then calling methods on it.
HTH
First of all: self does NOT cause a retain cycle. This is an urban legend. The incorrectness is obvious: A single reference can never cause a cycle. The usage of self inside a block causes a retain cycle, if the block is directly or indirectly referred by self, too, for example via a property.
To your Q:
If you "call" a method inside the block, the message probably has the receiver self, so you have a usage of self inside the block. For this reason it is captured and retained.
If you really have no usage of self inside the block by neither using self nor using a property of self you do not have a usage of self and it is not captured, therefore not retained. But in this case you can have a dangling pointer or a nil'd reference.
You don't need to worry about references while the block is executing - eventually it finishes doing whatever it does, and all these references go away.
What you need to worry about are the references that are captured when the block is created. These references stay until the block goes away. So if your block has a reference to "self", that reference is there just because the block exists. And if you store that block in a property of self, you have a cycle.
So if you store a block as a property in self, then the block shouldn't capture self. That's easily done by letting it access and capture a weak copy of self. Remember that when the block is executing, the weak copy of self may be nil. Which means the self object has already left our world, and your block might not need to do anything.
Short answer: no, in this situation self is not retained.
Long answer
First of all, retaining self and a reference cycle are not the same thing. Reference cycle is a cycle of strong references between a number of objects: A->B->C->A is a retain cycle.
The general idea is, you want to always guarantee that if you are referencing self in a block, you don't reference this block strongly, and don't reference it through a chain of strong references. In reality, retain cycles can be used purposefully if you are making sure you're breaking the retain cycle under certain conditions. Not that I personally recommend this.
Take a look at documentation on Apple's website. It clearly states that values are captured in blocks, and capturing an object reference retains this object in block.
Basically what this means is that referencing an object in a block increments its retainCount by 1, and when this block gets deallocated, retainCount is decremented by 1.
However, when using a __weak pointer in a block, the retain count is untouched.
Here's an example:
- (void) doSomething {
NSLog(#"%#", self);
}
- (void) callBlock {
__weak typeof(self) weakSelf = self;
dispatch_block_t block = ^{
[weakSelf doSomething];
};
}
When you write [obj method:params] this actually translates into following call:
objc_msgSend(obj, #selector(method:), params). One of the features of Objective-C is that if you call a method on nil pointer, it returns nil. This is guaranteed by the fact that objc_msgSend(nil, #selector(anyselector), ...) always return nil. Note that SEL is just a const char[] under the covers, so it doesn't affect retain counts by any means.
Hence when the block will be executed, if your object was deallocated, the weak weakSelf variable will be nullified, and the block's body will translate into objc_msgSending to zero, which does nothing except of wasting few CPU cycles.
To sum it up, the Objective-C messaging system is implemented in such a way that calling a method does not retain this object or this method or this method's implementation, as it's a simple function call.
Which of the following code section is correct?
Definition of correct for "me":
It should not have a retain cycle and so should not leak.
It must guarantee the running of method2 and method3. So MyObject variable in block must never ever be nil.(which may occur in __weak definitions...) (I do not want to check if it is nil to prevent crash. I always want it to be non-nil)
Update: (Additional Info)
Instruments tool did show strange leaks until I replace __block with __weak. However, after that I remembered that __weak references may disappear anytime. I have to be sure that it doesn't disappear and leak too. I don't have a timer. This someMethod is called on main thread when it observes a specific NSNotification.
#implementation MyObject...
-(void)someMethod{
AnotherObject *abc=[[AnotherObject alloc]init];
__weak MyObject *weakSelf=self;
abc.onSuccess=^{
__strong MyObject * strongSelf = weakSelf;
[strongSelf method2];
[strongSelf method3];
}
}
OR
#implementation MyObject...
-(void)someMethod{
AnotherObject *abc=[[AnotherObject alloc]init];
__block MyObject *blockSelf=self;
abc.onSuccess=^{
[blockSelf method2];
[blockSelf method3];
blockSelf=nil;
}
}
Update 2: Actual Code which always leaks if I don't use __weak:
__block RButton *_self=self;
_aimageView.onSuccess=^(void){
[_self.headerLabel setText:[_self.book title]];
_self = nil;
};
A block can mention self without causing any leak. So the first thing to do is specify the circumstances. Why do you think your block leaks? Have you checked? There's no point worrying if there is no reason to worry.
If the block's mentioning self does cause a leak, then the steps you can take depend upon the reason why that is happening. But you haven't shown us that. For example, a dispatch timer block that mentions self might cause a retain cycle, but when you are done with the timer you can break the cycle, so then there's no leak.
Thus it is better to understand a particular retain cycle than to program every block defensively when you don't have to.
EDIT (in response to your comment) This code from my book demonstrates various ways of handling memory management in an NSNotification observer situation: click here
I have looked at your actual code in "Update 2", but it's missing a lot of information. For example, is _aimageView an instance variable? local variable? or what? And what causes this onSuccess to be called?
If _aimageView is a local variable then I don't see evidence of a retain cycle.
My first thought is I don't understand why you want to guarantee that the code inside the body of the block runs in this example. It looks like the code inside is just updating some UI elements. Well, if the UI is no longer displaying (as when the current object has no references to it other than perhaps by this block), what's the point of updating the UI elements?
It's important to know what causes onSuccess to be called because different types of callbacks require different memory management architectures. For example, if the block is fired in response to a touch or some kind of event like that, then chances are that the object pointed to by self (which is probably some kind of view or view controller) must be still alive in order that the event occurs. If that's the case, then __weak will do what you want.
Basically, by the naming of these variables, it is reasonable to conclude that _aimageView is probably an image view that is conceptually "owned" by the current object, and the onSuccess is a completion block that is "owned" by the image view. Unless some other object has a strong reference to it, the "owned" object's lifetime is limited to its "owning" object's lifetime. Thus the block will not outlive the image view, which will not outlive the current object.
The only way that what you are afraid of (when the block runs, the object pointed to by self is deallocated) can happen, is if some other object stores a strong reference to _aimageView, or to the block. For the block, it's very unlikely that a "success block" of one object will be stored with other objects. For the image view, it's similarly unlikely if the image view "belongs" to the current object. (It's conceivable that it may be stored by the autorelease pool or something; but the autorelease pool will not call stuff on it except release, so that's not a problem.)
The only exception I can think of is if the image view is kept by a pending network operation or something, which when it is done calls the onSucess block. But if that were the case, I would say it's bad design to have a single object serve as both a view and a network operation. Rather, in that case, one should have a dedicated network operation object, which is a local variable, and set a completion block on it (e.g. store image in image view, set labels, etc.), start the operation, and not need to store the operation. Then the block can refer to self strongly, but there is no retain cycle.
To summarize, the block (and the image view that owns it) should fall into one of two categories, based on who keeps it alive (i.e. who retains it, who maintains a strong reference to it):
If self keeps it alive: e.g. A view controller keeps its views and subviews alive. In this case, it is safe to use __weak because the block does not exist outside of the life of self.
If someone else keeps it alive: e.g. an alert view -- you just create it and show it; the system maintains it on screen afterwards. In this case, self should not (and does not need to) have a reference to it, and it's okay to reference self strongly in the block; it won't cause a retain cycle.
Try to avoid situations where both self and someone else keep it alive.
As you require to guarantee that method2 and method3 are executed then you have a requirement that the object referenced by self stays alive. To do this you follow the standard pattern: keep a strong reference for as long as you need it. Your second code fragment does that.
Reference cycles are not inherently bad, it is unmanaged ones that are. Here you make a cycle and then break it, so there is no issue.
(Note as you can send a message to nil the first code fragment will not crash if strongSelf is nil - it just won't do anything.)
-(void)someMethod{
AnotherObject *abc=[[AnotherObject alloc]init];
abc.onSuccess=^{
[self method2];
[self method3];
}
}
This will make. It won't cause a retain cycle.
I am a Obj-C programmer who was born, and has only lived in a post ARC world. For my own efficacy though, I recently decided to go through Apple's Transitioning to ARC Release Notes. In the ARC Introduces New Lifetime Qualifiers section, there is a subsection titled Use Lifetime Qualifiers to Avoid Strong Reference Cycles that describes various ways to use qualifiers in potential in order to avoid potential retain cycles.
My question has to do with the last two examples. The first of the last two examples uses a pattern that I often utilize in order to avoid deallocating a UIKit object prematurely from a non-main thread:
MyViewController *myController = [[MyViewController alloc] init…];
// ...
MyViewController * __weak weakMyViewController = myController;
myController.completionHandler = ^(NSInteger result) {
[weakMyViewController dismissViewControllerAnimated:YES completion:nil];
};
In the above example, the weakMyViewController object is created with a weak reference to myController so that the block referencing weakMyViewController can use it, and upon return of the block, weakMyViewController can safely fall out of scope without decrementing the reference count of the underlying UIKit object being referenced.
In the next example though, Apple shows the following code for "non-trivial cycles":
MyViewController *myController = [[MyViewController alloc] init…];
// ...
MyViewController * __weak weakMyController = myController;
myController.completionHandler = ^(NSInteger result) {
MyViewController *strongMyController = weakMyController;
if (strongMyController) {
// ...
[strongMyController dismissViewControllerAnimated:YES completion:nil];
// ...
}
else {
// Probably nothing...
}
};
In the above "non-trivial" example offered, the same __weak qualifier is used to reference the UIKit object from within the block, but then the code creates an local implicit __strong reference to the same object. Then that local __strong reference is tested for a non-nil condition, and is then operated on.
My two questions are:
Under what considerations should an Obj-C programmer implement the second design pattern (as opposed the former)? I don't understand Apple's comment about "non-trivial cycles"
How does the __strong reference to weakMyController not increment the retain count of the original myController object? If weakMyController is only a pointer to the underlying object that myController points to, wouldn't a strong pointer (i.e. stringMyController) increment the retain count of the underlying object (the object that myController is pointing to)?
Regarding your first example, the motivation you ascribe to having the block literal only keep a weak reference to the instance pointed to by myController is not quite correct. weak references won't stop an object from deallocating, and the purpose of the weak reference is to prevent a strong reference cycle (also called a retain cycle). In this situation, the strong reference cycle would be manifested by myController maintaining a strong reference to the block stored in completionHandler, while the block maintains a strong reference back to myController - neither would ever be deallocated (without un-setting the completionHandler property at some future time). Thus, the motivation here is quite the opposite of keeping an object alive - it's to allow myController to deallocate normally when all other references to it cease to exist.
The second example is an extension of the first, but by assigning the captured weak reference to a strong reference local to the block, we can ensure that so long as the controller is still alive when block execution begins, it will remain alive until the end of block execution. Since the strong reference is scoped only to the block, it doesn't create a strong reference cycle. In other words, strongMyController is local only to the scope of the block's code, and is not retained by the block object itself.
Now, to address your specific questions:
You would take this approach when you want to ensure the block completes execution with a reference to a live, non-nil object from its enclosing scope, if that object was alive when the block begins execution. If there's a chance that all other strong references to an object may disappear during execution of the block, you should seriously consider using this.
The strong reference certainly does increment the reference count, and is the point - while the scope of the block's code is active, the controller will be kept alive. This does not form a strong reference cycle since, again, it's not the block object that maintains the reference, but the variable used in the block's code, which only exists when the block is executing. Assuming the block does not continue execution to infinity, then the cycle will be broken.
If I declare a static object handle in a class file in global scope. And the object assigned to this handle is an autoreleased one. Then for how long will this object remain in memory during my application life cycle ?
If I declare a static object handle in a class file in global scope. And the object assigned to this handle is an autoreleased one. Then for how long will this object remain in memory during my application life cycle?
Short Answer: You want your global to be a strong reference. In MRC, you must add the retains and releases for globals. In ARC, the global is implicitly strong (and ARC adds them for you).
Long Answer:
Under ARC, your static global variable is a strong reference. In MRC, you would retain such a variable when set and then release the previous object. If you did not, then you could still access it after it were deallocated (dangling pointer).
Because it is a strong reference, your object will remain valid until a) the strong reference by the global variable is given up and b) the autorelease pool is drained c) and of course any other strong references are given up.
So if you are using strong references for that global and you never reassign it (logically, giving up the global's strong reference), then your object would never be dealloc'ed.
When you use unsafe nonretained semantics (by decoration in ARC, or the default for a static in MRC), the object would be -dealloced when the current autorelease pool is drained and all strong references are removed. This is easiest to illustrate with a program (MRC);
static MONObject * GlobalObject;
//
// In MRC, you must add the reference counting to ensure you do not end up with a dangling
// pointer, so false is what how your program should be written in MRC.
//
// In ARC, your program will look like NonRetainedOwnership because it treats the global
// as a strong reference.
static const bool NonRetainedOwnership = ...T/F...;
...
// assume GlobalObject is accessed from one thread only -- i won't bother with
// the supporting code to illustrate how this should be made thread safe.
- (MONObject *)sharedObject
{
if (nil == GlobalObject) {
if (NonRetainedOwnership) {
// don't do this! lifetime will be determined by strong client references
// and the reference you rely on now will be lost when the thread's current
// autorelease pool is drained -- leaving you with a dangling pointer which
// will cause issues when -sharedObject is called again.
GlobalObject = [[MONObject new] autorelease];
}
else {
// Good - keep a strong reference:
GlobalObject = [MONObject new];
}
}
return GlobalObject;
}
- (void)disposeSharedObject
{
if (NonRetainedOwnership) {
GlobalObject = nil;
}
else {
// remove our reference, which was established at [MONObject new]
// assuming there are no strong external references, the object
// will be dealloc'ed -- but you should not make that assumption
// if you return it.
[GlobalObject release], GlobalObject = nil;
}
}
So if NonRetainedOwnership is true and you use MRC, then your object would typically be -dealloc-ed shortly after -sharedObject returns (assuming whoever called -sharedObject holds no strong reference). In this case, 'shortly' means the pool will often be drained a few frames back in your current callstack, often in AppKit or UIKit when you are on the main thread since I don't see many people explicitly create autorelease pools on the main thread. borrrden said after "1/60th of a second", and the assumption there is that the object is created and autoreleased in the main thread's run loop (correct me if I am wrong). The 'Kits create autorelease pools at each iteration of the main run loop, but your program could be running on a secondary thread or there could be an inner autorelease pool, so the lifetime has the possibility to be shorter or longer. Normally, you don't need to think about these things in much depth -- just use a strong reference here since you really have no other way to ensure the right thing happens with this global variable.
If you simply wrote: #autoreleasepool{[[MONObject new] autorelease];} NSLog("Hi"); then the object would (under normal circumstances) be released by the time NSLog were called.
The declaration of variable doesn't matter as such, The thing what matters is when did you assigned an autoreleased object to it, If it is assigned under any autorelease pool than it would drain it else it would be released on program termination by autorelease pool in main method!
The Variable is just a pointer and does not retain the object unless done explicitly, thats why retaining static objects is preferred: Why retain a static variable?
When the pool is 'drained'. This may not happen right away.
Please see a similar question
It depends. If the variable is initialized only once, and should stay around for the lifetime of the application, then no, it shouldn't be released (its memory will essentially be freed when the application exits, anyway). If, however, the value of the static variable changes, then yes, the previous object should be released when the static variable is set to a new object.