0

라고 점점되지 않습니다 내 중첩 된 블록을 살펴 가지고하시기 바랍니다 : 아래의 블록을 가지고,중첩 completionBlock는 objc

- (void)getVideoList:(NSDictionary*)videoData 
    completionBlock:(void (^)(NSMutableArray *)) 
completionBlock { 
    NSArray *videos = (NSArray*)[videoData objectForKey:@"items"]; 
    NSMutableArray* videoList = [[NSMutableArray alloc] init]; 

    for (NSDictionary *videoDetail in videos) { 
     if (videoDetail[@"id"][@"videoId"]){ 
      [self initializeDictionary:videoDetail completionBlock:^(YoutubeVideo * utubeVideo) { 
       [videoList addObject:utubeVideo]; 
//    NSLog(@"zuuudo %@", utubeVideo.channelProfileImageURL); 
      }]; 
     } 
    } 
    completionBlock(videoList); 
} 

- (void)initializeDictionary:(NSDictionary *)dictionary completionBlock:(void (^)(YoutubeVideo *)) 
completionBlock { 
    YoutubeVideo *youtubeVideo = [[YoutubeVideo alloc] init]; 

    youtubeVideo.videoTitle = dictionary[@"snippet"][@"title"]; 
    youtubeVideo.videoID = dictionary[@"id"][@"videoId"]; 
    youtubeVideo.channelID = dictionary[@"snippet"][@"channelId"]; 
    [self getChannelProfilePictureForChannelID:youtubeVideo.channelID completionBlock:^(NSMutableArray *channelList) { 
     NSLog(@"[channelList objectAtIndex:0] %@", [channelList objectAtIndex:0]); 
     youtubeVideo.channelProfileImageURL = [channelList objectAtIndex:0]; 
    }]; 
    youtubeVideo.channelTitle = dictionary[@"snippet"][@"channelTitle"]; 
    youtubeVideo.videoDescription = dictionary[@"snippet"][@"description"]; 
    youtubeVideo.pubDate = [self dateWithJSONString:dictionary[@"snippet"][@"publishedAt"]]; 
    youtubeVideo.thumbnailURL = dictionary[@"snippet"][@"thumbnails"] 
    [@"high"][@"url"]; 
    completionBlock(youtubeVideo); 
} 

- (void)getChannelProfilePictureForChannelID:(NSString*)channelID completionBlock:(void (^)(NSMutableArray *))completionBlock 
{ 
    NSString *URL = [NSString stringWithFormat:@"https://www.googleapis.com/youtube/v3/channels?part=snippet&fields=items/snippet/thumbnails/default&id=%@&key=%@", channelID, apiKey]; 
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:[URL stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]]]; 

    NSURLSession *session = [NSURLSession sharedSession]; 
    [[session dataTaskWithRequest:request 
       completionHandler:^(NSData *data, 
            NSURLResponse *response, 
            NSError *error) { 
        if (!error){ 
         [self getChannelProfileImageList:[NSJSONSerialization JSONObjectWithData:data options:0 error:nil] completionBlock: 
         ^(NSMutableArray * channelList) { 
          // return the final list 
          completionBlock(channelList); 
         }]; 
        } 
        else { 
         // TODO: better error handling 
         NSLog(@"error = %@", error); 
        } 
       }] resume]; 
} 

- (void)getChannelProfileImageList:(NSDictionary*)channelData 
    completionBlock:(void (^)(NSMutableArray *)) 
completionBlock { 
    NSArray *channels = (NSArray*)[channelData objectForKey:@"items"]; 
    NSMutableArray *channelList = [[NSMutableArray alloc] init]; 

    for (NSDictionary *channelDetail in channels) { 
     [self initializeDictionaryForChannelProfileImage:channelDetail completionBlock:^(NSString *chnlProfileImageURL) { 
      [channelList addObject:chnlProfileImageURL]; 
     }]; 
     //[channelList addObject:[self initializeDictionaryForChannelProfileImage:channelDetail]]; 
     //[channelList addObject:[[YoutubeVideo alloc] initWithDictionaryForChannelProfileImage:channelDetail]]; 
    } 
    completionBlock(channelList); 
} 

- (void)initializeDictionaryForChannelProfileImage:(NSDictionary *)dictionary completionBlock:(void (^)(NSString *)) 
completionBlock 
{ 
    _channelProfileImageURL = dictionary[@"snippet"][@"thumbnails"] 
    [@"default"][@"url"]; 

    completionBlock(_channelProfileImageURL); 
} 

