ios - 带有变音符号的图像 url 写入了错误的部分

标签 ios swift firebase firebase-realtime-database

我用 Firebase 做一些简单的任务,将图像 url 设置到 json 中,下载并显示它。但出于某种原因,如果 url 包含变音符号,例如(ö、ä、ü 等),则 url 设置为错误的部分。

编辑:我必须澄清一下,我对 url 进行了百分比编码。所以它实际上不包含任何变音符号。

因此 url 实际上看起来像这样,例如 Göteborgs Rapé Loose.png:https://firebasestorage.googleapis.com/v0/b/snuspedia.appspot.com/o/Go%CC%88teborgs%20Rape%CC%81%20Loose.png?alt=media&token=e8f2219b-d14e-46f6-a90f-ee21f912af6c

对于元音变音,它是这样的:

enter image description here

如果没有变音符号,它会像这样正确:

enter image description here

这就是我按照我所描述的执行所有这些步骤的方式:

if productsValue[indexPath.row]["productUrl"] != nil {
            cell.snusProductImageView!.kf_setImageWithURL(NSURL(string: productsValue[indexPath.row]["productUrl"] as! String)!)
        }
        else {
            let productImageref = productsValue[indexPath.row]["Products"] as! String

            let decomposedPath = productImageref.decomposedStringWithCanonicalMapping

            cell.snusProductImageView.image = nil
            cell.snusProductImageView.kf_showIndicatorWhenLoading = true

            FIRStorage.storage().reference().child("\(decomposedPath).png").downloadURLWithCompletion({(url, error)in

                FIRDatabase.database().reference().child("Snuses").child(decomposedPath).child("productUrl").setValue(url!.absoluteString)

                let resource = Resource(downloadURL: url!, cacheKey: decomposedPath)

                cell.snusProductImageView.kf_setImageWithURL(url)

            })

问题是什么,你能告诉我吗?我一直在寻找这个问题整整一周。

最佳答案

URL 不能直接包含“变音符号”。简单来说,URL 是一系列受限制的 ASCII 字符。

这意味着,不允许使用的字符(例如,öäü 等)需要正确编码。由于 URL 由几个不同的组件组成,每个组件可能使用略有不同的编码。此处介绍了详细信息:Uniform Resource Identifier (URI): Generic Syntax .

在 Cocoa 和 Cocoa Touch 中,有一个辅助类,NSURLComponents这让您可以轻松地从给定的原始组件以其自然字符编码组成正确的 URL 字符串。

请注意,简单地将“百分比编码”应用于整个编码不正确的 URL 通常会产生另一个编码不正确的 URL。不要那样做!使用 NSURLComponents!

编辑:

让我对您的代码应用一些 - 希望有用的 - 注释:

这个表达式有问题:

  1. NSURL(string: productsValue[indexPath.row]["productUrl"] as!String)!

最好从索引 "productUrl" 处可能缺失的值显式初始化一个 URL 并包括适当的错误处理。众所周知,将字符串转换为 URL 很容易出错。

然后

  1. 让 decomposedPath = productImageref.decomposedStringWithCanonicalMapping

这是没有意义的,因为根据定义,URL 字符串无论如何都由一组受限制的 ASCII 字符组成。

因此,总而言之,检查应该成为 URL 的给定字符串,并确保您可以从中初始化一个正确的 URL(作为 URL 类型的值)并将其再次正确转换回一个字符串,分别为一个 ASCII 字符数组,当通过网络发送时。

编辑 2:

下面的代码演示了如何利用 NSURLComponents 从给定的基本 URL、引用端点的部分路径组件和给定的参数集安全地创建 URL。

将其复制/粘贴到 playground 中进行尝试。

import Cocoa

extension String: ErrorType {}


// First, create a base URL and save it later for reuse:
// Caution: The given string must be properly encoded! But usually, the base address
// in native form should only use allowed characters anyway, so the encoded form 
// should be equal to the native form (otherwise, you have to encode it per component).
let urlBaseString = "https://firebasestorage.googleapis.com/v0/b/snuspedia.appspot.com/o"
guard let urlBase = NSURL(string: urlBaseString) else {
    throw "bad base URL"
}

print("Base URL path: \"\(urlBase.path!)\"")

// Get the current path and parameters using strings using their "native character set":
let itemPath = "Göteborgs Rapé Loose.png"
let params = ["alt": "media", "token": "e8f2219b-d14e-46f6-a90f-ee21f912af6c"]

// Create a partial URL components (representing a relative URL) with the given 
// path and query component:
let components = NSURLComponents() 
components.path = itemPath
components.queryItems = params.map { NSURLQueryItem(name: $0, value: $1) }

// Combine the base URL with the partial URL in order to get a fully specified URL:
guard let url = components.URLRelativeToURL(urlBase) else {
    throw "Failed to create final URL"
}
print("URL: \(url.absoluteString)")

输出:

网址:https://firebasestorage.googleapis.com/v0/b/snuspedia.appspot.com/G%C3%B6teborgs%20Rap%C3%A9%20Loose.png?alt=media&token=e8f2219b- d14e-46f6-a90f-ee21f912af6c

关于ios - 带有变音符号的图像 url 写入了错误的部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39178778/

相关文章:

ios - 栏按钮项目无法执行操作 Swift

ios - 在 XCode 中添加声音时应该使用哪种格式?

ios - Xcode 错误 : Class <name> is implemented in both <path> and <path>. 将使用两者之一。哪一个是未定义的?

Angular 通用 Firebase : no provider for InjectionToken MODULE_MAP

objective-c - 一对一关系的值类型 Not Acceptable 。所需类型=(空);

ios - 在 didSelectRowAtIndexPath 处更改单元格的顶部边框宽度和颜色的最佳方法是什么?

ios - 将注释应用于 map 工具包

IOS 内存和电池管理 - 内存与工作

ios - 如何使用 swift 在 IOS 中的两个扩展之间共享变量值而不使用 Coredata

node.js - 如何编写 Firebase Cloud Messaging 函数来发送推送通知