2012-12-11 2 views
2

두 작업 모두 완료 블록을 특정 작업에 추가해야하는 여러 클래스의 인스턴스가 있습니다. 내 앱이 시도하고있는 모든 것을 설명하지 않고 일반적인 문제를 설명하려고 노력할 것이다.완료 블록 연결

보기 컨트롤러가 자원을 저장하기 위해 자원 관리자 클래스의 인스턴스를 호출 중입니다. 그런 다음 자원 관리자는 저장 될 자원의 클래스를 호출하여 저장을위한 네트워크 조작을 확보합니다.

리소스 인스턴스는 작업을 생성하고 리소스가 실행될 때 리소스 상태에 영향을주는 완료 블록을 제공합니다.

이것은 내 문제입니다. 리소스 클래스는보기 컨트롤러가 저장 성공 또는 실패를 알 수 있도록이 작업에 완료 블록을 추가해야합니다. 나는이 일을 기술적으로 생각하지만 나는 그것에 대해 미치지 않았어,

-(void)save:resource withCompletion:completion 
{ 
. 
. 
. 

NSOperation *operation = [resource operationForSave]; 

NSOperation __weak *weakOperation = operation; 
void(^__weak resourceCompletion)(void)= operation.completionBlock; 

[operation setCompletionBlock:^{ 
    if (resourceCompletion) { 
     resourceCompletion(); 
     } 

    if (completion) { 
     if (weakOperation.error) { 
      completion(NO, operation.error); 
      } 
     else { 
      completion(YES, nil); 
      } 
     } 
    }]; 

. 
. 
. 
// add the operation to a network operation queue 
} 

:

다음은 관리자에 저장 방법의 SNIPPIT입니다. 그것은 꽤 펑키 한 느낌. 하나의 블록이 두 번째 블록을 캡슐화하는 것을 선호하지만보기 컨트롤러와 리소스가 자체 완성 블록을 만들고 관리자 클래스가 함께 충돌해야하기 때문에 불가능합니다.

이 두 가지 완료 블록을이 상황에서 함께 연결하는 더 우아한 방법이 있습니까, 아니면 내가 얻으려는 최상의 두 블록을 포함하는 블록을 만드는 현재 방법입니까?

모든 의견을 주시면 감사하겠습니다.

+1

왜 '__weak'을 사용하고 있습니까? –

+0

http://programmers.stackexchange.com에서 도움을 얻을 수 있습니다. 실제 문제보다는 디자인 문제 일뿐입니다. 귀하의 방법은 소리지만, 때로는 이런 것들을해야합니다. 또는 대리자 패턴이나 알림 또는이 세 가지 조합을 사용할 수 있습니다. 프로그래밍을위한 만세. – Bergasms

+0

보존주기를 피하기 위해 __weak을 사용하고 있습니다. 완료 블록이 작업을 캡처하고 있으며 블록에 대한 참조가 강합니다. – alivingston

답변

1

게시 한 코드는 아마도 이 아니며이 아닙니다. 작업의 완료 블록을 자신의 블록으로 바꿀 때 원래 완료 블록 (리소스에 의해 설정된)에 대한 강력한 참조 만 제거 할 수 있습니다. 따라서 resourceCompletion 변수가 약한 경우 setCompletionBlock:이 반환 할 때까지 0이됩니다.

그냥 resourceCompletion으로 설정하면 문제를 해결할 수 있습니다. 당신이 깨끗한 방법으로 그것을하고 싶은 경우에, (자원의) operationForSave 메시지를 수정 완료 블록 자체를 취할 :

__block NSNetworkOperation *operation = [resource operationForSaveWithCompletion:^{ 
    NSError *error = operation.error; 
    completion(error == nil, error); 

    // Break the retain cycle between this block and the operation object. 
    operation = nil; 
}]; 

을 그리고 전화를 그에게 자원의 자신의 내부 완료 블록의 작업을 완료 블록. 나는 진심으로 당신이 정말없는 희망, 또한

__block NSNetworkOperation *operation = [resource operationForSave]; 
__block void (^priorCompletion)(void) = operation.completionBlock; 
operation.completionBlock = ^{ 
    if (priorCompletion) { 
     priorCompletion); 
     // Break possible retain cycle. 
     priorCompletion = nil; 
    } 

    NSError *error = operation.error; 
    completion(error == nil, error); 
    // Break the retain cycle between this block and the operation object. 
    operation = nil; 
}; 

: 당신이 원하지 않는 또는 자원의 API를 수정할 수없는 경우

, 당신은 여전히 ​​약한 참조를 제거하여 코드를 단순화 할 수 있습니다 NSNetworkOperation이라는 클래스가 있기 때문에 Apple reserves the NS prefix (and all other two-letter prefixes) for its own use.

+0

그것은 오타였습니다. – alivingston

+0

답변 해 주셔서 감사합니다.유지 기간을 피하기 위해 약한 참조를 사용했습니다. 보존주기를 깨기 위해 그것들을 제로로 설정하는 것을 생각하지 않았습니다. – alivingston

관련 문제