【问题标题】:Passing data between objects/threads in Cocoa在 Cocoa 中的对象/线程之间传递数据
【发布时间】:2011-09-06 21:31:01
【问题描述】:

我从这样的控制器创建一个新线程:

[NSThread detachNewThreadSelector:@selector(makeMovie) toTarget:movieMaker withObject:nil];

从新线程/movieMaker 对象调用控制器上的方法的最佳方式是什么?

【问题讨论】:

    标签: objective-c cocoa macos


    【解决方案1】:

    在这种情况下,您可能希望使用委托模式。在你的电影制作者类的 .h 文件中:

    @protocol MovieMakerDelegate;
    
    @interface MovieMaker : NSObject
    {
        id<MovieMakerDelegate> delegate;
    
        ...
    }
    
    @property (nonatomic, assign) id<MovieMakerDelegate> delegate;
    
    ...
    
    @end
    
    @protocol MovieMakerDelegate <NSObject>
    - (void)movieMaker:(MovieMaker *)maker didSomething:(id)result;
    @end
    

    ...在它的 .m:

    @implementation MovieMaker
    
    @synthesize delegate;
    
    ...
    
    - (void)makeMovie
    {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
        ...
    
        [self performSelectorOnMainThread:@selector(notifyDelegateOfDoingSomethingWithObject:) withObject:someObject waitUntilDone:YES];
    
        [pool release];
    }
    
    - (void)notifyDelegateOfDoingSomethingWithObject:(id)someObject
    {
        [self.delegate movieMaker:self didSomething:someObject];
    }
    
    ...
    
    @end
    

    然后在你的控制器的头部,声明它支持 MovieMakerDelegate 协议,像这样:

    @interface MyController : Whatever <MovieMakerDelegate>
    

    在您的 .m 中,在致电您的 -detachNewThreadSelector:etc: 之前,请致电 movieMaker.delegate = self;。在您的控制器类上实现-movieMaker:didSomething: 方法,一切顺利。

    【讨论】:

    • 感谢您的回答。虽然这次我认为有一个更简单的解决方案,因为我只需要调用一个方法,但我以后肯定会使用它。谢谢。
    • @whg:没关系。无论如何,视图通常不应该知道它的控制器。即使协议只有一个方法,仍然值得使用协议将其作为委托关系。这有助于可重用性和可修改性(更改此应用程序或制作新的一个/端口到不同平台会更容易)。
    【解决方案2】:

    您可以使用withObject 参数将控制器实例传递给您的makeMovie 方法。

    [NSThread detachNewThreadSelector:@selector(makeMovie) toTarget:movieMaker withObject:self];
    

    如果适用,您还可以使用类似单例的模式从线程中检索控制器实例。

    【讨论】:

    • makeMovie 方法需要重新定义以接受参数(即具有签名-makeMovie:)。除此之外,是的,这也可以。
    • 刚刚看到你的答案。代表会更优雅,这是肯定的,但对于初学者来说可能有点混乱:)
    • 我试过这个,但我得到一个 'posix_spawn 致命错误:9! ' 错误,并假设我是这样的,因为我做错了什么。但它现在有效。谢谢。
    【解决方案3】:

    使用performSelectorOnMainThread:withObject:waitUntilDone:(或类似的performSelector:...方法),这是最简单的方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-24
      • 1970-01-01
      • 2010-10-04
      相关资源
      最近更新 更多