そのため、暇なときに HTTP リクエストの「エンジン」に取り組んでいます。私が構築しようとしているのは、iPhone アプリの汎用オブジェクトに対する要求/解析応答を生成する「エンジン」です。
そして何よりも、_常に_ UI をコールバックする必要があります。
何が起こったとしても (NSURLRequest のタイムアウト / 解析エラー / NSExcept の発生) (おそらく SIG もいつか ?)
だから私はブロックとdispatch_onceを使って恐ろしいものを作りました。動作しますが、この Clang 警告が表示されます。つまり、リクエストが機能し、例外が発生した場合、UI は明らかに 1 回呼び出されます。
「dispatch_once」への呼び出しは、述語値にローカル変数「once」を使用します。このような一時的なメモリを述語に使用することは潜在的に危険です
これが問題の核心
// invoke a bloc in a proper thread with a proper autorelease / trycatch / logs
static inline void api_dispatch_concurrent(EngineOnceCallback block, SEL caller, EngineCallback callback) {
dispatch_async(APIengineQueue(), ^{ // serial dispatch_queue
@autoreleasepool {
dispatch_once_t once = 0;
@try {
// block may callback using 'once'
(block) ? block(once) : NULL;
}
@catch (NSException *exception) {
[[ACLogs sharedLogs] logException:exception caller:caller
class:[ACRetroscopeEngine class]];
APILog(@"NSException invoking API block:%@", exception);
dispatch_once(&once, ^{
APILog(@"Perform callback as recover from exception");
ACResponse *defaultResponse = [ACResponse responseWithException:exception];
try_catch(block_safe_invoke_main_thread(callback, defaultResponse));
});
}
@finally {
}
}
});
}
そこで使用されるいくつかのマクロ:
#define block_safe_invoke(block, ...) (block != NULL) ? block(__VA_ARGS__) : NULL;
#define block_safe_invoke_main_thread(block, ...) \
if ([NSThread isMainThread]) { \
block_safe_invoke(block, __VA_ARGS__) \
} else { \
dispatch_sync(dispatch_get_main_queue(), ^{ \
block_safe_invoke(block, __VA_ARGS__) \
}); \
} \
前もって感謝します:p