I heard from people that you should use self in viewDidUnload. For instance, this is good:
- (void)viewDidUnload
{
self.object = nil;
self.object2 = nil
}
- (void)viewDidUnload
{
object = nil;
object2 = nil;
}
Is there a difference between the 2? And what is it?
There is a difference. The code that is generated by #synthesize will call release on the references to the objects you have before setting the new value. A call to self.object = nil will effectively both release the reference and set it to nil. Without the self it will just set the reference to nil.
What is almost the same as your second example is this:
- (void)viewDidUnload
{
[object release]; object = nil;
[object2 release]; object2 = nil;
}
Note they are not quite the same - if you had defined a custom getter/setter, or had KVC observers set up around one of those properties the self.object = nil would trigger them, whereas the straight [object release] above would not.
First of all, using self eliminates ambiguity.
- (void)viewDidUnload
{
id object = #"whatever";
object = nil; // This refers to the local variable above
self.object = nil; // This refers to the setter of the ivar belonging to the class
}
Another thing to watch out for is if you have the variables synthesized (meaning if you tell the compiler to generate getter & setter automatically), self.object will invoke the getter/setter, while simply object refers to the actual ivar. To prevent this ambiguity when accessing ivar vs calling the setter, you can write something like this:
self->object = nil; // This refers to the ivar object, not the getter/setter
// Or
#synthesize object = _object; // With this, you refer to the ivar as _object
// Then somewhere else
_object = nil; // This refers to the ivar
object = nil; // Compile error, undeclared identifier
self.object = nil; // This refers to the setter
According to Cocoa coding guidelines, we should avoid using underscores in naming variables though. So personally, if I really need to access the ivar directly (for example, when you are overriding the setter), I prefer using ->.
Related
I know the definition of unsafe_unretained.
So i don't expect anyone to write its definition.
I want to know its use with example, and how it works with memory management.
unsafe_unretained only exists in ARC (Automatic Reference Counting). It works like assign in MRC (Manual Reference Counting). These properties won't be retained. Usually, you'd want to use such properties for delegates, because they don't need an owner which retains them.
weak properties are like unsafe_unretained, except that they work a bit smarter. When the object assigned to the property is released, a weak reference automatically becomes nil, to avoid crashes when sending messages to that object (its memory address).
unsafe_unretained properties don't do this. They will always hold on to the memory address (unless you manually change it) assigned to it, regardless of the object associated to that address. Weak references can prevent crashes in such a case, but the result still won't be as expected. If your code is organized and well-written, this shouldn't happen.
So why would you use unsafe_unretained instead of weak? Weak references are only available on iOS 5 and higher, so if you're building an ARC app targeting iOS 4, you need to use unsafe_unretained properties. And again, sending messages to a released property isn't anything you want to have in any code. If your code is well organized then you shouldn't have any problems with this.
Previously to ARC, one might specify a delegate or other reference-to-parent property as assign to prevent retain cycles. With the introduction of ARC and the newer compilers you would instead use unsafe_unretained.
So you use it any time you do not need ownership of the reference, and when you don't need or want to use the new weak reference type (which nulls out the reference when it is deallocated).
Here is a specific use case for unsafe_unretained. Say two classes reference each other, one direction being strong and the other direction weak. During dealloc of the first class the weak reference to it from the second class will already be nil, preventing proper cleanup to take place. Replacing the weak reference with an unsafe_unretained reference will solve this issue. See the code sample below:
#class Foo;
#interface Bar: NSObject
//Replacing weak with unsafe_unretained prevents this property from becoming nil during Foo.dealloc
#property (nonatomic, weak) Foo *foo;
- (id)initWithFoo:(Foo *)foo;
#end
#interface Foo : NSObject
#property (nonatomic, strong) Bar *bar;
- (void)startObserving;
- (void)endObserving;
#end
#implementation Bar
- (id)initWithFoo:(Foo *)foo {
if ((self = [super init])) {
self.foo = foo;
//Start observing
[self.foo startObserving];
}
return self;
}
- (void)dealloc {
//Since foo is a weak property, self.foo may actually be nil at this point! See dealloc of class Foo.
[self.foo endObserving];
}
#end
#implementation Foo
- (id)init {
if ((self = [super init])) {
self.bar = [[Bar alloc] initWithFoo:self];
}
return self;
}
- (void)dealloc {
//This will trigger the deallocation of bar. However, at this point all weak references to self will return nil already!
self.bar = nil;
//endObserving is never called, because Bar.foo reference was already nil.
}
- (void)startObserving {
NSLog(#"Start observing");
}
- (void)endObserving {
NSLog(#"End observing");
}
#end
unsafe_unretained does not interact with memory management at all. In ARC, the following code
{
__strong id obj = someObject;
obj = someOtherObject;
}
is equivalent to
{
id obj = [someObject retain];
[obj release];
obj = [someOtherObject retain];
[obj release];
}
in a non-ARC environment. So strong references keep the object alive. If you assign them a reference to another object, the old reference is first released. The same thing happens if such a reference goes out of scope. Note that references are strong by default, so usually you never have to use __strong unless you want to emphasize that a variable is strong.
A weak reference won't keep the object alive and becomes nil if the retain count of the object last assigned to it becomes zero.
__weak id wobj = nil;
{
__strong id obj = [Object new];
wobj = obj;
// wobj points to the same object as obj
}
// wobj is nil again
Inside the scope obj keeps the object alive and thus wobjc points to the same object as obj. But when obj goes out of scope, the object is released and as that was the only strong reference to it, is deallocated. As a result wobj becomes nil.
An unsafe_unretained retain reference is just a pointer to the object that has no knowledge about Obj-C memory management at all. The code
_unsafe_unretained id wobj = nil;
{
__strong id obj = [Object new];
wobj = obj;
// wobj points to the same object as obj
}
// wobj points to the memory address where an object used to be.
// This object has been deallocated! wobj is a dangling pointer!
// Trying to access the object via wobj may crash the app or cause
// other undefined behavior.
is equivalent to
id wobj = nil;
{
id obj = [Object new];
wobj = obj;
[obj release];
}
in a non-ARC environment. wobj won't be nil but the object it used to point to has already been dealloced and the memory may not even belong to the process anymore or it may have been recycled to store another object or any kind of allocated data (e.g. using malloc()).
Usually you want to use weak for references that don't keep the object alive. A typical situation where this is a problem is if object A has a strong references to object B A->B, and the other way round B->A. That is a retain cycle and now neither object A nor B will ever get released again, because A keeps B alive and B keeps A alive, and that is still true if nobody else has any reference to either A or B, both objects will always have a retain count of at least one. To fix that, one of both must have a weak reference to the other one.
E.g. if you write a XML parser, then XML nodes will have strong references to all their sub-nodes, to keep those alive and accessible but sub-nodes typically have a reference to their parent node and that would then be a weak node. That way you can get back to the parent node from any sub-node but they don't keep the parent alive, so if nobody else does (neither its parent nor any external reference), the parent node dies and the sub-nodes of it die with it.
Usually the only reason to use unsafe_unretained is performance. First of all, every object has a linked list containing all the address pointers of weak variables pointing to this object, so when the object dies, all these variables can be set to nil. Managing that linked list consumes time and the list itself consumes memory. Then every weak reference must temporarily become strong to ensure an object won't be released why you call a method on it. And finally, all of this must happen thread-safe, so it will always involve locking, even if your process is single threaded.
__weak id obj = someObject;
[obj performMethod];
obj = nil;
in fact is complex code behind the scenes and roughly equivalent to
lock(memlockOf(someObject));
id obj = someObject;
addWeakRefToLinkList(someObject, &obj);
unlock(memlockOf(someObject));
lock(memlockOf(obj));
id temp = [obj retain];
unlock(memlockOf(obj));
[temp performMethod];
[temp release];
lock(memlockOf(obj));
removeWeakRefFromLinkList(obj, &obj);
obj = nil;
unlock(memlockOf(obj));
And keep in mind that C pointers cannot be weak, so they are always unsafe_unretained. If you do this
id obj = [Object new];
void * cptr = (__bridge void *)obj;
Then cptr is in fact an unsafe_unretained reference to the object. You can make a C reference "quasi strong" if increase the retain count
id obj = [Object new];
void * cptr = (__bridge_retained void *)obj;
this is equivalent to
id obj = [Object new];
void * cptr = (void *)[obj retain];
in a non-ARC environment. The retain counter is increased by one and thus ARC will never release that object, as even if all ARC references go away, the object has at least a retain counter of one left.
But now the object is never released at all, unless you balance that with transfer bridging:
{
id obj = (__bridge_transfer id)cptr;
// Use obj all you want but don't touch cptr after that!
}
which is equivalent to
{
id obj = (id)cptr;
// Use obj all you want but don't touch cptr after that!
[obj release];
}
in a non-ARC environment. It's important that "transfer" means you are transferring the ownership back to ARC and thus you must not touch the cptr variable after doing so, as now ARC decides when the object dies and it won't set cptr to nil when that happens. Transfer means "make a strong ARC reference out of it but don't do anything with the retain count", so the retain count is not increased but once the strong reference is lost, the retain count is decreased as usual and this balances the extra retain of the retained bridging where the retain count was just increased but nothing else did happen.
i am new in ObjC and iPhone.
I downloaded an example of data sharing between multiple views. The basic approach is to create an data model object in the base UIApplication and get/set data from/to it. So in the init method i saw the following code:
- (id) init;
{
self.theAppDataObject = [[ExampleAppDataObject alloc] init];
[theAppDataObject release];
return [super init];
}
And after that, using delegate we can access this object.
id theDelegate = (id) [UIApplication sharedApplication].delegate;
ExampleAppDataObject* theDataObject;
theDataObject = (ExampleAppDataObject*) theDelegate.theAppDataObject;
So, my question is in the first code example. Why do we need to alloc memory for the theAppDataObject object, and immediately after that - release the object? Why don't we get nil when accessing this object later?
10x
I assume theAppDataObject is declared as #property (retain). Therefore, when setting the object by doing self.theAppDataObject (or [self setTheAppDataObject:]), this property will retain the ExampleAppDataObject. Therefore, you can release it afterwards.
When you alloc and init the ExampleAppDataObject, it's retain count goes up to 1. When you set the AppDataObject to this ExampleAppDataObject, it sends retain to it, so the retain count goes up to 2. You can then release your own ownership of the object; it won't get deallocated because theAppDataObject still has ownership.
If that makes sense.
That depends on how theAppDataObject property is defined.
If it provides a retaining setter-accessor the retain count of the appDataObject will flip to 2, one more than needed here.
So release one of it.
Better and more understandable way would be to write
if ( (self = [super init]) ) {
ExampleAppDataObject *myAppDataObject = [[ExampleAppDataObject alloc] init];
self.theAppDataObject = myAppDataObject;
[myAppDataObject release];
}
return self;
Iphone uses reference count based memory management model..See this tutorial first and then apple's technical documentation... theAppDataObject is a property (see the use of self. theAppDataObject) which should be retained for the above code to work..Any object which is retained should have a bonus plus 1 retain count...An object only gets released when its retain count gets to zero..
first things first: that code sample is terrible.
- (id) init
{
// assign self. super may return another address
self = [super init];
// then check for nil
if (self != nil) {
// then assign the ivar directly because you should
// not invoke methods of partially constructed objects
theAppDataObject = [[ExampleAppDataObject alloc] init];
}
// then return the address super returned
return self;
}
now for your questions:
Why do we need to alloc memory for the theAppDataObject object, and immediately after that - release the object?
self.theAppDataObject calls through the setter, which retains, copies, or assigns theAppDataObject. in this case, we could assume it is highly likely to be retained.
Why don't we get nil when accessing this object later?
release does not set a pointer to nil. it sends a message to the object which then decrements the retain count (in the typical case). what you might have expected in this case is an object which has been deallocated. that does not happen when the argument is retained because the reference count does not reach zero in the program you have shown. the object is still alive because it's been retained and the address of the object stored when the setter (self.theAppDataObject = arg) is called.
- (void)setSomeInstance:(SomeClass *)aSomeInstanceValue
{
if (someInstance == aSomeInstanceValue)
{
return;
}
SomeClass *oldValue = someInstance;
someInstance = [aSomeInstanceValue retain];
[oldValue release];
}
ok, so setter should look like. I understand first 3 lines - prevent before situation when new object is the same as the old one.
But what about this line:
SomeClass *oldValue = someInstance;
Why system have to keep address of old object. Why can't it be simply
[someinstance release];
someinstance = [aSomeInstanceValue retain];
Actually - no reason.
It's usually just a choice.
There are three idioms for writing accessors.
Autorelease:
- (void)setFoo:(id)newFoo {
[foo autorelease];
foo = [newFoo retain];
}
Less code to write, but I think autorelease in this case is being lazy.
Retain then release
- (void)setFoo:(id)newFoo {
[newFoo retain];
[foo release];
foo = newFoo;
}
Check first
- (void)setFoo:(id)newFoo {
if ([foo isEqual:newFoo]) {
return;
}
[foo release];
foo = [newFoo retain];
}
The only difference between the last two is that the second checks to see if the new value is different to the current value before trying to set the property. At the cost of an extra if statement. So - if the new value is likely to be the same as the old value, using this construction gives better performance.
Generally, and if you're not using properties for some strange reason, use retain then release, and then if profiling shows that there's a bottleneck - use the check first method.
I would suggest the default retain setter works something like this:
- (void) setFoo:(id) foo {
if ( foo == _foo) return;
[_foo release];
_foo = [foo retain];
}
if you don't check if the old and the new foo are the same, you might end up with a reference to a deallocated object if you for some reason write something like this:
myObject.foo = myObject.foo;
Because the same object would first be released, and then retained. If the myObject is the sole owner, the object would be deallocated after the first release, leaving you with a dangling pointer.
The default retain setter works like that :
- (void)setFoo:(Foo *)aFood
{
if (_foo != nil)
[_foo release];
if (aFood != nil)
_foo = [aFood retain];
}
I have an object that I alloc/init like normal just to get a instance. Later in my application I want to load state from disk for that object. I figure I could unarchive my class (which conforms to NSCoding) and just swap where my instance points to. To this end I use this code...
NSString* pathForDataFile = [self pathForDataFile];
if([[NSFileManager defaultManager] fileExistsAtPath:pathForDataFile] == YES)
{
NSLog(#"Save file exists");
NSData *data = [[NSMutableData alloc] initWithContentsOfFile:pathForDataFile];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
[data release];
Person *tempPerson = [unarchiver decodeObjectForKey:#"Person"];
[unarchiver finishDecoding];
[unarchiver release];
if (tempPerson)
{
[self release];
self = [tempPerson retain];
}
}
Now when I sprinkled some NSLogs throughout my application I noticed
self.person: <Person: 0x3d01a10> (After I create the object with alloc/init)
self: <Person: 0x3d01a10> (At the start of this method)
tempPerson: <Person: 0x3b1b880> (When I create the tempPerson)
self: <Person: 0x3b1b880> (after i point self to the location of the tempPerson)
self.person: <Person: 0x3d01a10> (After the method back in the main program)
What am I missing?
Don't do this. Besides that it breaks identity rules, you can't change the pointer values other parts of a program hold.
A better approach would be to use the PIMPL idiom: your class holds a pointer to an implementation object and you only swap that.
E.g. something along the lines of this:
#class FooImpl;
#interface Foo {
FooImpl* impl;
}
// ...
- (void)load;
#end
#implementation Foo
- (void)load {
FooImpl* tmp = loadFromDisk();
if (tmp) {
FooImpl* old = impl;
impl = tmp;
[old release];
}
}
#end
self is a function argument to instance methods. Assigning to self is perfectly reasonable, just like assigning values to other function arguments is perfectly reasonable. Since the scope of self is the current function, your code leaks one object and releases another in a way that will most likely cause a crash.
The only time it is meaningful to assign to self is in an init method. Although it is almost never used, init methods are allowed to release self and allocate a new object to return or just return nil. The only reason this works is because the return value is self and callers of init expect to use the return value.
As gf pointed out, the correct approach is a load function that assigns new values to the members of your instance, not that tries to replace the instance.
I've got a problem (in Objective-C/iPhone dev) since more than one week, so I'd be really grateful if someone can help me out.
When I instantiate an object from a class that I've written, it returns me nil, but when I launch the debug mode I actually see in the init method that the attributes of self are correctly initialized and it seems like it doesn't execute the return self instruction.
EDIT:
Thanks for your answers Here is the init code
-(id)initWithDate:(NSString *)aDate
type:(NSString *)aType
amount:(NSString *)anAmount
currency:(NSString *)aCurrency
merchantName:(NSString *)aMerchant
status:(NSString *)aStatus
{
if (!(self = [super init])) return nil;
self->date=aDate;
self->type=aType;
self->amount=anAmount;
self->currency=aCurrency;
self->merchantName=aMerchant;
self->status=aStatus;
return self;
}
Don't use self->instanceVariable.
Just use instanceVariable.
I'd put your code inside the following
if (self = [super init]) {
// Custom initialization
}
return self;
rather than the if (!(self... return nil you have used. But that's just a habit.
I would also avoid the C++ style '->' assignments and instead use self.currency=aCurrency; (or [self setCurrency:aCurrency]; which is closer to the c++ calls I guess) assuming these are declared as #property or have getters and setters.
I'm sure one of those will get you going!
You should write
self.date = aDate;
// etc....
if date etc. is declared as a #property in the #interface, or if it's just a class instance variable, use
date = aDate;
// etc...
Also, if the strings are not declared as #property with retain or copy modifiers, you'll need to manually retain them thus:
date = [aDate retain];