CLGeocoder单列产生的问题

来源:互联网 发布:手机桌面软件排行 编辑:程序博客网 时间:2024/05/29 10:02

如果你的代码中CLGeocoder是单列的,那么就会产生以下问题:

代码:

-(CLGeocoder *)coder{    if (_coder == nil) {        _coder = [CLGeocoder new];    }    return _coder;}#pragma marks 地理编码和反编码-(void)geoCode{    //西安坐标:34.25833330,108.92861110    CLLocation* location = [[CLLocation alloc]initWithLatitude:34.258 longitude:108.92];    [self.coder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {        if (error != nil) {            NSLog(@"error2");            return ;        }        for (CLPlacemark* place in placemarks) {            NSLog(@"city----->%@",place.locality);        }        self.coder = nil;    }];        NSString* city = @"西安";    [self.coder geocodeAddressString:city completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error)    {        [NSThread sleepForTimeInterval:5];        if (error != nil) {            NSLog(@"error");            return ;        }        for (CLPlacemark* place in placemarks) {            NSLog(@"place---->%@  %@",place.location,place.locality);        }            }];}

调用以上代码会产生以下输出:

2016-01-15 11:56:10.523 CLLocationLearning[1377:70938] city----->西安市

只打印了地理反编码的城市,而没有打印地理编码部分,很奇怪对不对。

这里查一下文档:

The CLGeocoder class provides services for converting between a coordinate (specified as a latitude and longitude) and the user-friendly representation of that coordinate. A user-friendly representation of the coordinate typically consists of the street, city, state, and country information corresponding to the given location, but it may also contain a relevant point of interest, landmarks, or other identifying information. <span style="color:#ff0000;">A geocoder object is a single-shot object </span>that works with a network-based service to look up placemark information for its specified coordinate value.
这里标红部分是说CLGeocoder类是一个单发类,只会发送一次消息。因此第二段
NSLog(@"place---->%@  %@",place.location,place.locality);

就没有打印。如果需要打印第二次,那么需要在第二次给self.coder发消息之前将self.coder = nil,然后发送消息时会自动调用单利方法重新生成一个新对象。这样就可以实现地址编码了。


另外发现了一个有趣现象,即编码和反编码任务都是在主线程中执行的,并且编码任务先执行,即使代码顺序是反编码任务在前。

2016/1/20注:这句话说错了,编码和反编码不一定是在主线程中执行的,只能说block是在主线程中执行的。这里应该是编码和反编码在子线程中执行完了,将block放到主线程中执行。因此不能在block中放入耗时操作

#pragma marks 地理编码和反编码-(void)geoCode{    NSLog(@"%s",__func__);    self.coder = nil;    //西安坐标:34.25833330,108.92861110
    //反编码任务在前    CLLocation* location = [[CLLocation alloc]initWithLatitude:34.258 longitude:108.92];    [self.coder reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {        NSLog(@"regeoThread--->%@",[NSThread currentThread]);        if (error != nil) {            NSLog(@"error2");            return ;        }        for (CLPlacemark* place in placemarks) {            NSLog(@"city----->%@",place.locality);        }        self.coder = nil;    }];    self.coder = nil;        NSString* city = @"西安";    [self.coder geocodeAddressString:city completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error)    {        [NSThread sleepForTimeInterval:5];        NSLog(@"geoThread--->%@",[NSThread currentThread]);        if (error != nil) {            NSLog(@"error");            return ;        }        for (CLPlacemark* place in placemarks) {            NSLog(@"place---->%@  %@",place.location,place.locality);        }            }];        self.coder = nil;    NSString* city2 = @"北京";    [self.coder geocodeAddressString:city2 completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error)     {         NSLog(@"geoThread--->%@",[NSThread currentThread]);         if (error != nil) {             NSLog(@"error");             return ;         }         for (CLPlacemark* place in placemarks) {             NSLog(@"place---->%@  %@",place.location,place.locality);         }     }];}
打印结果:

2016-01-15 14:12:51.356 CLLocationLearning[1417:92623] -[ViewController geoCode]2016-01-15 14:12:51.479 CLLocationLearning[1417:92623] geoThread---><NSThread: 0x7fa918f06410>{number = 1, name = main}2016-01-15 14:12:51.481 CLLocationLearning[1417:92623] place----><+39.92888890,+116.38833330> +/- 100.00m (speed -1.00 mps / course -1.00) @ 16/1/15 中国标准时间 下午2:12:51  北京市2016-01-15 14:12:56.487 CLLocationLearning[1417:92623] geoThread---><NSThread: 0x7fa918f06410>{number = 1, name = main}2016-01-15 14:12:56.488 CLLocationLearning[1417:92623] place----><+34.25833330,+108.92861110> +/- 100.00m (speed -1.00 mps / course -1.00) @ 16/1/15 中国标准时间 下午2:12:51  西安市2016-01-15 14:12:56.490 CLLocationLearning[1417:92623] regeoThread---><NSThread: 0x7fa918f06410>{number = 1, name = main}2016-01-15 14:12:56.490 CLLocationLearning[1417:92623] city----->西安市

总结:

1.CLGeocoder最好不要使用单列。

2.使用上一个CLGeocoder反编码产生的结果去执行编码操作,很有可能失败,因为编码任务会先执行。



0 0
原创粉丝点击