2012-04-07 5 views
0

좋아 생성 될 때까지이 대기받는 것은 내가 할 노력하고있어입니다 : 나는 일부 네트워크 데이터로 채워지는 모델 객체가객체를 만들고 여기에

, 나는처럼 만들 수 있도록하려면 이 :

// createWithID will fire off a request to a server 
MyObject *newObject = [MyObject createWithID:123]; 
if(newObject){ 
    //do something! 

} 

난 데 문제는 통화가 완료되기 전에 방법이 항상 돌아갑니다 있도록 createWithID 방법 내에서 네트워크 호출이 비동기입니다.

먼저이 작업을 수행 할 수 있습니까? 나는 그 방법으로 네트워크 호출을 캡슐화하는 아이디어를 좋아한다. 둘째, 주 스레드를 차단하지 않고 수행 할 수 있습니까?

감사합니다.

+0

잠깐, 당신은 *** 당신이 *** 메인 스레드를 차단하고 싶다고 말 했나요?!? –

+0

** MAIN ** 스레드가 앱을 막아 버리는 것을 동의합니다 ... – Sirens

+1

새 스레드를 만든 다음 UIActivityIndictor 또는 네트워크 통화가 진행 중임을 나타내는 내용을 추가하는 것이 좋습니다. – Otium

답변

3

는 @의 DANH의 대답에 약간의 확장하려면, 당신이 그것을 모두 끝낼 때까지 개체에 대한 포인터가 안된다고 말하고 싶지만. 예를 들면 :

[MyObject makeObjectWithID:123 completion:^(MyObject *object, NSError *error) { 
    if (object == nil) { 
    NSLog(@"error creating object: %@", error); 
    } else { 
    NSLog(@"created object: %@", object); 
    } 
}]; 

그리고 생성 방법은 다음과 같이 될 것이다 :

원칙적으로
+ (void)makeObjectWithID:(NSInteger)objectID completion:(void(^)(MyObject*,NSError*))handler { 
    handler = Block_copy(handler); 
    dispatch_async(dispatch_get_global_queue(0,0), ^{ 
    MyObject *object = [[MyObject alloc] initWithID:objectID]; 

    NSError *error = nil; 
    BOOL succeeded = [object doTheExpensiveAndBlockingSetupThingWithError:&error]; 

    if (succeeded == NO) { 
     [object release], object = nil; 
    } 

    dispatch_async(dispatch_get_main_queue(), ^{ 
     handler([object autorelease], error); 
    }); 
    }); 
    Block_release(handler); 
} 

, 나는 안전 당신이 API가 덜 가능성이 당신이 스크류 수 있습니다 만들 것을 발견 뭔가가. 이 방법은 부분적으로 생성 된 MyObject에 대한 포인터가 없기 때문에 안전합니다. 당신이 그것을 얻을 수있는 방법이 없으며 이 아니라을 완전히 사용할 준비가되어 있어야합니다. 취소 메커니즘은 없지만이를 허용하기 위해이 기능을 확장 할 수 있습니다.

2

당신을 이해한다면, MyObject는 설정을 완료하기 위해 asynch 요청을하고 있으므로, 호출자는 비동기 설정이 완료 될 때까지 작성한 인스턴스가 준비되었다고 추측 할 수 없습니다.

이 문제를 해결하는 방법은 발신자에게 설정이 완료되었음을 알리는 것입니다. 호출자를 MyObject의 대리자로 만들거나 MyObject가 NSNotification을 게시하도록하는 방법을 포함하여 몇 가지 좋은 방법이 있지만 블록을 선호하는 경향이 있습니다. 종종 호출자의 코드를 읽기 쉽게 만들기 때문입니다.

그렇게하는 방법은 다음과 같이이다 ... MyObject.h에 : 그것은 (A @property (복사본을 사용 할 필요가있는 경우

typedef void (^CompletionBlock)(id result, NSError *error); 

+ (MyObject *)createWithId:(NSInteger)anId completion:(CompletionBlock)completion; 

내 객체가 바르로 블록을 유지할 수 ...)), 설치가 완료되면 호출하십시오.

이제 호출자는 다음과 같이 표시됩니다

// do something to indicate activity, like show an activity indicator 
MyObject *newObject = [MyObject createWithID:123 completion::^(id r, NSError *e) { 
    // hide the activity indicator 
    if (!error) { 
     // code here gets executed when newObject is ready... update the ui accordingly 
    } 
}]; 

// code here gets executed right away, and should not assume that newObject is ready 
관련 문제