Ios NSOperationQueue:无法理解订单

Ios NSOperationQueue:无法理解订单,ios,objective-c,multithreading,cocoa-touch,objective-c-blocks,Ios,Objective C,Multithreading,Cocoa Touch,Objective C Blocks,我无法理解NSOperationQueue的工作方式 假设我有: NSOperationQueue *queue = [[NSOperationQueue alloc] init]; queue.maxConcurrentOperationCount=1; [queue addOperationWithBlock:^{ [someObject someSelector]; }]; [queue addOperationWithBlock:^{

我无法理解
NSOperationQueue
的工作方式

假设我有:

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        queue.maxConcurrentOperationCount=1;

        [queue addOperationWithBlock:^{
[someObject someSelector];
}];

        [queue addOperationWithBlock:^{
[someObject anotherSelector];
}];
第二个块甚至在第一个块完成之前就被调用了,这与我想要的正好相反。我尝试改用–
performSelectorOnMainThread:withObject:waitUntilDone:
,但第二个块仍在首先执行——可能是因为块线程没有在主线程上完成,因此它没有被waitUntilDone阻塞。我在someSelector块中添加了一个断点,它是在第二个块中的断点之后到达的


我不太明白。救救我

如果操作之间存在明确的依赖关系,则使用
addDependency

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount=1;

NSOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
    [someObject someSelector];
}];

NSOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
    [someObject anotherSelector];
}];

[operation2 addDependency:operation1];

[queue addOperation:operation1];
[queue addOperation:operation2];

如果您的操作正在执行异步活动,那么您应该定义一个自定义操作,并且在异步任务完成时只调用
completeOperation
(它将发布
isFinished
消息)

因此,使用下面的代码,它不会启动
operation2
,直到
SomeOperation
对象
operation1
中的
main
中启动的异步任务调用其
completeOperation
方法

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount=1;

NSOperation *operation1 = [[SomeOperation alloc] init];

NSOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
    [someObject anotherSelector];
}];

[operation2 addDependency:operation1];

[queue addOperation:operation1];
[queue addOperation:operation2];

我还是不太明白。为了保证FIFO,我应该对我的代码做什么?我认为必须设置操作依赖项来保证操作顺序。只需使用
addDependency
就可以了,除非这两种方法中的任何一种都是异步运行的,在这种情况下,您可能需要使用
NSOperation
子类。啊,是的,这是我的问题。在我的someSelector方法中是对执行同步URL请求的NSObject的调用,但我猜对该方法的调用本身是异步的。具体来说,它看起来像data=[customObject getDataWithURL:(NSString*)url]——但不能对具有返回值的对象调用PerformSelect或WaitUntildOne。我打算调查NSInvocation,在这种情况下这是正确的做法吗?我在这里提出了一个新问题:没有解决我的特殊问题,但肯定回答了我提出的问题。@JoshDG我已经用示例代码更新了我的答案,用于将异步任务包装到自定义的
NSOperation
中,在异步过程完成之前,它不会发布
isFinished
。非常感谢所有这些代码!所以,正如您所说,最终发生的事情是,我将对NSURLConnection的调用放在另一个NSOperationQueue中,我猜这样做是将它放在另一个线程中?我最后取出了第二个操作队列,现在它按预期运行。我的推理正确吗?@JoshDG Yep,这完全有道理:将添加到队列中的块本身同步(例如通过消除冗余操作队列),这样就可以修复它。当您无法(或不想)使提交的操作同步时(例如,通常人们不喜欢使用
sendSynchronousRequest
,因为您会丢失很多功能),上述将异步进程包装到自定义
NSOperation
中的技术是一种有用的模式。但是看起来你有一些适合你的东西。我真的很感谢你的帮助!
//  SomeOperation.m

#import "SomeOperation.h"

@interface SomeOperation ()
@property (nonatomic, readwrite, getter = isFinished)  BOOL finished;
@property (nonatomic, readwrite, getter = isExecuting) BOOL executing;
@end

@implementation SomeOperation

@synthesize finished  = _finished;
@synthesize executing = _executing;

#pragma Configure basic operation

- (id)init
{
    self = [super init];
    if (self) {
        _finished  = NO;
        _executing = NO;
    }
    return self;
}

- (void)start
{
    if ([self isCancelled]) {
        self.finished = YES;
        return;
    }

    self.executing = YES;

    [self main];
}

- (void)completeOperation
{
    self.executing = NO;
    self.finished  = YES;
}

- (void)main
{
    // start some asynchronous operation

    // when it's done, call `completeOperation`
}

#pragma mark - Standard NSOperation methods

- (BOOL)isConcurrent
{
    return 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"];
}

@end
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount=1;

NSOperation *operation1 = [[SomeOperation alloc] init];

NSOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
    [someObject anotherSelector];
}];

[operation2 addDependency:operation1];

[queue addOperation:operation1];
[queue addOperation:operation2];