1
votes

I converted to Swift 4. My tableview that pulls data from firebase and organizes it by distance from the users location has stopped working. The problem is my users location keeps on turning up nil. I've heard people having trouble with mapkit recently because of the conversion but unsure if this falls under the same category. So the line that says "let userLocation = CLLocation(latitude: latitude!, longitude: longitude!)" returns nil. Thanks.

BreakPoint

override func viewDidLoad() {
    super.viewDidLoad()

    searchController.searchResultsUpdater = self
    searchController.dimsBackgroundDuringPresentation = false
    definesPresentationContext = true
    tableView.tableHeaderView = searchController.searchBar

    locationManager.delegate = self
    locationManager.distanceFilter = kCLLocationAccuracyNearestTenMeters
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.startUpdatingLocation()
    locationManager.stopUpdatingLocation()
    locationManager.requestAlwaysAuthorization()

    getTableViewData()

    refresher = UIRefreshControl()
    refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
    refresher.addTarget(self, action: #selector(RegisteredLocations.handleRefresh(refreshControl:)), for: UIControlEvents.valueChanged)
    tableView.addSubview(refresher)
}

func getTableViewData() {
    Database.database().reference().child("Businesses").queryOrdered(byChild: "businessName").observe(.childAdded, with: { (snapshot) in

        let key = snapshot.key

        if(key == self.loggedInUser?.uid) {
            print("Same as logged in user, so don't show!")
        } else {
            if let locationValue = snapshot.value as? [String: AnyObject] {
                let lat = Double(locationValue["businessLatitude"] as! String)
                let long = Double(locationValue["businessLongitude"] as! String)
                let businessLocation = CLLocation(latitude: lat!, longitude: long!)

                let latitude = self.locationManager.location?.coordinate.latitude
                let longitude = self.locationManager.location?.coordinate.longitude
                let userLocation = CLLocation(latitude: latitude!, longitude: longitude!)

                let distanceInMeters: Double = userLocation.distance(from: businessLocation)
                let distanceInMiles: Double = distanceInMeters * 0.00062137
                let distanceLabelText = String(format: "%.2f miles away", distanceInMiles)

                var singleChildDictionary = locationValue
                singleChildDictionary["distanceLabelText"] = distanceLabelText as AnyObject
                singleChildDictionary["distanceInMiles"] = distanceInMiles as AnyObject
                self.usersArray.append(singleChildDictionary as NSDictionary)
                self.usersArray = self.usersArray.sorted {
                    !($0?["distanceInMiles"] as! Double > $1?["distanceInMiles"] as! Double)
                }

            }
            //insert the rows
            //self.followUsersTableView.insertRows(at: [IndexPath(row:self.usersArray.count-1,section:0)], with: UITableViewRowAnimation.automatic)
            self.followUsersTableView.reloadData()
        }

    }) { (error) in
        print(error.localizedDescription)
    }

}
1
What does these lines return: let latitude = self.locationManager.location?.coordinate.latitude let longitude = self.locationManager.location?.coordinate.longitudeazamsharp
I just added a screenshot of a breakpoint and the long & lat of the user location actually being returnedLukas Bimba
Thanks! Your latitude and longitude values looks very weird. When the app ran for first time did it asked for permission to use the location.azamsharp
You are calling locationManager.stopUpdatingLocation() immediately after you call locationManager.startUpdatingLocation(). You need to allow time for the location to be determined and you should not use location until you have received a call to didUpdateLocations. If you are targeting iOS 9 and later and you only need a single location, then you should call requestLocation, but you still need to wait for the callback to the delegate method. Once you have received a location, then you can load your table data.Paulw11
The latitude and longitude values you are seeing in the debugger are invalid since they have not been assigned yet; you can see that the debugger has not yet executed the let latitude=... statementPaulw11

1 Answers

3
votes

You are calling locationManager.stopUpdatingLocation() immediately after you call locationManager.startUpdatingLocation().

This won't work as you need to allow time for the location to be determined. You should not use location until you have received a call to the didUpdateLocations delegate method.

If you are targeting iOS 9 and later and you only need a single location, then you should call requestLocation() rather than startUpdatingLocation() but you still need to wait for the callback to the delegate method.

Once you have received a location, then you can load your table data.