[objective-c] iOS 시작 백그라운드 스레드

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)
    }


답변