【问题标题】:How to store CLLocation using Core Data (iPhone)?如何使用 Core Data (iPhone) 存储 CLLocation?
【发布时间】:2011-04-17 08:42:41
【问题描述】:

我正在尝试保存一个位置,然后使用 Core Location、MapKit 和 Core Data 框架在地图上检索该位置。

我所做的只是创建了名为 POI 的实体,并添加了一些属性,例如纬度(双精度类型)、经度(双精度类型)以及其他一些属性。

简单地说,我的应用使用两个 NSNumber 保存 POI。 (经纬度)但我觉得必须有比这更聪明的方式来存储 CLLocation。

干杯。

【问题讨论】:

    标签: iphone core-data save store cllocation


    【解决方案1】:

    你正在做的很好。您应该在核心数据中将纬度和经度保存为双精度值。当您需要再次获取信息时,从 Core Data 中获取双精度数据并构造一个具有类似 CLLocationCoordinate2DMake 的函数的 CLLocationCoordinate2D 结构体。没有内置存储位置的方法,因此存储纬度和经度分量就可以了。

    如果您没有对纬度或经度进行任何数学运算(查找边界框等),您可以将它们存储为字符串。浮点数和双精度数可以稍微改变它们的值,导致比较操作失败。

    【讨论】:

    • 感谢 nevan,实际上我将这些坐标值保存在 NSString 中,以便在 UILabel 中显示。我确实计划对坐标进行一些数学运算,但我不知道“浮点数和双精度数可以稍微改变它们的值,从而使比较操作失败。”这让我稍微改变了一下回到原来的问题;如果需要计算距离和比较,使用 Core Data 存储 CLLocation 坐标值的最佳方法是什么?
    • 如果您对它们进行一些计算,例如查找所有大于 12.34 的纬度,我会将它们存储为浮点数或双精度数。只是不要依赖浮点值在存储和获取它之间完全相同。如果您想确保该值不会改变(即使是一小部分),请使用小数。我只是不确定用十进制类型做数学有多快。这是一个链接:stackoverflow.com/questions/159255/…
    • 如果您需要以高精度存储数值并对其执行操作,您应该使用 NSDecimal 数字。使用价值转换器将它们存储在核心数据中。但是,我认为在这种情况下这将是矫枉过正。浮点数和双精度数可以更改值,但只能在其精度的极端情况下。纬度/经度最多只需要右边 4 位小数,因此您可以简单地控制有效数字以完美地存储和检索浮点值。
    • @TechZen:这也是我的感受。我在 SQLite 数据库中使用浮点数来映射商店位置,其准确性已经绰绰有余。如果我在绘制蚯蚓迁徙图,我可能会使用更准确的方法。
    • 呃,不。 CLLocation/CLLocationCoordinate2D/CLLocationDegrees 使用双精度;如果您不希望值“更改”,请将它们保留为双精度值。在 double 和 NSDecimal 之间转换 确实 会丢失精度。不知何故,人们错误地认为 NSDecimal 是完美的;它不是。它是十进制浮点而不是二进制浮点。
    【解决方案2】:

    CLLocation 实现了 NSCoding 协议,因此您可以将它们作为可转换属性存储在 Core Data 中。您可以使用默认的 NSKeyedUnarchiveFromData 值转换器。

    您只需将 CCLocation 对象传递给托管对象属性,它会将其序列化为数据并将其作为 blob 存储在 SQL 存储中。当您需要返回位置对象时,它会自动反转该过程并返回给您一个完全填充的 CCLocation 对象。

    这可能是获得您想要的东西的最简单方法。

    【讨论】:

    • 如果数据是序列化的,如果不从商店中获取每个位置,您将无法获取边界框内的位置。
    • 可能很简单,但以该格式存储时无法查询。
    【解决方案3】:

    存储它的“最佳”方式取决于你想用它做什么:

    • 如果您想要“相同”的 CLLocation,请将其序列化。 NSKeyedUnarchiveFromData 很好。
    • 如果您只想搜索纬度和经度,请将它们存储为双精度(并选中“索引”复选框)。

    如果您手动操作,您可以保存/恢复许多附加属性(高度、水平准确度、垂直准确度、时间戳)。还有一些你做不到的(速度、航向); CLLocation 没有提供合适的初始化方法并且属性是只读的。

    如果您正在录制曲目,所有额外的属性都非常有用。如果您在山区记录 POI(“我们仍然必须爬 100 m”),海拔高度很有用。水平/垂直精度可用于表示 POI 有多大(例如,一个城市可能有几公里的“水平精度”并显示为一个大圆圈)。

    【讨论】:

    • 您现在可以在 2020 年恢复除地面以外的所有区域。
    【解决方案4】:

    只需将Core Data 属性类型设置为Transformable,您就可以非常简单地做到这一点。如果您将 Value Transformer Name 留空,则默认转换器是 NSKeyedArchiver,它适用于大多数 Foundation 类型,例如 NSURL 和 CLLocation。

    【讨论】:

      【解决方案5】:

      您不需要使用 NSNumber 来存储纬度和经度点。您可以改为将 CLLocation 直接存储到核心数据。

      为每个 CLLocation 设置一个实体,无论实体使用位置点,这都会是一个太多的关系。我们称之为 LocationPoint:

      class LocationPoint: NSManagedObject {
      
      @NSManaged var game: NSNumber
      @NSManaged var time: NSDate
      @NSManaged var location: AnyObject
      
      }
      

      然后在 Xcode 数据模型中将 location 属性设置为可转换。就是这样!

      在 Objective-c 中,您实际上仍然可以将此 LocationPoint 属性声明为 CLLocation 而不会出现任何错误:

      @property (nonatomic, strong) CLLocation *location
      

      More info here.

      【讨论】:

        猜你喜欢
        • 2012-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多