IOSデバイスに小さなsqlitedbがあります。ユーザーがボタンを押すと、sqliteからデータを取得してユーザーに表示します。
このフェッチ部分は、バックグラウンドスレッドで行いたい(UIメインスレッドをブロックしないため)。私はこれをそうする-
[self performSelectorInBackground:@selector(getResultSetFromDB:) withObject:docids];
取得と少しの処理の後、UIを更新する必要があります。ただし、(良い習慣として)バックグラウンドスレッドからUIの更新を実行しないでください。私はメインスレッドでselector
を次のように呼び出します-
[self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];
しかし、私のアプリは最初のステップでクラッシュします。つまり、バックグラウンドスレッドを開始します。これはiOSでバックグラウンドスレッドを開始する方法ではありませんか?
PDATE 1:[self performSelectorInBackground....
の後、このスタックトレースを取得しましたが、何も情報がありません-
PDATE 2:私も、バックグラウンドスレッドを開始しようとしました-[NSThread detachNewThreadSelector:@selector(getResultSetFromDB:) toTarget:self withObject:docids];
ですが、それでも同じスタックトレースを取得します。
私が明確にするように、メインスレッドでこの操作を実行すると、すべてがスムーズに実行されます...
PDATEこれは、バックグラウンドから実行しようとしているメソッドです
- (void)getResultSetFromDB:(NSMutableArray *)toProceessDocids
{
SpotMain *mirror = [[SpotMain alloc] init];
NSMutableArray *filteredDocids = toProceessDocids;
if(![gMediaBucket isEqualToString:@""])
filteredDocids = [mirror FetchDocIdsForMediaBucketWithDocID:filteredDocids mBucket:gMediaBucket numRes:-1];
if(![gMediaType isEqualToString:@""])
filteredDocids = [mirror FetchDocIdsForMediaType:filteredDocids mediaType:gMediaType numRes:-1];
if(![gPlatform isEqualToString:@""])
filteredDocids = [mirror FetchDocIdsForPlatformID:filteredDocids platformId:@"1" numRes:-1];
self.resultSet = [mirror FetchObjectFromDocid:filteredDocids];
[filteredDocids release];
[mirror release];
[self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];
return;
}
performSelectorInBackground:withObject:
を使用して新しいスレッドを生成する場合、実行されるセレクターは、新しいスレッドの自動解放プール、実行ループ、およびその他の構成の詳細を設定します。 「NSObjectを使用したスレッドの生成」 AppleのThreading Programming Guideにあります。
ただし、 Grand Central Dispatch を使用した方がよいでしょう。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self getResultSetFromDB:docids];
});
GCDは新しいテクノロジーであり、メモリオーバーヘッドとコード行の点でより効率的です。
更新Chris Nolet へのハットチップ、上記のコードをよりシンプルにし、維持する変更を提案した人Appleの最新のGCDコード例を使用します。
GCDを使用すると、実際には非常に簡単です。典型的なワークフローは次のようなものです。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
dispatch_async(queue, ^{
// Perform async operation
// Call your method/function here
// Example:
// NSString *result = [anObject calculateSomething];
dispatch_sync(dispatch_get_main_queue(), ^{
// Update UI
// Example:
// self.myLabel.text = result;
});
});
GCDの詳細については、 Appleのドキュメントはこちら をご覧ください。
NSZombieEnabled を有効にして、どのオブジェクトが解放されてからアクセスされるかを確認します。次に、getResultSetFromDB:
がそれと関係があるかどうかを確認します。また、docids
の内部に何かがあるかどうか、および保持されているかどうかを確認します。
これにより、問題がないことを確認できます。
Swift 2.xの答え:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
self.getResultSetFromDB(docids)
}
IOSに付属するデフォルトのsqliteライブラリは、SQLITE_THREADSAFEマクロを使用してコンパイルされません。これが、コードがクラッシュする理由かもしれません。