【问题标题】:Cyrillic symbols in URLURL 中的西里尔符号
【发布时间】:2016-05-10 23:09:54
【问题描述】:

应用程序崩溃并显示以下网址:

let jsonUrl = "http://api.com/алматы/events"
let session = NSURLSession.sharedSession()
let shotsUrl = NSURL(string: jsonUrl)
let task = session.dataTaskWithURL(shotsUrl!)

日志:

fatal error: unexpectedly found nil while unwrapping an Optional value

这是因为 url 中的西里尔符号。我该如何解决这个问题。感谢您的帮助!

【问题讨论】:

    标签: ios swift nsurl


    【解决方案1】:

    斯威夫特 4
    使用字符串扩展 创建一个名为 String+Extension.swift 的 swift 文件并粘贴此代码

    import UIKit
    extension String{
        var encodeUrl : String
        {
            return self.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed)!
        }
        var decodeUrl : String
        {
            return self.removingPercentEncoding!
        }
    }
    

    并像这样使用它:(根据问题示例):

    "http://api.com/алматы/events".encodeUrl
    

    【讨论】:

    • Tnx,非常有用的答案
    • 非常欢迎。如果有更多要求,请发表评论。并将链接发送给我。我已经创建了一堆 xcode 扩展.. 以确保开发简单快捷。
    【解决方案2】:

    试试这个:

    let encodedUrl = jsonUrl.stringByAddingPercentEncodingWithAllowedCharacters(URLQueryAllowedCharacterSet)
    

    【讨论】:

      【解决方案3】:

      类似这样的:

      let apiHost = "http://api.com/"
      let apiPath = "алматы/events"
      let escapedPath = apiPath.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
      let url = NSURL(string: "\(apiHost)\(escapedPath!)")
      

      显然你应该做一些更聪明的事情,而不是仅仅强制打开 escapedPath。

      以 Swift 的 Wikipedia 页面为例: https://ru.wikipedia.org/wiki/Swift_(язык_программирования)

      变成:

      https://ru.wikipedia.org/wiki/Swift_(%D1%8F%D0%B7%D1%8B%D0%BA_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F)
      

      将其粘贴到浏览器中时,您会转到正确的页面(大多数浏览器会方便地为您呈现 UFT-8 字符)。

      【讨论】:

        【解决方案4】:

        非 ASCII 字符(和许多特殊字符)需要在 URL 中进行转义。 Chrome 和其他浏览器会自动执行此操作。他们在地址栏中取消转义 URL 以获得更好的显示效果。

        因此,如果您有一个静态 URL,只需将其粘贴到地址栏中,按 Enter,再次选择该 URL,然后将其复制并粘贴到您的应用中:

        所以而不是:

        let jsonUrl = "http://api.com/алматы/events"
        

        你会得到:

        let jsonUrl = "http://api.com/%D0%B0%D0%BB%D0%BC%D0%B0%D1%82%D1%8B/events"
        

        【讨论】:

        • @aaisataev 我提供了一个基本答案,应该足以让您从那里弄清楚。
        【解决方案5】:

        尝试在 NSString 上定义的 stringByAddingPercentEncodingWithAllowedCharacters:。您可能会看到有人建议 stringByAddingPercentEscapesUsingEncoding:,但该方法在 iOS 9 中已被弃用。

        Foundation中也有一些预定义的NSCharacterSets,如URLHostAllowedCharacterSet和URLPathAllowedCharacterSet。因此,如果您确实必须在代码中解析未转义的 URL(使用已接受的答案中提到的预处理 URL 通常是一个更好的主意),您可以编写一个这样的辅助方法:

        import Foundation
        
        func url(scheme scheme: String, host: String, path: String) -> NSURL? {
            let components = NSURLComponents()
            components.scheme = scheme
            components.host = host.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
            components.path = path.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLPathAllowedCharacterSet())
            return components.URL
        }
        
        // evaluates to http://api.com/%25D0%25B0%25D0%25BB%25D0%25BC%25D0%25B0%25D1%2582%25D1%258B/events
        url(scheme: "http", host: "api.com", path: "/алматы/events")
        

        请注意,上述文档中提到了

        此方法旨在对 URL 组件或子组件字符串进行百分比编码,而不是整个 URL 字符串。

        这是因为根据 RFC 3986,并非 URL 的所有部分都可以进行百分比编码(例如 scheme - http/https/等)

        【讨论】:

          【解决方案6】:

          在 xamarin 中:

          var uri = new Uri (url);
          var nsurl = new NSUrl (uri.GetComponents (UriComponents.HttpRequestUrl, UriFormat.UriEscaped));
          UIApplication.SharedApplication.OpenUrl (nsurl);
          

          【讨论】:

            【解决方案7】:

            网址不能包含西里尔字符。有一些标准可以将西里尔字符转换为有效的 URL - 如果您搜索“Punicode”(P 是故意的),您可能会找到一些东西。

            【讨论】:

            • 例如:ru.wikipedia.org/wiki/Арктическая_экспедиция_Грили 维基百科上没有 Punicode。根据 NSURL 文档,百分比转义字符将被解释为 UTF-8。
            • "Punycode 用于对应用程序中的国际化域名 (IDNA) 框架中的标签进行编码,以便这些域名可以用域名系统中允许的 ASCII 字符集表示Internet。”所以你所说的仅适用于 URL 的域部分,而不是其余部分。
            猜你喜欢
            • 2018-02-19
            • 1970-01-01
            • 1970-01-01
            • 2011-09-08
            • 1970-01-01
            • 1970-01-01
            • 2011-12-17
            • 2014-06-01
            • 1970-01-01
            相关资源
            最近更新 更多