我是iOS和Objective-C的新手。
我正在开发一个项目,旨在尽可能简化复杂(或“复合”)操作的组合:https://github.com/stanislaw/SACompositeOperations
我在那里有四种操作:两种单一操作(同步和异步)和两种复杂操作(级联和“事务”)。单个操作被用作复杂操作的“原子”,因此我希望尽可能地使它们符合Objective-C最佳实践。
我感兴趣的是:我应该为这些单一操作选择哪些代码?
通过调用两个单个操作中的第一个“sync”,我的意思是:运行一些可能与完成处理程序异步的东西并锁定流程等待它完成。 “异步”意味着真正的异步操作 - 只需以异步方式运行操作块。
以下是我目前使用的单个操作代码:
同步操作
- (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);
});
}
如果有人可以为这些单同步和异步操作建议任何解决方案,我将感激不尽:更通用,更常见,更好< / em>对于我所描述的案例
简而言之:对于异步操作,强制同步操作的最佳代码是什么?
感谢。
答案 0 :(得分:0)
自从我提出这个问题以来,我的项目确实发生了很大变化。
从结构的角度来看,我不能说异步操作很有趣:在我的项目中,它们都基于dispatch_async,最有价值的功能是通过密集使用块来实现的(主要是:将操作本身放到了他们执行的块,允许控制这些操作的流程。)
这里要注意的更有趣的是我目前用于同步(或“强制同步”)操作的代码 - 尽管在真实应用程序中应避免使用它们,但它们仍然适用于单元测试:一个例子是在单元测试用例的上下文中,需要理顺异步网络请求的卷曲异步流以测试其结果。
虽然我发布这个作为我的非特定问题的答案,但我仍然希望看到任何关于我的SASyncOperation是否足以用于强制同步操作的权威性答案(在某种意义上我已经在此描述了它)问题)或者可能会进一步改进。
目前正在编写这是代码中最重要的部分:
#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