Advertise here




Advertise here

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Slick's Definitive Guide To Properties

13

Replies

  • Duncan CDuncan C Posts: 9,114 @ @ @ @ @ @ @
    edited July 2010
    BrianSlick wrote: »
    placeMark *placemark = [[placeMark alloc] initWithCoordinate:pubLocation title:pubTitle subtitle:pubSubtitle];
    [mapView addAnnotation:placemark];
    	
    placemark = nil;
    	
    NSLog(@Placemark: %i, [placeMark retainCount]);
    

    1. Remember the 3-line pattern that was referenced earlier. Build it, do something with it, get rid of it. You do have 3 lines, but your 3rd one is incorrect. You did an alloc, you are supposed to release. By going straight to nil, you are not releasing, thus you are leaking the object.

    2. retainCount is not a reliable tool, for a number of reasons. For one, you have no idea what Apple's classes do behind the scenes. Let's say you add the object to an array, and then the retainCount becomes 200. Is that a problem? No idea. That could be 100% normal. But you have to trust Apple's classes to clean up after themselves.

    Additionally, you are asking the wrong thing for retainCount. You are asking the class for the retainCount, not a particular instance. I'm a little surprised this works at all, but it is a nonsense question if you think about it. This would be like asking NSArray for a retainCount. You don't want to ask the class, you want to ask the specific myParticularObject variable. And as a side note, follow proper naming convention. Class names should begin with a capital letter.

    Now let's pretend that you had done this entire block of code here correctly. You created it, you added it to the map, and then you released it and nil'ed out your variable. And then you ask the instance for a retainCount. But the variable is nil. So you are asking for the retainCount of nil. That is a meaningless question.

    Bottom line: retainCount is not a reliable method. Don't use it.
    - (id)initWithCoordinate:(CLLocationCoordinate2D)c title:(NSString *)markTitle subtitle:(NSString *)markSubtitle {
       if (self = [super init]) {
          coordinate = c;
    [B]      title = markTitle;
          subtitle = markSubtitle;[/B]
       }
    return self;
    }
    

    As noted previously, the use of instance variables in init methods is fine, and arguably preferred. But that doesn't free you from following the necessary memory management steps.

    Your strings are defined as retain properties. As mentioned already, if you do not use the @property's setter, then you are not participating in the memory management actions that it performs. So these string values are being assigned without a retain happening. This leaves you with several issues:

    1. Since the objects are not retained, they could die at any time.
    2. If you use the setter correctly later, then keep in mind what it does. It releases the old value and retains the new one. The old value would be the object you have assigned here. So you are releasing it, but that release is not balancing a retain. This means you are over-releasing it, which means your program will crash.
    3. You don't show it in your code, but you should have a dealloc method in your class, and you should be releasing all retain and copy properties there. So even if you never change the value, those strings will/should be released in dealloc, which will again be over-releasing, and you'll crash.

    So you'll have to take matters into your own hands and do some manual memory management, like so:
    title = [markTitle retain];
    subtitle = [markSubtitle retain];
    

    Now you are performing the same action that would happen if you were using the setter. The objects remain alive, and any releases that would happen later are now balanced.


    Brian,

    You beat me to the punch.

    One thing I would add for the OP: It's usually better to make string properties copy rather than retain. If your placemark class retains its title and subtitle properties, it ends up sharing ownership of those objects with the caller that sets them.

    Imagine that you have a class that sets up a string instance variable as a mutable string that it uses to parse user input. Let's say this class' instance variable is called workingString. It gets it's instance variable set up with the value it needs for a title, and then sets the title of a placemark with that value:
    PlaceMark* myPlaceMark;
    //Set up placemark var...
    [workingString appendString: titlePart];
    myPlacemark.title = workingString;
    

    If the PlaceMark object's title property is set to retain, then the statement:
    myPlacemark.title = workingString;
    

    causes the myPlaceMark object's title property to POINT to workingString.

    If you later change the value of workingString, the myPlaceMark object will point to the changed value of workingString, which is not what you expect to happen.

    The statement
    [workingString setString: @foo];
    

    would cause myPlaceMark to pick up the new value "foo" as it's title value as a side-effect.
    Regards,
    Duncan C
    WareTo

    widehead.gif
    Animated GIF created with Face Dancer, available for free in the app store.

    I'm available for one-on-one help at CodeMentor
  • chrigilchrigil Posts: 19
    edited September 2010
    Am I correct in thinking that if I explicitly declare Getter/Setter pairs for each of my instance variables, I don't need to use the @property @synthesize declarations?

    I think I initially misunderstood your example and created a header/implementation as follows but WITH @property and @synthesize in addition to the getters/setters:
    #import <Foundation/Foundation.h>
    
    @interface Whatever : NSObject {
        NSString *ivMyString;
    }
    
    - (void)doSomething;
    
    - (void)setString:(NSString *)input;
    - (NSString *)getString;
    
    @end
    
    #import "Whatever.h"
    
    @implementation Whatever
    
    - (void)doSomething {
        [self setString:@Bish bash bosh];
        NSLog(@MyString = ,  [self getString]);
    }
    
    - (void) setString: (NSString *)input {
        [input retain];
        [ivString release];
        ivString = input;
    }
    
    - (NSString *) getString {
        return ivString;
    }
    
    - (void)dealloc {
        [ivString release], ivString = nil;
        [super dealloc];
    }
    
    @end
    

    The code works without @property and @synthesize which initially lead me to believe that I was directly accessing IV's somehow but I don't think this is the case. Personally, whilst I understand it's more work, I actually prefer using getter/setters.

    Could somebosy clarify this for me?

    Thanks

    Chris
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,687 @ @ @ @ @ @ @ @
    edited September 2010
    @property and @synthesize are shortcuts for what you have done manually. You are still allowed to customize either the setter or the getter, or both, if you have synthesized properties.

    Less code means fewer opportunities for errors. And with the synthesized properties, you are getting what Apple feels is the best behavior for each case.

    Your getters/setters appear to be standard, so there is no reason to do them manually. Synthesize the properties and be done with it. Save the customizing for when you actually need a custom behavior.
    Professional iOS App Development. Available for hire.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn

    BTIKit | BTICoreDataKit | SlickShopper 2 | Leave a PayPal donation
  • chrigilchrigil Posts: 19
    edited September 2010
    BrianSlick wrote: »
    @property and @synthesize are shortcuts for what you have done manually. You are still allowed to customize either the setter or the getter, or both, if you have synthesized properties.

    Less code means fewer opportunities for errors. And with the synthesized properties, you are getting what Apple feels is the best behavior for each case.

    Your getters/setters appear to be standard, so there is no reason to do them manually. Synthesize the properties and be done with it. Save the customizing for when you actually need a custom behavior.

    Hell's bell's Brian do you have some sort of auto alert for when this thread gets a reply? I only post my question about 1 minute ago :D !

    I'll follow your's and Apple's suggestion and use the @property @synthesize declarations. Your argument for doing things this way seem pretty sound.

    One further question though; you stated in your initial thread that "You don't need to create these (getter/setter) methods (unless you have a reason to customize them). These are what are created behind-the-scenes when you @synthesize a @property".

    If I'm not implementing the 3 step retain, release, assign process (as suggested for setters), how do I know it's being done the best way?
    How can I be sure that when I set a @synthesized IV that it's releasing the IV before assigning it?

    Does that make sense or have I just shown another fundamental lack of understanding?!

    Thanks for taking the time to post this fantastic thread in the first place BTW. Absolutely essential for the likes of me.

    Chris
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,687 @ @ @ @ @ @ @ @
    edited September 2010
    You can receive an email for any thread that you've posted in or subscribed to.

    What the property does will depend on how you defined it. Retain, copy, assign all do different things, and you have to make a decision about how it should be declared for your usage needs. The nitty-gritty details of how they work are not necessarily anything you need to know (understand, sure, but the specifics are an implementation detail).

    All you need to know is that a retain property will retain whatever is incoming, and release whatever is outgoing. A copy property will copy whatever is incoming and release whatever is outgoing. An assign property performs no memory management actions. You need to know what they do, not how they work.

    This is no different than, say, reloading a table. You call
    [theTable reloadData];
    
    You expect this to reload the table, and it does. How it does that is not something you need to know. Same deal:
    [self setWhatever:...];
    
    What it does will depend on how it was defined. How it does it is not something you should worry about. At some point, you have to trust Apple.
    Professional iOS App Development. Available for hire.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn

    BTIKit | BTICoreDataKit | SlickShopper 2 | Leave a PayPal donation
  • chrigilchrigil Posts: 19
    edited September 2010
    Thanks again for everything, very, very helpful.

    One last thing. You mentioned in post #15 that you should "not be doing a manual release of properties like that - that is only done in dealloc. If you wish to clear out a property, do this:"

    [self setMyProperty: nil];

    From what I can tell, the way EAGLE (the poster who asked the question) was manually releasing was by doing:
    [myIV release]; //, myImageView = nil;
    

    Is the problem the fact that EAGLE is setting it to nil after the release? Is it ok to release an IV object as follows?
    [[self myObject] release];
    

    Thanks

    Chris
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,687 @ @ @ @ @ @ @ @
    edited September 2010
    Let's say you have some object, and you are using a retain property.
    NSArray *exampleArray = ...;
    
    [self setTheProperty: exampleArray];
    

    I don't like dealing in absolute retain counts, so let's talk strictly in terms of relative retain counts. So, when you put the array into the property, it receives a +1 retain count.

    Now you have a different object, and use the property again:
    NSArray *differentArray = ...;
    
    [self setTheProperty: differentArray];
    

    Two things happen here:

    - the old object is released. So, exampleArray -1
    - the new object is retained. differentArray +1

    exampleArray is balanced. It was retained on the way in, it was released on the way out. Net result is no change. It is not leaked, it is not over-released.

    The case you are describing is actually this:
    NSArray *sampleArray = ...;
    
    [self setTheProperty: sampleArray];
    
    [ivTheProperty'sInstanceVariable release];
    

    So you're thinking:

    +1 on the way in
    -1 from the release
    0, no change, balanced, perfect!

    If you do nothing else, you can get away with this. But you just stepped in to the lion's den wearing a meat suit. If you keep going:
    NSArray *sampleArray = ...;
    
    [self setTheProperty: sampleArray];
    
    [ivTheProperty'sInstanceVariable release];
    
    NSArray *anotherArray = ...;
    
    [self setTheProperty: anotherArray];
    

    Now you're dead.

    sampleArray on the way in: +1
    Manual release of ivar: -1
    anotherArray on the way in: +1
    sampleArray on the way out: -1

    So here is what sampleArray experienced:

    +1
    -1
    -1

    -1. Over-released. Crash

    As far as your rewrite is concerned, yes you used the property to retrieve the object, but look at what your own getter does. It simply returns whatever is in the instance variable at the time, with no memory management actions taking place. I'm not suggesting that this is wrong, just that you should be aware that this is the case. So, there is effectively no difference between the first version and the second version of that code. You are still releasing something in the wrong way.

    Even if you do NOT give a new object to the property, you are still in danger. All retain and copy properties should be released in dealloc. So whether you get the -1 from supplying a new object to the property, or you get the -1 from releasing in dealloc, it is still coming. That will be harder to track down because the object won't be over-released until your view controller dies. This can mislead you as to the cause of the crash.
    Professional iOS App Development. Available for hire.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn

    BTIKit | BTICoreDataKit | SlickShopper 2 | Leave a PayPal donation
  • chrigilchrigil Posts: 19
    edited September 2010
    This memory management stuff is gonna send me over the edge!

    I understand all of the above and now realise that my rewrite is actually no different to the original. Are you going as far as to say that it's better to leave an object hanging around until dealloc is called rather than releasing manually? Surely if I do that I risk calling release once on an IV with a retainCount that is greater than one. Or would the release in the setter mean that the retain count can never be more than 1?

    This whole memory management thing is quite a change from the VB.Net world I'm used to. Everything is ByVal so whilst it's less efficient, to all intents and purposes when I dispose of an object, I'm doing just that, there's only ever one reference to it. In Objective C it seems that you never actually dispose of an object you just attempt to destroy all reference to the memory used by that object.
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,687 @ @ @ @ @ @ @ @
    edited September 2010
    Your questions don't really make sense in this environment, so I'm having trouble answering.
    Is it better to leave an object hanging around?

    The purpose of an instance variable is to make that item available to all methods in the class. The purpose of properties is to talk to the instance variable in a memory-management friendly way. So, using a property means 1) You want the object to live, and 2) you want the object accessible from anywhere. It will therefore hang around.

    The object will remain (assuming that you follow good memory management techniques throughout) until any of the following happens:
    1) A new object is provided to the property
    2) The property is set to nil
    3) The class/parent object is destroyed

    If you want the object to be alive the entire time, then it will be killed with #3. If you only want it to remain for a certain amount of time, then you will do #1 or #2. #2 could be done, for example, in response to a memory warning.
    Surely if I do that I risk calling release once on an IV with a retainCount that is greater than one.

    If the retain count is 0, then the object dies. So you will always call release on something with a retain count greater than one.
    Or would the release in the setter mean that the retain count can never be more than 1?

    The setter only balances itself. Retain incoming, release outgoing. But the incoming object could already be retained by any number of other objects, so it is quite possible for the retain count to be more than one.

    Again, don't think in terms of absolute retain counts. The number is largely meaningless. The only numbers that matter are "zero" and "anything other than zero". If it is zero, it's dead, so you aren't getting a useful reply anyway. If it is non-zero, it is alive, and the specific number doesn't matter.
    In Objective C it seems that you never actually dispose of an object you just attempt to destroy all reference to the memory used by that object.

    Mmm, I think you're close but the phrasing is off just enough that this should be clarified.

    You can imagine 3 categories of actions taking place on an object:

    1. Create. alloc, copy, new
    2. Borrow. retain
    3. Give away. release

    Those aren't the best descriptors, but I'm kind of drawing a blank at the moment. 1 is for new objects, 2 is for existing objects.

    So you need an object. Does one exist? If not, you need to create it. When you create it, you own it. You will keep it alive until you are done with it. Maybe someone else needs to borrow it before you are done with it. So they grab it. If you are done with it, you give it away. If the other person still has it, then they will keep it alive until they are done with it. When you are both done with it, there is no one to keep it anymore, so it dies.

    #1 and #2 are the same from a retain count standpoint. All result in a +1 retain count. So in either case, #3 is the balancing act, causing a -1 retain count.

    Any given class should only worry about balancing its own actions. For example, when you add an object to an NSMutableArray, the array will retain that object. If you remove that object from the array, the array will release it. The array balances its own actions. The array does not try to kill the object when it is removed. It simply indicates that it no longer wants that object by releasing it. If no one else is using the object when that happens, then it will die. But it dies because no one is using it, not because the array released it. This is a subtle but important distinction.
    Professional iOS App Development. Available for hire.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn

    BTIKit | BTICoreDataKit | SlickShopper 2 | Leave a PayPal donation
  • ParentalParental Posts: 68
    edited September 2010
    Hi Brian.

    What's the difference between

    self.myObject=[NSMutableArray array];

    or

    NSMutableArray *_myObject = [NSMutableArray alloc] init];
    self.myObject = _myObject;
    [myObject release];
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,687 @ @ @ @ @ @ @ @
    edited September 2010
    3 lines vs. 1 line.
    Professional iOS App Development. Available for hire.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn

    BTIKit | BTICoreDataKit | SlickShopper 2 | Leave a PayPal donation
  • longstlongst Posts: 115
    edited October 2010
    a great tutorial for new comers, especial for someone like me coming from C# and Java.
    I am still not sure I did quite understand with this part
    "
    The same would be true if a new value gets assigned to the property. Remember, the setter will release (-1) the old value, and the object we created is now the old value. So again we are left with a +1 net retain count, again we do not have any means to communicate with the object, and again it is a leak. And as a double-bonus, if the new object is another alloc/init creation, we're replacing a leaked object with another leaked object.
    "

    Could you please show me a sample code regarding this part Thank you
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,687 @ @ @ @ @ @ @ @
    edited October 2010
    [self setProperty:[[NSMutableArray alloc] init]];
    ...
    [self setProperty:[[NSMutableArray alloc] init]];
    
    Professional iOS App Development. Available for hire.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn

    BTIKit | BTICoreDataKit | SlickShopper 2 | Leave a PayPal donation
  • intomointomo Posts: 62
    edited November 2010
    Thanks again for this thread.
    It's been very enlightening.

    I come from another language where we didn't have pointers so the distinction between properties and ivars was escaping me.

    I have a couple questions, though:

    1. Am I correct in assuming that if you want to save a value in a class you don't have to use a property? You could just save it in an instance variable. You would only need to save it as a property if you wanted to access it outside of that class.

    2. I have seen where other developers create the instance variable and then synthesize the property
    //In the header file
    
    Class *_instance;
    
    @property (nonatomic, retain) Class *instance;
    
    //In the implementation
    
    @synthesize instance=_instance;
    

    But in the dealloc they release the property instead of the instance variable.
    - (void)dealloc {
         [instance release];
    }
    

    Does that make a difference being as the property is just pointing to the variable?

    Thanks in advance.
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,687 @ @ @ @ @ @ @ @
    edited November 2010
    1. You should use properties any time that you want to access the instance variables in a memory-management-friendly way, so pretty much all the time. Internal vs. external is moot.

    2. I'm pretty sure you haven't actually seen that (the dealloc part), since it isn't valid code.
    Professional iOS App Development. Available for hire.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn

    BTIKit | BTICoreDataKit | SlickShopper 2 | Leave a PayPal donation
  • intomointomo Posts: 62
    edited November 2010
    BrianSlick wrote: »
    1. You should use properties any time that you want to access the instance variables in a memory-management-friendly way, so pretty much all the time. Internal vs. external is moot.

    2. I'm pretty sure you haven't actually seen that (the dealloc part), since it isn't valid code.

    Yeah, thanks.
    #2 my mistake.
    I was a little unclear of the diff between the way Apple does it and the way you do it. Now I'm clear. Both ways always release the instance. I got it.
  • DazedNConfusedDazedNConfused Posts: 2
    edited January 2011
    BrianSlick wrote: »
    First, let's make sure we have our terminology on the same page. So a sample view controller would look like this:

    [...]
    @implementation TemplateViewController
    
    @synthesize myProperty = ivInstanceVariable;
    

    [...]

    I really like this idea to seperate the ivar from the setter/getter. I have just been going through my code (200 files!!!) and implementing this and it is highlighting alot of places where I have potential memory leaks.

    I have one question though. Should I bother to do this for non-objects which have an assign property. For that matter why bother with a property/synthesize for a non-object assign type ivar? Is there any benefit?

    This thread is awesome.

    Cheers,
    Brett
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,687 @ @ @ @ @ @ @ @
    edited January 2011
    Technical answer: the property type for a non-object would be assign, and assign properties don't really do anything. So from a functional standpoint, there isn't much of a reason to use a property for primitives, unless other objects would need to be able to set/access them. You could even argue that the property is slower, since it would take more effort to go through the method calls vs. going direct.

    Personal answer: I use properties for all instance variables, regardless of type. I do it mostly for consistency.

    If you were asking about the naming convention, then I'd say that's up to you. I personally do the ivBlah all of the time, and I do [self blah] all of the time. So I can copy-paste any segment of code and instantly know what is a property, what is an instance variable, and what is a local variable, and I can do this without needing any context color coding.
    Professional iOS App Development. Available for hire.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn

    BTIKit | BTICoreDataKit | SlickShopper 2 | Leave a PayPal donation
  • DazedNConfusedDazedNConfused Posts: 2
    edited January 2011
    BrianSlick wrote: »
    Technical answer: the property type for a non-object would be assign, and assign properties don't really do anything. So from a functional standpoint, there isn't much of a reason to use a property for primitives, unless other objects would need to be able to set/access them. You could even argue that the property is slower, since it would take more effort to go through the method calls vs. going direct.

    Personal answer: I use properties for all instance variables, regardless of type. I do it mostly for consistency.

    If you were asking about the naming convention, then I'd say that's up to you. I personally do the ivBlah all of the time, and I do [self blah] all of the time. So I can copy-paste any segment of code and instantly know what is a property, what is an instance variable, and what is a local variable, and I can do this without needing any context color coding.

    Thanks for the quick reply Brian. My understanding was the same as your technical answer which pleases me. After iOS programming for a year and writing lots of code I seem to have no trouble with achieving complex things but its the "simple" things that trip me up in obj-c.

    I have decided on the leading underscore to name my ivars. I am only going to use properties on objects, and those simple types which need access external to the class. I may change my mind in the future.

    Strangely I am using [self object] for objects and self.simple for simple types.

    Thanks again,
    Brett
  • schniggesschnigges Posts: 8
    edited July 2011
    Great Guide Slick,

    since I'm new to Objective-C it helped a lot and made me refactor some of my code...

    One thing I'm still not that sure about is the following :

    When you create a new Core-Data project, three getters for NSManagedObjectModel, NSManagedObjectContext and NSPersistentStoreCoordinator are created for you. In all of them, the ivar is addressed in a way a leak should be generated :
    - (NSManagedObjectModel *)managedObjectModel
    {
        if (__managedObjectModel != nil)
        {
            return __managedObjectModel;
        }
        NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@MensaApp withExtension:@momd];
        __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];    
        return __managedObjectModel;
    }
    
    @property @property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
    
    @synthesize managedObjectModel=__managedObjectModel;
    

    Wouldn't it be correct to say :
    NSManagedObjectModel *localManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    [self setManagedObjectModel:localManagedObjectModel];
    [localManagedObjectModel release];
    

    Thanks in advance,
    Schnigges
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,687 @ @ @ @ @ @ @ @
    edited July 2011
    As noted, it is perfectly acceptable, and in some cases required, to use direct instance variable access within custom getters/setters. I personally don't like calling the 'other' getter/setter from within a particular custom getter/setter, but as long as you make sure you aren't getting into a loop, you should be fine.

    But let's take a look at why theirs isn't leaking. First there is a test:
    if (__managedObjectModel != nil)
    {
       return __managedObjectModel;
    }
    

    If an object as already been given to the instance variable, then we exit the method right here. So the only way to proceed to the next part is if the instance variable is nil.

    So we finish up with this:
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@MensaApp withExtension:@momd];
    __managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];    
    return __managedObjectModel;
    

    This code is only run if the value is nil, so there is no danger of leaking old objects with this assignment.

    As far as what will happen in the future, if at some point later you do a:
    [self setManagedObjectModel:whatever];
    
    ...this will release the old value, which is what we just created. That balances the alloc, so not a leak.

    Or, if that never happens, then the value should be released in dealloc:
    [__managedObjectModel release];
    
    ...which will again balance the alloc, so still not a leak.
    Professional iOS App Development. Available for hire.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn

    BTIKit | BTICoreDataKit | SlickShopper 2 | Leave a PayPal donation
  • schniggesschnigges Posts: 8
    edited July 2011
    Thanks for the quick reply,

    got the idea of why there is no leaking.

    One last thing, would it be wrong to write :
    NSManagedObjectModel *localManagedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    [self setManagedObjectModel:localManagedObjectModel];
    [localManagedObjectModel release];
    
    ?

    You said that in some cases it is required to directly access an ivar, is the above one of those? And if not, could you name another one?

    Thanks again,
    schnigges
  • schniggesschnigges Posts: 8
    edited July 2011
    Ok, bad example....the properties I listed in my previous post are all marked 'readonly', so accessing the ivar is the only possible way here.
  • BrianSlickBrianSlick Treadmill Desk Ninja Posts: 10,687 @ @ @ @ @ @ @ @
    edited July 2011
    BrianSlick wrote: »
    I personally don't like calling the 'other' getter/setter from within a particular custom getter/setter, but as long as you make sure you aren't getting into a loop, you should be fine.

    You can potentially get into trouble doing things like this:
    - (void)setSomeProperty:(NSString *)newValue
    {
       if (some test criteria)
       {
          [self setSomeProperty:anotherValue];   // Infinite loop risk
       }
    }
    
    Professional iOS App Development. Available for hire.
    BriTer Ideas LLC - WWW | Facebook | Twitter | LinkedIn

    BTIKit | BTICoreDataKit | SlickShopper 2 | Leave a PayPal donation
  • JoeAppsJoeApps Posts: 10
    edited August 2011
    longst wrote: »
    a great tutorial for new comers, especial for someone like me coming from C# and Java.
    I am still not sure I did quite understand with this part
    "
    The same would be true if a new value gets assigned to the property. Remember, the setter will release (-1) the old value, and the object we created is now the old value. So again we are left with a +1 net retain count, again we do not have any means to communicate with the object, and again it is a leak. And as a double-bonus, if the new object is another alloc/init creation, we're replacing a leaked object with another leaked object.
    "

    Could you please show me a sample code regarding this part Thank you

    "For every "alloc or retain" you should have a "release" and vice-versa."

    So just using ivars:
    someView = [[UIView alloc] init]; // Alloc message sent.

    Using accessors:
    self.someView = [[UIView alloc] init]; // Alloc and retain message sent.

    So if your project was setup up with:
    .h
    @property (nonatomic, retain) UIView *someView; //telling accessors to include a retain message using the retain attribute.
    .m
    @synthesize someView;


    Step 1: allocates space for the object and initializes it, then "do stuff with object", then releases it.
    someView = [[UIView alloc] init];
    "Do stuff with object"
    [someView release];

    someView was released from the allocated space. But now the ivar points to an empty space that once contained your object because you did not nil out the ivar using someView = nil;


    Step 2: accessor which will call a release on the old value in Step 1: and retain the new value we see here
    self.someView = [[UIView alloc] init]; // Alloc & Retain *Needs 2 releases sometime in the future

    but since the old value in step 1 has already used a release for its alloc, it has long already left the place someView is currently still pointing to.

    It will crash because it tries to release something not there!

    Remember: someView is different than self.someView

    FUN ANALOGY

    The cookie monsta tells you to stick your hand out and then put a cookie in it (alloc),
    you take a bite(do stuff),
    then the cookie monsta takes it away from you because he is the cookie monsta and he does what he wants,
    "I DO WHAT I WANT!!!"(release sucka!)
    OM NOM NOM!

    You don't have a cookie anymore and feel sad and hungry....awwwww.
    COOKIE MONSTA DON'T CARE!!!

    Cookie monsta come back still looking for the cookie in your hand...Again...
    (release sucka!)
    ...but you don't have anything to give the cookie monsta...
    COOKIE MONSTA DON'T CARE!!!

    He rears up, opens his mouth, and BITES YOUR ARM OFF! OM NOM NOM NOM!

    THE END

    - It's a harsh life. lol
    - Joe<br />
    <a href="http://j.mp/qSEEHO"; target="_blank">/*** My Apps ***/</a><br />
    <a href="http://j.mp/lDwBug"; target="_blank">prankcaller-m
Sign In or Register to comment.