天天看点

Swift教程_CoreData实例(四)_构建控制层(查询、更新数据)

<a target="_blank" href="http://write.blog.csdn.net/postedit/40661957">swift教程_coredata实例(一)_构建storyboard</a>

<a target="_blank" href="http://blog.csdn.net/ooppookid/article/details/40867835">swift教程_coredata实例(三)_构建控制层(列表数据加载、删除数据)</a>

swift教程_coredata实例(四)_构建控制层(查询、更新数据)

<a target="_blank" href="http://blog.csdn.net/ooppookid/article/details/41149291">swift教程_coredata实例(五)_构建控制层(添加数据)</a>

我们自定义一个列表控制器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() -&gt; 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(&amp;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(&amp;error)  

    // mark: - table view data source  

    //点击编辑按钮时的row编辑样式,默认delete,row前有一个删除标记,这里用none,没有任何标记  

    override func tableview(tableview: uitableview, editingstyleforrowatindexpath indexpath: nsindexpath) -&gt; uitableviewcelleditingstyle {  

        return uitableviewcelleditingstyle.none  

    //点击编辑按钮时row是否需要缩进,这里不需要  

    override func tableview(tableview: uitableview, shouldindentwhileeditingrowatindexpath indexpath: nsindexpath) -&gt; bool {  

        return false  

    //在行将要选择的时候执行。通常,你可以使用这个方法来阻止选定特定的行。返回结果是选择的行  

    override func tableview(tableview: uitableview, willselectrowatindexpath indexpath: nsindexpath) -&gt; nsindexpath? {  

        if(self.editing){  

            return indexpath  

        return nil  

    //在选择行后执行,这里是编辑状态选中一行时创建一个编辑页面  

    override func tableview(tableview: uitableview, didselectrowatindexpath indexpath: nsindexpath) {  

            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() {  

        //移除撤回和取消撤回监听  

        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==")  

    //监听到取消撤回触发,重载数据和导航右侧按钮状态  

    func undomanagerdidredo(notification : nsnotification){  

        nslog("==undomanagerdidredo==")  

    // mark: - date formatter  

    //日期格式化  

    func dateformatter() -&gt; 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==")  

}  

我们自定义一个基本的view控制器pkobookeditviewcontroller,并应用到storyboard的编辑view中,用来编辑所选中的字段。通过pkobookdetailtableviewcontroller中所选择的字段为编辑view的字段赋值。

其中用到了日期选择控件,需要根据pkobookdetailtableviewcontroller选择的字段来判断显示哪种控件。

代码如下,注释非常详细:

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  

        //为标题赋值  

        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()  

    //点击保存  

    @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)  

        //更新该对象,然后抛出  

            self.editedobject.setvalue(self.datepicker.date, forkey:self.editedfieldkey)  

            self.editedobject.setvalue(self.textfield.text, forkey:self.editedfieldkey)  

        self.navigationcontroller?.popviewcontrolleranimated(true)  

原文地址:http://blog.csdn.net/ooppookid/article/details/40887317