How is this object being prematurely released?
I received a crash report from Apple and I'm trying to determine what happened. I haven't been able to recreate the crash by following their steps and I haven't seen a similar crash in any of my testing. Here is the important parts of the crash report:
9 libobjc.A.dylib 0x00004838 objc_exception_throw + 64
10 CoreFoundation 0x000a167c -[NSObject(NSObject) doesNotRecognizeSelector:] + 96
11 CoreFoundation 0x000491d2 ___forwarding___ + 502
12 CoreFoundation 0x00048f88 _CF_forwarding_prep_0 + 40
13 TheApp 0x0001cd28 -[Tumblelog initWithDictionary:] (Tumblelog.m:40)
14 TheApp 0x0001ef8c -[TumblrEngine userFromRequest:] (TumblrEngine.m:589)
This looks to me like my dictionary is being prematu开发者_运维技巧rely released. This code path is called multiple times during most runs of the app and it hasn't crashed for me yet, so I'm confident that I'm not accidentally sending the wrong object to initWithDictionary
.
Here is the code from TumblrEngine
and Tumblelog
.
// TumblrEngine.m
- (TumblrUser *)userFromRequest:(ASIHTTPRequest *)request{
NSData *data = [request responseData];
NSError *parseError = nil;
NSXMLDocument *doc = [[[NSXMLDocument alloc] initWithData:data options:NSXMLDocumentTidyXML error:&parseError] autorelease];
NSDictionary *dictionary = [doc toDictionary];
NSDictionary *userDict = [dictionary valueForKeyPath:kParseKeyPathUserInfo];
TumblrUser *user = [[TumblrUser alloc] initWithDictionary:userDict];
NSArray *tumblelogs = [dictionary valueForKeyPath:kParseKeyPathTumblelogsInfo];
NSMutableArray *userTumblelogs = [NSMutableArray array];
for(NSDictionary *tumblelogDictionary in tumblelogs){
Tumblelog *tumblelog = [[Tumblelog alloc] initWithDictionary:tumblelogDictionary]; //line 589
[userTumblelogs addObject:tumblelog];
[tumblelog release];
}
[user setTumblelogs:userTumblelogs];
return [user autorelease];
}
// Tumblelog.m
- (id)initWithDictionary:(NSDictionary *)aDictionary{
if((self = [super init])){
[self setAvatarURL:[aDictionary restURLForKey:kParseKeyTumblelogAvatarURL]]; //line 40
// this was the line that started the crash
}
return self;
}
My main question is: do you see how it would be possible for aDictionary
to be released at any point between when it's created and when I attempt to use it in Tumblelog.m
?
Otherwise, I'm exploring if there's a problem loading the category on NSDictionary
. It works fine when I directly load the app onto my three test phones (iPhone 4/iOS 4.1, iPhone 3GS/iOS 4.0.1, iPhone 3G/3.1.3). The phone that the app crashed on was iPhone 4/iOS 4.1, identical to my main test phone.
Only other thing I can think of is perhaps something in the binary I sent Apple was corrupted. I'm doubtful this is the answer, since those binaries are checksumed, but I'm running out of ideas here. I don't want to just resubmit if it's going to crash again on the tester's phone.
It could be a threading issue (where the objects are being released on another thread), but that seems really unlikely with the code above.
It's far more likely (as @imaginaryboy says) that you don't really have a dictionary.
A much safer loop would look like this.
for(id tumblelogDictionary in tumblelogs){
if ([tumblelogDictionary isKindOfClass:[NSDictionary class]]) {
Tumblelog *tumblelog = [[Tumblelog alloc] initWithDictionary:tumblelogDictionary]; //line 589
[userTumblelogs addObject:tumblelog];
[tumblelog release];
} else {
// Appropriate error handling and / or logging.
}
}
NOTE: I haven't actually tried compiling this. It may have a typo or syntax error or two.
精彩评论