2016-09-25 3 views
2

Я пытаюсь сохранить массив в UserDefaults, но не нашел удачи в поиске решения. У меня есть struct и func, которые работают, чтобы хранить «имя» и «описание» в массиве. Код выглядит следующим образом ...Swift 3.0: хранить массив в UserDefaults для tableView

struct task { 
    var name = "Untitled" 
    var description = "No description available" 
} 

var tasks = [task]() 

func addTask(name: String, description: String) { 
    tasks.append(task(name: name, description: description)) 
} 

Какой самый лучший способ для хранения данных в UserDefaults и добавить информацию в cell.textLabel?.text и cell.detailTextLabel?.text после перезапуска?

+1

Если имя вашего начиная с-структуру прописной буквы. Вам нужно создать класс, сделать его совместимым с NSCoding и использовать KeyedArchiever для сохранения данных объекта. –

+0

@LeoDabus. Невозможно сохранить данные массива с помощью NSUserDefaults? –

+0

Вы можете использовать UserDeafaults для сохранения объекта Data из KeyedArchiever –

ответ

0

Это соглашение Swift, чтобы называть ваши структуры, начиная с прописной буквы. Вам нужно сделать класс, сделать его NSCoding податливыми и использовать KeyedArchiever для сохранения данных объекта

class Task: NSObject, NSCoding { 
    let name: String 
    let desc: String 
    required init(name: String, desc: String) { 
     self.name = name 
     self.desc = desc 
    } 
    func encode(with coder: NSCoder) { 
     coder.encode(name, forKey: "name") 
     coder.encode(desc, forKey: "desc") 
    } 
    required init(coder decoder: NSCoder) { 
     self.name = decoder.decodeObject(forKey: "name") as? String ?? "" 
     self.desc = decoder.decodeObject(forKey: "desc") as? String ?? "" 
    } 
} 

Тестирование

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { 
    @IBOutlet weak var nameField: UITextField! 
    @IBOutlet weak var descField: UITextField! 
    @IBOutlet weak var tableView: UITableView! 
    var tasks: [Task] = [] 
    override func viewDidLoad() { 
     super.viewDidLoad() 
     tableView.delegate = self 
     tableView.dataSource = self 
     if let data = UserDefaults.standard.data(forKey: "tasks") { 
      tasks = NSKeyedUnarchiver.unarchiveObject(with: data) as? [Task] ?? [] 
      tableView.reloadData() 
     } 
    } 
    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
    } 
    @IBAction func addTask(_ sender: UIButton) { 
     guard let name = nameField.text, let desc = descField.text else { return } 
     tasks.append(Task(name: name, desc: desc)) 
     UserDefaults.standard.set(NSKeyedArchiver.archivedData(withRootObject: tasks) , forKey: "tasks") 
     tableView.reloadData() 
    } 
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return tasks.count 
    } 
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCell(withIdentifier: "cellID")! 
     cell.textLabel?.text = tasks[indexPath.row].name + " - " + tasks[indexPath.row].desc 
     return cell 
    } 
} 
+0

Спасибо за ответ. Я создал тестовый проект, одно приложение с двумя текстовыми полями и кнопкой, одно для имени, описания и для добавления задачи. Верхняя часть кода находится в отдельном файле Task.swift, а остальная часть кода находится в viewDidLoad. Кажется, что элементы массива не сохраняются при следующих мыслях о запуске? –

+1

@SebVidal https://www.dropbox.com/s/sb4jm6asm3cistw/Tasks.zip?dl=1 –

+0

Это работало до сих пор при выполнении 'UserDefaults.standard.set (NSKeyedArchiver.archivedData (withRootObject: tasks) , forKey: «tasks»), приложение завершает и возвращает Thread 1: SIGABRT. Это сообщение появляется в консоли: '2016-10-02 12: 22: 00.930576 Расписание [8448: 2049895] - [Расписание.Task encodeWithCoder:]: непризнанный селектор, отправленный в экземпляр 0x174134e60 2016-10-02 12: 22: 00.937006 Расписание [8448: 2049895] *** Завершение приложения из-за неперехваченного исключения «NSInvalidArgumentException», причина: '- [Timetable.Task encodeWithCoder:]: непризнанный селектор, отправленный в экземпляр 0x174134e60'' –