URL 中的西里尔符号
Cyrillic symbols in URL
应用崩溃并出现以下 url:
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 中的西里尔符号。我该如何解决这个问题。感谢您的帮助!
URL 不能包含西里尔字符。有如何将西里尔字符翻译成有效 URL 的标准——如果您搜索 "Punicode"(P 是故意的),您可能会找到一些东西。
非 ASCII 字符(以及许多特殊字符)需要在 URL 中转义。 Chrome 和其他浏览器自动执行。他们取消转义地址栏中的 URL 以获得更好的显示效果。
因此,如果您有静态 URL,只需将其粘贴到地址栏,按回车键,再次选择 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"
试试这个:
let encodedUrl = jsonUrl.stringByAddingPercentEncodingWithAllowedCharacters(URLQueryAllowedCharacterSet)
像这样:
let apiHost = "http://api.com/"
let apiPath = "алматы/events"
let escapedPath = apiPath.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
let url = NSURL(string: "\(apiHost)\(escapedPath!)")
显然你应该做一些比强制解包更聪明的事情 escapedPath
。
以 Swift 的维基百科页面为例:
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 字符)。
尝试在 NSString 上定义 stringByAddingPercentEncodingWithAllowedCharacters:。您可能会看到有人建议 stringByAddingPercentEscapesUsingEncoding:
,但该方法在 iOS 9.
中已弃用
Foundation 中也有一些预定义的NSCharacterSet
,例如URLHostAllowedCharacterSet
和URLPathAllowedCharacterSet
。因此,如果你真的必须在代码中解析未转义的 URL(使用预处理的 URLs,在接受的答案中提到,通常是一个更好的主意),你可以编写这样的辅助方法:
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")
注意上面的文档提到
This method is intended to percent-encode an URL component or subcomponent string, NOT an entire URL string.
这是因为根据 RFC 3986,并非 URL 的所有部分都可以进行百分比编码(例如 scheme
- http/https/etc。)
在 xamarin 中:
var uri = new Uri (url);
var nsurl = new NSUrl (uri.GetComponents (UriComponents.HttpRequestUrl, UriFormat.UriEscaped));
UIApplication.SharedApplication.OpenUrl (nsurl);
Swift 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
应用崩溃并出现以下 url:
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 中的西里尔符号。我该如何解决这个问题。感谢您的帮助!
URL 不能包含西里尔字符。有如何将西里尔字符翻译成有效 URL 的标准——如果您搜索 "Punicode"(P 是故意的),您可能会找到一些东西。
非 ASCII 字符(以及许多特殊字符)需要在 URL 中转义。 Chrome 和其他浏览器自动执行。他们取消转义地址栏中的 URL 以获得更好的显示效果。
因此,如果您有静态 URL,只需将其粘贴到地址栏,按回车键,再次选择 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"
试试这个:
let encodedUrl = jsonUrl.stringByAddingPercentEncodingWithAllowedCharacters(URLQueryAllowedCharacterSet)
像这样:
let apiHost = "http://api.com/"
let apiPath = "алматы/events"
let escapedPath = apiPath.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
let url = NSURL(string: "\(apiHost)\(escapedPath!)")
显然你应该做一些比强制解包更聪明的事情 escapedPath
。
以 Swift 的维基百科页面为例:
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 字符)。
尝试在 NSString 上定义 stringByAddingPercentEncodingWithAllowedCharacters:。您可能会看到有人建议 stringByAddingPercentEscapesUsingEncoding:
,但该方法在 iOS 9.
Foundation 中也有一些预定义的NSCharacterSet
,例如URLHostAllowedCharacterSet
和URLPathAllowedCharacterSet
。因此,如果你真的必须在代码中解析未转义的 URL(使用预处理的 URLs,在接受的答案中提到,通常是一个更好的主意),你可以编写这样的辅助方法:
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")
注意上面的文档提到
This method is intended to percent-encode an URL component or subcomponent string, NOT an entire URL string.
这是因为根据 RFC 3986,并非 URL 的所有部分都可以进行百分比编码(例如 scheme
- http/https/etc。)
在 xamarin 中:
var uri = new Uri (url);
var nsurl = new NSUrl (uri.GetComponents (UriComponents.HttpRequestUrl, UriFormat.UriEscaped));
UIApplication.SharedApplication.OpenUrl (nsurl);
Swift 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