私は、EmberJS の JS バックグラウンドから来た iOS 開発の初心者です。EmberJS アプリを iOS アプリに移植したいと考えています。したがって、iOS アプリで同様の構造を使用したいと考えています。EmberJS は Promise を多用するため、iOS 用に似たものを探していたところ、ReactiveCocoa にたどり着きました。ReactiveCocoa の紹介で、このフレームワークを使用して Promises を実装できると言われています。やってみたのですが、うまくいきません。私は非常に単純な例から始めたかった:
- 非同期ネットワーク リクエストを作成します (UITableViewController を満たすため)。このメソッドから promise を返します。
- この promise にサブスクライブし、終了したら TableView をリロードします。
データが正常にロードされた後、いくつかのことを実行する必要があるため、この方法で実行したいと考えています。私のアプローチは基本的に機能しますが、次の問題が発生しています。
- リクエストが終了した直後に TableView がリロードされません。
subscribeCompleted
リクエストが終了した直後にログ ステートメントが表示されます。ただし、TableView は空白のままです。- TableView は、数秒待ってからデータをロードします。
- ログ出力を見た後に TableView のスクロールを開始すると、TableView が突然読み込まれます。
バックグラウンドスレッドでデータをフェッチしているため、これが発生する可能性があると思われます。promise ( subscribeCompleted
) の解決はバックグラウンド スレッドでも発生する可能性があり、Cocoa Touch がこれを気に入らない可能性があると思います。私は正しいですか?しかし、これが事実である場合、どのように約束を実装する必要がありますか?
ReactiveCocoa を使い始めるのを手伝ってくれることを願っています。どうも!:-)
更新:reloadData
toを a で
ラップすることでなんとか修正できましたdispatch_async(dispatch_get_main_queue(), ^{...
が、これが最善の方法なのか、ReactiveCocoa によって推奨されているのかはまだわかりません。だから私はまだいくつかの答えを聞きたいと思っています:-)
// this method wants to use the promise
- (void) loadDataAndPerformActionsAfterwards{
RACSignal *signal = [self fetchObjects];
[signal subscribeCompleted:^{
NSLog(@"Entered subscribeCompleted block signal!");
NSLog(@"Number of objects: %i", self.objects.count);
[self.tableView reloadData];
}];
}
// this method returns a promise. I omitted some parts but it shows basically how i go about resolving the promise.
- (RACSignal*) fetchMoviesForCurrentFormState{
return [RACSignal createSignal:^RACDisposable*(id<RACSubscriber> subscriber) {
NSLog(@"RAC createSignal Block called");
NSString *requestURL = @"...";
NSURL *urlObj = [NSURL URLWithString: requestURL];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData* data = [NSData dataWithContentsOfURL: urlObj];
if(data){
[self performSelectorOnMainThread:@selector(fetchedData:)
withObject:data waitUntilDone:YES];
[subscriber sendCompleted];
}else{
// Not implemented yet: handle the error case
[subscriber sendCompleted];
}
});
// actually i do not know yet what i should return here. Copied from a basic example.
return nil;
}];
}