在块中修改后未更新 Swift 结构

Posted

技术标签:

【中文标题】在块中修改后未更新 Swift 结构【英文标题】:Swift structure not updated after modifying in a block 【发布时间】:2015-06-17 09:50:39 【问题描述】:

我正在用 Swift 编写一个 ios 应用程序,但遇到了一些关于结构和块的问题。当用户编辑他的教育信息并单击保存按钮时,我向服务器发送请求并更新成功处理程序中的本地数据。这里我在EditController类中写了一个editItem()函数,在UserModel类结构中写了一个editEducation()

class EditController: UITableViewController 

    //...

    func editItem<T>(item: T, completion: () -> Void) 
        switch selectedType 
            case .Education:
                let educationItem = item as! EducationModel
                // self.user is a object of type "UserModel"
                user!.editEducation(index: selectedRow, educationItem: educationItem) 
                    // breakpoint 2 here
                    completion()
                    self.tableView.reloadData()
                
            default:
                return
        
    

    //...



struct UserModel 

    //...

    var education = [EducationModel]()
    //EducationModel is also a structure

    //...

    mutating func editEducation(#index: Int, educationItem: EducationModel, completion: () -> Void) 
       let manager = HTTPClient.sharedManager
       manager.POST("/user/education/update",
           parameters: [
               // params
           ],
           success:  (task, responseObject) in
               if responseObject["status"] as! Int == 0 
                   self.education[index] = educationItem
                   // breakpoint 1 here
                   completion()
                else 
                   println(responseObject)
               
           ,
           failure:  (task, error) in
               println(error)
           
       )
    

    //...


问题是,尽管self.education 在程序到达断点 1 时成功更新(如上所述),self.user.education 仍然包含断点 2 处的旧数据。如果我移动

self.education[index] = educationItem

在 POST 请求之外,数据在断点 2 处按预期更新。我尝试通过在断点 2 处添加调度来延迟,但它仍然不会更新。我还打印了相关变量的内存地址,但它没有提供任何有用的信息。我现在通过向editEducation 添加一个controller 参数来处理这个问题,在EditController 中传递self 并强制更新控制器的user 属性。我认为这不是一个适当的解决方案。那么有没有更好的方法来做到这一点?

更新 1

我尝试将 UserModel 转换为一个类,它解决了问题,但我不想这样做,因为:首先,如果我将它设为一个类,应用程序其他部分的某些行为可能会变得奇怪,其次我必须这样做将其他数十个模型转为类以确保一致性。

【问题讨论】:

【参考方案1】:

您在这里看到的是值类型(结构)和引用类型(类)之间的区别。您应该阅读 Apple 网站上关于差异的博文:https://developer.apple.com/swift/blog/?id=10

基本上,一旦您将结构传递到块中,它就会被复制而不是被引用,因此您正在处理一个全新的副本。通过课程,您可以获得对原始副本的参考。

【讨论】:

我尝试在成功块外部和内部的 editEducation() 中打印 self 的内存,结果它们是相同的。这是否意味着进入块时不会复制该值? 它们在写入时复制。所有引用类型将是同一个实例,即使在它们被修改之前被复制。我猜你在修改它之前检查了地址之前

以上是关于在块中修改后未更新 Swift 结构的主要内容,如果未能解决你的问题,请参考以下文章

如何使用从 Swift 3 中的滑块中选择的 JSON 数据更新 tableviewcell?

更新数据源后未重新加载 Rx 表视图

Oracle在块内是如何组织和管理数据的

在块中调用 autorelease

在块中复制和自动释放本地变量

ALAssetLibraryGroup 在块中找到相机胶卷