Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/94.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 在异步工作完成之前返回数据的闭包 更新了建议的解决方案和附加问题_Ios_Swift_Firebase Realtime Database_Firebase Storage_Grand Central Dispatch - Fatal编程技术网

Ios 在异步工作完成之前返回数据的闭包 更新了建议的解决方案和附加问题

Ios 在异步工作完成之前返回数据的闭包 更新了建议的解决方案和附加问题,ios,swift,firebase-realtime-database,firebase-storage,grand-central-dispatch,Ios,Swift,Firebase Realtime Database,Firebase Storage,Grand Central Dispatch,我正式被困在地狱里了。我打电话到Firebase检索FireStore中的所有物品。在每个项目对象中都有一个图像文件名,该文件名转换为存储引用位置,需要将该位置传递给函数才能返回绝对URL。我会将URL存储在数据中,但它可能会更改。问题是ArticleListener函数在没有所有数据的情况下过早返回闭包(returnArray),我无法找出我缺少了什么。在我添加self.getURL代码之前,它工作得很好,但是现在它返回空数组,然后完成所有工作 如果有人在这里有一些额外的技巧,可以将这些方法链

我正式被困在地狱里了。我打电话到Firebase检索FireStore中的所有物品。在每个项目对象中都有一个图像文件名,该文件名转换为存储引用位置,需要将该位置传递给函数才能返回绝对URL。我会将URL存储在数据中,但它可能会更改。问题是ArticleListener函数在没有所有数据的情况下过早返回闭包(returnArray),我无法找出我缺少了什么。在我添加self.getURL代码之前,它工作得很好,但是现在它返回空数组,然后完成所有工作

如果有人在这里有一些额外的技巧,可以将这些方法链接在一起,而不必求助于PromiseKit或GCD,那将是非常棒的,但是可以接受所有建议,让它们按原样工作 和/或重构以提高效率/可读性

具有GCD和更新示例的建议解决方案

这是在创建文章后调用Author init。我正在尝试转换dataDict字典,以便在键[“Author”]的Author init期间使用它。我想我很接近了,但我不能100%确定我的GCD进入/离开电话是否按正确的顺序进行

public func SetupArticleListener(completion: @escaping ([Article]) -> Void) {
        var returnArray = [Article]()
        let db = FIRdb.articles.reference()

        let listener = db.addSnapshotListener() { (querySnapshot, error) in
            returnArray = [] // nil this out every time
            if let error = error {
                print("Error in setting up snapshot listener - \(error)")
                } else {

                let fireStoreDispatchGrp = DispatchGroup() /// 1

                querySnapshot?.documents.forEach {
                    var dataDict = $0.data() //mutable copy of the dictionary data
                    let id = $0.documentID

//NEW EXAMPLE WITH ADDITIONAL TASK HERE
                    if let author = $0.data()["author"] as? DocumentReference {
                        author.getDocument() {(authorSnapshot, error) in
                            fireStoreDispatchGrp.enter() //1
                            if let error = error {
                                print("Error getting Author from snapshot inside Article getDocumentFunction - leaving dispatch group and returning early")
                                fireStoreDispatchGrp.leave()
                                return
                            }

                            if let newAuthor = authorSnapshot.flatMap(Author.init) {
                                print("Able to build new author \(newAuthor)")
                                dataDict["author"] = newAuthor
                                dataDict["authorId"] = authorSnapshot?.documentID
                                print("Data Dict successfully mutated \(dataDict)")
                            }
                            fireStoreDispatchGrp.leave() //2
                        }

                    }

///END OF NEW EXAMPLE

                    if let imageURL = $0.data()["image"] as? String {
                        let reference = FIRStorage.articles.referenceForFile(filename: imageURL)

                        fireStoreDispatchGrp.enter() /// 2

                        self.getURL(reference: reference){ result in
                            switch result {
                            case .success(let url) :
                                dataDict["image"] = url.absoluteString

                            case .failure(let error):
                                print("Error getting URL for author: \n Error: \(error) \n forReference: \(reference) \n forArticleID: \(id)")
                            }

                            if let newArticle = Article(id: id, dictionary: dataDict) {
                                returnArray.append(newArticle)
                            }

                            fireStoreDispatchGrp.leave() ///3
                        }
                    }
                }
                //Completion block
                print("Exiting dispatchGroup all data should be setup correctly")
                fireStoreDispatchGrp.notify(queue: .main) { ///4
                completion(returnArray)

                }
            }
        }
        updateListeners(for: listener)
    }
