mick1996
mick1996

Reputation: 606

Out of range, threading issue

I have a problem with threading. I am trying to populate data from firebase into an array (Working successfully) and then use the data retrieved to setup markers on a map.

The problem is that I am unable to retrieve the data before the Extension function requires it.

I believe this to be a threading issue but am unsure as how to fix it, Please help.

override func viewDidLoad() {
        super.viewDidLoad()

        loadDataFromFirebase()

        secondfunction()
    }

First function, which is working:

func loadDataFromFirebase() {

        let db = Firestore.firestore()
        db.collection("test").getDocuments { (snapshot, err) in

            if let err = err {
                print("Error getting documents: \(err)")
                return
            } else {
                for document in snapshot!.documents {
                    let name = document.get("Name") as! String
                    self.names.append(name)
                }
                }
            }
        }
    }

second function:

func secondfunction() {
        let mapView = MGLMapView(frame: view.bounds)
        mapView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

        mapView.centerCoordinate = CLLocationCoordinate2D(latitude: x, longitude: y)
        mapView.zoomLevel = 14
        mapView.delegate = self
        view.addSubview(mapView)

        // Specify coordinates for our annotations.
        locationsList = [
            CLLocationCoordinate2D(latitude: x, longitude: y),
            CLLocationCoordinate2D(latitude: x, longitude: y),
            CLLocationCoordinate2D(latitude: x, longitude: y),
        ]

        var pointAnnotations = [MGLPointAnnotation]()
        for coordinate in locationsList {
            let point = MGLPointAnnotation()
            point.coordinate = coordinate
            pointAnnotations.append(point)
        }

        mapView.addAnnotations(pointAnnotations)
    }

Extension Function:

extension ViewController: MGLMapViewDelegate {
    // MGLMapViewDelegate method for adding static images to point annotations
    func mapView(_ mapView: MGLMapView, imageFor annotation: MGLAnnotation) -> MGLAnnotationImage? {
        let annotationImage: MGLAnnotationImage
        let annotationImageCocktail = mapView.dequeueReusableAnnotationImage(withIdentifier: names[counter])

        annotationImage = annotationImageCocktail ?? MGLAnnotationImage(image: UIImage(named: names[counter])!, reuseIdentifier: names[counter])

        counter += 1
        return annotationImage
    }
}

Then I get the error:

Fatal error: Index out of range

Upvotes: 1

Views: 50

Answers (1)

vadian
vadian

Reputation: 285059

It's a timing issue, all databases work asynchronously.

Simplest solution

override func viewDidLoad() {
    super.viewDidLoad()
    loadDataFromFirebase()
}

func loadDataFromFirebase() {

    let db = Firestore.firestore()
    db.collection("test").getDocuments { (snapshot, err) in

        if let err = err {
            print("Error getting documents: \(err)")
            return
        } else {
            for document in snapshot!.documents {
                let name = document.get("Name") as! String
                self.names.append(name)
            }
            self.secondfunction()
        }
    }
}

For safety reasons you should check if counter < names.count in imageFor annotation

Upvotes: 2

Related Questions