实现在Objective-C中链接消息的机制?

时间:2012-07-08 06:50:38

标签: iphone objective-c ios block

我正在编写一个需要在另一个方法完成后运行方法的应用程序。 (常见情况,对吗?)

我试图实现链式方法。我提出的最好的方法是致电performSelector:withObject:afterDelay:。我不确定这是否是最好的方法。我已经研究了Cocos2d游戏引擎如何实现其CCSequence课程,但我不确定我是否理解它。

我怀疑块会在这里做得很好,除了我不确定如何将它们用作回调对象或其他任何东西。

如何实现一个接一个地运行方法的机制? (我打算使用计时器或块,但我不知道在这种情况下我是如何使用块的。)

修改

为了澄清,我试图实施一个类似cocos2d' CCSequence类的系统,它采用了一些方法和#34;发送"他们按顺序。像动画这样的东西,需要花费不止一个时钟周期才能运行。

我不想阻止主线程,也不想相互硬编码方法。 Cocos2d有一个排序系统,我可以将方法传递给队列并按顺序运行。

编辑2:

此外,我希望能够取消我的预定队列,所以我不确定GCD是否适合这一点。可以取消GCD串行队列吗?

5 个答案:

答案 0 :(得分:7)

您可以使用 Thread Migration

的技巧

接下来是一个名为 GCD-Grand Central Dispatch

的有趣任务
  

Grand Central Dispatch(GCD)是Apple Inc.开发的一项技术。   优化具有多核处理器的系统的应用程序支持   和其他对称多处理系统。它是一个实现   基于线程池模式的任务并行。

     

GCD通过允许可运行的程序中的特定任务来工作   并行排队等待执行,具体取决于可用性   处理资源,安排它们在任何一个上执行   可用的处理器核心

     

Dispatch Queues 是维护任务队列的对象,无论是匿名代码块还是函数,并在其中执行这些任务   转。该库自动创建多个不同的队列   同时执行多个任务的优先级,选择   根据操作环境运行的最佳任务数。一个   客户端到库也可以创建任意数量的串行队列,   它们按照提交的顺序执行任务,一次一个。   因为串行队列一次只能运行一个任务,每个任务   提交到队列对于其他任务至关重要   队列,因此可以使用串行队列而不是锁定   争用资源。

     

Dispatch队列与其他队列同时执行任务   派遣队列。任务的序列化仅限于任务中的任务   单个调度队列。

     

在您的情况下,您可以使用串行调度队列

     

当您希望在a中执行任务时,串行队列非常有用   特定的顺序。串行队列一次只执行一个任务   总是从队列的头部拉出任务。您可以使用序列号   队列而不是锁来保护共享资源或可变数据   结构体。与锁不同,串行队列可确保执行任务   以可预测的顺序执行。只要你提交你的任务   异步到串行队列,队列永远不会死锁。

     

与为您创建的并发队列不同,您必须这样做   显式创建和管理您要使用的任何串行队列。您   可以为您的应用程序创建任意数量的串行队列   避免仅仅作为一种手段来创建大量的串行队列   尽可能多地同时执行任务。如果你想   同时执行大量任务,将它们提交给其中一个   全局并发队列。创建串行队列时,请尝试识别   每个队列的目的,例如保护资源或   同步应用程序的一些关键行为。

dispatch_queue_t queue;

queue = dispatch_queue_create("com.example.MyQueue", NULL);
     

此代码显示了创建自定义串行队列所需的步骤。   dispatch_queue_create函数有两个参数:队列   名称和一组队列属性。调试器和性能工具   显示队列名称以帮助您跟踪任务的执行情况   执行。队列属性保留供将来使用,并且应该   是NULL。

     

Grand Central Dispatch提供了允许您访问多个功能的功能   来自您的应用程序的常见调度队列:

     

使用 dispatch_get_current_queue 功能进行调试   或者测试当前队列的身份。调用此功能   从块对象内部返回块所在的队列   提交(并且现在可能正在运行)。打电话给这个   来自块外部的函数返回默认的并发队列   为您的申请。

     

使用 dispatch_get_main_queue 函数获取序列号   与应用程序主线程关联的调度队列。这个   为Cocoa应用程序自动创建队列   调用dispatch_main函数或配置的应用程序   运行循环(使用CFRunLoopRef类型或NSRunLoop对象)   在主线上。

     

使用 dispatch_get_global_queue 功能获取任何内容   共享并发队列。

     

注意:您无需保留或释放任何全局调度   队列,包括并发调度队列或主调度   队列。任何保留或释放队列的尝试都将被忽略。

来源:Concurrency Programming Guide

答案 1 :(得分:6)

使用串行GCD队列怎么样?

  

私人调度队列

     

串行队列(也称为专用调度队列)按照将它们添加到队列的顺序一次执行一个任务。当前正在执行的任务在由调度队列管理的不同线程(可能因任务而异)上运行。串行队列通常用于同步对特定资源的访问。   您可以根据需要创建任意数量的串行队列,并且每个队列与所有其他队列同时运行。换句话说,如果您创建四个串行队列,则每个队列一次只执行一个任务,但最多可以同时执行四个任务,每个队列一个。有关如何创建串行队列的信息,请参阅“创建串行调度队列”。

source

如果您希望在后台线程中处理所有消息,这将非常有用。

答案 2 :(得分:2)

有两个performSelector方法可以等待完成,无需猜测时间。

[self performSelector:<#(SEL)#> onThread:<#(NSThread *)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>];

[self performSelectorOnMainThread:<#(SEL)#> withObject:<#(id)#> waitUntilDone:<#(BOOL)#>];

答案 3 :(得分:1)

听起来您想查看NSOperationQueueNSOperation以及NSBlockOperationNSInvocationOperation。与GCD队列不同,NSOperationQueue支持取消作业。

您可以创建自己的队列并将其最大并发操作数设置为1,以强制它以串行方式执行操作。或者,您可以在操作之间设置依赖关系,以强制这些操作以串行方式运行。

Concurrency Programming Guide

中的“操作队列”一章开始

答案 4 :(得分:1)

我终于找到了我正在寻找的东西。完成块。简单地说,我会写一个这样的方法:

- (void) performSomeActionWithCompletion:(void (^)()) completion{

     [self someAction];

     if(completion()){
       completion(); 
     }

}

现在我可以这样调用我的方法:

[self performSomeActionWithCompletion:^{
  NSLog(@"All done! (Well, not the async stuff, but at any rate...)");
}];