ios - 如何正确地将子类传递给 Swift 'inout' 方法进行更新?

标签 ios swift parse-platform

我想为我的项目创建一个通用的“refreshInBackground”方法,允许更新我的各种 PFObject 子类。我不能只使用 PFObject.refreshInBackground 因为我想“包含”几个“键”(指向其他对象的指针)

问题是,当我将我的子类作为“inout”参数传递时,我被告知

Cannot pass immutable value as inout argument: implicit conversion from 'ParseUser' to 'PFObject' requires a temporary

1) 为什么 'currentUser' 是不可变的?那是因为它正在尝试进行隐式转换吗?

我的子类很简单

class ParseUser : PFUser {
    @NSManaged var teams : [ParseTeam]           // Teams that the user is a member of

    ..more stuff..
}

更新它的调用

var currentUser : ParseUser?
if currentUser != nil {
    // utilize the local user cache... but refresh the user
    // to get the teams
    self.refreshInBackground(parseObject: &currentUser!, withKeys: ["teams"], withCompletion: nil)
}

最后,通用更新函数:

// 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"]))
    }
}

我尝试通过设置一个临时变量、转换它并传入它来解决它,但这当然不会更新 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)

最后,这可以通过返回更新的对象然后在完成处理程序中设置它来解决......但我想了解如何在 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???

就错误消息而言,Swift 的错误消息还不是很好。您经常会收到误导性消息,您可能遇到了其中一种情况。

另一件不能工作的事情是 inout 参数不应该包含在转义闭包中。您对变量的 inout 引用仅在接受它的函数结束之前有效,我的理解是 getFirstObjectInBackground 很容易比 refreshInBackground 长寿(并且违反了引用的生命周期)。 SE-0035解释了为什么它现在不能工作,以及它将如何与 Swift 3 一起工作。

总而言之,inout 参数创建变量的“影子副本”,并在函数调用结束时将该可能修改的副本分配回原始副本,因此您想要进行的任何修改变量必须在函数调用结束之前发生(这与后台任务不兼容,后台任务意味着在未来的不确定点结束)。在转义闭包中使用 inout 参数将是 Swift 3 中的编译时错误。它目前可以编译,但不起作用。

关于ios - 如何正确地将子类传递给 Swift 'inout' 方法进行更新?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37867941/

相关文章:

ios - parse.com objective-c 获取PfUser对象及相关对象

ios - 如何调用我们的应用程序并获取来电的详细信息?

ios - UIScrollView:setContentOffset:animated 和 scrollRectToVisible:animated 之间的区别

ios - 在 iPad 上禁用手写笔滚动

ios - Swift:出现错误 "A stable connection to the server could not be established."

Swift 组合嵌套发布者

javascript - 使用 Parse.com javascript 并保持 401 未经授权

swift - 解析视频上传 - fatal error : unexpectedly found nil while unwrapping an Optional Value

ios - 代码签名 "libswiftAVFoundation.dylib"失败

ios - MFMailComposeViewController 邮件收件人限制