Swift: сохранить задание в закрытии - PullRequest
0 голосов
/ 16 февраля 2020

Попытка сохранить измененное значение за пределами замыкания. Назначение length от дочернего элемента в базе данных Firebase в вызове observeSingleEvent(). Однако после функции присвоение length не сохраняется для использования в for l oop, используется начальное значение.

Кроме того, I append() связка GMSMarker объектов к списку markers, но снова добавления не сохраняются, и список возвращается пустым

Как я могу сохранить выполненные назначения в замыканиях. Я знаю, что в C ++ вы можете использовать & как [&varName] для передачи по ссылке. Не удалось найти что-то похожее в отношении Swift.

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], как это, но затем получил ошибку компиляции: Cannot assign to value: 'length' is an immutable capture

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

Ответы [ 2 ]

0 голосов
/ 17 февраля 2020

Однако после функции присвоение длины не сохраняется для использования в for l oop, используется начальное значение.

Изменения в markers сохраняются , Проблема в том, что вы делаете неправильные предположения о порядке выполнения вещей. Вы предполагаете, что функция loadMarkersFromDatabase возвращает «после» закрытия, но это не так. Метод observeSingleEvent не выполняет замыкание, которое вы даете ему синхронно, но сохраняет его для выполнения позже. (Тот факт, что вам нужно передать закрытие, является большим намеком на это; поскольку он был синхронным, он мог просто возвращать снимок напрямую, а не передавать его в ваше закрытие.)

Если вы положили в журнале операторов в двух местах, вы можете увидеть фактический порядок, в котором они выполняются. Когда выполняется замыкание, оно добавляет элементы к markers, и любой другой код, который имеет доступ к markers, увидит это изменение. Но вы этим не пользуетесь, потому что ваша функция loadMarkersFromDatabase уже вернулась.

0 голосов
/ 16 февраля 2020

Замыкания выполняются асинхронно в другом фоновом потоке. Из-за этого вы не можете изменять переменные вне этого блока и, возможно, придется использовать замыкания завершения. Для достижения sh того, что вы хотите, вы можете вызвать другую функцию в вашем закрытии:

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...