Objective C - Custom setter with ARC?

19,920

Solution 1

The strong takes care of itself on the ivar level, so you can merely do

- (void)setMyObject:(MyObject *)anObject
{
   _myObject = anObject;
   // other stuff
}

and that's it.

Note: if you're doing this without automatic properties, the ivar would be

MyObject *_myObject;

and then ARC takes cares of the retains and releases for you (thankfully). __strong is the qualifier by default.

Solution 2

Just to sum up the answer

.h file

//If you are doing this without the ivar
@property (nonatomic, strong) MyObject *myObject;

.m file

@synthesize myObject = _myObject;

- (void)setMyObject:(MyObject *)anObject
{
    if (_myObject != anObject)
    {
        _myObject = nil;
        _myObject = anObject;
    }
    // other stuff
}
Share:
19,920

Related videos on Youtube

aryaxt
Author by

aryaxt

Updated on December 10, 2020

Comments

  • aryaxt
    aryaxt over 3 years

    Here is how I used to write a custom retained setter before:

    - (void)setMyObject:(MyObject *)anObject
    {
       [_myObject release], _myObject =  nil;
       _myObject = [anObject retain];
    
       // Other stuff
    }
    

    How can I achieve this with ARC when the property is set to strong. How can I make sure that the variable has strong pointer?

    • Tricertops
      Tricertops about 11 years
      Is this really how you used to write setters? I think you should add an if statement checking, if anObject is not the same as _myObject. If they both reference the same object with retain count 1, you deallocates the object on first line and crash on second.
    • Tricertops
      Tricertops about 11 years
      Sorry about the crash, you are right, you are nullifying it. You are almost right with that second part, but there is one case: the only place where the object is referenced is this property itself. Very simplified: self.title = self.title;, but this may happen in more complex situation. You don't know where the object came from, you assign it to property, and boom it is lost.
    • Tricertops
      Tricertops about 11 years
      … and not just it is lost, but in this specific case the code will crash. On release, it may get deallocated, you nullify ivar, but then retain deallocated object – crash.
    • aryaxt
      aryaxt about 11 years
      @iMartin I couldn't get it to crash using your example, but you are right it may cause a crash, so it's best to do the equal check
    • Töre Çağrı Uyar
      Töre Çağrı Uyar almost 11 years
      @aryaxt, actually, you are not wrong. If the only place an object is referenced is a property and you set another object to that property first object should be deallocated anyway. self.title = self.title; won't crash but not because of the setter, it's because of the getter. Getter should always return an autoreleased object, a getter never should assume it will have object longer than receiver needs to. Returning an object in a getter without retaining and autoreleasing it again is a mistake. That's exactly why above code won't crash.
  • Alex Gray
    Alex Gray almost 12 years
    what does your @synthesize look like with (both) of these options?
  • Dan Rosenstark
    Dan Rosenstark almost 12 years
    @alexgray your synthesize generally looks like @synthesize myObject = _myObject to keep the names of the iVar and property different. See here (stackoverflow.com/questions/822487) for whether that's a good idea.
  • Dan Rosenstark
    Dan Rosenstark over 11 years
    @alexgray UPDATE with the new stuff (um, LLVM 4.0 or Xcode 4.4 or something) you don't have to write synthesize, IF you were lucky enough to ignore all the know-it-alls on SO and use the underscore as a prefix.
  • ma11hew28
    ma11hew28 over 11 years
    I don't think you need __strong because it's inferred if left out.
  • Dan Rosenstark
    Dan Rosenstark over 11 years
    Thanks @MattDiPasquale... fixed.
  • Robert Nall
    Robert Nall over 11 years
    I may be missing something here, but I'm confused by the ivar you have listed for non-auto properties—wouldn't the ivar for this situation be MyObject *_myObject;?
  • Dan Rosenstark
    Dan Rosenstark over 11 years
    @RobertNall you can call the ivar whatever you want, but you're right. I've adjusted the answer.
  • Alec
    Alec about 11 years
    @Yar thanks for the answer. Now what if the myObject property was copy instead of strong? Do you need to copy it in the custom setter via _myObject = [anObject copy]; with ARC?
  • Dan Rosenstark
    Dan Rosenstark about 11 years
    If you're doing the setter (a custom setter), then you have to do the copy as you suggest. If you don't, then the copy is done automatically for you. Copy implies strong ownership, so if you're doing the ivar, it should be like it is here (with no specification it would be strong). See here for more confusion: clang.llvm.org/docs/AutomaticReferenceCounting.html and search on "copy implies __strong ownership"
  • Töre Çağrı Uyar
    Töre Çağrı Uyar almost 11 years
    Checking is unnecessary, you won't get a performance increase or reliability with checking like _myObject != anObject, you can only get a little bit performance decrease. Also setting iVar to nil is unnecessary, too. Won't get any reliability with _myObject = nil;, too.