0

임은 블록 변수를 넘기려고하고 편의 편의 초기화 도구에 넣으려고하지만 변수가 null을 반환합니다. 누군가가 내게 올바른 방법을 보여줄 수 있습니까? 감사합니다. 내가 도울 수있는 사람을 사전에 여기 코드는 제대로블록 변수가 블록 외부에서 null을 가져옵니다 - xcode

- (void) retrieveData 
{ 
NSURL *url = [NSURL URLWithString:jsonFile]; 
NSData *data = [NSData dataWithContentsOfURL:url]; 

_jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; 

_salesArray = [[NSMutableArray alloc]init]; 

for (int i = 0; i < _jsonArray.count; i++) { 

    NSString *sID = [[_jsonArray objectAtIndex:i] objectForKey:@"id"]; 
    NSString *sName = [[_jsonArray objectAtIndex:i] objectForKey:@"name"]; 
    NSString *sAddress = [[_jsonArray objectAtIndex:i] objectForKey:@"address"]; 
    NSString *sPostcode = [[_jsonArray objectAtIndex:i] objectForKey:@"postcode"]; 


    __block NSString *distance; 
    CLGeocoder *geocoder = [[CLGeocoder alloc]init]; 
    [geocoder geocodeAddressString:sPostcode completionHandler:^(NSArray *placemarks, NSError *error) { 


     if (error == nil && placemarks.count > 0) { 

      CLPlacemark *placemark = [placemarks objectAtIndex:0]; 


      CLLocation *location = placemark.location; 
      CLLocation *myLocation = self.manager.location; 
      CLLocationDistance miles = [location distanceFromLocation:myLocation]; 
      //this is the variable i want in my convenience init. 
      distance = [NSString stringWithFormat:@"%.1f m", (miles/1609.344)]; 

     } 

    }]; 

    [_salesArray addObject:[[sales alloc] initWithSales:sID andName:sName andAddress:sAddress andPostcode:distance]]; 

} 

[_salesArray sortUsingComparator: 
^NSComparisonResult(id obj1, id obj2){ 

    sales *p1 = (sales *)obj1; 
    sales *p2 = (sales *)obj2; 
    if (p1.postcode > p2.postcode) { 
     return (NSComparisonResult)NSOrderedDescending; 
    } 

    if (p1.postcode < p2.postcode) { 
     return (NSComparisonResult)NSOrderedAscending; 
    } 
    return (NSComparisonResult)NSOrderedSame; 
} 
]; 

[self.tableView reloadData]; 

} 

덕분에 내 NSComparison 결과를 수행 한이 완료 :)

+0

이 질문은 많이 묻습니다. 여기에 예제가 있습니다. http://stackoverflow.com/questions/24870458/waiting-for-a-block-to-finish – CrimsonChris

답변

1

-[CLGeocoder geocodeAddressString:completionHandler:]가 완료 될 때까지입니다 내 응용 프로그램의 마지막 부분 될 일이 처리기를 비동기 적으로 처리하고 그 함수의 나머지가 완료되기 전에 블록을 실행하지 않습니다. distance "null"이 아닙니다. 오히려 아직 설정되지 않았습니다.

+0

블록 안에서 null을 얻지 못할 수도 있지만 _salesArray [[sales alloc ]] 이니셜 라이저는 블록 밖에서 null을 얻습니다.이 주위에있는 방법은 무엇입니까? –

+0

@silly_cone : 내가 말했듯이 "null"을 얻지는 못했지만 아직 설정되지 않았습니다. 근본적인 문제는 이것이 비동기 작업이므로, 그 시간에 얻을 수있는 방법이 없다는 것입니다. 완성 블록에서 나중에 salesArray에 개체를 추가 할 수 있도록 워크 플로를 변경해야합니다. – newacct

+0

당신은 나에게 예를 들어주세요. 정말 고마워요. 고마워요. –

0

함수가 완료된 후 블록이 실행됩니다. '코드 줄'이 블록 전후인지 여부는 중요하지 않습니다.

예 :

용액을 '연속'함수를 호출 차단하는 것이다 - (void) retrieveData
이 블록을 호출 한 다음 블록에 의해 호출되고 블록 전에 실행하지 않는 - (void) finishRetrieveData을 가지고 - (void) beginRetrieveData을 가지고 대신)

여기

은 당신의 코드는 볼 수 있었다 방법 :

- (void) beginRetrieveData 
{ 
    NSURL *url = [NSURL URLWithString:jsonFile]; 
    NSData *data = [NSData dataWithContentsOfURL:url]; 

    _jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]; 

    _salesArray = [[NSMutableArray alloc]init]; 

    for (int i = 0; i < _jsonArray.count; i++) { 

     NSString *sID = [[_jsonArray objectAtIndex:i] objectForKey:@"id"]; 
     NSString *sName = [[_jsonArray objectAtIndex:i] objectForKey:@"name"]; 
     NSString *sAddress = [[_jsonArray objectAtIndex:i] objectForKey:@"address"]; 
     NSString *sPostcode = [[_jsonArray objectAtIndex:i] objectForKey:@"postcode"]; 


     CLGeocoder *geocoder = [[CLGeocoder alloc]init]; 
     [geocoder geocodeAddressString:sPostcode completionHandler:^(NSArray *placemarks, NSError *error) { 


      if (error == nil && placemarks.count > 0) { 

       CLPlacemark *placemark = [placemarks objectAtIndex:0]; 


       CLLocation *location = placemark.location; 
       CLLocation *myLocation = self.manager.location; 
       CLLocationDistance miles = [location distanceFromLocation:myLocation]; 
       //this is the variable i want in my convenience init. 
       NSString *distance = [NSString stringWithFormat:@"%.1f m", (miles/1609.344)]; 
       [self finishRetrieveData:distance]; //continue 
      } 

     }]; 
    } 
} 

- (void) finishRetrieveData:(NSString*)distance 
{ 
    [_salesArray addObject:[[sales alloc] initWithSales:sID andName:sName andAddress:sAddress andPostcode:distance]]; 
} 
+0

이것은 작동하지만 테이블 뷰를 몇 번 새로 고치면 충돌이 발생하고이 오류가 발생합니다. 캐치되지 않은 예외로 인해 'NSRangeException'이유로 응용 프로그램이 종료됩니다. 이유 : '*** - [__ NSArrayM objectAtIndex :] : 인덱스 4가 빈 배열의 범위를 벗어납니다.' 왜냐하면 나는 [self.tableview reloadData]를 finishedRetrieveData 메서드의 마지막 줄로 가지고 있기 때문이다. –

+0

괜찮을 것 같지 않다. 거기에 당신의 코드에 뭐가 잘못 말할 수 없다 --- 나는 또한 위의 코드에서 아무것도 잘못 보지 않는다. –