自定义类符合MKAnotnotation和Codable [英] Custom class conformance to MKAnnotation and 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.
推荐答案
一些观察结果:
-
MKAnnotation
协议具有title
和subtitle
属性(许多注释视图都使用)属性.我可能建议分别重命名locationName
和locationDescription
.
MKAnnotation
protocol hastitle
andsubtitle
properties (that many annotation views use). I might suggest renaminglocationName
andlocationDescription
, 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:)
andencode(to:)
to do the decoding and encoding, respectively. See Encoding and Decoding Custom Types for examples.
鉴于
CLLocationCoordinate2D
和UIImage
都不符合Codable
,我倾向于第二种选择.Given that neither
CLLocationCoordinate2D
norUIImage
conform toCodable
, 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 withAnnotation
in the name, to make it clear what the object is. It also helps avoid confusion with location objects, e.g.CLLocation
. I usedCustomAnnotation
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 hasAnnotation
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屋!