Mob*_*Vet 3 ios parse-platform swift
我想为我的项目创建一个通用的'refreshInBackground'方法,允许更新我的各种PFObject子类.我不能只使用PFObject.refreshInBackground因为我想'包含'几个'键'(指向其他对象的指针)
问题在于,当我将子类作为'inout'参数传递时,我被告知
无法将不可变值作为inout参数传递:从'ParseUser'到'PFObject'的隐式转换需要临时的
1)为什么'currentUser'不可变?那是因为它试图进行隐式转换吗?
我的子类很简单
class ParseUser : PFUser {
@NSManaged var teams : [ParseTeam] // Teams that the user is a member of
..more stuff..
}
Run Code Online (Sandbox Code Playgroud)
要求更新它
var currentUser : ParseUser?
if currentUser != nil {
// utilize the local user cache... but refresh the user
// to get the teams
self.refreshInBackground(parseObject: ¤tUser!, withKeys: ["teams"], withCompletion: nil)
}
Run Code Online (Sandbox Code Playgroud)
最后,通用更新功能:
// fetch and refresh an object in the background, including various pointers to included keys
// this is necessary because the native Parse fetchInBackground does not allow 'includeKeys'
func refreshInBackground(inout parseObject object : PFObject, withKeys includeKeys : [String]?, withCompletion completion : ((error : NSError) -> Void)?) {
// make sure our object has been stored on the server before refershing
// if it has an objectId, it has been stored
if let objectId = object.objectId {
let query = PFQuery(className:object.parseClassName)
query.whereKey("objectId", equalTo: objectId)
if let keys = includeKeys {
query.includeKeys(keys)
}
query.getFirstObjectInBackgroundWithBlock({ (updatedObject, error) in
if error == nil, let update = updatedObject {
object = update
}
completion?(error: error)
})
}
else {
// oops the object hasn't been saved yet, so don't refresh it
completion?(error: NSError(domain: "xxxxx", code: 911, userInfo: ["message":"Object Not saved"]))
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试通过设置一个临时变量,投射它并传入它来解决它,但当然不会更新currentUser指针...只是临时变量
// Clearly doesn't work as the assignment is made to a placeholder
var user = currentUser! as PFObject
self.refreshInBackground(parseObject: &user, withKeys: ["teams"], withCompletion: nil)
Run Code Online (Sandbox Code Playgroud)
最后,这可以通过返回更新的对象然后在完成处理程序中设置它来解决...但我想了解如何在Swift中执行此操作,这样我每次都不必这样做.理想情况下,"刷新"调用是自包含的.
谢谢
您无法将派生类型作为inout基类型的参数传递的原因是,这将允许调用者破坏类型安全性.考虑这个例子(不起作用):
class Base {}
class Derived1: Base {}
class Derived2: Base {}
func updateFoo(inout foo: Base) {
foo = Derived2()
}
var derived1: Derived1 = Derived1()
updateFoo(&derived1)
// derived1 is of type Derived2???
Run Code Online (Sandbox Code Playgroud)
至于错误消息,Swift的错误消息还不是很好.你经常会得到误导性的信息,你可能会遇到其中一种情况.
另一件不起作用的是inout参数不应该包含在转义闭包中.你inout对变量的引用只有在接受它的函数结束时才有效,而我的理解是它getFirstObjectInBackground会很容易refreshInBackground生存(并且违反了引用的生命周期).SE-0035解释了为什么它现在不起作用以及它如何与Swift 3一起工作.
综上所述,inout参数创建变量的"卷影副本",并且可能已修改的副本指派回原来在函数调用结束时,让你想给变量的任何修改必须在函数结束之前发生调用(与后台任务不兼容,意味着将来无限期结束).Swift 3中的编译时错误是inout在转义闭包中使用参数.它目前正在编译,但它不起作用.
| 归档时间: |
|
| 查看次数: |
913 次 |
| 最近记录: |