发布 MKReverseGeocoder 会使我的应用程序崩溃!

发布于 2024-11-02 06:08:50 字数 3335 浏览 3 评论 0原文

我需要知道我的用户来自哪里,所以我制作了一个小的单例对象来获取坐标并使用 Mapkit 来获取我需要的国家/地区代码。

这是我的头文件:

#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>

#define TW_GEO_CODER_CHANGED_STATE  @"TW_GEO_CODER_CHANGED_STATE"

@interface TWGeoCoder : NSObject <CLLocationManagerDelegate, MKReverseGeocoderDelegate>
{
    CLLocationManager *locationManager;
    MKReverseGeocoder *geoCoder;

    NSString *currentCountryIsoCode;
}

+ (TWGeoCoder*) sharedTWGeoCoder;

-(void) startGeoCoder;
-(void) stopGeoCoder;


@property (nonatomic, retain) NSString *currentCountryIsoCode;

@end

以及实现:

#import "TWGeoCoder.h"

@implementation TWGeoCoder


static TWGeoCoder* _singleton;

+ (TWGeoCoder*) sharedTWGeoCoder
{
    @synchronized([TWGeoCoder class])
    {
        if (_singleton == nil)
        {
            _singleton = [[TWGeoCoder alloc] init];
        }
    }
    return _singleton;
}


- (void)startGeoCoder
{  
    if (locationManager == nil) 
    {
        locationManager = [[CLLocationManager alloc] init];
    }
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
    locationManager.distanceFilter = kCLDistanceFilterNone;
    locationManager.purpose = NSLocalizedString(@"#LocalizationPurpose",nil);
    [locationManager startUpdatingLocation];
}

- (void) stopGeoCoder 
{            
    if (geoCoder != nil)
    {
        [geoCoder cancel];
        [geoCoder release];
        geoCoder = nil;
    }

    if (locationManager != nil)
    {
        [locationManager stopUpdatingLocation];
        [locationManager release];
        locationManager = nil;
    }
}


#pragma mark -
#pragma mark locationManager Delegate 

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{
    if (geoCoder == nil)
    {
        geoCoder = [[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate];
    }

    geoCoder.delegate = self;
    [geoCoder start];       
}


- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error 
{
    NSLog(@"locationManager:%@ didFailWithError:%@", manager, error);
    [self stopGeoCoder];
}



#pragma mark -
#pragma mark reverseGeocoder Delegate 

- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark
{

    self.currentCountryIsoCode = placemark.countryCode;

    [[NSNotificationCenter defaultCenter] postNotificationName:TW_GEO_CODER_CHANGED_STATE 
                                                        object:self];
}


- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error
{
    NSLog(@"reverseGeocoder:%@ didFailWithError:%@", geocoder, error);
    [self stopGeoCoder];    
}


#pragma mark -
#pragma mark Synthesizes

@synthesize currentCountryIsoCode;

@end

好吧,调用 stopGeoCoder 方法会使我的应用程序崩溃,甚至通过 PerformSelectorOnMainThread 调用它...

问题出在这些行中:

if (geoCoder != nil)
    {
        [geoCoder cancel];
        [geoCoder release];
        geoCoder = nil;
    }

当我尝试释放它时,MKReverseGeocoder 似乎变得非常生气! 我仅在“didFail”方法上发生崩溃。 实际上,当它找到地标时,另一个类将收到通知,执行某些操作并调用 stopGeocoder 并且......它不会崩溃! 搞什么?

I need to know where my users are from, so I made a little singleton object which gets the coordinates and uses mapkit to get the country code I need.

Here's my header file:

#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>

#define TW_GEO_CODER_CHANGED_STATE  @"TW_GEO_CODER_CHANGED_STATE"

@interface TWGeoCoder : NSObject <CLLocationManagerDelegate, MKReverseGeocoderDelegate>
{
    CLLocationManager *locationManager;
    MKReverseGeocoder *geoCoder;

    NSString *currentCountryIsoCode;
}

+ (TWGeoCoder*) sharedTWGeoCoder;

-(void) startGeoCoder;
-(void) stopGeoCoder;


@property (nonatomic, retain) NSString *currentCountryIsoCode;

@end

And the implementation:

#import "TWGeoCoder.h"

@implementation TWGeoCoder


static TWGeoCoder* _singleton;

+ (TWGeoCoder*) sharedTWGeoCoder
{
    @synchronized([TWGeoCoder class])
    {
        if (_singleton == nil)
        {
            _singleton = [[TWGeoCoder alloc] init];
        }
    }
    return _singleton;
}


- (void)startGeoCoder
{  
    if (locationManager == nil) 
    {
        locationManager = [[CLLocationManager alloc] init];
    }
    locationManager.delegate = self;
    locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
    locationManager.distanceFilter = kCLDistanceFilterNone;
    locationManager.purpose = NSLocalizedString(@"#LocalizationPurpose",nil);
    [locationManager startUpdatingLocation];
}

- (void) stopGeoCoder 
{            
    if (geoCoder != nil)
    {
        [geoCoder cancel];
        [geoCoder release];
        geoCoder = nil;
    }

    if (locationManager != nil)
    {
        [locationManager stopUpdatingLocation];
        [locationManager release];
        locationManager = nil;
    }
}


#pragma mark -
#pragma mark locationManager Delegate 

- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation 
{
    if (geoCoder == nil)
    {
        geoCoder = [[MKReverseGeocoder alloc] initWithCoordinate:newLocation.coordinate];
    }

    geoCoder.delegate = self;
    [geoCoder start];       
}


- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error 
{
    NSLog(@"locationManager:%@ didFailWithError:%@", manager, error);
    [self stopGeoCoder];
}



#pragma mark -
#pragma mark reverseGeocoder Delegate 

- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark
{

    self.currentCountryIsoCode = placemark.countryCode;

    [[NSNotificationCenter defaultCenter] postNotificationName:TW_GEO_CODER_CHANGED_STATE 
                                                        object:self];
}


- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error
{
    NSLog(@"reverseGeocoder:%@ didFailWithError:%@", geocoder, error);
    [self stopGeoCoder];    
}


#pragma mark -
#pragma mark Synthesizes

@synthesize currentCountryIsoCode;

@end

Well, calling stopGeoCoder method makes my app crash, even calling it via performSelectorOnMainThread...

The problem is in these lines:

if (geoCoder != nil)
    {
        [geoCoder cancel];
        [geoCoder release];
        geoCoder = nil;
    }

It seems like MKReverseGeocoder become really angry when I try to release it!
I get the crash only on the "didFail" method.
Actually, when it finds the placemark, another class will get the notification, does something and call stopGeocoder and... it doesn't crash!
WTF?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

唯憾梦倾城 2024-11-09 06:08:50

您应该参考堆栈溢出中的另一篇文章及其解决方案:

cllocation 和 mkreversegeocoder

you should refer to another post in stack overflow with the solution:

cllocation and mkreversegeocoder

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文