存储 1000 个 MapKit 注释的最佳方式 + 在 tableView 中显示注释

Best way to store 1000's of MapKit annotations + show annotations in tableView

问题:存储 1000 条 MapKit 注释的最佳方法是什么,这些注释将显示在地图上并且也应该可以在 tableView 中浏览?用户还应该能够将选定的注释标记为收藏,并将它们显示在单独的 tableView.

背景:我正在学习 iOS 编程(通过 Udemy、Google 和 Stack Overflow)。我目前正在尝试制作一个基于 MapKit 的应用程序,它可以在地图上显示大量注释。每个注释代表一种特定类型的位置。出于测试目的,我制作了一个虚拟 GeoJSON 文件(位于应用程序中,而不是服务器上),它存储每个位置,如下所示:

 {
        "type" : "Feature",
        "properties" : {
            "location" : "Norway",
            "title" : "Annotation Title",
            "website" : "http://www.whosebug.com",
        },
        "geometry" : {
            "type" : "Point",
            "coordinates" : [10, 60]
        }
    },

这很好用;我的虚拟 objects 被解析并放在地图上就好了。但最终,我将拥有 1000 多个真实注释,而不仅仅是我的一些虚拟注释。

Map View

这是我的技能不足之处:我希望用户能够将特定位置标记为收藏夹,这当然应该通过应用程序更新、iOS 更新以及理想情况下在用户的多个设备之间持续存在.

Favorites view

用户还应该能够浏览所有注释,按国家和州排序。

Browse view

解决这个问题的好方法是什么?我试图将其分解为:

  1. 找到一种存储注释的好方法——鉴于第 2 点和(特别是)第 3 点,GeoJSON 可能并不理想?我应该查看数据库设置吗?

  2. 用数据库中的所有注释填充 tableView,第一个 tableView 显示所有国家,然后点击一行进入另一个 tableView该国家/地区的所有州,另一个进入第三个 tableView,每个注释都在该州。

  3. 让用户将选定的注释标记为收藏,并仅使用标记为收藏的注释填充新的 tableView

在我回答这个问题之前,我想指出在地图上显示 1000 多个 MKAnnotationView 本身也是一个完整的问题,您可能想研究使用 dequeueReusableAnnotationViewWithIdentifier: 方法或MKClusterAnnotation 这些注释可以避免屏幕延迟。

现在回答您实际提出的问题,而不是考虑如何为您的应用中的一项功能存储数据。多想想应该如何为整个应用程序本身存储数据。

https://www.iosapptemplates.com/blog/ios-development/data-persistence-ios-swift - 此 link 讨论了持久数据存储的各种选项及其 advantages/disadvantages。正如您所说,您目前正在学习 iOS 课程 我建议使用 CoreData,因为它是一个原生的 IOS 特定框架,可以很好地补充您的学习和可能会被 Udemy 覆盖。另一个原因是 CoreData 很容易设置和学习 Apple 提供的大量文档,因此对于“新手”来说应该是一个好的开始。

核心数据示例

创建你的模型

创建 CoreData 管理器

class CoreDataManager {
static let shared = CoreDataManager()
private init() {}
private lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "PillReminder")
    container.loadPersistentStores(completionHandler: { _, error in
        _ = error.map { fatalError("Unresolved error \([=10=])") }
    })
    return container
}()

var mainContext: NSManagedObjectContext {
    return persistentContainer.viewContext
}

func backgroundContext() -> NSManagedObjectContext {
    return persistentContainer.newBackgroundContext()
}

正在加载一组药丸

func loadPills() -> [Pill] {
let mainContext = CoreDataManager.shared.mainContext
let fetchRequest: NSFetchRequest<Pill> = Pill.fetchRequest()
do {
    let results = try mainContext.fetch(fetchRequest)
    return results
}
catch {
    debugPrint(error)
}

保存一个新的 Pill 实体

func savePill(name: String) throws {
let context = CoreDataManager.shared.backgroundContext()
context.perform {
    let entity = Pill.entity()
    let pill = Pill(entity: entity, insertInto: context)
    pill.name = name
    pill.amount = 2
    pill.dozePerDay = 1
    pill.lastUpdate = Date()
    try context.save()
}

}