IOS Swift: сохранение массива пользовательских классов
Я новичок в программировании. Я делаю небольшую программу базы данных для iOS в быстром режиме.
У меня есть класс человека:
class Person : NSObject {
var firstName : String
var lastName : String
init (firstName : String, lastName : String) {
self.firstName = firstName
self.lastName = lastName
}
}
Я объявляю массив класса в верхней части моего контроллера представления:
var peopleArray = [Person]()
Затем я заполняю массив, объявляя некоторых примерных пользователей и добавляя их в массив:
var nateB = Person(firstName: "Nate", lastName: "Birkholz")
var nateC = Person(firstName: "Nate", lastName: "Carson")
var nateD = Person(firstName: "Nate", lastName: "Donnelly")
self.peopleArray.append(nateB)
self.peopleArray.append(nateC)
self.peopleArray.append(nateD)
Затем я пытаюсь сохранить данные в файле plist:
let fileManager = (NSFileManager.defaultManager())
let directorys : [String]? = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory,NSSearchPathDomainMask.AllDomainsMask, true) as? [String]
if (directorys != nil){
let directories:[String] = directorys!;
let pathToFile = directories[0]; //documents directory
let plistfile = "PeopleArray.plist"
let plistpath = pathToFile.stringByAppendingPathComponent(plistfile);
if !fileManager.fileExistsAtPath(plistpath){
println("Declaring cocoaArray")
var cocoaArray : NSArray = peopleArray
cocoaArray.writeToFile(plistpath, atomically: true)
println("I wrote an array to the file at\n\n\(plistpath)")
}
Файл plist не создается, он автоматически не создает и функция завершается так, как если бы она была. Есть предположения?
Неясные процессы совместимости быстрых типов данных и структур данных с классами cocoa расстраивают меня. Я просто хочу сохранить файл danged. Я также не могу использовать функцию "добавить", если я объявляю свой массив как NSArray, и я не могу + элемент в массиве...
Обновление
Я добавил следующие функции в класс Person:
func encodeWithCoder(aCoder: NSCoder!) {
aCoder.encodeObject(firstName, forKey:"firstName")
aCoder.encodeObject(lastName, forKey:"lastName")
}
init (coder aDecoder: NSCoder!) {
self.firstName = aDecoder.decodeObjectForKey("firstName") as String
self.lastName = aDecoder.decodeObjectForKey("lasName") as String
}
Сохранение файла:
let fileManager = (NSFileManager.defaultManager())
let directorys : [String]? = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory,NSSearchPathDomainMask.AllDomainsMask, true) as? [String]
println("value of directorys is \(directorys)")
if (directorys != nil){
let directories:[String] = directorys!;
let pathToFile = directories[0]; //documents directory
let plistfile = "PeopleArray.plist"
let plistpath = pathToFile.stringByAppendingPathComponent(plistfile);
if !fileManager.fileExistsAtPath(plistpath){ //writing Plist file
self.createInitialPeople()
println("Declaring cocoaArray")
var cocoaArray : NSArray = [NSKeyedArchiver.archivedDataWithRootObject(peopleArray)]
println("writing to path")
cocoaArray.writeToFile(plistpath, atomically: true)
let tellMe = cocoaArray.writeToFile(plistpath, atomically: true)
println("Return of write is \(tellMe)")
}
Создается файл Plist с непостижимыми данными.
Я закрою приложение и запустил его снова, затем попробую загрузить файл:
else { //Reading Plist file
println("\n\nPlist file found at \(plistpath)")
let cocoaArray = NSMutableArray.arrayWithContentsOfFile(plistpath)
peopleArray = cocoaArray as Array
}
}
И я терпеть неудачу, потому что я не могу упустить "AnyObject не идентичен" Person ". Я попытался уменьшить его несколькими способами и просто не могу сделать это успешно. Это действительно расстраивает.
Ответы
Ответ 1
Прежде всего, основная причина [NSArray writeToFile:atomically:]
поддерживает только определенные типы данных. Вы можете проверить документацию здесь.
Если вы распечатаете код возврата из cocoaArray.writeToFile(plistpath, atomically: true)
, вы увидите, что он установлен на False
.
Чтобы преодолеть это ограничение, вам нужно
1) реализовать функцию кодирования в классе Person
func encodeWithCoder(aCoder: NSCoder!) {
aCoder.encodeObject(firstName, forKey:"firstName")
aCoder.encodeObject(lastName, forKey:"lastName")
}
2) Преобразуйте элементы в массив в NSData
, например.
var cocoaArray : NSArray = [NSKeyedArchiver.archivedDataWithRootObject(nateB)]
В конце вам также понадобится функция декодирования в классе Person
для поддержки их чтения из файла plist
Ответ 2
После того, как вы добавили в свой класс Person следующие функции:
func encodeWithCoder(aCoder: NSCoder!) {
aCoder.encodeObject(firstName, forKey:"firstName")
aCoder.encodeObject(lastName, forKey:"lastName")
}
init (coder aDecoder: NSCoder!) {
self.firstName = aDecoder.decodeObjectForKey("firstName") as String
self.lastName = aDecoder.decodeObjectForKey("lasName") as String
}
Вы должны использовать 【NSKeyedArchiver】 и 【NSKeyedUnarchiver】 для хранения и выборки массива.
Спасибо @Энтони Конг.
Его ответ очень помогает, но я думаю, что следующие коды действительно могут решить проблему.
ЗАПУСК МАССЫ В ПЛИТЕ
let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory,NSSearchPathDomainMask.AllDomainsMask, true)
let path: AnyObject = paths[0]
let arrPath = path.stringByAppendingString("/array.plist")
NSKeyedArchiver.archiveRootObject(peopleArray, toFile: arrPath)
ДЛЯ ОБРАБОТКИ ПЛАТЫ МАССОВОЙ ФОРМЫ
if let tempArr: [Person] = NSKeyedUnarchiver.unarchiveObjectWithFile(arrPath) as? [Person] {
peopleArray = tempArr
}