문제는이 - (void)initializeDictionary:(NSDictionary *)dictionary completionBlock:(void (^)(YoutubeVideo *)) completionBlock { } 블록입니다

[self getChannelProfilePictureForChannelID:youtubeVideo.channelID completionBlock:^(NSMutableArray *channelList) { NSLog(@"[channelList objectAtIndex:0] %@", [channelList objectAtIndex:0]); youtubeVideo.channelProfileImageURL = [channelList objectAtIndex:0]; }];

경우 이 코드 행은 블록 반환 값 NSSting 값이 실행될 때 실행되지 않습니다.

youtubeVideo.channelProfileImageURL = _channelProfileImageURL; 
NSLog(@"youtubeVideo.channelProfileImageURL %@", youtubeVideo.channelProfileImageURL); 

는 코드의 나머지 부분을 실행 한 후 호출지고 :

youtubeVideo.channelTitle = dictionary[@"snippet"][@"channelTitle"]; 
    youtubeVideo.videoDescription = dictionary[@"snippet"][@"description"]; 
    youtubeVideo.pubDate = [self dateWithJSONString:dictionary[@"snippet"][@"publishedAt"]]; 
    youtubeVideo.thumbnailURL = dictionary[@"snippet"][@"thumbnails"] 
    [@"high"][@"url"]; 

그래서 값이 내 개체 모델에 삽입되지 않습니다. 제게 제안 해주세요. 미리 감사드립니다.
좋은 하루 보내십시오. 당신은 코드가 실행될 것이라는 기대 비동기 실행을 혼합하는

답변

1

It is getting called after executing rest of the code

동 기적으로 :

- (void)initializeDictionary:(NSDictionary *)dictionary 
      completionBlock:(void (^)(YoutubeVideo *))completionBlock 
{ 

이것은 completionBlock 인수를 호출 할 필요가 비동기 방식의 일반적인 선언입니다 비동기식으로 다음에 initializeDictionary의 모든 작업이 완료되었습니다.

YoutubeVideo *youtubeVideo = [[YoutubeVideo alloc] init]; 

    youtubeVideo.videoTitle = dictionary[@"snippet"][@"title"]; 
    youtubeVideo.videoID = dictionary[@"id"][@"videoId"]; 
    youtubeVideo.channelID = dictionary[@"snippet"][@"channelId"]; 

3 개의 동기 지정.

[self getChannelProfilePictureForChannelID:youtubeVideo.channelID 
           completionBlock:^(NSMutableArray *channelList) 
     { 
      NSLog(@"[channelList objectAtIndex:0] %@", [channelList objectAtIndex:0]); 
      youtubeVideo.channelProfileImageURL = [channelList objectAtIndex:0]; 
     } 
    ]; 

이는이 완료된 후 완성 블록 호출 다른 비동기 방법에 중첩 된 호출이다. 그 시점에서 그것은 아마도 경쟁 블록을 호출하지 않았을 것입니다.

youtubeVideo.channelTitle = dictionary[@"snippet"][@"channelTitle"]; 
    youtubeVideo.videoDescription = dictionary[@"snippet"][@"description"]; 
    youtubeVideo.pubDate = [self dateWithJSONString:dictionary[@"snippet"][@"publishedAt"]]; 
    youtubeVideo.thumbnailURL = dictionary[@"snippet"][@"thumbnails"] 
    [@"high"][@"url"]; 

네 더 동기 할당 ...

completionBlock(youtubeVideo); 

그리고 당신은 getChannelProfilePictureForChannelID:이 완료되었음을 알고 완성 블록이라고 전에 initializeDictionary:의 완료 블록을 호출합니다.

} 

당신이 자체가 내포 된 비동기 방식의 완료에 당신의 방법을 완료해야 다음 비동기 메소드를 호출 할 필요가 비동기 방법을 작성하는 경우 ...

예 그 단어에 조금 혼란!지금, 당신이 원하는 무엇을 getChannelProfilePictureForChannelID의 완료 블록이 수행 한이 시점에서

