【问题标题】:Extending CLPlacemark results in EXC BAD ACCESS扩展 CLPlacemark 会导致 EXC BAD ACCESS
【发布时间】:2015-12-16 15:02:03
【问题描述】:

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

我的问题是: 由于CoreLocation 地理编码受到速率限制,并且我正在为其开发应用程序的(网络)服务提供其自己的后备地理编码服务,因此我想使用此自定义地理编码服务以防达到 Apple 的速率限制。此外,我觉得避免自定义 REST API 返回的结果的自定义数据类型是完全有意义的,因此我想使用返回的数据来生成CLPlacemarks。但是,文档指出 CLPlacemark 属性(例如 location, locality, administrativeArea 等)是 read-only。 因此,我创建了一个 CLPlacemark 的子类,将所需的属性综合到我可以访问的私有变量上,即:

// 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

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

非常感谢任何帮助!

【问题讨论】:

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


    【解决方案1】:

    作为参考任何登陆这里有类似问题的人:

    经过一些密集的 Google-Fu 和深入研究 Apple 的资源之后,似乎没有打算扩展 CLPlacemark

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

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

    【讨论】:

      【解决方案2】:

      谢谢@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()
          }
      }
      

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

      【讨论】:

        猜你喜欢
        • 2011-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多