NSCoding表示不兼容的对象(MKMapItem)

时间:2016-11-05 18:57:03

标签: swift mapkit nscoding

尝试将MKMapItem保存为自定义类的一部分。

 import UIKit
 import MapKit

 class Place: NSObject, NSCoding {

 var mapItem : MKMapItem!
 var type : Category!

 init(mapItem: MKMapItem, type: Category) {
   self.mapItem = mapItem
   self.type = type

 }

// MARK: NSCoding
    required init?(coder decoder: NSCoder) {

       mapItem = decoder.decodeObject(forKey: "mapItem") as! MKMapItem?
       type = decoder.decodeObject(forKey: "type") as! Category?
    }

    func encode(with coder: NSCoder) {

      coder.encode(mapItem, forKey: "mapItem")
      coder.encode(type, forKey: "type")
    }

 }

但这不会起作用,因为MKMapItem不符合NSCoding(编译器并不抱怨)。我确实理解如何编码自定义类,但无法弄清楚如何为已经由iOS定义的对象执行此操作。

我知道Objective-C对此有一个答案,但真的很喜欢Swift解决方案。感谢。

PS我试图将MKMapItem子类化并提供" new"初始化程序,即使在其他地方需要相当多的代码更改。但这导致"无法分配给财产:'地标'是一个只有获得的财产"。两个'地标'和' isCurrentLocation'是得到的。

import UIKit
import MapKit

class NewMapItem: MKMapItem {


    required init(placemark: MKPlacemark, isCurrentLocation:Bool, name: String,         phoneNumber: String, url: URL, timeZone: TimeZone) {
    self.placemark = placemark  //compiler complains "get-only"
    self.isCurrentLocation = isCurrentLocation  //compiler complains "get-only"
    self.name = name
    self.phoneNumber  = phoneNumber
    self.url = url
    self.timeZone = timeZone

}

// MARK: NSCoding

init?(coder decoder: NSCoder) {

    placemark = (decoder.decodeObject(forKey: "placemark") as! MKPlacemark?)! //compiler complains "get-only"
    isCurrentLocation = decoder.decodeBool(forKey: "isCurrentLocation")  //compiler complains "get-only"
    name = decoder.decodeObject(forKey: "name") as? String
    phoneNumber = decoder.decodeObject(forKey: "phoneNumber") as? String
    url = decoder.decodeObject(forKey: "url") as! URL?
    timeZone = decoder.decodeObject(forKey: "timeZone") as! TimeZone?
}

func encode(with coder: NSCoder) {

    coder.encode(placemark, forKey: "placemark")
    coder.encode(isCurrentLocation, forKey: "isCurrentLocation")
    coder.encode(name, forKey: "name")
    coder.encode(phoneNumber, forKey: "phoneNumber")
    coder.encode(url, forKey: "url")
    coder.encode(timeZone, forKey: "timeZone")
}
}

3 个答案:

答案 0 :(得分:0)

我已经弄清楚了。

在" func编码(使用编码器:NSCoder)"中分解mapItem。并在" init?(编码器解码器:NSCoder)"

中重新构建它

我确实利用了带有地标的MKMapItem初始化程序。

   MKMapItem(placemark: placemark!)

这是我的工人阶级:

import UIKit
import MapKit

class Place: NSObject, NSCoding {

  var mapItem : MKMapItem!
  var type : Category!

  init(mapItem: MKMapItem, type: Category) {
    self.mapItem = mapItem
    self.type = type
  }

// MARK: NSCoding
    required init?(coder decoder: NSCoder) {

    //liberate the properties of mapItem and rebuild it
    // let isCurrentLocation = decoder.decodeObject(forKey: "isCurrentLocation") as! Bool //don't need set already
      let name = decoder.decodeObject(forKey: "name") as! String?
      let phoneNumber = decoder.decodeObject(forKey: "phoneNumber") as! String?
      let url = decoder.decodeObject(forKey: "url") as! URL?
      let timeZone = decoder.decodeObject(forKey: "timeZone") as! TimeZone?
      let placemark = decoder.decodeObject(forKey: "placemark") as! MKPlacemark?

     self.mapItem = MKMapItem(placemark: placemark!)
     self.mapItem.name = name
     self.mapItem.url = url
     self.mapItem.phoneNumber = phoneNumber
     //self.mapItem.isCurrentLocation = isCurrentLocation //don't need this. Set already
     self.mapItem.timeZone = timeZone

     type = decoder.decodeObject(forKey: "type") as! Category?

   }

   func encode(with coder: NSCoder) {
     let placemark = mapItem.placemark
     let name = mapItem.name
     let phoneNumber  = mapItem.phoneNumber
     let url = mapItem.url
     let timeZone = mapItem.timeZone

     coder.encode(name, forKey: "name")
     coder.encode(phoneNumber,forKey: "phoneNumber")
     coder.encode(url, forKey: "url")
     coder.encode(timeZone, forKey: "timeZone")
     coder.encode(type, forKey: "type")
     coder.encode(placemark, forKey: "placemark")

   }

}

答案 1 :(得分:0)

MKMapItem使用NSSecureCoding,因此您可以使类符合NSSecureCoding,如以下示例所示,而不必重新创建MKMapItem:

class BGFPlaceItem: NSObject, NSSecureCoding {
    static var supportsSecureCoding: Bool {
        return true
    }
    func encode(with aCoder: NSCoder) {
        aCoder.encode(loadedAs.rawValue, forKey: "loadedAs")
        aCoder.encode(favorited, forKey: "favorited")
        aCoder.encode(mapItem, forKey: "mapItem")
    }
    required convenience init?(coder aDecoder: NSCoder) {
        let la = aDecoder.decodeObject(forKey: "loadedAs") as! String
        let fav = aDecoder.decodeBool(forKey: "favorited")
        let mi = aDecoder.decodeObject(forKey: "mapItem") as! MKMapItem
        let la2 = LoadedType(rawValue: la)!
        self.init(loadedAs: la2, isFavorited: fav, with: mi)
    }
    enum LoadedType: String {
        case generalPlace
        case favorite
        case searchResult

        var color: UIColor {
            switch self {
            case .generalPlace: return UIColor(named: "generalPlaceColor")!
            case .favorite: return UIColor(named: "favoriteColor")!
            case .searchResult: return UIColor.yellow
            }
        }
    }
    var loadedAs: LoadedType
    var favorited: Bool
    var mapItem: MKMapItem

    init(loadedAs: LoadedType, isFavorited favorited: Bool, with mi: MKMapItem) {
        self.loadedAs = loadedAs
        self.favorited = favorited
        self.mapItem = mi

        super.init()
    }
}

答案 2 :(得分:0)

您始终可以通过扩展使其符合要求

extension MKMapItem: NSCoding {
   required init?(coder decoder: NSCoder) {
       // codes
   }

   func encode(with coder: NSCoder) {
       // more codes
   }
}