0

I have a class that has a property:

@property (nonatomic, assign) id customDatePicker

Based upon user choice I will need a UIDatePicker or a UIPicker so I typecast the ivar and retain it and subsequently dealloc it. Is this the correct way to manage the property's memory?

// init snippet
if (useUIDatePicker) {
  customDatePicker = (UIDatePicker *)[[[UIDatePicker alloc] initWithFrame:frame] retain];
} else {
  customDatePicker = (UIPickerView *)[[[UIPickerView alloc] initWithFrame:frame] retain];
}

- (void)dealloc {
  [customDatePicker release];
  [super dealloc];
}
Cory D. Wiles
  • 556
  • 1
  • 6
  • 21

1 Answers1

3

No.

When you declare the property as assign, you should not be retaining the object. The assign option is used for non-object variables and for situations where having a retained property would create a cycle, with both objects retaining each other. Declaring a property as assign means you will not be managing the memory of the object; you should neither call retain nor release on it.

You are also over-retaining the picker object. Retaining an object creates a claim on the object; you don't want it to disappear until you say you are done with it. You relinquish a claim, allowing an object to be deleted, by calling release. When you call alloc, that creates the same kind of claim as calling retain. So this line:

[[[UIDatePicker alloc] initWithFrame:frame] retain];

creates two claims, one for alloc and one for retain. Later, you only call release once, which means that you will always still have one claim on this object, and it will have turned into a memory leak.

What you should do is:

@property (nonatomic, retain) id customDatePicker


if (useUIDatePicker) {
    customDatePicker = [[UIDatePicker alloc] initWithFrame:frame];
} else {
    customDatePicker = [[UIPickerView alloc] initWithFrame:frame];
}

Now you have only one claim on the picker because you used alloc.

(You don't need to cast the assignment; when you are assign to a generic pointer you can use any kind of object.)

Also take a look at the Apple Memory Management docs.

jscs
  • 63,694
  • 13
  • 151
  • 195
  • 1
    @Cory Also if you want to send retain and release to an object of type id at least make sure it conforms to the NSObject protocol by declaring it as `id`. – Joe Jul 08 '11 at 18:01
  • @Josh thanks for the answer. I had a feeling I was going about it the wrong way. Thanks. – Cory D. Wiles Jul 08 '11 at 19:21
  • @Josh Caswell, then was is the difference between weak and assign ? I thought, that assign is for non object types and weak is work object types, but apparently they do the same thing ? Or weak sets the object to nil, when the retainCount is 0 and the assign doesn't do that ? So is assign like unsafe_unretained ? – denis631 Aug 28 '15 at 06:32
  • 1
    This answer was written before the introduction of ARC, and thus before weak references, @denis631. Weak references under ARC are auto-nilling: you will either have a valid object or `nil`. Yes, an `assign` property is equivalent to an `__unsafe_unretained` pointer: if the object is deallocated, the property will have a dangling reference to an invalid object. – jscs Aug 28 '15 at 06:36
  • Thanks @JoshCaswell ! I since was surprised, when I looked at `UIAlertView.h` header file and the delegate wasn't declared as `weak`, but rather as `assign`, which made me really confused. Just why ? From Apple AlertView header : `@property(nonatomic,assign) id /**/ delegate; // weak reference` – denis631 Aug 28 '15 at 06:55
  • 1
    [Why does Apple use assign rather than weak to store a delegate?](http://stackoverflow.com/q/20419317), @denis631. – jscs Aug 28 '15 at 07:02
  • @JoshCaswell Thank you, Sir! – denis631 Aug 28 '15 at 07:07