3

我正在尝试将我的所有任务从不同的 NSTimer 分配到一个队列,以便可以一项一项地完成任务。任务完成后,我将通过另一个班级的委托通知我。

更新:任务
我的应用程序正在尝试与另一台设备通信,但该设备一次只能接受一个任务,所以我必须每次向它发送一个任务,并确保我收到了表明任务已完成的确认完成,然后我可以要求它做下一个任务。

我尝试使用一个 BOOL 来控制 IDLE 的状态,SENDING 状态。但我无法使其同步,即使我使用了以下代码:

@property (atomic) BOOL ready2Send;
@end
@implementation ...
@synthesize ready2Send = _ready2Send;
- (BOOL)ready2Send
{
        BOOL tmp;
        @synchronized(self) {
            tmp = _ready2Send;
        }
        return tmp;
    }

- (void)setReady2Send:(BOOL)ready2Send
{
    @synchronized(self){
        if (_ready2Send != ready2Send) {
            _ready2Send = ready2Send;
        }
    }
}

但它不起作用,总有一种情况,这个属性会一直保持 NO 直到死亡。

所以我开始考虑使用队列,也许是dispatch_queue。我的 UIViewController 需要一个队列。

我的问题是:

  1. 我上面的代码有什么问题?
  2. 如何用 dispatch_queue 实现我的想法。
  3. 如果有任何其他解决方案比上述两个更好,请告诉我。

感谢你。

4

1 回答 1

6

假设您的“与另一台设备通信”是异步发生的,有两种方法:

  1. 在完成一项任务后,启动下一项任务。

    例如,您可能有一个NSMutableArray要发送到其他设备的项目:

    @property (nonatomic, strong) NSMutableArray *itemsToSend;
    

    一旦你填充了这个数组,要开始这个过程,你可以做一个

    [self sendItem:itemsToSend[0]];
    

    完成后,您可以执行以下操作:

    [itemsToSend removeObjectAtIndex:0];
    if ([itemsToSend count] > 0)
    {
        [self sendItem:itemsToSend[0];
    }
    
  2. 更优雅(虽然更复杂)的方法是子类化NSOperation(请参阅定义自定义操作)。例如,您可以:

    @interface TaskOperation ()
    
    @property (nonatomic, readwrite, getter = isExecuting) BOOL executing;
    @property (nonatomic, readwrite, getter = isFinished)  BOOL finished;
    
    @end
    
    @implementation TaskOperation
    
    @synthesize finished  = _finished;
    @synthesize executing = _executing;
    
    - (id)init
    {
        self = [super init];
        if (self) {
            _executing = NO;
            _finished = NO;
        }
        return self;
    }
    
    - (void)start
    {
        if (self.isCancelled) {
            self.finished = YES;
            return;
        }
    
        self.executing = YES;
    
        // initiate your time consuming process here
        // when it's done, have it call `[self complete]`
    }
    
    - (void)complete
    {
        self.executing = NO;
        self.finished = YES;
    }
    
    - (void)setExecuting:(BOOL)executing
    {
        [self willChangeValueForKey:@"isExecuting"];
        _executing = executing;
        [self didChangeValueForKey:@"isExecuting"];
    }
    
    - (void)setFinished:(BOOL)finished
    {
        [self willChangeValueForKey:@"isFinished"];
        _finished = finished;
        [self didChangeValueForKey:@"isFinished"];
    }
    
    - (BOOL)isConcurrent
    {
        return NO;
    }
    
    @end
    

    然后,您启动这些发送请求的进程可以执行以下操作:

    // create a serial queue
    
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 1;
    
    TaskOperation *operation;
    
    // create and submit the three operations
    
    operation = [[TaskOperation alloc] init ...];
    [queue addOperation:operation];
    
    operation = [[TaskOperation alloc] init ...];
    [queue addOperation:operation];
    
    operation = [[TaskOperation alloc] init ...];
    [queue addOperation:operation];
    

    请注意,我在 init 方法之后添加了省略号,因为通常在这种情况下,您编写自己的自定义 init 方法来传递操作完成其任务所需的任何信息(例如,正在传输的内容的名称,可能正在传输的位置等)。

    但希望你能明白。您定义一个操作类来执行您的任务,然后您可以创建一个串行队列并提交您的任务,它们将按顺序执行,一个接一个。

如果您的“与另一台设备通信”过程同步发生,那么它甚至比这更容易。(但话又说回来,如果它是同步发生的,你可能不会一开始就搞乱计时器和状态标志。)

于 2013-07-02T20:46:17.107 回答