问题
I'm using the Pinterest iOS SDK to share an item in my iPad app. The following snippet of code will always crash with a message sent to deallocated instance
on the line with the comment:
NSString *clientId = [NSMutableString stringWithString:@"1431665"];
NSLog(@"clientId: %@", clientId);
Pinterest *pinterest = [[Pinterest alloc] initWithClientId:clientId];
NSLog(@"gone: %@", clientId); // <- CRASH!
I'm using NSMutableString stringWithString
to simulate the conditions in my app. I don't actually use that line in my code.
Even if don't output the clientId
on the last line, the app crashes when leaving the block. I assume it's because ARC is trying to release the reference which has already been deallocated.
It seems like the Pinterest SDK must be doing something wonky and trashing the string I'm passing in. Is there some way I can get around this while they fix their code?
EDIT 1
Simplified the test case.
EDIT 2
It looks like the Pinterest SDK is consuming the clientId
argument. Based on the clang ARC documentation, the way to indicate this to clang is to indicate this with __attribute((ns_consumed))
.
New question: Is it possible to indicate this to ARC without modifying the signature of the method to add the attribute?
EDIT 3
So this works, but it's ugly as sin? Is there another way?
NSString *clientId = [NSMutableString stringWithString:@"1431665"];
[clientId performSelector:NSSelectorFromString(@"retain")]; // <- UGLY!
NSLog(@"clientId: %@", clientId);
Pinterest *pinterest = [[Pinterest alloc] initWithClientId:clientId];
NSLog(@"gone: %@", clientId);
回答1:
What I did was make a static variable that represented the Pinterest class:
//I put this outside my @implementation code at the top of my m file
static Pinterest *_pinterest = nil;
// instantiating
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_pinterest = [[Pinterest alloc] initWithClientId:clientId];
});
I think that Pinterest assumed that everyone would use their class as a static singleton because that's probably what they do internally. To be fair, I don't foresee using multiple client ID's with a single app in most cases. I agree, though, this is a stupefying oversight on their part. They didn't even document this behavior, what were they thinking?!
回答2:
My current workaround, which seems to be the least hacky of the ideas so far is this wrapper class that doesn't use ARC:
+ (void) createPinWithClientId:(NSString *)clientId
imageURL:(NSURL *)imageURL
sourceURL:(NSURL *)sourceURL
description:(NSString *)descriptionText {
Pinterest *pinterest = [[Pinterest alloc] initWithClientId:clientId];
[pinterest createPinWithImageURL:imageURL
sourceURL:sourceURL
description:descriptionText];
}
The key is to disable ARC for the class, which keeps the runtime from deallocating the clientId
.
来源:https://stackoverflow.com/questions/17139092/message-sent-to-deallocated-instance-using-pinterest-sdk