按下 UILabel 时分配变量值以打开 Apple 地图

Posted

技术标签:

【中文标题】按下 UILabel 时分配变量值以打开 Apple 地图【英文标题】:Issue assigning variable value to open Apple Maps when pressing a UILabel 【发布时间】:2019-05-10 14:23:24 【问题描述】:

基本上我是在解析 JSON 数据并将其分配给一个名为 addressPressNow 的变量,然后当用户点击 UILabel 时,我会执行以下函数:

目标是打开 Apple 地图,前提是它包含的变量值。

因为我将地址分配给变量,所以它将包含空格 例如:3981 试驾库比蒂诺 CA 95014

注意:变量的值被正确传递,因为当我在func tapFunction 中执行print(addressPressNow) 时,它会正确打印。

@objc
func tapFunction(sender:UITapGestureRecognizer) 

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


    UIApplication.shared.openURL(targetURL as URL)


问题是我无法将变量应用于字符串 URL,并出现以下错误:

线程 1:致命错误:打开包装时意外发现 nil 可选值

以下是我将值分配给变量的方式:

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
        

    

【问题讨论】:

【参考方案1】:

“我正在为一个包含空格的变量分配一个地址”

如果地址包含空格,则使用字符串创建NSURL 将崩溃。可以使用addingPercentEncoding解决问题

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)


按照马特的建议使用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)

【讨论】:

感谢您的帮助 我很抱歉,但我不得不不同意。无需添加百分比编码。他应该通过 URLComponents 并且所有内容都将根据需要进行百分比编码。像这样手动形成一个 URL 字符串是从来没有正确的做法。【参考方案2】:

你在说

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。

【讨论】:

以上是关于按下 UILabel 时分配变量值以打开 Apple 地图的主要内容,如果未能解决你的问题,请参考以下文章

智能配变终端TTU-新型融合终端ttu

智能配变终端TTU-新型融合终端ttu

按下按钮时未从数组中填充 UILabel

当按下自定义按钮时,UILabel 不会更新(Objective-C)

动画改变 UILabel 的行数

vs2010调试怎么查看变量