Проблема с назначением значения переменной для открытия Apple Maps при нажатии UILabel - PullRequest
2 голосов
/ 10 мая 2019

По сути, я анализирую данные JSON и присваиваю их переменной addressPressNow. Затем у меня появляется следующая функция, которая выполняется, когда пользователь нажимает на UILabel:

Цель состоит в том, чтобы открыть открытые Apple Mapsзначение переменной, которое оно содержит.

Поскольку я назначаю адрес переменной, она будет содержать пробелы, например: 3981 Test Drive Cupertino CA 95014

ПРИМЕЧАНИЕ : Значениепеременная передается правильно, потому что когда я выполняю print(addressPressNow) в func tapFunction, она печатается правильно.

@objc
func tapFunction(sender:UITapGestureRecognizer) {

    let targetURL = NSURL(string: "http://maps.apple.com/?q=" + addressPressNow)!


    UIApplication.shared.openURL(targetURL as URL)

}

Проблема в том, что у меня возникают проблемы с применением переменной к строковому URL со следующей ошибкой:

Поток 1: фатальная ошибка: неожиданно обнаружен ноль при развертывании необязательного значения

Ниже описано, как я присваиваю значение переменной:

struct FacilityInfo: Decodable {
    let address: String

class infoViewController: UIViewController {

    var addressPressNow : String = ""

override func viewDidLoad() {
    super.viewDidLoad()



    let tap = UITapGestureRecognizer(target: self, action: #selector(infoViewController.tapFunction))
    addressInfo.isUserInteractionEnabled = true
    addressInfo.addGestureRecognizer(tap)


    let url = URL(string: "https://test/test/example”)!

    let task = URLSession.shared.dataTask(with: url) { data, response, error in

        // ensure there is no error for this HTTP response
        guard error == nil else {
            print ("error: \(error!)")
            return
        }

        // ensure there is data returned from this HTTP response
        guard let data = data else {
            print("No data")
            return
        }

        // Parse JSON into array of Car struct using JSONDecoder


        guard let cars = try? JSONDecoder().decode([FacilityInfo].self, from: data), let secondCar = cars.first
        else {
            print("Error: Couldn't decode data into cars array")
            return
        }
        DispatchQueue.main.async {
            self.addressPressNow = secondCar.facility_address
        }

    }

Ответы [ 2 ]

2 голосов
/ 10 мая 2019

«Я назначаю адрес переменной, которая будет содержать пробелы»

Если адрес содержит пробелы, создание NSURL со строкой приведет к сбою.Вы можете использовать добавлениеPercentEncoding для решения проблемы

if let encodedAddress = addressPressNow.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) {
    let targetURL = NSURL(string: "http://maps.apple.com/?q=" + encodedAddress)!
    UIApplication.shared.openURL(targetURL as URL)
}

И не используйте NSURL и принудительное развертывание.Обновите его следующим образом

if let encodedAddress = addressPressNow.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
    let targetURL = URL(string: "http://maps.apple.com/?q=" + encodedAddress) {
        UIApplication.shared.openURL(targetURL)
}

В соответствии с предложением matt use URLComponents

let addressPressNow = "3981 Test Drive Cupertino CA 95014"
var components = URLComponents(string: "http://maps.apple.com")
components?.queryItems = [URLQueryItem(name: "q", value: addressPressNow)]
print(components?.url)//http://maps.apple.com?q=3981%20Test%20Drive%20Cupertino%20CA%2095014
if let targetURL = components?.url {
    UIApplication.shared.open(targetURL, options: [:], completionHandler: nil)
}
1 голос
/ 10 мая 2019

Вы говорите

NSURL(string: "http://maps.apple.com/?q=" + addressPressNow)!

Обратите внимание на восклицательный знак в конце.Это означает «если есть проблема, разбей меня».Вы вряд ли можете жаловаться, если вы действительно потерпите крах;это то, что вы просили сделать.

По сути, никогда используйте NSURL(string:), если вы можете избежать этого.Чтобы сформировать действительный URL, создайте его, используя URLComponents.И сформируйте его из действительных компонентов.(Невозможно сказать, является ли facility_address допустимым URL-запросом, поскольку вы не показали, что это такое.)

Пример:

var comp = URLComponents()
comp.scheme = "https"
comp.host = "maps.apple.com"
comp.queryItems = [URLQueryItem(name: "q", value: "1 Infinite Loop, Cupertino, CA")]
if let url = comp.url {
    print(url) // https://maps.apple.com?q=1%20Infinite%20Loop,%20Cupertino,%20CA

}

Это дает нам действительный URL, которыйна самом деле работает.

...