我从控制器初始化类myClass的对象,然后在3个不同的dispatch_async
函数内对该对象执行3个方法。
这是myClass:
@interface myClass : NSObject
@property (retain) NSString* aString;
-(void)method1;
-(void)method2;
-(void)method3;
@end
@implementation myClass
@synthetize aString;
-(void)method1 {
aString = [NSTemporaryDirectory() stringByAppendingPathComponent:@"my_file"];
[someData writeToFile:aString];
// ...
}
-(void)method2 {
// ...
}
-(void)method3 {
aFunction([aString UTF8String]);
}
@end
和控制器
-(void) viewDidLoad{
myClass* myObject = [[myClass alloc] init];
}
-(void)meth1 {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[myObject method1];
});
}
-(void)meth2 {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[myObject method2];
});
}
-(void)meth3 {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[myObject method3];
});
}
收到3个特定通知时会执行 meth1
,meth2
和meth3
,但它们始终以相同的顺序执行一次。
执行meth3
时,我得到[NSPathStore2 UTF8String]: message sent to deallocated instance 0x107eb36a0
。启用NSZombie时,Instruments会告诉我{libner}已发布aString
。我可以通过copy
aString
method1
method3
并在{{1}}结束时释放它来绕过这个问题。尽管如此,我认为这不是正确的方法,并且libdispatch释放实例变量似乎很奇怪。
谢谢你的帮助。
答案 0 :(得分:2)
使用aString
作为属性 - self.aString
(请注意,self.myString = anotherString;
只是[self setMyString:anotherString]
),因此它将为您保留此字符串(如您在财产声明)像这样:
- (void)setMyString:(NSString *)newString {
[newString retain];
[_myString release];
// Make the new assignment.
_myString = newString;
}
每个属性都使用iVar备份,因此直接使用iVar(无点语法)不会调用setter(也不会为您保留新值)。
查看Apple文档here
修改强>:
stringByAppendingPathComponent:
是一个工厂方法,因此它会返回一个自动释放的字符串。
答案 1 :(得分:-1)
您正在修改块中的字符串,因此不会保留其值。一旦块执行完毕,你需要使用__block来保留值。