ios URL(字符串:)始终不起作用

时间:2018-02-02 05:39:17

标签: ios swift url nsurl url-encoding

let testurl = "http://akns-
images.eonline.com/eol_images/Entire_Site/2018029/rs_1024x759-
180129200032-1024.lupita-nyongo-angela-bassett-black-panther-
premiere.ct.012918.jpg?fit=inside|900:auto"

if let url = URL(string: testurl){
    print("valid")
}else {
   print("invalid")
}

这将打印为无效的URL。但是在Web浏览器中显示图像。我已经看到了很多方法,但它会引发Apple警告使用stringByAddingPercentEncodingWithAllowedCharacters,但这并不总是有效。

我更倾向于使用一种解决方案来清理网址而不编码完整的urlstring。在初始步骤对其进行编码可能会在传递到外部库时产生摩擦,这将对URL进行重新编码并使其无效。

5 个答案:

答案 0 :(得分:7)

使用URLComponents,它会自动处理转义字符并对网址进行正确编码。无需使用addingPercentEncoding

func computeURL() {
    let testurlStr = "http://akns-images.eonline.com/eol_images/Entire_Site/2018029/rs_1024x759-180129200032-1024.lupita-nyongo-angela-bassett-black-panther-premiere.ct.012918.jpg?fit=inside|900:auto"
    let components = transformURLString(testurlStr)

    if let url = components?.url {
        print("valid")
    } else {
        print("invalid")
    }
}

func transformURLString(_ string: String) -> URLComponents? {
    guard let urlPath = string.components(separatedBy: "?").first else {
        return nil
    }
    var components = URLComponents(string: urlPath)
    if let queryString = string.components(separatedBy: "?").last {
        components?.queryItems = []
        let queryItems = queryString.components(separatedBy: "&")
        for queryItem in queryItems {
            guard let itemName = queryItem.components(separatedBy: "=").first,
                  let itemValue = queryItem.components(separatedBy: "=").last else {
                    continue
            }
            components?.queryItems?.append(URLQueryItem(name: itemName, value: itemValue))
        }
    }
    return components!
}

答案 1 :(得分:4)

如果URL包含特殊字符,则必须使用URL编码从字符串构建URL。

为什么我们需要URL编码

来自this answer

  
    

URI表示为字符序列,而不是八位字节序列。这是因为URI可能会被传输"通过不通过计算机网络的方式,例如印刷在纸上,通过无线电读取等等。

  
     

     
    

但是,对于包含非ASCII字符的原始字符序列,情况更加困难。如果可能存在多个[RFC2277],那么传输用于表示字符序列的八位字节序列的因特网协议有望提供一些识别所用字符集的方法。但是,通用URI语法中目前没有提供完成此标识的规定。单个URI方案可能需要单个字符集,定义默认字符集,或提供指示所使用字符集的方法。

  

在IOS SDK中,我们有以下内容:

用户:URLUserAllowedCharacterSet
密码:URLPasswordAllowedCharacterSet
主持人:URLHostAllowedCharacterSet
路径:URLPathAllowedCharacterSet
片段:URLFragmentAllowedCharacterSet
查询:URLQueryAllowedCharacterSet

您可以使用addingPercentEncoding(withAllowedCharacters:)正确编码字符串。

根据the apple docs for that method的一个重要说明:

  

整个URL字符串不能进行百分比编码,因为每个URL组件都指定了一组不同的允许字符。例如,URL的查询组件允许使用“@”字符,但该字符必须在密码组件中进行百分比编码。

     

UTF-8编码用于确定正确的百分比编码字符。将忽略7位ASCII范围之外的allowedCharacters中的任何字符。

一个例子:

let encodedURL = testurl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
if let url = URL(string: finalUrl) {
    print("valid url")
} else {
    print("invalid url")
}

我希望这有用。

答案 2 :(得分:3)

我想我找到了答案。仍将检查任何副作用,欢迎提出意见:

let urlst = "http://akns-
images.eonline.com/eol_images/Entire_Site/2018029/rs_1024x759-
180129200032-1024.lupita-nyongo-angela-bassett-black-panther-
premiere.ct.012918.jpg?fit=inside|900:auto"
extension String {
 func getCleanedURL() -> URL? {
    guard self.isEmpty == false else {
        return nil
    }
    if let url = URL(string: self) {
        return url
    } else {
        if let urlEscapedString = self.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) , let escapedURL = URL(string: urlEscapedString){
            return escapedURL
        }
    }
    return nil
 }
}

这不会对完整的URL进行编码,只会对无效的查询字符进行编码(例如,在url中对其进行编码' |')。因此,它仍然可以作为字符串或有效URL传递。

答案 3 :(得分:0)

根据您自己的回答,我什至会进一步简化它,使其成为 URL 而不是 String 的扩展,这样我们仍然可以使用与 URL(string:) 类似的初始化程序,并具有相同的输出:

extension URL {
    init?(_ string: String) {
        guard string.isEmpty == false else {
            return nil
        }
        if let url = URL(string: string) {
            self = url
        } else if let urlEscapedString = string.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed),
                  let escapedURL = URL(string: urlEscapedString) {
            self = escapedURL
        } else {
            return nil
        }
    }
}

答案 4 :(得分:-2)

请用以下代码替换您的行:

let  finalUrl = testurl.addingPercentEncoding( withAllowedCharacters: .urlUserAllowed)
if let url = URL(string: finalUrl){
    print("valid")
} else {
   print("invalid")
}