0

我对 iOS 和 Objective-C 比较陌生。

我正在开发一个项目,旨在使复杂(或“复合”)操作的组合尽可能简单:https ://github.com/stanislaw/SACompositeOperations

我在那里有四种操作:两种单一操作(同步和异步)和两种复杂操作(级联和“事务”)。单个操作被用作复杂操作的“原子”,所以我想让它们尽可能好,以符合 Objective-C 的最佳实践。

我感兴趣的是:我应该为这些单一操作选择什么代码

通过调用两个单一操作中的第一个“同步”,我的意思是:运行可能与完成处理程序异步的东西并锁定流程等待它完成。“异步”意味着真正的异步操作 - 只需以异步方式运行操作块。

这是我目前使用的单一操作代码:

同步操作

- (void)run:(syncOperationBlock)block {
    self.semaphore = dispatch_semaphore_create(0);

    block(self);

    while (dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_NOW))
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                                                       beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];
}

- (void)finish {
    dispatch_semaphore_signal(self.semaphore);
}

@end

异步操作

- (void)run:(asyncOperationBlock)block {
    dispatch_queue_t queue = dispatch_queue_create("async_operation.queue", 0);

    dispatch_async(queue, ^{
        block(self);
    });
}

如果有人可以为这些单一的同步和异步操作建议任何解决方案,我将不胜感激:更通用更常见,对于我描述的情况更好

很快:对于异步操作,强制同步操作的最佳代码是什么?

谢谢。

4

1 回答 1

0

自从我问了这个问题后,我的项目确实有了很大的发展。

从结构的角度来看,异步操作我不能说太多有趣:在我的项目中,它们都是基于 dispatch_async 的,并且最有价值的功能是通过大量使用块来实现的(主要是:将操作本身让给它们执行的块,允许控制这些操作的流程)。

这里要注意的更有趣的事情是我目前用于同步(或“强制同步”)操作的代码 - 虽然在实际应用程序中应该避免使用它们,但它们仍然适用于单元测试:一个例子是需要理顺在单元测试用例的上下文中,异步网络请求的卷曲异步流测试其结果。

尽管我将其发布为对我的非特定问题的回答,但我仍然非常希望看到任何关于我的 SASyncOperation 是否足以用于强制同步操作的权威答案(从某种意义上说,我已经在这个问题中描述了它)或也许它可以进一步改进。

当前编写的SASyncOperation

  • 如果它在主线程上运行,则不会阻塞主线程。
  • 不会像使用while(!completed){}的简单方法那样产生过多的 CPU 轮询;做。

这是代码中最重要的部分:

#import "SASyncOperation.h"

@interface SASyncOperation () {
    BOOL _isOnMainThread;
    dispatch_semaphore_t _semaphore;
}
@end

@implementation SASyncOperation

// …

- (void)start {
    _semaphore = dispatch_semaphore_create(0);

    _operation(self);

    if (_finished) return;

    if ((_isOnMainThread = [NSThread isMainThread])) {
        while (dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_NOW)) {
            CFRunLoopRunInMode(kCFRunLoopDefaultMode, [[NSDate distantFuture] timeIntervalSinceNow], NO);
        }
    } else {
        dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
    }

    _finished = YES;
}

- (void)run:(^(void)(SASyncOperation *)block {
    _operation = [block copy];

    [self start];
}

- (void)finish {
    _finished = YES;

    dispatch_semaphore_signal(_semaphore);

    if (_isOnMainThread) {
        dispatch_async(dispatch_get_main_queue(), ^{
            CFRunLoopStop(CFRunLoopGetMain());
        });
    }
}

// …
@end

这就是 SASyncOperation 的使用方式:

SASyncOperation *syncOperation = [[SASyncOperation alloc] init];

[syncOperation run:^(SASyncOperation *so) {
    doSomeThingMultiQueuedPossiblyMultiblockedAndAsynchronous(^{
        soOver = YES;
        [so finish];
    });
}]; // <- (*)

// (*) The flow will be stopped at this point waiting when 'so' operation will finish itself
于 2013-01-11T04:08:12.933 回答