无法将对象从块添加到 NSMutableArray
Posted
技术标签:
【中文标题】无法将对象从块添加到 NSMutableArray【英文标题】:Cannot AddObject to NSMutableArray from Block 【发布时间】:2013-10-10 05:27:53 【问题描述】:我有一种感觉,我的问题实际上与阻塞有关,但也可能是其他问题。我正在尝试转发地址地理编码并将坐标放入数组中以供以后使用。
当我尝试调用我尝试添加到块中数组的对象之一时,底部会引发异常。在任何 NSLog 在块文本中打印出来之前,也会引发异常。
处理这个问题的正确方法是什么?谢谢。
- (NSMutableArray *)convertAddressToGeocode:(NSString *)addressString
//return array with lat/lng
__block NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:0];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:addressString
completionHandler:^ (NSArray* placemarks, NSError* error)
for (CLPlacemark* aPlacemark in placemarks)
// Process the placemark.
if (error)
NSLog(@"Geocode failed with error: %@", error);
[self displayError:error];
return;
else
NSArray const *keys = @[@"coordinate.latitude",
@"coordinate.longitude",
@"altitude",
@"horizontalAccuracy",
@"verticalAccuracy",
@"course",
@"speed",
@"timestamp"];
NSString *keylat = keys[0];
NSString *keylng = keys[1];
if (aPlacemark.location == nil)
NSLog(@"location is nil.");
else if ([keylat isEqualToString:@"coordinate.latitude"] && [keylng isEqualToString:@"coordinate.longitude"])
NSString *lat = @"";
NSString *lng = @"";
lat = [self displayStringForDouble: [aPlacemark.location coordinate].latitude];
lng = [self displayStringForDouble: [aPlacemark.location coordinate].longitude];
NSLog(@"This never gets executed"): //THIS NEVER GETS EXECUTED
[coordinates addObject:[NSString stringWithFormat:@"%@",lat]];
[coordinates addObject:[NSString stringWithFormat:@"%@",lng]];
];
NSLog(@"Array: %@", coordinates[0]); //EXCEPTION RAISED HERE, Nothing ever gets added
return coordinates;
这是应该插入此方法的代码,但我没有从 convertAddresstoGeocode 中获取坐标以传递给 convertCoordinatestoRepModel:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
NSString *addressToSearch = self.addressSearchField.text;
NSMutableArray *coordinateArray = [self convertAddressToGeocode:addressToSearch];
NSMutableArray *repModelArray = [self convertCoordinatesToRepModel:coordinateArray];
...
【问题讨论】:
在每个“if”下设置一些断点,看看发生了什么 [initWithCapacity:0] 绵羊 最好是coordinates = [NSMutableArray array];
但这不是导致您问题的原因。
@PuneethKamath 你错了,这只是为了优化,来自苹果文档:可变数组根据需要扩展; numItems 只是建立对象的初始容量。
检查您的“地标”数组计数..
【参考方案1】:
如果geocodeAddressString
是异步操作,那么您的块将在之后执行
NSLog(@"Array: %@", coordinates[0]);
此外,在您的方法调用结束后(当事件已处理时)坐标数组
释放(这是因为 __block 修饰符 - 块不保留带有 __block 修饰符的对象),并且在您的块中您尝试使用已释放的 coordinates
数组。
再一次:
你的块将在NSLog(@"Array: %@", coordinates[0]);
之后被调用
f.e.:
-
删除
NSLog(@"Array: %@", coordinates[0]);
- 在那一刻数组为空是正常的。
将你的coordinates
数组存储在一些@property
中,你可以在块中使用后释放它
更新:
在.h文件中
typedef void (^ConverteArrayCallback)(NSArray *coordinates);
@intrerface
下
- (void)convertAddressToGeocode:(NSString *)addressString callback:(ConverteArrayCallback) callback;
在 .m 文件中
- (void)convertAddressToGeocode:(NSString *)addressString callback:(ConverteArrayCallback) callback
NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:0];
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:addressString
completionHandler:^ (NSArray* placemarks, NSError* error)
for (CLPlacemark* aPlacemark in placemarks)
// Process the placemark.
if (error)
NSLog(@"Geocode failed with error: %@", error);
[self displayError:error];
return;
else
NSArray const *keys = @[@"coordinate.latitude",
@"coordinate.longitude",
@"altitude",
@"horizontalAccuracy",
@"verticalAccuracy",
@"course",
@"speed",
@"timestamp"];
NSString *keylat = keys[0];
NSString *keylng = keys[1];
if (aPlacemark.location == nil)
NSLog(@"location is nil.");
else if ([keylat isEqualToString:@"coordinate.latitude"] && [keylng isEqualToString:@"coordinate.longitude"])
NSString *lat = @"";
NSString *lng = @"";
lat = [self displayStringForDouble: [aPlacemark.location coordinate].latitude];
lng = [self displayStringForDouble: [aPlacemark.location coordinate].longitude];
NSLog(@"This never gets executed"): //THIS NEVER GETS EXECUTED
[coordinates addObject:[NSString stringWithFormat:@"%@",lat]];
[coordinates addObject:[NSString s
tringWithFormat:@"%@",lng]];
if (callback != NULL)
callback(coordinates);
];
应该可以!
- (BOOL)textFieldShouldReturn:(UITextField *)textField
NSString *addressToSearch = self.addressSearchField.text;
[self convertAddressToGeocode:addressToSearch callback:^(NSArray *coordinates)
self.textView.text = [coordinates objectAtIndex:0];
];
【讨论】:
为了更新@property坐标,我应该把这个方法变成(void)而不是NSMutable数组方法吗? @user2033783 是的,你应该把它变成void,如果你需要在数组被填充后获取回调,你可以将带有所需参数的块作为方法的参数传递 f.e. typedef void (^ConverteArrayCallback)(NSArray *坐标); - (NSMutableArray *)convertAddressToGeocode:(NSString *)addressString 回调:(ConverteArrayCallback) 回调 ... @user2033783 请检查更新的解决方案,我现在无法访问 XCode :)【参考方案2】:__block NSMutableArray *coordinates = [[NSMutableArray alloc] initWithCapacity:0];
问题就在这里;只需将上面的代码替换为:
NSMutableArray *coordinates = [[NSMutableArray alloc] init];
【讨论】:
为什么,容量有什么问题?只是为了优化,我错了吗? 来自苹果文档:可变数组根据需要扩展; numItems 只是建立对象的初始容量。以上是关于无法将对象从块添加到 NSMutableArray的主要内容,如果未能解决你的问题,请参考以下文章
将对象 NSMutableArray 添加到 NSDictionary
iOS/Objective-C:将 NSString 对象添加到 NSMutableArray,NSMutableArray 为 (null)