块变量在块外部变为空--xcode

时间:2014-07-18 15:32:51

标签: xcode uitableview objective-c-blocks distance nssortdescriptor

我试图继承一个块变量并把它放在我的方便初始化器中,但变量返回null,有人能告诉我正确的方法,谢谢,还请检查我是否正确完成了我的NSComparison结果,这里是代码,

- (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];

}

提前感谢任何可以提供帮助的人,这恰好是我的应用程序的最后一部分,直到完成:)

2 个答案:

答案 0 :(得分:1)

-[CLGeocoder geocodeAddressString:completionHandler:]以异步方式运行完成处理程序,并且在该函数的其余部分完成之前不会运行该块。 distance不会“无效”;相反,它还没有确定。

答案 1 :(得分:0)

您的块在函数完成后运行...如果“代码行”在块之后或之前,则无关紧要。

解决方案是必须阻止调用'延续'函数:

e.g。而不是- (void) retrieveData
- (void) beginRetrieveData,它调用块然后有一个- (void) finishRetrieveData,由块调用,不会在块之前运行;)


以下是您的代码的外观:

- (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]];
}