Swift:在结束时完成任务

Swift:在结束时完成任务,swift,firebase,closures,Swift,Firebase,Closures,试图将更改的值保留在闭包之外。在observeSingleEvent()调用中从Firebase数据库中的子级分配length。但是,在函数之后,length的赋值不会保留在for循环中使用,而是使用初始值 此外,我将append() 如何在闭包中完成作业。我知道C++中可以使用和,如 [VARNAME] 通过引用。我们还没有发现与斯威夫特类似的东西 func loadMarkersFromDatabase(ref:DatabaseReference, node:String) -> [G

试图将更改的值保留在闭包之外。在
observeSingleEvent()
调用中从Firebase数据库中的子级分配
length
。但是,在函数之后,
length
的赋值不会保留在for循环中使用,而是使用初始值

此外,我将
append()

如何在闭包中完成作业。我知道C++中可以使用<代码>和<代码>,如<代码> [VARNAME] 通过引用。我们还没有发现与斯威夫特类似的东西

func loadMarkersFromDatabase(ref:DatabaseReference, node:String) -> [GMSMarker] {
        var markers = [GMSMarker]()
        var length:Int? = 1
        ref.child("Config").observeSingleEvent(of: .value, with: { (snapshot) in
                let value = snapshot.value as? NSDictionary
                length = (value?["AcademicBuildingsLength"] as? Int ?? 0)
            })
        print(length!)
        for i in 0...length! {
            ref.child(node).child(String(i)).observeSingleEvent(of: .value, with: { (snapshot) in
                let value = snapshot.value as? NSDictionary
                let building = value?["building"] as? String ?? ""
                let lat = value?["lat"] as? Double ?? 0.0
                let lon = value?["long"] as? Double ?? 0.0
                let marker = GMSMarker()
                marker.position = CLLocationCoordinate2D(latitude: lat, longitude: lon)
                marker.title = building
                marker.snippet = node
                markers.append(marker)
            })

        }
        return markers

    }
我曾尝试像这样添加一个闭包块
[length]
,但随后出现以下编译错误:
无法赋值:'length'是一个不可变的捕获

ref.child("Config").observeSingleEvent(of: .value, with: { [length](snapshot) in
                let value = snapshot.value as? NSDictionary
                length = (value?["AcademicBuildingsLength"] as? Int ?? 0)
            })

闭包在另一个后台线程上异步执行。因此,不能在该块之外变异变量,可能必须使用完成闭包。要实现您想要的功能,您可以在闭包中调用另一个函数:

func loadMarkersFromDatabase(ref:DatabaseReference, node:String, completion: @escaping ([GMSMarker]) -> Void) {
    ref.child("Config").observeSingleEvent(of: .value, with: { [length](snapshot) in
        let value = snapshot.value as? NSDictionary
        let markers = myFunction((value?["AcademicBuildingsLength"] as? Int ?? 0))
        completion(markers)
    }
}
然后:

func myFunction(length: Int) -> [GMSMarker] {
    var markers: [GMSMarker] = []
    for i in 0...length! {
            ref.child(node).child(String(i)).observeSingleEvent(of: .value, with: { (snapshot) in
                let value = snapshot.value as? NSDictionary
                let building = value?["building"] as? String ?? ""
                let lat = value?["lat"] as? Double ?? 0.0
                let lon = value?["long"] as? Double ?? 0.0
                let marker = GMSMarker()
                marker.position = CLLocationCoordinate2D(latitude: lat, longitude: lon)
                marker.title = building
                marker.snippet = node
                markers.append(marker)
            })
        }
    return markers
}
但是,在函数之后,长度的赋值不会保留以供使用 在for循环中,使用初始值

保留对
标记的修改。问题是你对事物的执行顺序做出了错误的假设。假设执行闭包后,
loadMarkersFromDatabase
函数返回“after”,但事实并非如此。
observeSingleEvent
方法不会同步执行您给它的闭包,但会保留它以供以后执行。(您需要向它传递一个闭包的事实就是一个很好的提示;因为它是同步的,所以它可以直接返回快照,而不是将其传递到您的闭包中。)


如果将日志语句放在这两个位置,可以看到它们的实际执行顺序。当闭包运行时,它会将元素添加到
标记
,共享对
标记
访问权限的任何其他代码都会看到该更改。但是您没有使用它,因为您的
loadMarkersFromDatabase
函数已经返回。

调用loadMarkersFromDatabase(ref:node:completion)时,我需要完成什么?它调用一个函数,该函数接受一个gmsmarker列表,但不返回任何内容。没错,您需要传入一个函数,该函数接受一个gmsmarker数组,但不返回任何内容。