I'm developing an iPad app and I ran into a really weird issue here. I'll try to explain it as good as possible.
I have a class named TranslationObject
which is holding a key and a textual value. I have created this class as the following:
@interface TranslationObject : NSObject {
NSNumber *_key;
NSString *_value;
}
@property (nonatomic, retain)开发者_如何学Python NSNumber *key;
@property (nonatomic, retain) NSString *value;
- (id) initWithKey:(NSNumber *) key andValue:(NSString *) value;
@end
The translations will be pulled from a XML or DB in the future, but for now I do the following:
@interface Translation : NSObject {
NSMutableArray *m_extfeat;
}
@property (nonatomic, retain) NSMutableArray *extfeat;
+ (Translation *) getInstance;
- (id) init;
- (NSMutableArray *) getExtFeat;
@end
Implementation:
@implementation Translation
@synthesize extfeat = m_extfeat;
- (id) init {
self = [super init];
if (self) {
m_extfeat = [[self getExtFeat] retain];
}
return self;
}
- (NSMutableArray *) getExtFeat {
TranslationObject *obj1 = [[[TranslationObject alloc] initWithKey:[NSNumber numberWithInt: 0] andValue:@"Animal house"] autorelease];
.... more items declared ....
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11, obj12, obj13, obj14, obj15, obj16, obj17, nil];
return [array autorelease];
}
@end
These translations are being used in a UITableViewController
and are being fetched in the viewDidLoad
method as:
- (void)viewDidLoad
{
_data = [[Translation getInstance].extfeat retain];
}
I use these values at its cellForRowAtIndexPath
, where I call a method to configure the cell:
- (void) configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *) indexPath {
TranslationObject *object = (TranslationObject *) [_data objectAtIndex:indexPath.row];
//Crashes here at 13th item:
NSLog("Object key: %@", [object.key stringValue]);
}
As the snippet above says, strangely, the app crashes when fetching the key value only if the _data array contains more than 12 items. So if I only fill the _data variable with 12 items or less, my code works fine. If I add more than 12, the app crashes as soon as it fetches the 13th object.
So I enabled NSZombies and so when I check the 13th item in that method, the value is still fine, but it's only the key that turned into a Zombie. And again.. Only from the 13th item on!
Does anyone know how this is possible? Is it maybe so that there is a maximum number of items that can be stored in the memory? Is the memory full at the 12 item? But if that'd be the case, then why would the value still be there. How would it be possible that it's just the key that is being released before?! And how?!
I hope this explanation makes sense and someone can shine a light over this case.. =/
Thanks!
EDIT: Here's the implementation of the initWithKey method of the TranslationObject:
- (id) initWithKey:(NSNumber *) key andValue:(NSString *) value {
self = [super init];
if (self) {
_key = key;
_value = value;
}
return self; }
Make sure your using the property accessors in the TranslationObject
or retaining the number:
@implementation TranslationObject
@synthesize key=_key, value=_value;
- (id) initWithKey:(NSNumber *) key andValue:(NSString *) value {
self = [super init];
if (!self) return nil;
self.key = key; // ensures key is retained
self.value = value;
return self;
}
…
@end
Specifics:
self.key = key;
is the syntax for calling the accessor methods for the property; in this case the set accessor. Given you declared your property with the nonatomic
and retain
attributes as follows:
@property (nonatomic, retain) NSNumber *key;
the set accessor will look something like
- (void)setKey:(NSNumber *)value {
if (value != _key) {
id old = _key;
[value retain];
_key = value
[old release];
}
}
The set accessor is automatically generated by the compiler when you added:
@synthesize key=_key;
Conversely, calling
_key = key;
simply copies the value of the pointer in key
to _key
, but does not retain
the object referred to by key
. TranslationObject
does not assume ownership of key. If you did not want to use the accessor, the correct implementation would be
_key = [key retain];
精彩评论