2017-04-17 4 views
1

에서 작동하지 않습니다 신속 엑스 코드 8.3NSKeyedArchiver.archivedData는 스위프트 3 아이폰 OS

unrecognized selector sent to instance 0x60800166fe80 *** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.

그리고 이런 내 코드에서이 오류가 발생합니다 :

수입 UIKit 수입 재단은

class Place: NSObject { 

    func setCustomObject(CustomObject obj:Any,Key key:String) { 

     let encodedObject : Data = NSKeyedArchiver.archivedData(withRootObject: obj) 
     UserDefaults.standard.set(encodedObject, forKey: key) 

    } 
} 
+0

해야 할 것 당신의'CustomObject'가'NSCoding' 프로토콜을 준수합니까? – njuri

+0

@ njuri가 필요하지 않습니다. –

+1

예, 답변에 설명되어 있습니다. – njuri

답변

1

여기 객체가 NSCoding을 준수 할 수 있도록하는 방법을 예입니다. 기본적으로 당신은 두 가지 방법의 구현을 제공 할 필요가 - required convenience init?(coder decoder: NSCoder)

class Book: NSObject, NSCoding { 
    var title: String? 
    var pageCount: Int? 

    // Memberwise initializer 
    init(title: String,pageCount: Int) { 
    self.title = title 
    self.pageCount = pageCount 
    } 

    // MARK: NSCoding 


    // Here you will try to initialize an object from archve using keys you did set in `encode` method. 
    required convenience init?(coder decoder: NSCoder) { 
    guard let title = decoder.decodeObject(forKey: "title") as? String else { return nil } 

    self.init(title: title, pageCount: decoder.decodeInteger(forKey: "pageCount")) 
    } 

    // Here you need to set properties to specific keys in archive 
    func encode(with aCoder: NSCoder) { 
    aCoder.encode(self.title, forKey: "title") 
    aCoder.encodeCInt(Int32(self.pageCount), forKey: "pageCount") 
    } 
} 

encode(with aCoder: NSCoder)는 또한 나는이에 setCustomObject 방법을 변경하는 것이 좋습니다 :

컴파일러는 당신이하지 않는 객체를 NSKeyedArchiver 통과 방지
func setCustomObject(obj:NSCoding, key:String) { 
    let encodedObject : Data = NSKeyedArchiver.archivedData(withRootObject: obj) 
    UserDefaults.standard.set(encodedObject, forKey: key) 
} 

이 방법 NSCoding 프로토콜을 준수하십시오.

당신이 기본값을 사용할 수 init 방법의 모든 속성을 제공하지 않으려면

:

init(title : String? = nil, pageCount: Int? = nil){ 
    self.title = title 
    self.pageCount = pageCount 
} 

지금 당신은 어떤 특성없이 개체를 init을 할 수 있습니다. 여기에 Book()

+0

이 예제에서는 큰 문제가 있습니다. My 객체의 속성이 너무 많아서 인스턴스를 새로 만들 때마다 nesesarry가 아닌 모든 속성으로 init 객체를 초기화해야합니다. @njuri –

+0

개체의 새로운 인스턴스에 nil 속성이 포함되어 있습니다. –

+0

Objective C에서 RMMAper를 이미 사용하고있어 사용하기가 쉽지만 새로 작성되어 사용하기가 복잡합니다. @njuri –

0

이 솔루션처럼, 당신은 두 가지 방법

인코딩 방법

func encode(with aCoder: NSCoder) 

디코딩 방법을 구현해야

required init?(coder aDecoder: NSCoder) 

전체 예제 코드

class User: NSObject , NSCoding 
{ 


var userID : Int = 0 
var name : String = "" 
var firstName : String = "" 
var lastName : String = "" 
var username : String = "" 
var email : String = "" 

override init(){ 
    super.init(); 
} 

func encode(with aCoder: NSCoder) { 

    aCoder.encode(self.userID, forKey: "id"); 
    aCoder.encode(self.firstName, forKey: "first_name"); 
    aCoder.encode(self.lastName, forKey: "last_name"); 
    aCoder.encode(self.name, forKey: "name"); 
    aCoder.encode(self.username,forKey: "username"); 
    aCoder.encode(self.email, forKey: "email"); 
} 

required init?(coder aDecoder: NSCoder) { 
    super.init() 

    self.userID  = aDecoder.decodeInteger(forKey: "id"); 
    self.firstName = aDecoder.decodeObject(forKey: "first_name") as! String; 
    self.lastName = aDecoder.decodeObject(forKey: "last_name") as! String; 
    self.name  = aDecoder.decodeObject(forKey: "name") as! String 
    self.username = aDecoder.decodeObject(forKey: "username") as! String 
    self.email  = aDecoder.decodeObject(forKey: "email") as! String; 
} 

init(data : [String: AnyObject]) { 

    super.init() 

    self.userID = String.numberValue(data["user_id"]).intValue; 
    self.firstName = String.stringValue(data["first_name"]); 
    self.lastName = String.stringValue(data["last_name"]); 
    self.email = String.stringValue(data["email"]); 
    self.username = String.stringValue(data["user_name"]); 
} 

class func loadLoggedInUser() -> User { 

    if let archivedObject = UserDefaults.standard.object(forKey:"CurrentUserAcc"){ 

     if let user = NSKeyedUnarchiver.unarchiveObject(with: (archivedObject as! NSData) as Data) as? User { 

      return user; 
     } 

    } 

    return User() 
} 

func saveUser(){ 

    let archivedObject : NSData = NSKeyedArchiver.archivedData(withRootObject: self) as NSData 

    UserDefaults.standard.set(archivedObject, forKey: "CurrentUserAcc"); 

    UserDefaults.standard.synchronize(); 
} 

func deleteUser(){ 

    UserDefaults.standard.set(nil, forKey: "CurrentUserAcc") 

    UserDefaults.standard.synchronize(); 
} 
} 
관련 문제