美文网首页Swift基础入坑
可视化建模--CoreData

可视化建模--CoreData

作者: iOS_July | 来源:发表于2018-06-11 10:41 被阅读32次

    想要实现可视化建模,需要New File,选择Core Data>Data Model,建立模型,模型名称,最好与工程名相同

    一、对象与实体的映射

    对象(Object)与数据库的实体(Entity)对应
    对象与实体都拥有属性(Attribute)
    CoreData.png
    @图片是二进制文件

    二、创建托管对象

    一旦使用CoreData,必须要把对象置于CoreData框架托管

    在当前创建的可视化模型中,在其属性的Class > Name,加上MO,这样,在Build工程后,会自动创建name+MO的托管对象 的类定义,但文件是不可见的

    //由于此时 不需要再没次都用代码写数据,数据源可以留空
    var areas : [AreaMO] = []
    

    三、保存数据的步骤

    iOS10中大幅度简化了Core Data用法,保存数据只需要2步
    3.1、类似一下代码,创建一个AreaMO实例,设置属性
    var area: AreaMO!
    
    3.2、调用AppDelegate中的saveContext方法
    @IBAction func saveTap(_ sender: UIBarButtonItem) {
            
            //获取appDelegate
            let appDelegate = UIApplication.shared.delegate as! AppDelegate
            
            //Core Data持久化容器中的context
            area = AreaMO(context: appDelegate.persistentContainer.viewContext)
            area.name = tfName.text
            area.province = tfProvince.text
            area.part = tfPart.text
            area.visited = isVisited
            
            //图片转为 JPG格式
            if let imageData = UIImageJPEGRepresentation(coverImageView.image!, 0.7) {
                area.thumbImage = NSData(data: imageData) as Data
            }
            
            //保存并返回首页
            print("正在保存")
            appDelegate.saveContext()
            performSegue(withIdentifier: "unwindToHomeList", sender: self)
        }
    

    四、读取保存的数据

    // MARK: - 写一个获取所有Area Entity下数据的方法
        func fetchAllData() {
            let appDelegate = UIApplication.shared.delegate as! AppDelegate
            
            //do-try-catch错误处理
            do {
                //AreaMO.fetchRequest() 获取AreaMO此Entity的所有条目
                
                areas = try appDelegate.persistentContainer.viewContext.fetch(AreaMO.fetchRequest())
            } catch  {
                print(error)
            }
            
        }
        
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(true)
            
            //放在viewDidAppear里执行
            fetchAllData()
            tableView.reloadData()
    
        }
    

    五、高效刷新:

    没次全部更新tableView,性能上是不可接受的
    能达到以下效果再好不过

    加一条,出现一条
    删一条,少一条

    NSFetchedResultsController
    可把单元格内容与数据进行绑定,响应数据变化
    
    @第一步:
    import CoreData
    
    @第二步:
    遵从NSFetchedResultsControllerDelegate协议
    此协议提供数据变化时的通知及代理的方法
    
    @第三步:
    定义一个NSFetchedResultsController变量
    var fc : NSFetchedResultsController<AreaMO>!
    
    @主体代码:
    func fetchAllData2() {
            //请求结果是AreaMO
            let request : NSFetchRequest<AreaMO> = AreaMO.fetchRequest()
            //NSSortDescriptor指定请求结果如何排序
            let sd = NSSortDescriptor(key: "name", ascending: true)
            request.sortDescriptors = [sd]
            
            let appDelegate = UIApplication.shared.delegate as! AppDelegate
            let context = appDelegate.persistentContainer.viewContext
            //NSFetchedResultsController初始化后,指定代理
            fc = NSFetchedResultsController(fetchRequest: request, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
            fc.delegate = self
            
            //执行查询,将结果保存到数组中
            do {
                try fc.performFetch()
                if let objects = fc.fetchedObjects {
                    areas = objects
                    
                }
            } catch {
                print(error)
            }
            //如果执行,会显示上一次保存的数据,但新增数据后,表格不会更新
            
        }
    

    六、代理方法

    当数据内容发生变化时,NSFetchedResultsControllerDelegate协议的以下方法会被调用:

    //当控制器开始处理内容变化时
        func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
           tableView.beginUpdates()
        }
        //内容发生变更时
        func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
           
            switch type {
            case .delete:
                tableView.deleteRows(at: [indexPath!], with: .automatic)
            case .insert:
                tableView.insertRows(at: [newIndexPath!], with: .automatic)
            case .update:
                tableView.reloadRows(at: [indexPath!], with: .automatic)
            default:
                tableView.reloadData()
            }
            
            if let objects = controller.fetchedObjects {
                areas = objects as! [AreaMO]
            }
        }
        //当控制器已经处理完内容变更时
        func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
            tableView.endUpdates()
        }
    

    七、真正的删除

    @修改之前tableView的删除方法
                self.areas.remove(at: indexPath.row)
                let appDelegate = UIApplication.shared.delegate as! AppDelegate
                let context = appDelegate.persistentContainer.viewContext
                context.delete(self.fc.object(at: indexPath))
                appDelegate.saveContext()
    
    //            此处需要注释掉,因为我们已经控制了数据库的删除
    //            tableView.deleteRows(at: [indexPath], with: .fade)
    
    @然后更新对象
    reviewVC.ratingCloser = { (value:String) -> Void in
                self.area.rating = value
                self.RatingBtn.setImage(UIImage(named: value), for: .normal)
                    
            }
    let appDelegate = UIApplication.shared.delegate as! AppDelegate
    appDelegate.saveContext()
            
    
    @重新读取
    if let rating = area.rating {
       self.RatingBtn.setImage(UIImage(named: rating), for: .normal)
    }
    

    相关文章

      网友评论

        本文标题:可视化建模--CoreData

        本文链接:https://www.haomeiwen.com/subject/jbzisftx.html