Распределение результатов обратного геокодирования по глобальной переменной

Я использую Swift 4 и Xcode 9.3.1. Я в том числе скриншоты кода.

Я новичок в мобильной разработке / программировании в целом и думал о том, как это сформулировать. Так что это лучшее, что я могу объяснить:

Я создаю приложение, которое получает местоположение пользователя, чтобы отправить им помощь. Приложение получает координаты пользователя и отображает TextView с информацией об адресе. Так что довольно прямая функциональность mapKit / coreLocation. Пока все хорошо: получение координат с помощью startUpdatingLocation() работает нормально, и я использовал Reverse Geocoder, чтобы получить название улицы и местность. Но они - имея в виду расшифрованные строки улиц и населенных пунктов - распечатывают, только если я позвоню им в закрытом помещении, а не за его пределами. Я понял (правильно или неправильно?), Что переменные, которые должны быть доступны для нескольких функций в классе, должны быть объявлены глобально наверху. Однако я не могу понять, как извлечь информацию из этого замыкания, чтобы использовать ее в другом месте.

Я гуглял и читал вопросы в stackOverflow, и я чувствую, что чего-то действительно простого не хватает, но не могу понять, что. То, что я до сих пор безуспешно пытался:

1_ Определение глобальных переменных как пустых строк в начале класса и использование имен переменных внутри замыкания, где происходит обратный метод геокодирования, в попытке сохранить результирующие строки, но когда я пытаюсь распечатать переменные вне замыкания, Глобальная переменная - это еще и пустая строка ("").

[глобальные переменные объявлены вверху] [1]

2_Определение пустого глобального массива строк и добавление информации из замыкания в глобальный массив. Все еще получил пустой массив за пределами закрытия. (так же, как 1)

3_Создайте функцию --func decodedString()- чтобы вернуть данные в виде строки, чтобы я мог использовать их, объявив

*let streetLocation : String = decodedString()*

Однако, когда я объявляю эту функцию следующим образом:

var street = ""
var locality = ""

// Get the street address from the coordinates
    func deocodedString() -> String {
        let geocoder = CLGeocoder()
        geocoder.reverseGeocodeLocation(location) { placemarks, error in
        if let placemark = placemarks?.first {
        self.street = placemark.name!
        self.locality = placemark.locality!
        let string = "\(self.street), \(self.locality)"
        return string
        }
    }
}

Я получаю сообщение об ошибке: Неожиданное возвращаемое значение в void функции

неожиданное возвращаемое значение в пустую функцию

Наконец, если я передаю информацию прямо в TextView внутри замыкания с использованием приведенного ниже кода, мой textView успешно обновляется, но я не могу отформатировать строки, что мне нужно сделать, чтобы они выглядели как инструкции по проектированию Я следую (иначе жирный текст, обычный текст и текст разных размеров):

CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in
    if let placemark = placemarks?.first {
        self.street = placemark.name!
        self.locality = placemark.locality!
        let string = "\(self.street), \(self.locality)"
        self.addressTextView.text = string
    }
}

Вот почему я не могу просто пройти через метод textView.text = string.

Я был бы признателен за помощь... Я искал хотя бы StackOverFlow, YouTube и другие учебные места, но я не могу понять, что мне не хватает, или почему мое объявление функции вызывает ошибку. Я уже уничтожил и перевернул свой код несколько раз за последние 24 часа, не получив независимую строку, к которой я могу применить форматирование перед передачей его в textView, и я не знаю, как еще подойти к нему.

1 ответ

Решение

При вызове этой функции reverseGeocodeLocation выполняется в фоновом потоке. Так что если вы хотите вернуть адрес в этом методе, вы должны использовать escape-замыкание.

    func getaddress(_ position:CLLocationCoordinate2D,completion:@escaping (String)->()) {
     let geocoder = CLGeocoder()
        geocoder.reverseGeocodeLocation(location) { placemarks, error in
        if let placemark = placemarks?.first {
        let street = placemark.name!
        let locality = placemark.locality!
        let string = "\(street), \(locality)"
        completion(string)
        }
    } 
    }

   self.getaddress(position.target) { address in
        print(address)
        self.addressTextView.text = address    
   }

У меня была проблема с геокодером Google, чтобы обновить ярлык на экране карты.

Итак, я сделал это, во-первых, создать

быстрое имя файла: GoogleAPI просто называйте его как хотите.

class GoogleAPI {

    static let sharedInstance = GoogleAPI()

    private init() { }

    var addressValue = ""

    public func geocoding(lat: Double, long: Double) {
        Alamofire.request("https://maps.googleapis.com/maps/api/geocode/json?latlng=\(lat),\(long)&key=YOUR_GOOGLE_KEY").responseJSON { (response) in
            if response.result.isSuccess {
                let dataJSON : JSON = JSON(response.result.value!)
                self.geocoding(json: dataJSON)
            } else {
                print("Error \(response.result.error!)")
            }
        }
    }

    fileprivate func geocoding(json: JSON) {
        let json = json["results"]
        let address = json[1]["formatted_address"].stringValue
        addressValue = address
        print("pin address \(addressValue)")
    }
}

Это вызов API для Google, чтобы получить все из ответа и проанализировать единственную улицу.

После этого перейдите в свой View Controller с картой, где находится значок, карта и т. Д.

Установите булавку, маркер, чтобы быть перетаскиваемым. [marker1.isDraggable = true]

Затем добавьте эту функцию

mapView(_ mapView: GMSMapView, маркер didEndDragging: GMSMarker)

и добавьте вызов сверху вот так:

func mapView(_ mapView: GMSMapView, didEndDragging marker: GMSMarker) {
    GoogleAPI.sharedInstance.geocoding(lat: marker.position.latitude, long: marker.position.longitude)
    DispatchQueue.main.async {
        self.txtSearch.text = GoogleAPI.sharedInstance.addressValue
    }
}

txtSearch - это мое текстовое поле поиска.

да, я знаю, что это можно сделать лучше, но нет времени. это работает

Swift 4.2

Другие вопросы по тегам