retaining in 2 lines instead of 3?

Discussion in 'Mac Programming' started by bengimizrahi, Jun 1, 2008.

  1. bengimizrahi macrumors newbie

    bengimizrahi

    Joined:
    May 24, 2008
    Location:
    Istanbul
    #1
    Instead of:

    Code:
    UIWindow *localPortraitWindow;
    localPortraitWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.portraitWindow = localPortraitWindow;
    
    can we do the following?:

    Code:
    self.portraitWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [self.portraitWindow release];
    
    In the second one, [UIWindow alloc] increments reference count by 1;
    'self.portraitWindow = ...' increments by 1, too. Finally, [self.portraitWindow release] decrements by 1.

    Am I correct?
     
  2. cmaier macrumors G3

    Joined:
    Jul 25, 2007
    Location:
    California
    #2
    i assume you didn't declare the portraitWindow property as "assign?"
     
  3. therevolution macrumors 6502

    Joined:
    May 12, 2003
    #4
    Let me start of by saying I'm somewhat new to Objective-C, so I don't claim to be an expert. I probably shouldn't be giving out advice yet. ;) Someone please correct me if I'm wrong.

    I'm assuming self.portraitWindow is a property with 'retain' specified. In that case, BOTH #1 and #2 up the reference count when 'self.portraitWindow = ...' is invoked. Not just #2. So if the assumption is correct, then yes, you should call release. But you should be doing it in either case.

    If you're really just out to lower your lines of code count, I propose this:

    Code:
    self.portraitWindow = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    
     
  4. bengimizrahi thread starter macrumors newbie

    bengimizrahi

    Joined:
    May 24, 2008
    Location:
    Istanbul
    #5
    Oh, the property has "retain" attribute, I forgot to mention.

    So, in this case, all examples are correct including your 'autorelease' version. What can be the disadvantage of using 'autorelease' in this example?
     
  5. Nutter macrumors 6502

    Joined:
    Mar 31, 2005
    Location:
    London, England
    #6
    Code:
    UIWindow *localPortraitWindow;
    localPortraitWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.portraitWindow = localPortraitWindow;
    
    This is not correct. You're implicitly retaining the object with the initWithFrame: method, and again with the assignment to the portraitWindow property. This must be balanced with a release or autorelease.

    Code:
    self.portraitWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [self.portraitWindow release];
    
    This is technically correct, but I would consider it bad coding practise to manually release a property in this way. There's nothing wrong with this at all, I just don't like the semantics.

    Code:
    self.portraitWindow = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    
    This is what I'd do in most circumstances. The only downside to this is a slight performance penalty involved in autorelease over release, but this is only something worth worrying about if the code is being run hundreds or thousands of times a second (which this particular code obviously isn't).

    If I wanted to avoid autorelease, this is what I'd do:

    Code:
    UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.portraitWindow = window;
    [window release];
    
     
  6. GeeYouEye macrumors 68000

    GeeYouEye

    Joined:
    Dec 9, 2001
    Location:
    State of Denial
    #7
    If UIWindow is your own class, the typical Cocoa idiom would be to add a class method to return an instance already autoreleased (a convenience method), and to use that:

    Code:
    self.portraitWindow = [UIWindow windowWithFrame:[[UIScreen mainScreen] bounds];
    If UIWindow is not your own class, use Nutter's third code snippet; autorelease is exactly the right thing to do here.

    On that note, I rather wish Apple hadn't allowed a retain attribute on properties. Yes, it makes things simpler in some cases (specifically where you're using a lot of convenience methods returning autoreleased objects), but in cases where classes DON'T have convenience methods, it introduces headaches like this.
     
  7. bengimizrahi thread starter macrumors newbie

    bengimizrahi

    Joined:
    May 24, 2008
    Location:
    Istanbul
    #8
    Thank you all.

    So here is what I've learned:

    Use the following semantic as much as possible:
    Code:
    UIWindow *localPortraitWindow;
    localPortraitWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.portraitWindow = localPortraitWindow;
    [localPartraitWindow release];
    
    Using the following one is ok, but it does not emphisaze that there were actually 2 retains:
    Code:
    self.portraitWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    [self.portraitWindow release];
    
    If the code fragment is not repetitively executed, it is ok to do the following:
    Code:
    self.portraitWindow = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    
     
  8. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #9
    Autorelease pools are very fast... I would not worry about overhead from that unless Shark indicates that it's a problem.
     

Share This Page