Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/98.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 将自定义类对象转换为NSData_Ios_Swift_Nsdata - Fatal编程技术网

Ios 将自定义类对象转换为NSData

Ios 将自定义类对象转换为NSData,ios,swift,nsdata,Ios,Swift,Nsdata,我有一个自定义类,要保存到NSUserDefaults中。我被告知需要将类对象转换为数据,以便将其保存到NSUserDefaults。我在NSData示例中找到了很多离散字符串或int,但在自定义类中没有找到NSData。我对NSData编码等的复杂性知之甚少。如有任何帮助,我将不胜感激 编辑:虽然我知道这里有类似的答案,但没有一个是Swift。在两种语言之间进行翻译是可行的,但它极其乏味,有时甚至违反直觉。这里有一个简单的例子: //Custom class. class Person: NS

我有一个自定义类,要保存到
NSUserDefaults
中。我被告知需要将类对象转换为数据,以便将其保存到
NSUserDefaults
。我在
NSData
示例中找到了很多离散字符串或int,但在自定义类中没有找到
NSData
。我对
NSData
编码等的复杂性知之甚少。如有任何帮助,我将不胜感激


编辑:虽然我知道这里有类似的答案,但没有一个是Swift。在两种语言之间进行翻译是可行的,但它极其乏味,有时甚至违反直觉。

这里有一个简单的例子:

//Custom class.
class Person: NSObject, NSCoding {
    var name: String!
    var age: Int!
    required convenience init(coder decoder: NSCoder) {
        self.init()
        self.name = decoder.decodeObjectForKey("name") as! String
        self.age = decoder.decodeObjectForKey("age") as! Int
    }
    convenience init(name: String, age: Int) {
        self.init()
        self.name = name
        self.age = age
    }
    func encodeWithCoder(coder: NSCoder) {
        if let name = name { coder.encodeObject(name, forKey: "name") }
        if let age = age { coder.encodeObject(age, forKey: "age") }

    }
}

//create an instance of your custom class.
var newPerson = [Person]()

//add some values into custom class.
newPerson.append(Person(name: "Leo", age: 45))
newPerson.append(Person(name: "Dharmesh", age: 25))

//store you class object into NSUserDefaults.
let personData = NSKeyedArchiver.archivedDataWithRootObject(newPerson)
NSUserDefaults().setObject(personData, forKey: "personData")


//get your object from NSUserDefaults.
if let loadedData = NSUserDefaults().dataForKey("personData") {

    if let loadedPerson = NSKeyedUnarchiver.unarchiveObjectWithData(loadedData) as? [Person] {
        loadedPerson[0].name   //"Leo"
        loadedPerson[0].age    //45
    }
}
在操场上测试

希望这有帮助。

此链接可以帮助您

类扩展
NSObject
NSCoding
非常重要,因为转换需要是它的类,
NSCoding
是序列化和反序列化类的接口


以下示例代码基于Richie Rich的答案(见上文),并在此环境中通过测试:

  • Xcode版本9.1(9B55)
  • Swift版本4.0.2(swiftlang-900.0.69.2 clang-900.0.38,目标:x86_64-apple-macosx10.9)
  • MacBookAir(11英寸,2012年年中)搭载macOS High Sierra(10.13.1版)


类的可能副本只需符合NSCoding协议。如果let name=name,语法
是什么意思?名称本身不总是相等吗?@johnbakers它确保值不是相等的nil@johnbakers这主要是因为你不必打开它,因为你可以只做一个简单的
nil
检查,但是你必须在大括号内打开它<代码>如果让
为您打开它。如果此人是邮票收集者,因此拥有一系列邮票对象(带有年份、国家、价值等),该怎么办。那么,如何处理自定义类中的自定义类数组呢?Hi@dharmesh,我尝试着做同样的事情,但不是存储在用户默认值中,而是存储在文件中,但当我检索时,我得到的是nill数据。有什么办法吗?
// Foundation is required to NSObject and NSCoding
import Foundation

