改变Objective-C中块内的值

Mas*_*son 3 objective-c ios objective-c-blocks

我有一个代码块,它使用"__block"表示法将一个对象添加到块外部声明的数组(它是一个ivar).但是,一旦退出块,该数组就不包含任何值.我知道它并没有尝试将空字符串添加到数组中,因为我的控制台正确地打印了字符串.任何帮助,将不胜感激.这是我的代码:

__CODE__ 和C++ 0x中的字符串文字:

for(CLLocation *location in locationOutputArray)
{
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error)
     {
         if(placemarks && placemarks.count > 0)
         {
             CLPlacemark *topResult = [placemarks objectAtIndex:0];

             NSString *address = [NSString stringWithFormat:@"%@ %@,%@ %@", [topResult subThoroughfare],[topResult thoroughfare],[topResult locality], [topResult administrativeArea]];

             [addressOutputArray addObject:address];

             NSLog(@"%@",address);
         }

     }];

    [geocoder release];
}

NSLog(@"Address output array count: %d", [addressOutputArray count]);
Run Code Online (Sandbox Code Playgroud)

输出是:

for(CLLocation *location in locationOutputArray)
{
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error)
     {
         if(placemarks && placemarks.count > 0)
         {
             CLPlacemark *topResult = [placemarks objectAtIndex:0];

             NSString *address = [NSString stringWithFormat:@"%@ %@,%@ %@", [topResult subThoroughfare],[topResult thoroughfare],[topResult locality], [topResult administrativeArea]];

             [addressOutputArray addObject:address];

             NSLog(@"%@",address);
         }

     }];

    [geocoder release];
}

NSLog(@"Address output array count: %d", [addressOutputArray count]);
Run Code Online (Sandbox Code Playgroud)

我理解为什么会发生这种情况的机制:字符串文字实际上是一个包含空字符__CODE__的字符数组,当基于范围的for循环调用字符数组时,它会得到一个超过数组末尾的指针; 由于null字符是数组的一部分,因此它获得一个指向空字符的指针.

但是,我认为这是非常不受欢迎的:__CODE__当涉及到属性和基本长度时,字符串文字应该表现得一样吗?

有没有办法解决这种不一致?例如,可以__CODE____CODE__被重载字符数组,使得它们限定的范围不包括终止空字符?如果是这样,为什么没有这样做?

编辑:为了向那些说我正在遭受使用C风格字符串作为"遗留功能"的后果的人们多一点义务,请考虑以下代码:

for(CLLocation *location in locationOutputArray)
{
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error)
     {
         if(placemarks && placemarks.count > 0)
         {
             CLPlacemark *topResult = [placemarks objectAtIndex:0];

             NSString *address = [NSString stringWithFormat:@"%@ %@,%@ %@", [topResult subThoroughfare],[topResult thoroughfare],[topResult locality], [topResult administrativeArea]];

             [addressOutputArray addObject:address];

             NSLog(@"%@",address);
         }

     }];

    [geocoder release];
}

NSLog(@"Address output array count: %d", [addressOutputArray count]);
Run Code Online (Sandbox Code Playgroud)

你期望__CODE____CODE__做一些不同的事情吗?

aro*_*oth 5

问题是reverseGeocodeLocation异步执行,而不是在记录输出数组的大小之前等待调用完成.你可能会有更好的运气:

for(CLLocation *location in locationOutputArray)
{
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder reverseGeocodeLocation:location completionHandler:^(NSArray *placemarks, NSError *error)
     {
         if(placemarks && placemarks.count > 0)
         {
             CLPlacemark *topResult = [placemarks objectAtIndex:0];

             NSString *address = [NSString stringWithFormat:@"%@ %@,%@ %@", [topResult subThoroughfare],[topResult thoroughfare],[topResult locality], [topResult administrativeArea]];

             [addressOutputArray addObject:address];

             NSLog(@"%@",address);
             NSLog(@"Address output array count is now: %d", [addressOutputArray count]);
         }

     }];

    [geocoder release];
}
Run Code Online (Sandbox Code Playgroud)

在任何情况下,您都可以正确地使用块来完成设置,并使用它来修改addressOutputArrayivar 的状态.唯一的问题是,在检查结果之前,您没有等到所有块都完成执行.