If your UITableView crashes on scrolling


#1

Maybe your problem was same as mine:

The setter methods in Possession don’t retain.

I got the idea from http://forums.bignerdranch.com/viewtopic.php?f=85&t=2842#p5167

and totally fixed it by adding retains to the name, serial number, and date (you can’t for the int since it’s primitive right?)

[code]- (void) setPossessionName:(NSString *)str {
[str retain];
[possessionName release];
possessionName = str;
}

  • (NSString *)possessionName{
    return possessionName;
    }

  • (void)setSerialNumber:(NSString *)str{
    [str retain];
    [serialNumber release];
    serialNumber = str;
    }

  • (NSString *)serialNumber{
    return serialNumber;
    }

  • (void)setValueInDollars:(int)i{
    valueInDollars = i;
    }

  • (int)valueInDollars{
    return valueInDollars;
    }

  • (NSDate *)dateCreated{
    [dateCreated retain];
    return dateCreated;
    }
    [/code]


#2

My book is downstairs, but I think later on in the chapter you delete those functions because they’re synthesized as “copy”:

Header:
@property (nonatomic, copy) NSString *possessionName;
@property (nonatomic, copy) NSString *serialNumber;
@property (nonatomic) int valueInDollars;

Implementation:
@synthesize possessionName, serialNumber, valueInDollars, dateCreated;
// no need to implement setPossessionName, etc


#3

I believe the reason that it may be crashing is due to whether you call accessors in your initializer. If you don’t, the designated initializer looks like this:

[code]-(id) initWithName:(NSString *)name serialNumber:(NSString *)number value: (int)value{

self = [super init];

if (self) {
    possessionName = name;
    serialNumber = number;
    valueInDollars = value;
    dateCreated = [NSDate date];
}
return self;

}[/code]

As you can see, we are directly assigning our arguments to their respective instance variables. At no point are these arguments retained by the new Possession instance. If you retain the arguments like below, your table view will not crash on scrolling.

[code]-(id) initWithName:(NSString *)name serialNumber:(NSString *)number value: (int)value{

self = [super init];

if (self) {
    possessionName = [name retain];
    serialNumber = [number retain];
    valueInDollars = value;
    dateCreated = [[NSDate date] retain];
}
return self;

}[/code]

Here’s my question, if we would prefer to not call accessors in our initializers, is someVariable = [x retain] or someVariable = [x copy] an appropriate alternative? (I should used “copy” for the strings) Thanks in advance.


#4

The issue is that you are using the Possession class from before you start to use properties. If you look at the very final Possession class you have properties for all the attributes as opposed to your own accessors/mutators.

Once you use the correct Possession class this works.


#5

I understand the issue of using the final Possession class. My question is regarding accessors in the designated initializer. If we don’t use accessors to set instance variables, is it acceptable to directly access / set the variable while retaining that value? Also in ARC, since retain, release and autorelease are unable to be explicitly sent to objects, how would we reconcile this situation? Are accessors in the designated initializer unavoidable? Thanks!