Class retain counts - ios

Plenty is posted here about avoiding retain cycles with blocks, but what about when using classes and class methods? Say I have a class like this:
// MyClass.h
+ (void)doSomethingAsynch:(void (^)(void))block;
+ (void)doSomethingElse;
and callers would like to say this:
[MyClass doSomethingAsynch:^{
[MyClass doSomethingElse];
}
Must the caller declare an unsafe_unretained copy of MyClass? Or is a class like a singleton, which won't increase it's retain count? Does it matter if we send a class's retain count to the moon since we want it to exist all the time anyway?

[[NSObject class] retainCount] returns NSUIntegerMax, so, yes, classes are implemented as singletons and probably override release as a no-op.
Addendum:
In the objc runtime implementation of NSObject at line 1659 you find ...
+ (id)retain {
return (id)self;
}
... which verifies that [NSObject retain] does nothing.

As you suggest, classes are never going to be deallocated by the system, so it hardly matters if you retain them repeatedly and never release them. My guess would be that retain on a class does nothing.

You are exposing those methods as static/class methods (the '+' at the front instead of a '-' for instance methods), so of course you never need to do [[MyClass alloc] init] for this particular class if you only want to use those methods. Since you're not using alloc, you don't have to worry about retain or release.
These days with ARC (Auto Reference Counting) you mostly don't have to worry about retain and release anyway, it adds all that at compile time for you.
EDIT: stressed mostly, as there are times when you still need worry about it, also added some clarity

Related

Can an object be deallocated during method execution?

Let's assume that we create an instance of class var foo: Foo? = Foo() on the main thread and we call some time consuming instance method bar of Foo on another thread, after a short time we set foo to nil on main thread. What happens with the execution of bar, in my understanding bar should still continue its execution since invoking instance method implicitly passes self as the first argument, so even those the last explicit ref to foo was broken we still have a ref inside of a method and it should be good. But then I found this stackoverflow post which completely breaks my understanding. So, can somebody confirm/deny the fact that object cannot be deallocated during its method execution
Short answer is that your belief is correct, and you're looking at a question that's not relevant to Swift.
Your link is to non-ARC Objective-C. Swift always uses ARC, and ARC is very conservative about retains. Consider the following Objective-C call:
[target runMethod: parameter];
Under ARC, this is (conceptually) transformed into:
[target retain];
[parameter retain];
[target runMethod: parameter];
[parameter release];
[target release];
retain and release are atomic, thread-safe calls.
A similar behavior exists in Swift. Because of this, as a general rule (in the absence of Unsafe), a variable cannot "disappear" while you'll holding onto it.
This is the implementation detail. The better way to think about it is that by default variables and parameters are strong, and an object cannot be destroyed while there is a strong reference. This matches your understanding.
Prior to ARC, though, you needed to insert extra retains and releases yourself to protect against this kind of situation, and it was very common not to. (Prior to 10.6, most ObjC was single-threaded.)
Even without threads, there are ways this can go astray without ARC. Since callers often didn't immediately retain returned values if they only needed them temporarily, it was possible to get dangling pointers even without multiple threads. For example, with a trivial accessor with no memory management, this can crash:
NSString *name = [person name];
[person release];
[self doSomethingWithName: name];
This is why you often see old ObjC getters written in the form:
- (NSString*) title {
return [[title retain] autorelease];
}
This made sure that the returned value would survive until the end of the event loop even if self released it or self was deallocated.
Swift does similar things via ARC, but as the name suggests, it's all automatic.

Basic memory-management in objective-c (ios)

I am pretty new to Objective-C and iOS-development, and I am currently trying to grasp how to do memory-management. My app in non-ARC btw.
This object is not declared anywhere in the code (not .h or anything) other than the line belove. Do I need to release/dealloc this object in any way to clear the space for it when I am done using it, or is this done automatically?
NSMutableURLRequest *restRequest = [[NSMutableURLRequest alloc] init];
The same goes for this one. Not sure if this is the same question, but here I don't use the words alloc & init before using it. Does that make any difference?
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
In this case, I am defining the object in the .h-file as well as retaining it. Does this mean that the variable will always be in memory (when initialized once obsly) unless I release/dealloc it? I guess if that is the case, that is something I should do in views when the view is unloaded?
#interface Storeage : NSObject {
NSString *deviceToken;
}
#property (nonatomic, retain) NSString *deviceToken;
In the .m-file I will alloc and use this object like in the first or second case (does not seems to make any difference).
Please bear with me if this question is stupid. I am used to low level Java-programming with GC.
Do I need to release/dealloc this object in any way to clear the space for it when I am done using it, or is this done automatically?
Since you are not using ARC, you need to manually send it a release message in order to dispose of its ownership. (Good piece of advice: don't think in terms of "freeing memory". Reference counting means that you increase and decrease reference counts, you get to own and cease to own objects, the deallocation of an object upon having lost all its references is done automatically. In other words, release does not necessarily mean deallocation.)
The same goes for this one. Not sure if this is the same question, but here I don't use the words alloc & init before using it. Does that make any difference?
It does. You only own objects that you create using alloc, new, copy, mutableCopy or reference using retain. You do neither one here, so you don't have to worry about releasing it either. (Technically, it's an autoreleased instance that will be returned, the run loop will take care of it.)
In the .m-file I will alloc and use this object like in the first or second case (does not seems to make any difference).
Make the difference between instance variables and properties. A property setter method, if declared as retain or strong, will retain (increase the reference count of) your object. But that's true only if you use the accessor method, and not when you access the instance variable directly. If you wrote this:
variable = [[SomeObject alloc] init];
then you need to release it just like you would do with any other (local) variable:
[variable release];
If you use the accessor method to set it:
self.variable = [[[SomeObject alloc] init] autorelease];
then you have to use autorelease when creating it (else it will have a reference count of 2 and you'll leak memory).
In both cases, you can also use self.variable = nil; to relinquish ownership. This only works for properties.
All this radically changes with the introduction of ARC, which I don't explain here for three reasons:
I'm not an ARC expert by any means;
I'd like to encourage you to learn MRC (which you seem to have the intention to) perfectly before trying ARC;
It was not the question.

Proper retention of object using NSObject load method

I'm not quite sure where I'm going wrong with this implementation and what adjustment I need to make so that the loaded singleton stays in memory.
#implementation ApplicationSettings
static ApplicationSettings *sharedSettings = nil;
+ (void)load
{
#autoreleasepool {
sharedSettings = [self sharedSettings];
[self configureInitialSettings];
}
}
+ (ApplicationSettings*) sharedSettings {
if (sharedSettings)
return sharedSettings;
else {
return [[[ApplicationSettings alloc] init] autorelease];
}
}
- (void) dealloc {
[super dealloc];
}
The main methods for loading are shown here, along with the dealloc (I'm not using ARC).
I have started using this pattern recently. I'm going to have to check each implementation to make sure it's right. I found one case where it is being deallocated and causing a crash. Obviously the #autoreleasepool owns it. Should I remove the autorelease in the return statement so it doesn't go into the autorelease pool? If I do that, then it's retained until the program is killed, which is fine with me. Is there anything wrong with that?
That's not the correct way to declare a singleton class. (And as a result, your +load method and object retention does not fit with your usage here, and the reason of your crash)
Loading the singleton instance in the +load method is useless, as it is best to allocate the instance only when needed, that is when it is first requested (lazy loading)
But more important, returning an autoreleased instance in the sharedSettings method make the singleton pattern invalid and fail its purpose, as you return an instance that will be released as soon as the autorelease pool will be drained (that is at the end of the current RunLoop iteration -- if not sooner if you have any inner #autoreleasepool used). That's very likely to be the cause of your crash!
The implementation of dealloc is useless, first because it only call its super implementation (so you can avoid the whole method definition), and because as your class is meant to be a singleton, the instance will never be released from memory while your app is alive.
And last but not least, your implementation is not thread-safe at all.
Of course, normally you need to balance alloc and init calls with release or autorelease calls. That's the main rule of memory management. But for the Singleton Pattern, as per definition the shared instance of a singleton lives as long as the application live (that's is main role), this is the exception to the rule, and you should not release your sharedInstance that holds your singleton object, to make sure it keeps living and is not deallocated from memory.
One correct (legacy) implementation for a singleton without ARC would be to overload the alloc/retain/release/autorelease/retainCount methods, as explained in the Apple documentation about singleton. But in fact that's not really the way we do it anymore these days, as this documentation is quite old (was written before GCD existed) and obsolete, and as GCD now offers a way better alternative, that is guarantied to be thread-safe, and is compatible with both non-ARC and ARC too (whereas the latter is not possible to implement under ARC environment). So here it goes:
#implementation ApplicationSettings
+(ApplicationSettings*)sharedInstance
{
static ApplicationSettings* sharedInstance = nil;
static dispatch_once_t once;
dispatch_once(&once, ^{ sharedInstance = [[self alloc] init]; });
return sharedInstance;
}
#end
And that's all. No need for a global variable outside of the method or whatsoever. Simply declare this method and use it every time you need access to the singleton and you're done.
And if you need to fill some instance variables of your singleton then, like what you probably do in your configureInitialSettings method, simply do it in the init method of your singleton, as you would do in a standard class as usual.
Additional Note: If you want to be really strict, some may argue that it will not forbid the allocation/creation of other instances of the class using alloc/init (and neither do your own implementation in your question) so that is not a real singleton: one can still allocate multiple instances of it if s/he really wants to.
But in practice even if that's true, I don't see any reason why to really add these constraints (and if you switch to ARC one day, you can't add these constraints anyway). What you really want when you seek for the Singleton Pattern is more "a common instance shared accross the whole application" than "a way to forbid the creation of multiple instances", and that's what we have here. And actually that's the case for most of the classes that claim to be Singletons (like NSFileManager for example).

Releasing Singletons

I was wondering how you would release a singleton
+ (DSActivityView *)activityViewForView:(UIView *)addToView withLabel:(NSString *)labelText width:(NSUInteger)labelWidth;
{
// Not autoreleased, as it is basically a singleton:
return [[self alloc] initForView:addToView withLabel:labelText width:labelWidth];
}
When analysing this using the analyse tool i get the following error :
Potential leak of object on line 90. which is the line that returns.
I have tried autorelease that solves the error message problem but im not convinced its the right solution since i read that autoreleasing singletons is not good. Would someone be able to assist me in identifying how best to release this object?
Thanks
The reason why the analyzer gives you the warning is, basically, the method name:
+ (DSActivityView *)activityViewForView:(UIView *)addToView withLabel:(NSString *)labelText width:(NSUInteger)labelWidth;
according to Objective-C conventions, all method names starting with "create"/"new"/... return a retained object; your method falls under the category of convenience constructors, which are expected to return autoreleased objects, hence the warning.
On the other hand, you say this is a singleton, but in fact it is not. So, you could possibly end up calling this method more than once and thus have an actual leak. A basic way to make your method safer (and more singleton-like) is:
+ (DSActivityView *)activityViewForView:(UIView *)addToView withLabel:(NSString *)labelText width:(NSUInteger)labelWidth;
{
static DSActivityView* gDSActivityViewSingleton = nil;
if (!gDSActivityViewSingleton)
gDSActivityViewSingleton = [[self alloc] initForView:addToView withLabel:labelText width:labelWidth];
return gDSActivityViewSingleton;
}
This would both make the analyzer relax and give you more safety in front of the possibility of misuse of the method.
Use autorelease. There's no reason not to. Basically ownership of the object belongs to the object, so you're never going to be able to manually release it. As its a singleton it doesn't matter if you don't own it because presumably next time you call it and need it in scope you'll use another convenience method and it will get instantiated again.
If you want to have ownership of the object then you will need to instantiate it as normal and then you will be able to retain and release it.
Also, read sergio's edit about it not being a "proper" singleton. :p
Also, if you can, convert to ARC and you won't have to worry about this!
U are doing it wrong. Consider:
If you calling activityViewForView multiple times, you won't get get the same object over and over again. It only would initialize a new object and give you the pointer to it!!!
To make this thing a singleton, you have to store the created object in a constant variable and make sure, you have a reference to this object all the time your app is running (for instance declare your pointer to this object in appDelegate).
Then every time you call activityViewForView you have to check the constant variable if it is pointing to a valid object. If so, return the valid object, if not, create it and store it in your constant static variable (creation is done only once).
If you do use ARC you're all set. If not, release your object (use dealloc method)

Delegates - retain or assign - release?

I've seen a number of posts related to delegates, and I would like to know the proper way to reference them. Suppose I have an object declared like:
#interface MyViewController : UITableViewController {
id delegate;
}
#property (nonatomic, retain) id delegate;
#end
Through the lifecycle of MyViewController, it will make calls to methods of its delegate in response to interaction with the user.
When it's time to get rid of an instance of MyViewController, does the delegate ivar need to be release'ed in the implementation's dealloc method since it is declared with retain?
Or conversely, should delegate even be retained? Perhaps it should be #property (nonatomic, assign) id delegate? According to Apple's docs:
retain ... You typically use this attribute for scalar types such as NSInteger and CGRect, or (in a reference-counted environment) for objects you don’t own such as delegates.
Normally I'd just go with what the docs say, but I've seen a lot of code that calls retain on a delegate. Is this just "bad code?" I defer to the experts here... What is the proper way to handle this?
You generally want to assign delegates rather than retain them, in order to avoid circular retain counts where object A retains object B and object B retains object A. (You might see this referred to as keeping a "weak reference" to the delegate.) For example, consider the following common pattern:
-(void)someMethod {
self.utilityObject = [[[Bar alloc] init] autorelease];
self.utilityObject.delegate = self;
[self.utilityObject doSomeWork];
}
if the utilityObject and delegate properties are both declared using retain, then self now retains self.utilityObject and self.utilityObject retains self.
See Why are Objective-C delegates usually given the property assign instead of retain? for more on this.
If you assign the delegate rather than retaining it then you don't need to worry about releasing it in dealloc.
It is usually indicative of bad design, since most delegates retain their objects (creating the potential for retain loops and thus leaks.) But there are some cases where an object should retain its delegate. These are usually cases where no reference is available to the object, so the delegate cannot be the one to retain it--but that itself can sometimes indicate bad design.
I've heard a lot of opinions on this as well. I don't know the Right Way, but I can tell you what I've arrived at through my own work.
You want to retain anything that you need to preserve your handle on. That's all ownership is, in a reference-counted environment. It's a declaration that "I'll need this later, don't let it go away on me".
That ALSO means you're responsible for releasing your claim on it. If you don't specifically do that, you're prone to various problems, but especially dealing with delegates which might well retain the object they're a delegate of. If you don't deal with your retention of the delegate, the ownership will be cyclical and the objects will leak. But don't forget to release what you retain, and you'll be okay.

Resources