【问题标题】:Asynchronous Swift call into array异步 Swift 调用数组
【发布时间】:2020-08-11 16:08:47
【问题描述】:

目前我正在尝试将值从 firebase 推送到音符对象数组中 唯一的问题是由于 Firebase 的异步特性,我无法让主线程等待 fetch 函数完成。我已经在这个站点上查看了很多答案,并且我已经阅读了 Semaphores and Dispatch queue 文档,但是我无法让这个获取工作。看来这里的大多数人都在尝试使用我不是的表格视图。

这里是获取代码

func fetchUser(){


FIRDatabase.database().reference().child("notes").observe(.childAdded, with: { (snapshot) in
        if let dictionary = snapshot.value as? [String: AnyObject] {
            let user = noteClass(dictionary: dictionary)
            self.coordinotes.append(user)
        }
    }, withCancel: nil)
} 

我已经删除了我所有的信号量和调度主要尝试,因为它们都没有工作。在我看来这个函数被调用确实加载了。当我检查我的数组的值时,我将它们推入“坐标”,该值尚未放入,我得到一个超出范围的错误。

其余代码

import UIKit
import MapKit
import CoreLocation
import Firebase
import FirebaseDatabase

struct PreferencesKeys{
    static let savedItems = "savedItems"
}




class ViewController: UIViewController, CLLocationManagerDelegate{

    let manager = CLLocationManager()
    var coordinotes:[noteClass] = Array()
    var latitude = Double()
    var noteTime = noteBrain()

    //Map
    @IBOutlet weak var map: MKMapView!


    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
    {
        let location = locations[0]
        let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
        let region:MKCoordinateRegion = MKCoordinateRegionMake(myLocation, noteTime.span)
        map.setRegion(region, animated: true)
        self.map.showsUserLocation = true
    }


    override func viewDidLoad()
    {
        super.viewDidLoad()
        navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(handleLogout))

        if FIRAuth.auth()?.currentUser?.uid == nil {
            perform(#selector(handleLogout), with: nil, afterDelay: 0)
        }
        manager.delegate = self
        manager.desiredAccuracy = kCLLocationAccuracyBest
        manager.requestWhenInUseAuthorization()
        manager.startUpdatingLocation()
        fetchUser()
        loadAllCoordinotes()
    }

    func handleLogout() {

        do {
            try FIRAuth.auth()?.signOut()
        } catch let logoutError {
            print(logoutError)
        }

        let loginController = LoginController()
        present(loginController, animated: true, completion: nil)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }


func loadAllCoordinotes() {
    let length = coordinotes.count - 1
    map.addAnnotation(coordinotes[length])
}

【问题讨论】:

  • 不确定我是否理解您的问题,但您是否尝试过完成处理程序?
  • 是的,但是我尝试的实现总是处理到数据库的链接,并且没有将创建的数据放入数组中。您有任何我可以查看的其他文档吗?
  • 让 UI 等待长时间的操作结束并不是最好的方法。当操作结束时,您应该调用一个委托方法来通知您。
  • @JoséFonte 一旦线程完成,这个委托会返回 true 吗?那么剩下的代码可以继续吗?
  • 你在哪里声明coordinotes

标签: arrays swift asynchronous firebase firebase-realtime-database


【解决方案1】:
func fetchUser(_ completion:@escaping ([noteClass] , _ success: Bool)-> Void){
    let coordinotes = [noteClass]() 

FIRDatabase.database().reference().child("notes").observe(.childAdded, with: { (snapshot) in
        if let dictionary = snapshot.value as? [String: AnyObject] {
            let user = noteClass(dictionary: dictionary)
            coordinotes.append(user)
        }
        completion(coordinotes, true)
    }, withCancel: nil)

}

然后你像这样在viewDidLoad 中调用它:

  fetchUser { (coordinotes, success) in
            if success {
                self.coordinotes = coordinote
                self.loadAllCoordinotes()
            }
        }

【讨论】:

  • 感谢您发布此信息。第一行是给我一个“预期的声明”并告诉我“连续的声明必须用';'分隔”我会尝试使用它。
  • 立即尝试。有一个错字,签名末尾有一个额外的)
  • 代码已编译,但 loadAllCoordinotes 中“found”的值仍未打印,这意味着它仍然是空的,并且地图未显示图钉。它也应该是第 6 行的 self.coordinotes.append(user)。
  • 通过在“如果成功”期间使用打印语句,我发现如果永远不会执行。我会继续看的。
  • 在完成处理程序中返回第 2 行中声明的数组。然后在 viewDidLoad 中将所有值分配给 self。您是否尝试添加断点以查看是否要附加任何内容?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-02
  • 1970-01-01
  • 2018-10-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多