扩展CLPlacemark会导致EXC BAD ACCESS

时间:2015-09-19 14:29:08

标签: ios objective-c core-location extend clplacemark

虽然发现类似的问题here但它没有提供答案,至少不是一般问题。

我的问题是: 由于CoreLocation地理编码是速率限制的,并且我正在开发应用程序的(网络)服务提供其自己的后备地理编码服务,我想使用此自定义地理编码服务,以防我达到Apple的速率限制。此外,我觉得避免使用此自定义REST API返回的结果的自定义数据类型是完全有意义的,因此希望使用返回的数据生成CLPlacemark s。但是,文档指出CLPlacemarklocation, locality, administrativeArea属性为read-onlyCLPlacemark。 因此,我创建了一个// interface: (.h) @interface CustomPlacemark : CLPlacemark - (nonnull id)initWithLocation: (nonnull CLLocation *)location locality: (nullable NSString *)locality administrativeArea: (nullable NSString *)adminArea country: (nullable NSString *)country; @end // implementation (.m) @implementation CustomPlacemark @synthesize location = _location; @synthesize locality = _locality; @synthesize country = _country; @synthesize administrativeArea = _administrativeArea; - (nonnull id)initWithLocation: (nonnull CLLocation *)location locality: (nullable NSString *)locality administrativeArea: (nullable NSString *)adminArea country: (nullable NSString *)country{ self = [super init]; if(self){ _location = location; _locality = locality; _administrativeArea = adminArea; _country = country; } return self; } @end 的子类,将所需的属性合成到我可以访问的私有变量上,即:

initWithLocation: locality: administrativeArea: country:

使用单元测试来测试此代码,该单元测试解析来自JSON文件的数据,并在测试结束时使用数据结果EXC BAD ACCESS (code=1)调用我的}方法(在结束{{1虽然先前的nil输出正确的值,但是地标变量指向NSLog(@"placemark: %@", customPlacemark);的测试方法)。此外,逐行逐步测试显示CustomPlacemark工作(即指向正确填充的对象),直到测试结束。对我而言,这表明我的CustomPlacemark的释放出错了 - 但究竟是什么?

非常感谢任何帮助!

2 个答案:

答案 0 :(得分:5)

作为对这里遇到类似问题的任何人的参考:

经过一些密集的谷歌和深入研究苹果的消息来源后,似乎并不打算扩展CLPlacemark

然而,我能够根据找到的提示here实施变通方法,这基本上滥用了MKPlacemark扩展CLPlacemark的事实,并提供了使用自定义数据初始化的方法,即- (instancetype _Nonnull)initWithCoordinate:(CLLocationCoordinate2D)coordinate addressDictionary:(NSDictionary<NSString *, id> * _Nullable)addressDictionary。找到addressDictionaryCLPlacemark中映射所需属性的正确键可能需要一些试验和错误,尤其是因为iOS 9已弃用ABPerson/Address功能。 我找到的钥匙是:

@"City" -> CLPlacemark.city
@"State" -> CLPlacemark.administrativeArea
@"Country" -> CLPlacemark.country

答案 1 :(得分:0)

谢谢@hpd!

我的快速模拟类:

class TestPlacemark: CLPlacemark {
    static let coordinate = CLLocationCoordinate2D(latitude: CLLocationDegrees(35), longitude: CLLocationDegrees(-80))

    override init() {
        let mkPlacemark = MKPlacemark(coordinate: TestPlacemark.coordinate) as CLPlacemark
        super.init(placemark: mkPlacemark)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override static var supportsSecureCoding: Bool {
        return false
    }
    override var location: CLLocation? {
        return CLLocation(latitude: TestPlacemark.coordinate.latitude, longitude: TestPlacemark.coordinate.longitude)
    }
    override var postalAddress: CNPostalAddress?  {
        return TestPostalAddress()
    }
}

希望它可以节省其他人的时间。干杯!