Ios 完成处理程序-Parse+;敏捷的

Ios 完成处理程序-Parse+;敏捷的,ios,swift,parse-platform,Ios,Swift,Parse Platform,我正在尝试生成一个名为“areaList”的PFObjects数组。我已经对此进行了相当多的研究,并了解到使用完成处理程序来处理加载结果的异步性质会使我受益匪浅。具体来说,我的要求是获得一些关于我做错了什么的指导,以及如何“更好”实现结果的潜在提示 以下是我的带有完成处理程序的查询函数: func loadAreasNew(completion: (result: Bool) -> ()) -> [Area] { var areaList = self.are

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

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

    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")
    }
}
var areaList = [Area]()
我在viewDidLoad之前分配了此变量:

loadAreasNew { (result) -> () in
    if (result == true) {
        print(self.areaList)
    } else {
        print("Didn't Work")
    }
}
var areaList = [Area]()
在控制台中,我得到以下信息:

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

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

最好的做法是(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)
            }
        }
    }

然而!如果您确实觉得需要使用一些完成处理程序,请查看有关如何使用它们的更多信息。但请记住,所有工具都有时间和地点……

这里有一些问题

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

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

然后,当您调用函数时,它可能更像这样:

loadAreasNew { result in
    if (result == true) {
        print(self.areaList)
    } else {
        print("Didn't Work")
    }
}
我关注的是:

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

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

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

把“回报”也放在你的完成中

3) Parse已经有一个距离检查方法,您不必手动执行。aPARSEQUERRY.where(键:,近地点:,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)
    }
}

我喜欢这一思路,我将在上午讨论这一问题。我理解您关于不需要命名参数的第一条评论,所以我可以修复它。我无法修复您关于将areaList放入完成处理程序的第二部分。我明天早上再来,除非你有一个例子。我的最终目标是从函数中获取PFObjects(Areas)的列表,以便我可以将它们用作指针和/或填充tableview等。当然,您可以将areaList作为completionHandler的参数。然后,您在
result in…
中使用的结果将成为您的区域列表。例如,我假设areaList是一个[String]
func示例(completionHandler:([String])->(){}
看一下下面MacLean的答案。感谢您提醒我们传递局部变量,然后让它返回。我希望声明它,填充它,然后返回充满PFObjects的文件。也许我错了。我将尝试重写“返回”部分。至于地理点,这并不完全是我目前需要的,但我真的很感激你跳出谚语的框框思考……我觉得这有点道理,但经过一些语法调整后,出于某种原因,我没有真正为我工作。我用一个简单的“打印”替换了“代码化”部分来测试它,但这根本不起作用。再说一次,我明天早上再来。谢谢你的反馈!最终,我在做了几件事之后选择了这个答案。首先,我使用了ParseUI,它有自己的子类来处理PFObjects的返回数组,并将其呈现到表视图中。至于你的逻辑,你已经死定了——PFQuery有它自己的完成处理程序,而且,我最终像你建议的那样在函数中做了“Codeined”的事情。谢谢