自定义类符合MKAnotnotation和Codable [英] Custom class conformance to MKAnnotation and Codable

查看:72
本文介绍了自定义类符合MKAnotnotation和Codable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在iOS的Swift中开发一个小组项目应用程序,该应用程序允许用户使用Firebase将位置保存为Tour的一部分.我们的 User 对象是一个自定义类,我们希望它与 Codable 兼容,以便与CodableFirebase CocoaPod一起使用.但是,当尝试使 Location 对象与 Codable 符合时,就会出现问题,因为它也必须符合 MKAnnotation ...,我们都是相当新的.可能有一些解决方案使我望而却步...完全有可能.

I'm working on a group project application in Swift for iOS that allows users to save Location(s) as part of a Tour using Firebase. Our User object is a custom class that we hope to conform to Codable for use with the CodableFirebase CocoaPod. However, the issue arises when trying to conform the Location object to Codable because it also has to conform to MKAnnotation... and we are all fairly new to this. It's possible that some solutions have gone over my head... entirely possible.

这是我们的 Location 对象:

import Foundation
import MapKit
import CoreLocation
import CodableFirebase

class Location: NSObject, MKAnnotation {

    var coordinate: CLLocationCoordinate2D
    var locationName: String?
    var locationDescription: String?
    var locationImage: UIImage?

    init(coordinate: CLLocationCoordinate2D, locationName: String, locationDescription: String, locationImage: UIImage) {

        self.coordinate = coordinate
        self.locationName = locationName
        self.locationDescription = locationDescription
        self.locationImage = locationImage

    }
}

这是我们的 User 模型对象:

import UIKit
import CloudKit

class User {

    //MARK: - Editable Public Profile Info
    var firstName: String
    var lastName: String
    var userStateOfOrigin: States
    var userImage: UIImage?
    var aboutMe: String
    var languages: [Language]

    //MARK: - Editable Personal Info (Includes all Public Profile info)
    var email: String?
    var phoneNumber: String?

    //MARK: - Hidden Variables
    var userId: String
    var userCreatedTours: [Tour]
    var savedLocations: [Location]
    var savedTours: [Tour]
    var bookedTours: [Tour]
    var previouslyExperiencedTours: [Tour]
    var userRating: [Rating]

    init(firstName: String, lastName: String, userStateOfOrigin: States, userImage: UIImage? = nil, aboutMe: String, languages: [Language] = [], email: String?, phoneNumber: String? = "", userId: String, userCreatedTours: [Tour] = [], savedLocations: [Location] = [], savedTours: [Tour] = [], bookedTours: [Tour] = [], previouslyExperiencedTours: [Tour] = [], userRating: [Rating] = []) {

        // editable Public info
        self.firstName =  firstName
        self.lastName = lastName
        self.userStateOfOrigin = userStateOfOrigin
        self.userImage = userImage
        self.aboutMe = aboutMe
        self.languages = languages

        // editable personal info
        self.email = email
        self.phoneNumber = phoneNumber

        // Hidden Variables
        self.userId = userId
        self.userCreatedTours = userCreatedTours
        self.savedLocations = savedLocations
        self.savedTours = savedTours
        self.bookedTours = bookedTours
        self.previouslyExperiencedTours = previouslyExperiencedTours
        self.userRating = userRating

    }
}

我们确实还有其他一些自定义对象,但是我认为,一旦解决了这个问题,我们就应该能够轻松地使它们符合 Codable .最终,能够使它们都符合 Codable 以方便与Firebase一起使用将是很棒的.但是,如果这是不可能的,或者是最谨慎的方法,那么我很乐意提出建议.我真的很感激.

We do have a few other custom objects, but I think once this issue is solved, we should be able to easily conform those to Codable. Ultimately, it would be great to be able to make these both conform to Codable for easy use with Firebase. However, if that's not possible, or the most prudent route, I'm very open to suggestions. I really appreciate it.

推荐答案

一些观察结果:

  1. MKAnnotation 协议具有 title subtitle 属性(许多注释视图都使用)属性.我可能建议分别重命名 locationName locationDescription .

  1. MKAnnotation protocol has title and subtitle properties (that many annotation views use). I might suggest renaming locationName and locationDescription, respectively.

我建议使这些属性为 dynamic ,这样,如果您更新它们,则更改将在其各自的注释视图上进行更新.

I’d suggest making these properties dynamic, that way if you ever update them, the changes will be updated on their respective annotation views.

例如, coordinate 的文档说:

For example, the documentation for coordinate says:

您对该属性的实现必须符合键值观察(KVO).有关如何实现对KVO的支持的更多信息,请参见在Swift中执行此操作的简单方法是使用 dynamic 关键字.

The easy way to do this in Swift is with the dynamic keyword.

要使此 Codable 可用,

  • 属性也必须是 Codable ;或

您将需要分别手动实现 init(from:) encode(to:)进行解码和编码.有关示例,请参见对自定义类型进行编码和解码./p>

you will need to manually implement init(from:) and encode(to:) to do the decoding and encoding, respectively. See Encoding and Decoding Custom Types for examples.
 

鉴于 CLLocationCoordinate2D UIImage 都不符合 Codable ,我倾向于第二种选择.

Given that neither CLLocationCoordinate2D nor UIImage conform to Codable, I’d lean towards this second option.

非常重要的一点,但我可能不使用类型名称为 Location 的名称,而是使用名称中带有 Annotation 的名称什么是对象.它还有助于避免与位置对象混淆,例如 CLLocation .我在下面使用了 CustomAnnotation ,这不是一个好名字,但希望您能提供一个在您的应用程序中更有意义的名称,但在其中包含 Annotation 名称.

A very minor point, but I might not use a type name of Location, but rather using something with Annotation in the name, to make it clear what the object is. It also helps avoid confusion with location objects, e.g. CLLocation. I used CustomAnnotation below, which isn’t a great name, but hopefully you can come up with a name that makes more sense within your app, but also has Annotation within the name.

因此,将所有这些放在一起,您可能会做类似的事情:

Thus, pulling this all together you might do something like:

class CustomAnnotation: NSObject, MKAnnotation, Codable {
    dynamic var coordinate: CLLocationCoordinate2D
    dynamic var title: String?
    dynamic var subtitle: String?
    dynamic var image: UIImage?

    init(coordinate: CLLocationCoordinate2D, title: String?, subtitle: String?, locationImage: UIImage?) {
        self.coordinate = coordinate
        self.title = title
        self.subtitle = subtitle
        self.image = locationImage
    }

    enum CodingKeys: String, CodingKey {
        case title, subtitle, image, latitude, longitude
    }

    required init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)

        title = try values.decodeIfPresent(String.self, forKey: .title)
        subtitle = try values.decodeIfPresent(String.self, forKey: .subtitle)

        let latitude = try values.decode(CLLocationDegrees.self, forKey: .latitude)
        let longitude = try values.decode(CLLocationDegrees.self, forKey: .longitude)
        coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)

        let data = try values.decodeIfPresent(Data.self, forKey: .image)
        image = data.flatMap { UIImage(data: $0) }
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)

        try container.encodeIfPresent(title, forKey: .title)
        try container.encodeIfPresent(subtitle, forKey: .subtitle)
        try container.encode(coordinate.latitude, forKey: .latitude)
        try container.encode(coordinate.longitude, forKey: .longitude)
        try container.encodeIfPresent(image?.pngData(), forKey: .image)
    }
}

这篇关于自定义类符合MKAnotnotation和Codable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