原始代码 呼叫设置代码

self.manager.SetupArticleListener()

打印(“您需要调度组,因为for循环包含多个异步调用

public func SetupArticleListener(完成:@escaping([Article])->Void){
var returnArray=[Article]()
设db=FIRdb.articles.reference()
让listener=db.addSnapshotListener(){(querySnapshot,错误)在
returnArray=[]//每次都将其置零
如果let error=error{
printLog(“添加snapshotlistener时检索文档时出错,错误:\(Error.localizedDescription)”)
}否则{
设g=DispatchGroup()///1
querySnapshot?.documents.forEach{
var dataDict=$0.data()//字典数据的可变副本
let id=$0.documentID
如果让imageURL=$0.data()[“image”]作为字符串{
让reference=FIRStorage.articles.referenceForFile(文件名:imageURL)
g、 输入()///2
getURL(reference:reference){结果为
切换结果{
成功案例(让url):
打印(“从引用\(url)获取url成功”)
dataDict[“image”]=url.absoluteString
打印(“字典变换”)
案例。失败(let错误):
打印(“从引用检索URL时出错\(错误)”)
}
如果let newArticle=Article(id:id,dictionary:dataDict){
printLog(“使用xformed url成功创建文章”)
returnArray.append(newArticle)
}
g、 离开()///3
}
}
}
g、 通知(队列:.main){///4

打印(“您需要调度组,因为for循环包含多个异步调用

public func SetupArticleListener(完成:@escaping([Article])->Void){
var returnArray=[Article]()
设db=FIRdb.articles.reference()
让listener=db.addSnapshotListener(){(querySnapshot,错误)在
returnArray=[]//每次都将其置零
如果let error=error{
printLog(“添加snapshotlistener时检索文档时出错,错误:\(Error.localizedDescription)”)
}否则{
设g=DispatchGroup()///1
querySnapshot?.documents.forEach{
var dataDict=$0.data()//字典数据的可变副本
let id=$0.documentID
如果让imageURL=$0.data()[“image”]作为字符串{
让reference=FIRStorage.articles.referenceForFile(文件名:imageURL)
g、 输入()///2
getURL(reference:reference){结果为
切换结果{
成功案例(让url):
打印(“从引用\(url)获取url成功”)
dataDict[“image”]=url.absoluteString
打印(“字典变换”)
案例。失败(let错误):
打印(“从引用检索URL时出错\(错误)”)
}
如果let newArticle=Article(id:id,dictionary:dataDict){
printLog(“使用xformed url成功创建文章”)
returnArray.append(newArticle)
}
g、 离开()///3
}
}
}
g、 通知(队列:.main){///4

print(“谢谢@shu Khan。这解决了我眼前的问题,非常感谢!如果我添加另一个异步函数,这里还有一个问题(假设我想从返回的DocumentReference->Snapshot块初始化相应的Author对象,我是否要用另一个enter/leave调用来增加Dispatch Group?我假设是,并想确认我应该在执行异步调用之前调用enter,并在所有工作完成后立即离开。谢谢@Sh_Khan。这解决了my即时问题,非常感谢!这里还有一个问题,如果我添加另一个异步函数(假设我想从返回的DocumentReference->Snapshot块初始化相应的Author对象,我是否用另一个enter/l递增分派组