iOS 기기에 작은 sqlitedb가 있습니다. 사용자가 버튼을 누르면 sqlite에서 데이터를 가져 와서 사용자에게 보여줍니다.
이 가져 오기 부분은 백그라운드 스레드에서 수행하고 싶습니다 (UI 메인 스레드를 차단하지 않기 위해). 나는 이렇게한다-
[self performSelectorInBackground:@selector(getResultSetFromDB:) withObject:docids];
가져 오기 및 약간의 처리 후 UI를 업데이트해야합니다. 그러나 (좋은 방법으로) 백그라운드 스레드에서 UI 업데이트를 수행해서는 안됩니다. 나는 selector
그렇게 메인 스레드를 호출합니다 –
[self performSelectorOnMainThread:@selector(showResults) withObject:nil waitUntilDone:NO];
하지만 내 앱은 첫 번째 단계에서 충돌합니다. 즉, 백그라운드 스레드를 시작합니다. iOS에서 백그라운드 스레드를 시작하는 방법이 아닙니까?
업데이트 1 :[self performSelectorInBackground....
이 스택 트레이스를 얻은 후 정보가 없습니다.
업데이트 2 : 나는 심지어 그렇게 배경 스레드를 시작하려고 시도
[NSThread detachNewThreadSelector:@selector(getResultSetFromDB:) toTarget:self withObject:docids];
했지만 여전히 동일한 스택 추적을 얻습니다.
명확히하기 위해 메인 스레드에서이 작업을 수행하면 모든 것이 원활하게 실행됩니다.
업데이트 3 이것은 배경에서 실행하려는 방법입니다.
- (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:
하여 새 스레드를 생성하는 경우 수행 된 선택기는 새 스레드의 자동 릴리스 풀, 실행 루프 및 기타 구성 세부 정보를 설정합니다 . Apple의 Threading Programming Guide 에서 “Using NSObject to Spawn a Thread” 를 참조하십시오 .
그래도 Grand Central Dispatch를 사용하는 것이 더 나을 것입니다 .
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self getResultSetFromDB:docids];
});
GCD는 최신 기술이며 메모리 오버 헤드 및 코드 라인 측면에서 더 효율적입니다.
위의 코드를 더 간단하게 만들고 Apple의 최신 GCD 코드 예제를 따라 잡는 변경 사항을 제안한 Chris Nolet 에게 모자 팁으로 업데이트되었습니다 .
답변
실제로 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
내부에 무엇이 있는지, 보관 중인지 확인하십시오 .
이렇게하면 잘못된 것이 없는지 확인할 수 있습니다.
답변
iOS와 함께 제공되는 기본 sqlite 라이브러리는 SQLITE_THREADSAFE 매크로를 사용하여 컴파일되지 않습니다. 이것이 코드가 충돌하는 이유가 될 수 있습니다.
답변
Swift 2.x 답변 :
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
self.getResultSetFromDB(docids)
}