2014-09-27 1 views
3

Iv에서이 부분을 많이 검색하여 내 특정 질문에 대한 답변을 찾을 수 없습니다. 하지만 기본적으로 내 질문은, 나는 다른보기 컨트롤러에 완료 블록을 전달하고 새보기 컨트롤러에서 다시 정의 할 수 있습니다.보기 컨트롤러 사이에 블록 전달

예를 들어보기 컨트롤러 A에는 완료 블록을 사용하여 다운로드를 수행하는 방법이 있습니다. 먼저 뷰 컨트롤러 A에 내 블록 속성을 만듭니다.

이 속성을 복사하는 것과 반대로 강하게 변경하려고 시도했지만 문제가 해결되지 않았습니다.

그러면 완료 블록을 다음과 같이 정의합니다.

self.downloadCompleteBlock = ^(NSArray *downloadItems) { 

    NSLOG(@"download complete in view controller A"; 
}; 

그런 다음이 완료 블록에서 전달 방법을 호출합니다. 이 완료 핸들러가 시간에 의해 호출되지 않은 경우 (다운로드가 완료되지 않은 경우)

[self download:self.downloadCompleteBlock]; 

그러나, 나는 내가 완료 블록이 다음 뷰 컨트롤러에 다른 무언가를 perfrom 할 것이라고이보기 컨트롤러를 둡니다. SEGUE 준비 내에서 그래서 컨트롤러 B.

[controllerB setCompletionBlock:self.downloadCompleteBlock]; 

그리고 뷰 컨트롤러 B에서이 방법 다음이 완료 블록이 호출 될 때 발생하는 재정의 볼이 블록을 전달하려고했습니다.

- (void)setCompletionBlock:(void(^)(NSArray *downloadItems))downloadFinishedBlock { 

downloadFinishedBlock = ^(NSArray *downloadItems) { 

    self.collectionData = downloadItems; 
    [self.collectionView reloadData]; 
}; 

}

그러나, 뷰 컨트롤러 B. 누군가의 블록에 반대 다운로드가 뷰 컨트롤러 B에서 완료 블록을 가지고하는 방법을 알고 완료되면 뷰 컨트롤러에서 원래의 블록이 여전히 호출됩니다 다운로드가 완료되기 전에 해당 뷰가로드 된 경우 호출됩니다. 알리미를 사용할 수는 있지만 블록으로이 작업을 수행 할 수 있는지 궁금합니다.

감사합니다.

+0

수행하려는 작업과 관련하여 Blocks에 특별한 것은 없습니다. 이것은 다른 변수를 설정하는 것과 정확히 같습니다. 'int'는 똑같이 행동 할 것입니다. –

답변

1

이것은 다소 어려운 문제입니다. 그 핵심은 첫 번째 뷰 컨트롤러가 사라진 후 블록을 유지하는 방법의 문제입니다. 현재 코드는 블록이 self을 참조하도록함으로써이 문제를 무의식적으로 해결합니다. vc는 그 참조에 의해 유지된다. 요청이 끝났을 때 주위에 있어야 할 필요가 있다면 좋은 소식이지만, 이제 vc와 블록은 서로를 영원히 유지할 것이므로 나쁜 소식이다. (Google '보유주기')

완료되면 블록을 실행하고 둘 이상의보기 컨트롤러보다 오래 지속될 수있는 장기 실행 프로세스를 어떻게 얻습니까? 우선, 그 과정을 그 자체의 목적으로 쪼개십시오.

@interface DownloadThingy 

@property (copy)void (^downloadCompleteBlock)(NSArray *); // note, no need for dummy param names here 
- (id)initWithRequestParams:(id)whateverIsNeededToStart; 
- (void)start; 

@end 

자,이를 시작하려는 뷰 컨트롤러, 하나를 생성, 여기에 강한 속성을 선언 그것을 완료 블록 (아래 참조 **)를 제공 할 수 있습니다, 그리고 : 해당 객체의 인터페이스는 같을 것이다 시작해. segue를위한 시간이되면, 다른 완료 블록을 줄 수있는 다른 VC로 downloadThingy을 전달할 수 있습니다.

** 요청 객체가 하나 이상의 vcs에서 속성으로 유지되고 있기 때문에 블록을 보유하고 있으므로 유지 사이클을 알아야합니다. (vc-> downloadThingy-> block- > VC) VCA에서

은 이렇게 :

- (void)startADownloadThingy { 
    self.downloadThingy = [[DownloadThingy alloc] initWithRequestParams:someParams]; 
    __weak VcA *weakSelf = self; 
    self.downloadThingy.downloadCompleteBlock = ^(NSArray *downloadItems) { 
     // don't use self in here, use weakSelf 
    } 
} 

VCB는 SEGUE에 호출되는 것입니다; 동일한 예방 조치를 따를 필요가있을 수도 있고 그렇지 않을 수도 있습니다. 구별은이 두 번째 vc가 downloadThingy 속성을 유지하는지 여부입니다. 다른 VC로 넘겨 줄 계획이 없다면 속성을 건너 뛸 수 있으므로 보관주기에 대한 걱정을 건너 뛸 수 있습니다.

// another vc is handing off a running downloadThingy 
- (void)heresARunningDownloadThingy:(DownloadThingy *)downloadThingy { 
    // if we have our own property, then 
    self.downloadThingy = downloadThingy; 
    // and we need to do the weakSelf trick 
    __weak VcA *weakSelf = self; 
    self.downloadThingy.downloadCompleteBlock = ^(NSArray *downloadItems) { 
     // don't use self in here, use weakSelf 
    } 
} 

또는 ...

// another vc is handing off a running downloadThingy 
- (void)heresARunningDownloadThingy:(DownloadThingy *)downloadThingy { 
    // we do not have our own property 
    downloadThingy.downloadCompleteBlock = ^(NSArray *downloadItems) { 
     // feel free to use self in here 
    } 
} 

마지막 한가지는 : 그것을 호출을 통해입니다 후에는 DownloadThingy에 적극적으로 nil의 블록 아웃을위한 좋은 습관이다. 따라서 요청이 완료되면이 작업을 수행하십시오.

// DownloadThingy.m 
// request is complete 
self.downloadCompleteBlock(arrayFullOfResults); 
self.downloadCompleteBlock = nil;