使用dispatch_async时发布的实例变量?

时间:2013-04-03 16:05:46

标签: objective-c multithreading grand-central-dispatch

我从控制器初始化类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个特定通知时会执行

meth1meth2meth3,但它们始终以相同的顺序执行一次。

执行meth3时,我得到[NSPathStore2 UTF8String]: message sent to deallocated instance 0x107eb36a0。启用NSZombie时,Instruments会告诉我{libner}已发布aString。我可以通过copy aString method1 method3并在{{1}}结束时释放它来绕过这个问题。尽管如此,我认为这不是正确的方法,并且libdispatch释放实例变量似乎很奇怪。 谢谢你的帮助。

2 个答案:

答案 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来保留值。