Memory management semantics of Objective C "new" - objective-c

Is "new" an equivalent of "alloc init" or "alloc init autorelease"?
I cannot seem to find it in any tutorial or article that deals with Cocoa memory management.
Thanks for advise.

How about this one. Read them, understand them, they're simple.

new returns an object with a retain count of 1, just like [[alloc] init]. The object is not autoreleased.

+[NSObject new] is functionally equivalent to +[NSObject alloc] followed by -[NSObject init] (i.e. [[alloc] init]).
To answer your question, from the NSObject class docs:
If you are using managed memory (not
garbage collection), this method
retains the object before returning
it. The returned object is not
autoreleased. The invoker of this
method is responsible for releasing
the returned object, using either
release or autorelease.
Using new is rare in modern Cocoa code. Most Cocoa developers favor explicit, clear code over saving a couple of key strokes. Thus alloc/init is preferred.

Related

Need to release twice?

I can't seem to find the answer anywhere. I'm using Manual Memory Management in Objective-C developing for iOS.
I wrote a convenience function for getting UIColor from a hex string. In it, it returns
[[UIColor alloc] initWithRed:... alpha:alpha]
Apparently on certain platforms (we have a few devices, ranging iOS 8-9) the object would be destroyed on exiting the function, so that its returned UIColor* cannot be used. So now, we changed it to
[[[UIColor alloc] initWithRed:... alpha:alpha] retain]
My question is when I'm done using this object, do I have to release it twice? Once for the alloc, once for the retain? It seems very strange to me, and I can't find this online anywhere.
If I don't retain, it gets dealloc'd on exiting the function (on some platforms) making the function useless. If I do retain, I need to release twice when done?
EDIT:
https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html
"..., it is normally guaranteed to remain valid within the method or function it was received in. If you want it to remain valid beyond that scope, you should retain or copy it. "
So I'm not doing anything out of the ordinary. The docs say I "should retain it" if "I want it to remain valid beyond" the scope of a function. I will try what #FreeNickname suggested. That makes the most sense.
You said:
I wrote a convenience function for getting UIColor from a hex string. In it, it returns
[[UIColor alloc] initWithRed:... alpha:alpha]
According to the Basic Memory Management Rules, the proper memory management is dictated by the name of your method:
if your method name does not start with “alloc”, “new”, “copy”, or “mutableCopy”, then you should return an autorelease object:
- (UIColor *)colorWithHexString:(NSString *)hexString {
...
return [[[UIColor alloc] initWithRed:... alpha:alpha] autorelease];
}
if your method name does start with “alloc”, “new”, “copy”, or “mutableCopy”, then you can return an object like you have above:
- (UIColor *)newColorWithHexString:(NSString *)hexString {
...
return [[UIColor alloc] initWithRed:... alpha:alpha];
}
Note, this pattern is less common than the above convention of colorWithHexString.
(Note, this memory management dictated by the method name prefix was historically merely best practice, but now, for interoperability with ARC code, it's critical. Always follow the above rules in manual reference counting code.)
Now, if the code that is calling your convenience initializer is allowing the object to be deallocated, the problem rests with that code, not your convenience initializer. Do not start adding extra retain statements to your initializer because something that calls it doesn't manage its memory properly.
Instead, make sure that the calling code does the proper retain (and eventual release) of the result of colorWithHexString, itself.
By the way, Xcode's static analyzer (shift+command+B) is remarkably good at analyzing manual reference counting code and identifying the issues.
In an edit to your question, you quoted the documentation:
If you receive an object from elsewhere in your program, it is normally guaranteed to remain valid within the method or function it was received in. If you want it to remain valid beyond that scope, you should retain or copy it. If you try to release an object that has already been deallocated, your program crashes.
This is not saying that your convenience initializer should issue a retain or copy. It is saying that the code that calls colorWithHexString is responsible for establishing its own claim of ownership of the UIColor object that was returned via retain or copy, as discussed above.
I think you are looking for the concept of autorelease which is used in situations like yours. It is essentially a way to send a deferred release message to the newly created object so the caller has the chance to retain it if necessary, otherwise it is destroyed when the autoreleasepool is processed.
You "misunderstood" Apple's documentation, because it is simply wrong for this topic. You really should read clang's documentation about ARC instead of Apple's, because clang's ARC documentation explains MRC correctly to interact with it.
Let's have a closer look on it:
You own any object you create by allocating memory for it or copying it.
Related methods: alloc, allocWithZone:, copy, copyWithZone:, mutableCopy, mutableCopyWithZone:
…
Conversely, if you are not the creator of an object and have not expressed an ownership interest, you must not release it.
…
If you receive an object from elsewhere in your program, it is normally guaranteed to remain valid within the method or function it was received in.
Taking this documentation for serious, you are not an owner of the object:
[[UIColor alloc] initWithRed:... alpha:alpha]
This is, because you do not receive the object reference from +alloc et al., but from -init…. Following Apple's documentation you are not an owner and have to retain it. (So it is "elsewhere".)
In clang's documentation it is described differently and correctly:
Methods in the init family implicitly consume their self parameter and return a retained object. (5.2.1)
Therefore there is a special method family for -init… along with the others mentioned in Apple's documentation as correctly described in clang's documentation:
The families and their added restrictions are:
alloc methods must return a retainable object pointer type. [Apple: alloc, allocWithZone:)
copy methods must return a retainable object pointer type. [Apple: copy, copyWithZone:)
mutableCopy methods must return a retainable object pointer type.(Apple: mutableCopy, mutableCopyWithZone:)
new methods must return a retainable object pointer type. (Apple: Ooops, I forgot something)
init methods must be instance methods and must return an Objective-C pointer type. … (Apple: Oooops, I forgot something)
(5.)
So, what you get from -init is already retained, you have the ownership and there is definitely no reason to retain it.
According to Rob's answer there might be a reason to autorelease it.

Why is alloc needed in Objective-C object initialization?

I have been going over some tutorials in Objective-C and I am confused when it comes to the command alloc() and how it is used to initialize an object.
The tutorial says to do the following and I am having trouble figuring out why it is necessary.
Change
NSDate *now = [NSDate date];
to
NSDate *now = [[NSDate alloc] init];
Why is this change necessary since the first line works just fine? I guess I am looking for how the two lines differ. Thanks!
There's a simple difference and a deeper one.
The simple answer is that the first method includes an +alloc/-init pair internally—the documentation tells us that it returns a new date object initialized to the current time. Generally, somewhere, somebody has to call +alloc and an -init method of some sort. Sometimes that's you, sometimes a convenience method has been included for you.
The deeper answer about the difference is that +alloc/-init returns an object that is owned by the caller, who is then responsible for calling -release at some point, while convenience constructors that don't start with the words "alloc" or "new" return autoreleased objects that you don't have to release. However, if you are using ARC, this is mostly academic, as the compiler tracks that detail for you.
Break it down:
NSDate is a class. So NSDate alloc is a call to the class method alloc. That's actually inherited from NSObject and acts to create sufficient storage for a new instance of NSDate, then return it for use as an instance.
(instance) init is a call to the instance method init. Prior to calling init the instance you've received is not guaranteed to be in a valid state. Calling init or the relevant initialiser gives the instance the chance to establish itself.
NSDate also choses to supply the class method date. That does the same thing as [[[NSDate alloc] init] autorelease] and is provided as a mere shorthand.
As other posters have commented, there is a semantic difference here — alloc returns an owning reference. So it's the caller's responsibility to release the object later. date returns a non-owning reference. So the caller has no responsibilities. However the modern ARC compiler will deal with releasing things for you. So there's a difference but not one that has any real effect on you.
If your tutorial insists that date is more proper then either it was written before the ARC compiler or was written by someone that prefers to use the old conventions; using date would traditionally communicate that the thing you were creating was for transient use so there is arguably some extra value in the one way versus the other for an experienced developer.
With ARC it doesn't matter as you no longer have to release objects you alloc init.
Without ARC the difference in important:
[NSDate date]
returns an autoreleased object using a class method on NSDate.
[[NSDate alloc] init]
returns a non autoreleased object instance, with a retain count of one.
As in non- ARC, you need to take memory management in your own hands, So, alloc init is better option. So, that you can release it, once not required.
One further point to note, is that autoreleased objects are released when the autorelease pool is.
When you alloc init you know that your object will stay around until you release it (or you leak it because it goes out of scope).
The change is not necessary at all. It doesn't matter if you create object using alloc+init or using convenience methods. Think about them as legacy and convenience methods.

__bridge_transfer and performSelector:withObject:

I have a CFDictionaryRef that doesn't retain/release its objects. When I add an item in it, I take care of retaining it, and later :
NSMutableArray *array = (__bridge_transfer NSMutableArray *)CFDictionaryGetValue(...)
[self performSelector:someSelector withObject:array];
Where someSelector is a variable holding a selector I know about. Now, that second line makes Xcode tell the notorious warning:
PerformSelector may cause a leak because its selector is unknown
Does that mean I should worry about ARC not knowing how to manage memory for the array variable of which I just transferred ownership?
From a comment to the accepted answer of this question, it appears that somebody at Apple has confirmed this hypothesis (citing the answer itself):
In fact, there are times when memory management is tied to the name of the method by a specific convention. Specifically, I am thinking of convenience constructors versus make methods; the former return by convention an autoreleased object; the latter a retained object. The convention is based on the names of the selector, so if the compiler does not know the selector, then it cannot enforce the proper memory management rule.
Thus, it has nothing to do with a possible leak of arguments passed to the performSelector: call, but rather to its returned value, for which Objective-C has no way of knowing if it was autoreleased or not. This is also what Martin R from the comments was assuming.

difference between – initWithRequest:delegate: and +connectionWithRequest:delegate

I want to know the difference between –initWithRequest:delegate: and +connectionWithRequest:delegate: of NSURLConnection?
Just the first one is no-aotorelease object and second is autorelease?
I want to know which one should I use in my ios code?
You've already pointed out the difference
For iOS codes, it's best to use use Alloc/init rather than convenience auto release functions because they stay around after you are done using them and there is no way for you to release them
Use autorelease when it's not possible to know when to call release (such as when you are returning a object that is not being retained elsewhere) The closest autorelease pool will free the memory the next time the pool is drained.
If you do use alloc/init, remember to call release, otherwise it will linger on in the memory
All methods in Objective-C that starts with init require to be called only after alloc method. Also init-method returns non-autoreleased object.
All methods that starts from name similar to class name, for example, [NSString string], [NSArray array] and others returns autoreleased objects and don't require precalled alloc method.
Returning to you question: you can use any of that approaches: alloc + initWithRequest:delegate: or connectionWithRequest:delegate: but be sure to release object in first case.
I think you pointed out the only difference.
I use the +connectionWithRequest:delegate: method
I think something internal is retaining the connection until it fails or finishes

Objective-C, ownership and class methods

First off, I'm a Objective-C newbie. :)
I've learned that anything that starts with alloc, new, and copy, gives the caller ownership of the returned object. Does this also apply to class methods? I'm guessing it does, and a recent crash in one of my unit tests seems to confirm it. Apple's Advanced Memory Management Programming Guide doesn't say anything whether there's a difference between class and instance methods.
Update
What I mean that it also applies to class methods is really the "inverse". For instance, NSDecimalNumber has a class method called +decimalNumberWithDecimal:. It seems to return an auto released object (if I release it explicitly, a crash occurs shortly after that). In hindsight, the answer to my question is obvious, as Apple's guide refers to new and alloc as ownership-giving methods, and they're all class methods. Sorry for taking up your valuable time. :)
Also alloc and release. init does not indicate ownership, you are likely mixing that up with alloc. You can memorise it easily with the mnemonic NARC.
If you are naming any class methods init, copy or retain, you should stop that. Those are methods that only make sense in the context of instances. alloc and new are class methods and should only be used in that context. Don't name instance methods alloc or new.
The reason why the guide doesn't say that it applies to both instance methods and class methods is that the methods in question are clearly a mixture of both, so it's obviously the case.
Yes this applies to class methods since alloc and new are class methods which return ownership to the caller. The prefix of copy or mutableCopy should be used for instance methods returning ownership.
Edit For The Update:
You are correct a method like +decimalNumberWithDecimal: is expected to return an autoreleased object, therefore there is no reason to release it. If however they decided to name the method +newNumberWithDecimal: then you would have ownership of the returned object and need to release it. Clang static analyzer will actually complain if you prefix a method with new and return an autoreleased object.
Actually, this is almost correct. alloc, new, and copy give you ownership of the returned object. These are class methods. Other class methods should return an autoreleased object. Instance methods should also return an autoreleased object.
init does not effect ownership and should be use in conjunction with alloc as follows.
[[SomeCoolClass alloc] init]
new is usually the same thing as the above and is sometimes described as "almost deprecated" because it is a throwback to the NeXT days when the allocation and initialization were done in the same step and could not be plot apart as we do today with alloc and init.
Release does not effect ownership, but should only be used on object you already own. Otherwise a crash is likely to occur.
Retain also does not affect ownership, but should only be used on an object you already own. Otherwise the object may not be deallocated when it should be. The result could be a crash, but it can also be very very strange behavior that is difficult to troubleshoot because messages may be sent to the original object that was supposed to have been deallocated instead of a new object pointed to at the same address.