Kunal Shrivastava
Kunal Shrivastava

Reputation: 612

How is a property related to "self" and vice-versa?

My question is two-part:

First, Say I have a class:

MyClass.h

@interface MyClass: NSObject

-(id)initWithName:(NSString*)name;

@property(nonatomic, strong) NSString *name;

@end

MyClass.m

@implementation MyClass

-(id)initWithName:(NSString*)name
{
    if (self = [super init])
    {
        self.name = name;
    }
    return self;
}

@end

My question: I know that self will hold the name property strongly. But how will the name property relate to self? What I mean is that I can access name as self.name but while class instantiation, how is the children of self (which in this case is name) related to self? I am imagining the structure of the class as a tree, with the parent holding strong reference to the children and the children holding a weak reference to the parent. I want to know if I am thinking about it correctly or not. My guess is it will be a weak relationship.

Second, if I add a method which has a block that references the name property. So my updated implementation of MyClass.m is:

MyClass.m

@implementation MyClass

-(id)initWithName:(NSString*)name
{
    if (self = [super init])
    {
        self.name = name;
    }
    return self;
}

-(void)doSomeStuff
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        self.name = @"Name changed inside block";
}];
}

@end

My second question is: I am not referencing self directly inside my block. So, I guess there is no retain cycle here. But I am referencing name property which is held by self. So does this create a retain cycle?

Upvotes: 1

Views: 74

Answers (5)

Amin Negm-Awad
Amin Negm-Awad

Reputation: 16650

My question: I know that self will hold the name property strongly. But how will the name property relate to self? What I mean is that I can access name as self.name but while class instantiation, how is the children of self (which in this case is name) related to self? I am imagining the structure of the class as a tree, with the parent holding strong reference to the children and the children holding a weak reference to the parent. I want to know if I am thinking about it correctly or not. My guess is it will be a weak relationship.

The children can have a reference to the parent and then it should be weak for the reasons you mentioned. But NSString instances does not have such an up-reference. So there cannot be a retain cycle.

In general it is up to you to manage such inverse relationship. (Core Data does it automatically in its default setters,if you insert a inverse relationship.) Nothing is done automatically, no definition of an up-reference, no setting of a up-reference.

My second question is: I am not referencing self directly inside my block. So, I guess there is no retain cycle here. But I am referencing name property which is held by self. So does this create a retain cycle?

You refer self inside the block, because you use it. Period.

But a retain cycle needs two references. As long as self is used inside the block, but the block is not stored in a property of self (directly or indirectly) no retain cycle can occur.

Upvotes: 1

Avi
Avi

Reputation: 7552

But how will the name property relate to self? My guess is it will be a weak relationship.

The name property does not have a reference back to self, so the attributes strong and weak don't apply. An object instance is just a collection of instance variables, gathered into a struct. When we talk about object memory management, we are talking about the memory containing that struct. It doesn't make sense to say that a property (really the instance variable backing the property) has a reference to anything. It is simply one part of what self is.

Upvotes: 1

trojanfoe
trojanfoe

Reputation: 122381

I know that self will hold the name property strongly. But how will the name property relate to self?

Each property will have a backing instance variable, conventionally named the same as the property with a leading underscore and a getter and/or setter method. There is no relationship; the property generally makes the class instance larger (due to additional instance variable) and the class larger (due to additional methods).

I am not referencing self directly inside my block. So, I guess there is no retain cycle here. But I am referencing name property which is held by self. So does this create a retain cycle?

Yes you are referencing self directly, so a retain cycle is possible. However a retain cycle can only happen under certain circumstances, and it's often just safer to avoid this by creating a weak reference to self and using that within the block.

Upvotes: 2

ogres
ogres

Reputation: 3690

1: The MyClass instance has retained the name property, name property itself has no idea what is MyClass and therefore , there is nothing referring from String-name to the MyClass itself.

2: In the following code

-(void)doSomeStuff
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        self.name = @"Name changed inside block";
}];
}

self.name = @"Name changed inside block"; is the same as [self setName:@"Name changed inside block"];

So you are actually retaining MyClass instance inside Block and then executing its method to update the name , ( block needs pointer to this Name to change it , right ? block retains class object which contains this property ) , you are not retaining the property name itself.

Upvotes: 2

Phillip Mills
Phillip Mills

Reputation: 31016

First: The name property holds no relationship to MyClass, weak or otherwise. (That is, if you pass name to some arbitrary method, it doesn't carry any reference to the MyClass instance where it was a property.)

Second: Since you're simply executing the block rather than storing it, I don't see an opportunity for a retain cycle.

Upvotes: 2

Related Questions