Firebase 或 Swift 未检测到元音变音
Firebase or Swift not detecting umlauts
我在 Firebase
Database/Storage 中发现了一些最奇怪的东西。问题是我不知道 Firebase 或 Swift 是否没有检测变音符号,例如 (ä, ö, ü).
我用 Firebase 做了一些简单的事情,比如将图像上传到 Firebase 存储,然后将它们下载到 tableview
。我的一些 .png
文件的标题中有变音符号,例如 (Röda.png
).
所以如果我下载它们,现在就会出现问题。我的下载 url
唯一一次是 nil
是文件名是否包含我正在谈论的变音符号。
所以我尝试了一些替代方案,例如 HTML
ö - ö
。但这是行不通的。你们能给我一些建议吗?我无法使用 ö - o
、ü - u
等
这是当 url
为 nil
时尝试将一些值设置到 Firebase:
时的代码
FIRStorage.storage().reference()
.child("\(productImageref!).png")
.downloadURLWithCompletion({(url, error)in
FIRDatabase.database().reference()
.child("Snuses").child(productImageref!).child("productUrl")
.setValue(url!.absoluteString)
let resource = Resource(downloadURL: url!, cacheKey: productImageref)
在花了相当多的时间研究你的问题后,差异归结为字符 ö
的编码方式,我将其追溯到 Unicode 规范化形式。
字母ö
可以有两种写法,String
/NSString
认为它们相等:
let str1 = "o\u{308}" // decomposed : latin small letter o + combining diaeresis
let str2 = "\u{f6}" // precomposed: latin small letter o with diaeresis
print(str1, str2, str1 == str2) // ö ö true
但是当你对它们进行百分比编码时,它们会产生不同的结果:
print(str1.stringByAddingPercentEncodingWithAllowedCharacters(.URLPathAllowedCharacterSet())!)
print(str2.stringByAddingPercentEncodingWithAllowedCharacters(.URLPathAllowedCharacterSet())!)
// o%CC%88
// %C3%B6
我的猜测是 Google / Firebase 选择了分解形式,而 Apple 在其文本输入系统中更喜欢另一种形式。您可以将文件名转换为其分解形式以匹配 Firebase:
let str3 = str2.decomposedStringWithCanonicalMapping
print(str3.stringByAddingPercentEncodingWithAllowedCharacters(.URLPathAllowedCharacterSet()))
// o%CC%88
这与 ASCII 范围的字符无关。 Unicode 可能非常混乱。
参考文献:
Unicode 万岁!
简短的回答是不,我们实际上并没有在这里做任何特别的事情。基本上我们所做的一切都是:
// This is the list at https://cloud.google.com/storage/docs/json_api/ without the & because query parameters
NSString *const kGCSObjectAllowedCharacterSet =
@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$'()*+,;=:@";
- (nullable NSString *)GCSEscapedString:(NSString *)string {
NSCharacterSet *allowedCharacters =
[NSCharacterSet characterSetWithCharactersInString:kGCSObjectAllowedCharacterSet];
return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
}
令我震惊的是:
let str1 = "o\u{308}" // decomposed : latin small letter o + combining diaeresis
let str2 = "\u{f6}" // precomposed: latin small letter o with diaeresis
print(str1, str2, str1 == str2) // ö ö true
returnstrue
。在 Objective-C(内置 Firebase Storage 客户端)中,它完全不应该,因为它们是两个完全不同的字符(实际上,str1
的长度是 2
而str2
的长度在 Obj-C 中是 1
,而在 Swift 中我假设两者的答案都是 1
)。
Apple 必须在 Swift 中进行比较之前对字符串进行规范化(这可能是合理的做法,否则会导致 this where strings are "the same" but compare differently). Turns out, this is exactly what they do (see the "Extended Grapheme Clusters" section of their docs 等错误)。
因此,当您在 Swift 中提供两个不同的字符时,它们将作为不同的字符传播到 Obj-C,因此编码方式也不同。不是错误,只是 Swift 的 String
类型和 Obj-C 的 NSString
类型之间的众多差异之一。如有疑问,请选择您期望的规范表示并坚持使用,但作为库开发人员,我们很难为您选择那种表示。
因此,在命名包含 Unicode 字符的文件时,请确保选择标准表示法(C、D、KC 或 KD)并在创建引用时始终使用它。
let imageName = "smorgasbörd.jpg"
let path = "images/\(imageName)"
let decomposedPath = path.decomposedStringWithCanonicalMapping // Unicode Form D
let ref = FIRStorage.storage().reference().child(decomposedPath)
// use this ref and you'll always get the same objects
我在 Firebase
Database/Storage 中发现了一些最奇怪的东西。问题是我不知道 Firebase 或 Swift 是否没有检测变音符号,例如 (ä, ö, ü).
我用 Firebase 做了一些简单的事情,比如将图像上传到 Firebase 存储,然后将它们下载到 tableview
。我的一些 .png
文件的标题中有变音符号,例如 (Röda.png
).
所以如果我下载它们,现在就会出现问题。我的下载 url
唯一一次是 nil
是文件名是否包含我正在谈论的变音符号。
所以我尝试了一些替代方案,例如 HTML
ö - ö
。但这是行不通的。你们能给我一些建议吗?我无法使用 ö - o
、ü - u
等
这是当 url
为 nil
时尝试将一些值设置到 Firebase:
FIRStorage.storage().reference()
.child("\(productImageref!).png")
.downloadURLWithCompletion({(url, error)in
FIRDatabase.database().reference()
.child("Snuses").child(productImageref!).child("productUrl")
.setValue(url!.absoluteString)
let resource = Resource(downloadURL: url!, cacheKey: productImageref)
在花了相当多的时间研究你的问题后,差异归结为字符 ö
的编码方式,我将其追溯到 Unicode 规范化形式。
字母ö
可以有两种写法,String
/NSString
认为它们相等:
let str1 = "o\u{308}" // decomposed : latin small letter o + combining diaeresis
let str2 = "\u{f6}" // precomposed: latin small letter o with diaeresis
print(str1, str2, str1 == str2) // ö ö true
但是当你对它们进行百分比编码时,它们会产生不同的结果:
print(str1.stringByAddingPercentEncodingWithAllowedCharacters(.URLPathAllowedCharacterSet())!)
print(str2.stringByAddingPercentEncodingWithAllowedCharacters(.URLPathAllowedCharacterSet())!)
// o%CC%88
// %C3%B6
我的猜测是 Google / Firebase 选择了分解形式,而 Apple 在其文本输入系统中更喜欢另一种形式。您可以将文件名转换为其分解形式以匹配 Firebase:
let str3 = str2.decomposedStringWithCanonicalMapping
print(str3.stringByAddingPercentEncodingWithAllowedCharacters(.URLPathAllowedCharacterSet()))
// o%CC%88
这与 ASCII 范围的字符无关。 Unicode 可能非常混乱。
参考文献:
Unicode 万岁!
简短的回答是不,我们实际上并没有在这里做任何特别的事情。基本上我们所做的一切都是:
// This is the list at https://cloud.google.com/storage/docs/json_api/ without the & because query parameters
NSString *const kGCSObjectAllowedCharacterSet =
@"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$'()*+,;=:@";
- (nullable NSString *)GCSEscapedString:(NSString *)string {
NSCharacterSet *allowedCharacters =
[NSCharacterSet characterSetWithCharactersInString:kGCSObjectAllowedCharacterSet];
return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
}
令我震惊的是:
let str1 = "o\u{308}" // decomposed : latin small letter o + combining diaeresis
let str2 = "\u{f6}" // precomposed: latin small letter o with diaeresis
print(str1, str2, str1 == str2) // ö ö true
returnstrue
。在 Objective-C(内置 Firebase Storage 客户端)中,它完全不应该,因为它们是两个完全不同的字符(实际上,str1
的长度是 2
而str2
的长度在 Obj-C 中是 1
,而在 Swift 中我假设两者的答案都是 1
)。
Apple 必须在 Swift 中进行比较之前对字符串进行规范化(这可能是合理的做法,否则会导致 this where strings are "the same" but compare differently). Turns out, this is exactly what they do (see the "Extended Grapheme Clusters" section of their docs 等错误)。
因此,当您在 Swift 中提供两个不同的字符时,它们将作为不同的字符传播到 Obj-C,因此编码方式也不同。不是错误,只是 Swift 的 String
类型和 Obj-C 的 NSString
类型之间的众多差异之一。如有疑问,请选择您期望的规范表示并坚持使用,但作为库开发人员,我们很难为您选择那种表示。
因此,在命名包含 Unicode 字符的文件时,请确保选择标准表示法(C、D、KC 或 KD)并在创建引用时始终使用它。
let imageName = "smorgasbörd.jpg"
let path = "images/\(imageName)"
let decomposedPath = path.decomposedStringWithCanonicalMapping // Unicode Form D
let ref = FIRStorage.storage().reference().child(decomposedPath)
// use this ref and you'll always get the same objects