Swift:在后台同步核心数据对象

Posted

技术标签:

【中文标题】Swift:在后台同步核心数据对象【英文标题】:Swift: synchronise CoreData object in background 【发布时间】:2017-10-17 12:42:47 【问题描述】:

我需要在后台将CoreData 对象上传到 API 服务器。为此,我创建了一个新的私有上下文作为主上下文的子上下文,并在其上执行perform()。我使用此上下文从对象中获取 JSON 数据,并在上传后将一些数据写入对象。

看起来一切正常,但我有一些疑问。

下面是一个简单的例子,展示了这种情况。上下文在第二个函数中有一些强引用吗?我应该在某处保留对我的新上下文的强烈引用吗?

// ViewController.swift
func uploadObject(_ currentObject: MyManagedObject) 
    // we are in the main thread, go to another thread
    let objectId = currentObject.objectID
    let context = getNewPrivateContext()    // child context of the main context
    context.perform 
        if let object = context.object(with: objectId) as? MyManagedObject 
            SyncManager.shared.uploadObject(_ object: object, completion: 
                // ... update UI
            )
        
    


// SyncManager.swift
func uploadObject(_ object: MyManagedObject, completion: ()->()) 
    // does the context has some strong reference here?
    guard let context = object.managedObjectContext  completion(); return 

    let params = getJson(with: object)
    // ... prepare url, headers
    Alamofire.request(url, method: .put, parameters: params, encoding: JSONEncoding.default, headers: headers)
        .responseJSON( completionHandler:  (response) in
            // ... parse the response
            context.perform 
                // ... write some data to the Core Data and save the context
                completion()
            
        )

编辑

还有一个 lldb 问题支持我的怀疑:

(lldb) po context
error: <EXPR>:3:1: error: use of unresolved identifier 'context'
context
^~~~~~~

【问题讨论】:

我觉得一切都很好 请注意context.object(with: objectId) 将为您生成一个新对象。你可能想要existingObject(with:) 【参考方案1】:

这是一个强引用,但它是不安全的,这意味着如果接收者(对象)从其上下文中删除,它将返回 nil。

只是我的意见,我会使用if let 语句而不是守卫:

func uploadObject(_ object: MyManagedObject, completion: ()->()) 
    // does the context has some strong reference here?
    if let context = object.managedObjectContext 

        let params = getJson(with: object)
        // ... prepare url, headers
        Alamofire.request(url, method: .put, parameters: params, encoding: JSONEncoding.default, headers: headers)
    .responseJSON( completionHandler:  (response) in
            // ... parse the response
            context.perform 
                // ... write some data to the Core Data and save the context
                completion()
            
        )
     else 
        completion()
    

【讨论】:

guard 更改为if let 没有意义。这只是增加了不必要的代码嵌套。 很抱歉 :),那是我看到的唯一问题...您正在保存 privateMOC,这会将其更改推送到其父 MOC...我不是这个意思更好,只有两种不同的方式来处理选项。只有在设置context 时才会运行代码块的两种方式 其实你的context可能会随着范围的变化而被释放。设置断点,然后运行po context.userInfopo context.persistentStoreCoordinator。我通常在我的协调器类中保存两个 MOC 对象,一个是主对象,一个是私有对象,用于在后台解析数据/写入数据。我说这是一个强引用,因为查看 Apple 对象引用中的属性将其简单地列为 var,只要文档正确,它就会变得强大。 谢谢。现在我知道managedObjectContext 是强大但不​​安全的属性。我认为这是弱属性。 ) 请看我对帖子的编辑。由于某种原因,我不能po context

以上是关于Swift:在后台同步核心数据对象的主要内容,如果未能解决你的问题,请参考以下文章

ios - 如何在 ios swift 中正确实现后台获取

定期后台同步

核心数据:在后台将一批记录写入磁盘

定期后台同步

删除核心数据对象并保存在后台线程中

在后台和 tableView.reloadData() 中获取核心数据对象