// A custom class called Person with two properties (a string name and an
// integer age), that is a subclass of NSObject and adopts NSCoding protocol.
class Person: NSObject, NSCoding {
  var name: String!
  var age: Int!

  // The convenience initializer for class Person
  // Reference
  // https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID217
  convenience init(name: String, age: Int) {
    // self.init() is the designated initializer for class Person.
    // Reference
    // https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Initialization.html#//apple_ref/doc/uid/TP40014097-CH18-ID219
    self.init()
    self.name = name
    self.age = age
  }

  // The initializer init(coder:) is required by NSCoding protocol
  // Reference
  // https://developer.apple.com/documentation/foundation/nscoding
  // https://developer.apple.com/documentation/foundation/nscoding/1416145-init
  required convenience init(coder aDecoder: NSCoder) {
    self.init()
    // as! is a type casting operator
    // Reference
    // https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Expressions.html#//apple_ref/doc/uid/TP40014097-CH32-ID388
    self.name = aDecoder.decodeObject(forKey: "name") as! String
    self.age = aDecoder.decodeInteger(forKey: "age")
  }

  // The instance method encode(with:) is required by NSCoding protocol
  // Reference
  // https://developer.apple.com/documentation/foundation/nscoding
  // https://developer.apple.com/documentation/foundation/nscoding/1413933-encode
  func encode(with anEncoder: NSCoder) {
    if let name = name {
      anEncoder.encode(name, forKey: "name")
    }
    if let age = age {
      anEncoder.encode(age, forKey: "age")
    }
  }
}

// Create an array (or, generally speaking, a collection) as a container to
// hold instances of our custom class type Person.
// Reference
// https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html
var anArrayOfPersons = [Person]()
print(anArrayOfPersons.count) // 0

// Add two instances into anArrayOfPersons.
// Reference
// https://developer.apple.com/documentation/swift/array
// https://developer.apple.com/documentation/swift/array/1538872-append
anArrayOfPersons.append(Person(name: "Cong", age: 33))
anArrayOfPersons.append(Person(name: "Sunny", age: 2))

// Archive anArrayOfPersons into NSData using NSKeyedArchiver.
// Reference
// https://developer.apple.com/documentation/foundation/nskeyedarchiver
// https://developer.apple.com/documentation/foundation/nskeyedarchiver/1413189-archiveddata
let dataToSave = NSKeyedArchiver.archivedData(withRootObject: anArrayOfPersons)

// Persist data. Storing anArrayOfPersons into UserDefaults as data.
// Reference
// https://developer.apple.com/documentation/foundation/userdefaults
// https://developer.apple.com/documentation/foundation/userdefaults/1414067-set
UserDefaults().set(dataToSave, forKey: "tagOfData")

// Take our stored data (in previous step) from UserDefaults using the key
// "personData". Optional binding is used to make sure the retrieved data is
// not nil.
// Reference
// https://developer.apple.com/documentation/foundation/userdefaults
// https://developer.apple.com/documentation/foundation/userdefaults/1409590-data
// https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID333
if let dataRetrieved = UserDefaults().data(forKey: "tagOfData"),
  // Decode our instance objects from the retrieved data
  // Reference
  // https://developer.apple.com/documentation/foundation/nskeyedunarchiver
  // https://developer.apple.com/documentation/foundation/nskeyedunarchiver/1413894-unarchiveobject
  let anArrayOfPersonsRetrieved = NSKeyedUnarchiver.unarchiveObject(with: dataRetrieved) as? [Person] {
    // See how many bytes the data we retrieved has.
    print(dataRetrieved) // 393 bytes

    // See if the name and age properties are the same as what we stored.
    print(anArrayOfPersonsRetrieved[0].name) // "Cong"
    print(anArrayOfPersonsRetrieved[0].age)  // 45
    print(anArrayOfPersonsRetrieved[1].name) // "Sunny"
    print(anArrayOfPersonsRetrieved[1].age)  // 2
  }