简体   繁体   English

完成处理程序-解析+ Swift

[英]Completion Handler - Parse + Swift

I'm trying to generate an array of PFObjects called 'areaList'. 我正在尝试生成一个名为“ areaList”的PFObjects数组。 I've been researching this quite a bit and understand that I could benefit from using a completion handler to handle the asynchronous nature of the loaded results. 我已经对此进行了相当多的研究,并且了解到我可以从使用完成处理程序来处理加载结果的异步特性中受益。 My ask, specifically, is to get some guidance on what I'm doing wrong as well as potential tips on how to achieve the result "better". 我的要求是,特别是要获得关于我做错了什么的指导以及如何获得“更好”结果的潜在技巧。

Here is my query function with completion handler: 这是我的带有完成处理程序的查询功能:

    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
    }

Here is how I'm attempting to call it in viewDidLoad: 这是我尝试在viewDidLoad中调用它的方式:

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

I assigned this variable before viewDidLoad: 我在viewDidLoad之前分配了此变量:

var areaList = [Area]()

In the console, I get the following: 在控制台中,我得到以下信息:

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

Representing the 5 items that I know are there in Parse... 代表我知道的Parse中存在的5个项目...

This is an interesting question. 这是个有趣的问题。 First off, PFQuery basically has a built in completion handler, which is quiet nice! 首先,PFQuery基本上有一个内置的完成处理程序,这真是太好了! As you probably know, all of the code within the areaQuery.findObjectsInBackgroundWithBlock {...} triggers AFTER the server response. 您可能知道, areaQuery.findObjectsInBackgroundWithBlock {...}所有代码都会在服务器响应触发。 A completion most often serves the purpose of creating a block, with the ability of asynchronously returning data and errors. 完成通常以创建块为目的,并具有异步返回数据和错误的能力。

Best practice would (IMO) to just call the code that you want to use with the results from your PFQuery right after your area appending loop (which I'm gonna take out because I'm picky like that), like so: 最佳实践(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)
            }
        }
    }

HOWEVER! 然而! If you really feel the need to use some completion handlers, check out this other answer for more info on how to use them. 如果您确实需要使用一些完成处理程序,请查看其他答案以获取有关如何使用它们的更多信息。 But keep in mind all tools have a time and a place... 但是请记住,所有工具都有时间和地点。

There are a few issues here. 这里有一些问题。

Your completion handler doesn't require you to define the name for your completion handler's parameters, so you could easily use completion: (Bool) -> () 您的完成处理程序不需要您为完成处理程序的参数定义名称,因此您可以轻松地使用completion: (Bool) -> ()

Further in your function, you're returning areaList . 在函数的更areaList ,您将返回areaList This should be put through the completion handler like this onComplete(areaList) and change your completion handler parameter to expect your area list. 这应该通过像onComplete(areaList)这样的完成处理程序onComplete(areaList)并更改您的完成处理程序参数以期望您的区域列表。

Then, when you call your function, it could look more like this : 然后,当您调用函数时,它看起来可能像这样:

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

Here is my concern: 这是我的担心:

1) Don't pass in a local variable and make the function return it, it's meaningless and danger. 1)不要传入局部变量并使函数返回它,这是毫无意义和危险的。

You may want to initiate an empty array and make your fetch, then "return" it. 您可能要启动一个空数组并进行获取,然后“返回”它。

2) The fetch request is processed in background, you will have no idea when it will have finished. 2)提取请求是在后台处理的,您不知道何时完成。 If you return the array immediately it will always be an empty array. 如果立即返回数组,它将始终是一个空数组。

Put the "return" in your completion too. 在您的完成中也添加“返回”。

3) Parse already has a distance checking method, you don't have to do it manually. 3)解析已经有一种距离检查方法,您不必手动进行。 aPARSEQUERRY.where(key:,nearGeoPoint:,inKilometers:) aPARSEQUERRY.where(重点:,nearGeoPoint:,inKilometers :)

I will rewrite the function as: 我将函数重写为:

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)
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM