Question

I'm trying to better understand Strong References, but in the context of a particular example that I will list below.

Lets say that I have a global variable called gPrefs. It's of type Preference Class, a custom class I made.

I've declared in its interface the following...

@property (strong) NSURL            *masterFolder;

This is a pointer to a NSURL Object. I have given it (strong) reference meaning it will stick around and not release it's memory.

Now lets say I have an instance function somewhere else entirely that looks like the following below.

- (IBAction)masterDataSelectButtonAction:(id)sender
{
    NSOpenPanel *openPanel = [NSOpenPanel openPanel];//creates an open panel.
    [openPanel setCanChooseDirectories:YES];
    [openPanel setCanChooseFiles:NO];

    NSInteger panelResult = [openPanel runModal];

    if(panelResult == NSFileHandlingPanelCancelButton){
        NSLog(@"masterDataSelectButtonAction -> Cancel Button Pressed");
        return;
    }

    if(panelResult == NSFileHandlingPanelOKButton){
        NSLog(@"masterDataSelectButtonAction-> Ok Button Pressed");
        NSURL *theUrl = [openPanel URL];
        gPrefs.masterFolder = theUrl; //Setting (strong ref) point to local.
        [_masterDataLabel setStringValue:[gPrefs.masterFolder absoluteString]];
    }
}

If the person pressed the OK button of the panel, I create a local pointer instance variable called theUrl. I then set the global variables masterFolder pointer to the local instance variables pointer.

If I understand correctly ARC is supposed to release objects at the end of functions when it deems it's not being used anymore.

Therefore theUrl should be released at the end of the function.

However, if I understand (strong) reference, the compiler perhaps is smart enough to realize that since I changed the global preferences pointer to a different pointer it will keep the other pointers reference in memory alive (or retain it).

If I had not declared my masterFolder pointer as (strong) would the masterFolder pointer be nil after the function ended?

My experiments show that keeping it (strong) seems to retain the value from the localInstance pointer despite reaching the end of the local instance function.

My question is why? Even if masterFolder is a strong reference, if I assigned it to a localInstance pointer and that pointer is removed at the end of the Instance function, why did the value of masterFolder not NIL out when I read from it again outside the instance function anywhere else.

My understanding of (strong) references is a bit (weak). No pun intended.

Was it helpful?

Solution

NSURL *theUrl = [openPanel URL];

theURL is in the scope of the function (or within the if block, but that doesn't make a difference in this example). The object that theURL is pointing to is on the heap. At the end of the function, when theURL goes out of scope, the reference count of the object on the heap will be decreased by 1 (because theURL is a strong reference to the object. If at that point the reference count goes to 0, the object is released. In your case there is at least one other strong reference to the object (in your global singleton) so the object stays alive. The object on the heap is not local to anything, therefor the memory does not go out of scope.

If you global singleton has a weak reference it will automatically be set to nil once the object's reference count reaches 0 and the object is released.

OTHER TIPS

So strong is really just retain. When you call gPrefs.masterFolder = theUrl; what you're doing is you're setting the pointer masterFolder to be the same as theUrl and for retain to be called on masterFolder. So, when theUrl was created, it had a retain count of 1; with the setting to the strong property of masterFolder, theUrl had retain called on it which increased it's retain count to 2. This is why it doesn't disappear as after the instance method is done and the initial autorelease of theUrl takes place, theUrl still has a retain count of 1 due to it being set to the strong property.

Now if you set the property to weak, you would get the behavior of masterFolder being nil and theUrl being properly destroyed once the autorelease for it takes place as weak simply sets masterFolder to be the same as theUrl but does not call retain on it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top