[self getChannelProfilePictureForChannelID:youtubeVideo.channelID 
           completionBlock:^(NSMutableArray *channelList) 
     { 
      NSLog(@"[channelList objectAtIndex:0] %@", [channelList objectAtIndex:0]); 
      youtubeVideo.channelProfileImageURL = [channelList objectAtIndex:0]; 

:

- (void)initializeDictionary:(NSDictionary *)dictionary 
      completionBlock:(void (^)(YoutubeVideo *))completionBlock 
{ 
    YoutubeVideo *youtubeVideo = [[YoutubeVideo alloc] init]; 

    youtubeVideo.videoTitle = dictionary[@"snippet"][@"title"]; 
    youtubeVideo.videoID = dictionary[@"id"][@"videoId"]; 
    youtubeVideo.channelID = dictionary[@"snippet"][@"channelId"]; 

    youtubeVideo.channelTitle = dictionary[@"snippet"][@"channelTitle"]; 
    youtubeVideo.videoDescription = dictionary[@"snippet"][@"description"]; 
    youtubeVideo.pubDate = [self dateWithJSONString:dictionary[@"snippet"][@"publishedAt"]]; 
    youtubeVideo.thumbnailURL = dictionary[@"snippet"][@"thumbnails"] 
    [@"high"][@"url"]; 

모든 동기 과제는 첫째, 다음 중첩 된 비동기 호출을 수행의 당신의 방법을 재 배열하자 getChannelProfilePictureForChannelID 완료 후에 initializeDictionary:이 수행해야하는 나머지 작업을 수행하십시오. 난 당신이 비동기 체인이 작동 할 필요가 어떻게 오해 생각

  completionBlock(youtubeVideo); 
     } 
    ]; 
} 

HTH

부록

의견에서 :이이 경우에 많이하지, 그냥 initializeDictionary: 경쟁을 호출합니다. 다음 내용이 도움이되는지 봅시다.

당신이 쓴 방법은 형식이 있습니다

A - block of work to do before async nested call 
B - async call 
    nested async completion block 
    C - block of work to do after nested call completes 
D - second block of work 
E - call our async completion block 

이 방법 A를 호출

는, B는 D & E 순서대로 실행됩니다 다음 방법을 반환합니다. C가 실행될 때 어떤 생각이 들지 않고 실제로는 비동기 네트워크 호출로 E가 실행될 것이라는 보장이 없기 때문에 모든 경우에 비동기 네트워크 호출이 발생하지 않을 것입니다. 따라서 우발적 인 정확성을 얻지 못할 수도 있습니다.

비동기 작업 시퀀스를 수행하려면 연속 블록을 통해 연결해야합니다. 중첩 완료 블록에 D에게 & E 퍼팅

A - block of work to do before async nested call 
B - async call 
    nested async completion block 
    C - block of work to do after nested call completes 
    D - second block of work 
    E - call our async completion block 

: 그래서 당신은 당신의 방법을 변경할 수 있습니다. 이제 당신이 당신의 방법을 호출했을 때 A & B만이 돌아 오기 전에 실행됩니다. 나중에 어떤 시점에서 중첩 완료 블록이 비동기 적으로 실행되고 C와 D가 실행됩니다. 마지막으로 E가 실행되어 원래 호출의 완료 블록이 완료되어 작업을 완료합니다. 정확성을 보장 했으므로 중첩 된 비동기 호출이 완료된 후에 만 ​​E가 실행됩니다.

참고 :

: 난 당신의 코드를 읽는 것은 중첩 된 전화 그래서 난으로 코드를 재 배열 후 블록 D (코드에서 네 할당 세트)를 실행해야 할 것 같지 않았다 때 눈치 무엇
A & D - block of work to do before async nested call 
B - async call 
    nested async completion block 
    C - block of work to do after nested call completes 
    E - call our async completion block 

상단에 게양 D.

이 비동기 호출 체인은 비동기 메서드가 다른 비동기 메서드에 의존 할 때 기본적으로 필요합니다. 모든 단계에서 완료 블록 체인을 사용하여 올바른 순서로 코드를 실행해야합니다.

HTH

+0

귀하의 명확하고 명확한 설명에 대해 감사드립니다. 이해하기 쉬웠다. 하지만 모든 것은 4 개의 실행을 동기화 한 후에도 여전히 [self getChannelProfilePictureForChannelID'가 호출됩니다. 내 말은 이미'completionBlock (youtubeVideo); '를 반환한다는 것입니다. 내가'getChannelProfilePictureForChannelID'에서 발견 한 또 다른 사실은 [weakSelf getChannelProfileImageList : [NSJSONSerialization JSONObjectWithData : data options : 0 error : nil] completionBlock :''completionBlock'이 그때 호출하지 않았다는 것입니다. 이것은'initializeDictionary'에서 모든 메소드를 끝내고 호출됩니다. – Tulon

+0

그렇다면 어떻게하면 더 이상 'completionBlock'을'getChannelProfilePictureForChannelID'에서부터 asyncize, 즉 동기화 방식으로 asyncize라고 부를 수 있을까요? – Tulon

+0

@Tulon - 추가 정보가 추가되었습니다. – CRD