On Nov 29, 2008, at 2:58 PM, Glenn Bloom wrote:

// Implement loadView if you want to create a view hierarchy programmatically
- (void)loadView {

/* snip */

NSMutableString * stringCompleteMutable = [NSMutableString stringWithString:string00Local]; // local variable set with a constructor that handles release, so there will be no need to release it
        [stringCompleteMutable appendString: @", "];
        [stringCompleteMutable appendString: myStringA];
        [stringCompleteMutable appendString: @", "];
        [stringCompleteMutable appendString: self.myStringB];

This is fine and there's nothing wrong with it but it might be more readable to create your string with a format string:

NSString *stringComplete = [NSString stringWithFormat:@"%@, %@, %@", string00Local, myStringA, self.myStringB];

That's really a stylistic point though, it's not like this code will be running in a loop generating hundreds of strings where you'd want to send as few messages as possible.

        self.labelA.text = stringCompleteMutable;

        [self.labelA setText:stringCompleteMutable];

These two lines are equivalent but I think it's just remnants of some copy and pasting though.


As I understand it, all instances of UIViewController will receive the didReceiveMemoryWarning message when the OS warns the app. At that point you should clear out any caches. Since they all receive this message, even if they're visible, you can't know at that point whether the view will be released or not. Currently the only way to know that your view is going away is when you receive a setView:nil message. It's at that point, when your view is being released, that you should also release and nil out any references you may have to objects that are part of that view.

// Method setView:
// Overrides setter for UIViewController property view.
- (void)setView:(UIView *)theView;
{
        if (theView == nil){
                // release views and label when the argument is nil
// As long as this UIViewController subclass retains its top level view then all of the view's subviews will also be retained. However, they should all be released when the UIViewController releases its view... And we can't release them in method didReceiveMemoryWarning because... 1. MUST CONFIRM: we have declared them as properties, with "retain", and we can't determine accurately within didReceiveMemoryWarning when the view controller's view is in fact released (except by calling setView), so we can't conditionally release them within the didReceiveMemoryWarning method (except by actually setting the controller's view).
                self.labelA = nil;
                self.imageViewA = nil;  
                self.subViewA = nil;    
                
self.primaryViewA = nil; // We also release this here, not in didReceiveMemoryWarning, despite the fact that the controller's view is set to this rather than it be added to the controller's view as a subview. Since the view is going away here you need to remove all references to it, and in fact, must remove this reference specifically as it won't be dealloc'ed until you do since you've retained it.
        }
        [super setView:theView];
}// End Method setView:


- (void)didReceiveMemoryWarning {       
        
// Release anything that's not essential, such as cached data (meaning instance variables, and what else...?)
        
// Obviously can't access local variables such as defined in method loadView, so can't release them here
        
// We can set some instance variables as nil, rather than call the release method on them, if we have defined setters that retain nil and release their old values (such as through use of @synthesize). This can be a better approach than using the release method, because this prevents a variable from pointing to random remnant data. Note in contrast, that setting a variable directly (using "=" and not using the setter), would result in a memory leak.
        self.myStringB = nil;

        
// Even though no setters were defined for this object, still set it to nil after releasing it for precisely the same reason that you set properties to nil. // Note that because myStringA was only set to point to a static string, it doesn't really need to be released here, but pedantically this is correct - this is good form, anticipating for instance, a modification by which this string ends up being later created through some other class in some other manner
        [myStringA release], myStringA = nil;

        
        // Releases the view if it doesn't have a superview
        [super didReceiveMemoryWarning];
}




- (void)dealloc {
        
// In contrast to how you deallocated in didReceiveMemoryWarning, in dealloc you don't want to employ setters. As a general rule, you don't want to employ setters in either init methods or in dealloc. Conceptually, generic synthesized accessors look something like this:
        // - (void)setLabelA:(id)newValue {
        //      if (labelA != newValue) {
        //              [labelA release];
        //              labelA = [newValue retain];
        //      }
        // }
// Using self.labelA = nil would call this method with newValue set to nil. This would evaluate equivalently to [labelA release], labelA = nil; // However, It's not recommended to use such a setter during - dealloc and -init because they may not be the generic synthesized accessors and they may have side-effects that are unwanted during init and dealloc.... So just use release:
        [myStringA release];
[myStringB release]; // Note that this is different than what is employed in didReceiveMemoryWarning, where the following was preferrable, i.e., the setter was used:
        // self.myStringB = nil;
        
        
// primaryViewA does need to be explicitly released; the ViewController's view was set to it, but it must still be released separately // Again you don't want to use a setter (self.primaryViewA = nil) in dealloc, for the reasons stated previously. // And because UIViewController currently implements its dealloc method using the setView: accessor method (rather than simply releasing the variable directly...), you also want to set it to nil in dealloc as follows, in addition to releasing it.
        [primaryViewA  release], primaryViewA = nil;
        
        // likewise...
        [labelA release], labelA = nil; // rather than: self.labelA = nil;
[imageViewA release], imageViewA = nil; // rather than: self.imageViewA = nil; [subViewA release], subViewA = nil; // rather than: self.subViewA = nil;
        
        
// Note: you don't need to explicitly release the ViewController's view - the superclass will do this.
        
        [super dealloc];
}

@end
_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to