【问题标题】:How to fix the asynchronous nature of my appending function?如何修复我的附加函数的异步性质?
【发布时间】:2016-12-16 17:23:29
【问题描述】:

我设置了一个查询来从数据库(由 heroku 托管的解析服务器)中提取数据并将其附加到数组中;在此查询中是另一个查询,用于从不同的类中提取信息,但也用于附加另一个数组。我认为因为我使用.findObjectsinBackground 它是异步发生的,这导致了一个问题。这是代码(概括):

    func getQueries(completion: (() -> Void)?){

        let searchQuery = PFQuery(className: "Etc")         
        searchQuery.findObjectsInBackground(block: { (objects, error) in

            if let objectss = objects{

                for object in objectss {
                    //append some arrays
                    let otherQuery = PFQuery(className: "OtherClass")
                    otherQuery.whereKey("user", equalTo: object["User"] as String)
                    otherQuery.findObjectsInBackground(block: {(objects, error) in
                        if let objectss = objects{
                            for object in objectss{
                                array.append(object["ProfPic"] as PFFile)
                                print("\(array) and its count is \(array.count)") //this returns a non 0 value
                            }
                        }
                        completion!()
                    })

            print("\(array) and its count is \(array.count)") //this returns 0
                }
            }
         })
    }

array 的计数在附加到其自己的闭包中后返回为非 0,但在其闭包之外返回为 0。这是一个问题,因为数组用于迭代显示信息。无论如何要确保在完成searchQuery 的整体关闭之前,otherQuery 的附加已经完成? (此外,它是异步发生导致问题的事实是一个猜测......我可能是错的)

【问题讨论】:

    标签: swift multithreading grand-central-dispatch parse-server


    【解决方案1】:

    在后一种情况下,您在获取数据之前打印计数,例如在findObjectsInBackground 的完成块之外。

    您可以使用完成块将整个内容包装在自己的方法中:

    func fetchData(_ completion: () -> Void) {
    
        searchQuery.findObjectsInBackground(block: { (objects, error) in
            guard let objectss = objects else {
                completion() 
            }
    
            for object in objectss {
                let otherQuery = PFQuery(className: "OtherClass")
                otherQuery.whereKey("user", equalTo: object["User"] as String)
                otherQuery.findObjectsInBackground(block: {(objects, error) in
    
                    guard let objectss = objects else {
                        completion()
                    }
    
                    for object in objectss{
                        array.append(object["ProfPic"] as PFFile)
                    }
    
                    print("In loop: \(array) and its count is \(array.count)")                
                    completion()
                })
            }
        })
    }
    

    比这一切更重要的是:

    fetchData() {
         print("After completing: \(array) and its count is \(array.count)")
        // do stuff with your fetched data and display it
        // "use in iterating through to display information" here
    }
    

    更新:

    在您更新的问题中,您仅在成功情况下调用completion!()。无论如何,您都必须调用它:

    ...
    if let objectss = objects 
        ...
        completion!()
    } else {
        completion!()
    } 
    ...
    

    【讨论】:

    • shallowThought,我试着按照你的建议去做(看看编辑过的问题代码块......我把 completion!() 放在那里......它总是被包装在一个函数中,我只是没有'没有显示那个位)。但是,第二个打印语句仍然返回 0。有什么想法吗?
    • 如所写,您在获取数据之前打印计数。将您的 print() 语句放在您的完成块中(或在您的 completion!() 调用之前)。就像我编辑的答案一样。
    猜你喜欢
    • 2011-07-30
    • 2019-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-20
    相关资源
    最近更新 更多