【问题标题】:Completion Handler - Parse + Swift完成处理程序 - Parse + Swift
【发布时间】:2015-11-14 03:32:26
【问题描述】:

我正在尝试生成一个名为“areaList”的 PFObject 数组。我已经对此进行了大量研究,并且了解到我可以从使用完成处理程序来处理加载结果的异步性质中受益。具体来说,我的要求是获得一些关于我做错了什么的指导,以及关于如何“更好”地实现结果的潜在提示。

这是我的带有完成处理程序的查询函数:

    func loadAreasNew(completion: (result: Bool) -> ()) -> [Area] {
        var areaList = self.areaList
        let areaQuery = PFQuery(className: "Area")
        areaQuery.findObjectsInBackgroundWithBlock {
            (areas: [PFObject]?, error: NSError?) -> Void in
            if error == nil {
                for area in areas! {
                    let areaToAdd = area as! Area
                    areaList.append(areaToAdd)
//                    print(areaList)  // this prints the list each time
//                    print(areaToAdd)  // this prints the converted Area in the iteration
//                    print(area)  // this prints the PFObject in the iteration
                    if areaList.count == areas!.count {
                        completion(result: true)
                    } else {
                        completion(result: false)
                    }
                }
            } else {
                print("There was an error")
            }
        }
        return areaList
    }

这是我尝试在 viewDidLoad 中调用它的方式:

loadAreasNew { (result) -> () in
    if (result == true) {
        print(self.areaList)
    } else {
        print("Didn't Work")
    }
}

我在 viewDidLoad 之前分配了这个变量:

var areaList = [Area]()

在控制台中,我得到以下信息:

Didn't Work
Didn't Work
Didn't Work
Didn't Work
[]

代表我知道 Parse 中的 5 个项目...

【问题讨论】:

    标签: ios swift parse-platform


    【解决方案1】:

    这是一个有趣的问题。首先,PFQuery 基本上有一个内置的完成处理程序,非常安静!您可能知道,areaQuery.findObjectsInBackgroundWithBlock {...} 中的所有代码都会触发AFTER 服务器响应。完成通常用于创建块,具有异步返回数据和错误的能力。

    最佳做法是(IMO)在您的区域附加循环之后立即调用您想要与 PFQuery 的结果一起使用的代码(我将取出它,因为我很挑剔),就像这样:

         func loadAreasNew() {
            var areaList = self.areaList
            let areaQuery = PFQuery(className: "Area")
            areaQuery.findObjectsInBackgroundWithBlock {
                (areas: [PFObject]?, error: NSError?) -> Void in
                if error == nil {
                    let areasFormatted = areas! As [Areas]
                    areasList += areasFormatted
                    //Something like this
                    self.codeINeedAreasFor(areasList)
                    }
                } else {
                    print(error)
                }
            }
        }
    

    但是!如果您真的觉得需要使用一些完成处理程序,请查看this other answer 以获取有关如何使用它们的更多信息。但请记住,所有工具都有时间和地点......

    【讨论】:

    • 我觉得这有点腿,但经过一些语法调整后,出于某种原因,我并没有真正为我工作。我用一个简单的 'print' 替换了 'codeINeed' 部分来测试它,这甚至没有用。再说一次,我会在早上新鲜出炉。感谢您的反馈!
    • 最终,我在做了几件事后选择了这个答案。首先,我最终使用了 ParseUI,它有自己的子类来处理返回的 PFObject 数组并将其呈现到表视图中。至于你的逻辑,你已经死了 - PFQuery 有自己的完成处理程序,而且,我最终像你建议的那样在函数中执行了“CodeINeed”的东西。谢谢!
    【解决方案2】:

    这里有几个问题。

    您的完成处理程序不需要您为完成处理程序的参数定义名称,因此您可以轻松使用completion: (Bool) -> ()

    在您的函数中,您将返回 areaList。这应该通过像 onComplete(areaList) 这样的完成处理程序,并更改您的完成处理程序参数以期望您的区域列表。

    然后,当你调用你的函数时,它可能看起来更像这样:

    loadAreasNew { result in
        if (result == true) {
            print(self.areaList)
        } else {
            print("Didn't Work")
        }
    }
    

    【讨论】:

    • 我喜欢这种思路,我会在早上解决这个问题。我理解你关于不需要命名参数的第一条评论,所以可以解决这个问题。我无法修复关于将 areaList 放入完成处理程序的第二部分。除非你有一个样本 sn-p,否则我会在早上新鲜出炉。我的最终目标是从函数中获取 PFObject(区域)列表,以便我可以将它们用作指针和/或填充 tableViews 等...
    • 当然,您可以将 areaList 作为completionHandler 的参数包含在内。然后,您在result in ... 中使用的结果将成为您的 areaList。对于这个例子,我假设 areaList 是一个 [String]。 func example(completionHandler: ([String]) -> ()) {} 看看下面 MacLean 的回答。
    【解决方案3】:

    这是我的担忧:

    1) 不要传入一个局部变量,让函数返回它,这是没有意义和危险的。

    您可能想要启动一个空数组并进行提取,然后“返回”它。

    2) 获取请求在后台处理,您不知道它何时完成。如果您立即返回该数组,它将始终是一个空数组。

    在你的完成中也加入“return”。

    3) Parse 已经有距离检查方法,你不必手动进行。 aPARSEQUERRY.where(key:,nearGeoPoint:,inKilometers:)

    我将函数重写为:

    func loadNewAreas(completion:([Area],err?)->()){
        let areaQuery = PFQuery(className: "Area")
        areaQuery.where("location",nearGeoPoint:MYCURRENTLOCATION,inKilometers:50)
        areaQuery.findObjectInBackgroundWithBlock(){objects,err
            if objects.count == 0 
            {
                completion([],err)
            }
            let areas = Area.areasFromPFObjects(objects)
            completion(areas,err)
        }
    }
    

    【讨论】:

    • 感谢您对传递局部变量并使其返回的警告。我希望声明它,填充它,然后返回它充满 PFObjects。也许我来错了。我将尝试重写“返回”部分。至于 GeoPoints,不完全是我目前所需要的,但非常感谢您跳出众所周知的框框思考......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    • 2018-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多