在块中修改后未更新 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 结构的主要内容,如果未能解决你的问题,请参考以下文章