我目前正在
swift中试验持久性数据,但是我无法保存这些数据并再次检索它.基本上我有两个文本字段,当用户按下提交按钮时,该条目将保存到UITable,这里用户可以移动表格中的条目或删除它们,如果他们愿意的话.我的主要问题是保存和加载这些数据.
Taskmanager.swift – 这里我存储了我的基本类型
import Foundation
import UIKit
var taskMgr: TaskManager = TaskManager()
struct task {
var name = "Name"
var year = "Year"
}
//setting data
let defaults = UserDefaults.standard
//defaults.synchronize()
//getting data
class TaskManager: NSObject {
var tasks = [task]()
func addTask(name: String, year: String){
tasks.append(task(name: name, year: year))
}
}
ThirdViewController.swift – 这里我存储了我的表及其函数,我还有一个保存和加载数据函数的草图.
import Foundation
import UIKit
class ThirdViewController:UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet var tableView: UITableView!
@IBAction func deleteT(_ sender: Any) {
if(tableView.isEditing == true){
tableView.setEditing(false, animated: true)
}else{
tableView.setEditing(true, animated: true)
}
}
func saveData() {
let data = NSMutableData()
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let path = paths[0]
let file = (path as NSString).appendingPathComponent("Persistent.plist")
//2
let archiver = NSKeyedArchiver(forWritingWith: data)
archiver.encode(G, forKey: "name")
archiver.endode(year, forKey: "year")
archiver.finishEncoding()
data.write(toFile: file, atomically: true)
}
func loadData() {
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let path = paths[0]
let file = (path as NSString).appendingPathComponent("Persistent.plist")
// 1
if FileManager.default.fileExists(atPath: file) {
if let data = NSData(contentsOfFile: file) {
let unarchiver = NSKeyedUnarchiver(forReadingWith: data as Data)
name = unarchiver.decodeObjectForKey("name") as! [String]
year = unarchiver.decodeObjectForKey("year") as! [String]
unarchiver.finishDecoding()
}
}
}
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.reloadData()
loadData()
}
override func viewWillAppear(_ animated: Bool) {
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return taskMgr.tasks.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "TableView")
//Assign the contents of our var "items" to the textLabel of each cell
cell.textLabel!.text = taskMgr.tasks[indexPath.row].name
cell.detailTextLabel!.text = taskMgr.tasks[indexPath.row].year
//cell.editing = tableView(tableView, canMoveRowAtIndexPath: indexPath)
return cell
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath){
if (editingStyle == UITableViewCellEditingStyle.delete){
taskMgr.tasks.remove(at: indexPath.row)
tableView.reloadData()
}
}
}
FourthViewController.swift – 这里我有我的文本域和按钮,以及我如何将我的条目添加到表中.
import Foundation
import UIKit
class FourthViewController: UIViewController, UITextFieldDelegate{
@IBOutlet var addT: UITextField!
@IBOutlet var addY: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func confTask(_ sender:UIButton){
if (addT.text == ""){
}else{
//add record
let name: String = addT.text!
let Year: String = addY.text!
//taskMgr.addTask(name:name)
taskMgr.addTask(name:name, year:Year)
}
//dismiss keyboard and reset fields
self.view.endEditing(true)
addT.text = nil
addY.text = nil
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool{
textField.resignFirstResponder()
return true
}
}
最佳答案 我使用NSUserDefaults创建了一些示例代码来保存任务.这是一个相当简单的例子,只要你只是试验,并且只想要少于100个元素,它应该没问题.使用下面的代码,您应该能够显示,删除和保存任务.
但是,在将来,我强烈建议你阅读更多内容到Core Data.有很多很棒的教程,比如one.
我创建了一个Task对象模型,以及用于读取,保存和删除任务的TaskManager.
import Foundation
// Task Data Model
class Task: NSObject, NSCoding {
let name: String
let year: String
required init(name: String, year: String) {
self.name = name
self.year = year
}
required init(coder decoder: NSCoder) {
self.name = decoder.decodeObject(forKey: "name") as? String ?? ""
self.year = decoder.decodeObject(forKey: "year") as? String ?? ""
}
func encode(with coder: NSCoder) {
coder.encode(name, forKey: "name")
coder.encode(year, forKey: "year")
}
}
class TaskManager {
/// UserDefaults instance
private let defaults = UserDefaults.standard
/// Singleton instance, class **should** be accessed by this property
static let shared = TaskManager()
/// Indetifier of tasks container in `defaults`
private let kTasksIdentifier = "tasks"
/// Add a new task to your container and syncronize it into `defaults`
///
/// - Parameters:
/// - name: Name of the task
/// - year: Year of the task
func save(taskName name: String, year: String) {
let task = Task(name: name, year: year)
// Check if there is already saved tasks
guard let data = defaults.value(forKey: kTasksIdentifier) as? Data, var tasks = NSKeyedUnarchiver.unarchiveObject(with: data) as? [Task] else {
// If not, save it as the first one
syncronizeTasks(tasks: [task])
return
}
tasks.append(task)
syncronizeTasks(tasks: tasks)
}
/// Remove a task at an index
///
/// - Parameters:
/// - index: The index of the removeable task
func remove(at index: Int) {
guard let data = defaults.value(forKey: kTasksIdentifier) as? Data, var tasks = NSKeyedUnarchiver.unarchiveObject(with: data) as? [Task] else {
fatalError("Unable to retrive tasks from defaults")
}
tasks.remove(at: index)
syncronizeTasks(tasks: tasks)
}
/// Read all tasks elements
/// If there are tasks in memory, it returns the one from memory
/// Otherwise reads it from `UserDefaults`
///
/// - Returns: all tasks elements available, return empty array if no elements found
func readAllTasks() -> [Task] {
let data = UserDefaults.standard.value(forKey: kTasksIdentifier)
let allTasks = NSKeyedUnarchiver.unarchiveObject(with: data as! Data)
return allTasks as? [Task] ?? [Task]()
}
private func syncronizeTasks(tasks: [Task]) {
let data = NSKeyedArchiver.archivedData(withRootObject: tasks)
defaults.set(data, forKey: kTasksIdentifier)
defaults.synchronize()
}
}
我已经修改了你现有的ThirdViewController了.
import UIKit
import Foundation
class ThirdViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet var tableView: UITableView!
/// Your tasks being updated in this collection every time `refreshTasks()` is being called
private var tasks = [Task]()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.refreshTasks()
self.tableView.reloadData()
}
func refreshTasks() {
self.tasks = TaskManager.shared.readAllTasks()
}
@IBAction func deleteT(_ sender: Any) {
if(tableView.isEditing == true) {
tableView.setEditing(false, animated: true)
} else {
tableView.setEditing(true, animated: true)
}
}
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return tasks.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.subtitle, reuseIdentifier: "TableView")
//Assign the contents of our var "items" to the textLabel of each cell
cell.textLabel!.text = tasks[indexPath.row].name
cell.detailTextLabel!.text = tasks[indexPath.row].year
//cell.editing = tableView(tableView, canMoveRowAtIndexPath: indexPath)
return cell
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath){
if (editingStyle == UITableViewCellEditingStyle.delete) {
self.tableView.beginUpdates()
TaskManager.shared.remove(at: indexPath.row)
refreshTasks()
self.tableView.deleteRows(at: [indexPath], with: .fade)
self.tableView.endUpdates()
}
}
}
而且,为了以防万一,也编辑了你的FourthViewController
import Foundation
import UIKit
class FourthViewController: UIViewController, UITextFieldDelegate {
@IBOutlet var addT: UITextField!
@IBOutlet var addY: UITextField!
/// User has pressed `Submit` button
///
/// - Parameter sender: the pressed button
@IBAction func confTask(_ sender: UIButton) {
// Check if textfields are containing text
guard let nameText = addT.text, let yearText = addY.text, !nameText.isEmpty, !yearText.isEmpty else {
print("at least one of the textFields is not filled")
return
}
// Save the tasks
TaskManager.shared.save(taskName: nameText, year: yearText)
//dismiss keyboard and reset fields
self.view.endEditing(true)
addT.text = nil
addY.text = nil
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool{
textField.resignFirstResponder()
return true
}
}