如何在目标c中为我的一系列任务创建队列

ant*_*014 3 synchronization objective-c synchronized grand-central-dispatch ios

我试图将我的所有任务从不同的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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但它不起作用,总有一种情况,这个属性将一直保持不死.

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

我的问题是:

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

感谢你.

Rob*_*Rob 6

假设您的"与其他设备通信"是异步发生的,有两种方法:

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

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

    @property (nonatomic, strong) NSMutableArray *itemsToSend;
    
    Run Code Online (Sandbox Code Playgroud)

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

    [self sendItem:itemsToSend[0]];
    
    Run Code Online (Sandbox Code Playgroud)

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

    [itemsToSend removeObjectAtIndex:0];
    if ([itemsToSend count] > 0)
    {
        [self sendItem:itemsToSend[0];
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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
    
    Run Code Online (Sandbox Code Playgroud)

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

    // 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];
    
    Run Code Online (Sandbox Code Playgroud)

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

    但希望你能得到这个想法.您定义了一个操作类来执行您的任务,然后您可以创建一个串行队列并提交您的任务,它们将按顺序一个接一个地执行.

如果您的"与其他设备通信"进程同步发生,那么它就比这更容易了.(但话又说回来,如果它同步发生,你可能不会一直在搞定时器和状态标志.)