Swift教程_CoreData实例(一)_构建storyboard
Swift教程_CoreData实例(二)_构建数据层
Swift教程_CoreData实例(三)_构建控制层(列表数据加载、删除数据)
Swift教程_CoreData实例(四)_构建控制层(查询、更新数据)
Swift教程_CoreData实例(五)_构建控制层(添加数据)
我们自定义一个列表控制器PKOBookDetailTableViewController,并应用到storyboard的明细显示view中,用来显示所选中的book的明细。通过PKOBooksTableViewController传的Book对象来为列表赋值。
其中用到了监听系统语言变更通知的触发发放,以及coredata自带的undo、redo功能(撤销操作、取消撤销),当然不加这些功能也不影响最终效果,详细见代码与注释。
代码如下,注释非常详细,其中包含更新数据的部分代码,请结合下一小节的代码阅读:
import UIKit class PKOBookDetailTableViewController: UITableViewController { var book: Book! @IBOutlet weak var titleLabel: UILabel! @IBOutlet weak var authorLabel: UILabel! @IBOutlet weak var dateLabel: UILabel! //加载view时调用 override func viewDidLoad() { super.viewDidLoad() NSLog("==viewDidLoad==") self.navigationItem.rightBarButtonItem = self.editButtonItem() //编辑的时候允许选择 self.tableView.allowsSelectionDuringEditing = true //监听到NSCurrentLocaleDidChangeNotification时,即系统语言变化时触发的方法,与removeObserver是一对 NSNotificationCenter.defaultCenter().addObserver(self, selector: "localeChanged:", name: NSCurrentLocaleDidChangeNotification, object: nil) } //析构方法 deinit{ NSLog("==deinit==") NSNotificationCenter.defaultCenter().removeObserver(self, name: NSCurrentLocaleDidChangeNotification, object: nil) } /* The view controller must be first responder in order to be able to receive shake events for undo. It should resign first responder status when it disappears.指定是否可以时第一响应者,通俗来讲就是焦点 */ override func canBecomeFirstResponder() -> Bool { return true } //view显示时设置焦点 override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) self.becomeFirstResponder() } //view销毁前取消焦点 override func viewWillDisappear(animated: Bool) { super.viewWillDisappear(animated) self.resignFirstResponder() } //视图即将可见时调用,每次显示view就会调用 override func viewWillAppear(animated: Bool) { NSLog("==viewWillAppear==") super.viewWillAppear(animated) //重载数据 self.updateInterface() //改变右侧按钮状态 self.updateRightBarButtonItemState() } //设置为编辑模式时调用 override func setEditing(editing: Bool, animated: Bool) { super.setEditing(editing, animated: animated) NSLog("==setEditing==\(editing)") self.navigationItem.setHidesBackButton(editing, animated: animated) //编辑状态时设置撤销管理器 if(editing){ self.setUpundoManager() }else //非编辑状态时取消撤销管理器并保存数据 { self.cleanUpUndoManager() var error: NSError? = nil if (self.book.managedObjectContext?.save(&error) == nil) { NSLog("Unresolved error \(error), \(error?.userInfo)") abort() } } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } //更新数据 func updateInterface() { self.authorLabel.text = self.book.author self.titleLabel.text = self.book.title self.dateLabel.text = self.dateFormatter().stringFromDate(self.book.theDate) } func updateRightBarButtonItemState() { NSLog("==updateRightBarButtonItemState==") // 如果实体对象在保存状态,则允许右侧按钮 var error: NSError? = nil self.navigationItem.rightBarButtonItem?.enabled = self.book.validateForUpdate(&error) } // MARK: - Table view data source //点击编辑按钮时的row编辑样式,默认delete,row前有一个删除标记,这里用none,没有任何标记 override func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle { return UITableViewCellEditingStyle.None } //点击编辑按钮时row是否需要缩进,这里不需要 override func tableView(tableView: UITableView, shouldIndentWhileEditingRowAtIndexPath indexPath: NSIndexPath) -> Bool { return false } //在行将要选择的时候执行。通常,你可以使用这个方法来阻止选定特定的行。返回结果是选择的行 override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? { if(self.editing){ return indexPath } return nil } //在选择行后执行,这里是编辑状态选中一行时创建一个编辑页面 override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { if(self.editing){ self.performSegueWithIdentifier("DetailToEdit", sender: self) } } // MARK: - Undo support //设置撤回管理器 func setUpundoManager() { if self.book.managedObjectContext?.undoManager == nil { self.book.managedObjectContext?.undoManager = NSUndoManager() self.book.managedObjectContext?.undoManager?.levelsOfUndo = 3//撤销最大数 } var bookUndoManager = self.book.managedObjectContext?.undoManager //监听撤回和取消撤回 NSNotificationCenter.defaultCenter().addObserver(self, selector: "undoManagerDidUndo:", name: NSUndoManagerDidUndoChangeNotification, object: bookUndoManager) NSNotificationCenter.defaultCenter().addObserver(self, selector: "undoManagerDidRedo:", name: NSUndoManagerDidRedoChangeNotification, object: bookUndoManager) } //取消撤回管理器 func cleanUpUndoManager() { var bookUndoManager = self.book.managedObjectContext?.undoManager //移除撤回和取消撤回监听 NSNotificationCenter.defaultCenter().removeObserver(self, name: NSUndoManagerWillUndoChangeNotification, object: bookUndoManager) NSNotificationCenter.defaultCenter().removeObserver(self, name: NSUndoManagerWillRedoChangeNotification, object: bookUndoManager) //置空context的撤回管理器 self.book.managedObjectContext?.undoManager = nil } //监听到撤回触发,重载数据和导航右侧按钮状态 func undoManagerDidUndo(notification : NSNotification){ NSLog("==undoManagerDidUndo==") //重载数据 self.updateInterface() //改变右侧按钮状态 self.updateRightBarButtonItemState() } //监听到取消撤回触发,重载数据和导航右侧按钮状态 func undoManagerDidRedo(notification : NSNotification){ NSLog("==undoManagerDidRedo==") //重载数据 self.updateInterface() //改变右侧按钮状态 self.updateRightBarButtonItemState() } // MARK: - Date Formatter //日期格式化 func dateFormatter() -> NSDateFormatter{ var dateFormatter = NSDateFormatter() dateFormatter.dateStyle = NSDateFormatterStyle.ShortStyle dateFormatter.timeStyle = NSDateFormatterStyle.NoStyle return dateFormatter } // MARK: - Navigation //通过segue跳转前所做的工作 override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { if(segue.identifier == "DetailToEdit"){ var bookEditViewController = segue.destinationViewController as PKOBookEditViewController bookEditViewController.editedObject = self.book //根据选择的不同行为编辑view赋不同的值 switch(self.tableView.indexPathForSelectedRow()!.row) { case 0: bookEditViewController.editedFieldKey = "title" bookEditViewController.editedFieldName = "title" case 1: bookEditViewController.editedFieldKey = "author" bookEditViewController.editedFieldName = "author" case 2: bookEditViewController.editedFieldKey = "theDate" bookEditViewController.editedFieldName = "theDate" default: break } } } // MARK: - Locale changes //监听到语言变化时,重载数据 func localeChanged(notification : NSNotification) { NSLog("==localeChanged==") //重载数据 self.updateInterface() } }
我们自定义一个基本的view控制器PKOBookEditViewController,并应用到storyboard的编辑view中,用来编辑所选中的字段。通过PKOBookDetailTableViewController中所选择的字段为编辑view的字段赋值。
其中用到了日期选择控件,需要根据PKOBookDetailTableViewController选择的字段来判断显示哪种控件。
代码如下,注释非常详细:
import UIKit class PKOBookEditViewController: UIViewController { @IBOutlet weak var textField: UITextField! @IBOutlet weak var datePicker: UIDatePicker! var editedObject: Book! var editedFieldKey: String! var editedFieldName: String! var editingDate: Bool!{ get{ //判断是否是日期字段 var attributeClassName = self.editedObject.entity.attributesByName[self.editedFieldKey]?.attributeValueClassName? if attributeClassName == "NSDate" { return true } else { return false } } } override func viewDidLoad() { super.viewDidLoad() //为标题赋值 self.title = self.editedFieldName //如果选中日期,则显示日期控件 if self.editingDate! { self.textField.hidden = true self.datePicker.hidden = false var date = self.editedObject.valueForKey(self.editedFieldKey) as? NSDate if date == nil { date = NSDate() } self.datePicker.date = date! } else { self.textField.hidden = false self.datePicker.hidden = true self.textField.text = self.editedObject.valueForKey(self.editedFieldKey) as String self.textField.placeholder = self.title//空的时候显示值 self.textField.becomeFirstResponder() } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } //点击保存 @IBAction func saveAction(sender: AnyObject) { // Set the action name for the undo operation.给撤回操作设置name NSLog("==saveAction==\(self.editedFieldName)") var undoManager = self.editedObject.managedObjectContext?.undoManager undoManager?.setActionName(self.editedFieldName) //更新该对象,然后抛出 if self.editingDate! { self.editedObject.setValue(self.datePicker.date, forKey:self.editedFieldKey) } else { self.editedObject.setValue(self.textField.text, forKey:self.editedFieldKey) } self.navigationController?.popViewControllerAnimated(true) } }点击进入ooppookid的博客