我在Firebase
数据库/存储中找到了一些奇怪的东西。问题是我不知道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)
答案 0 :(得分:2)
花了相当多的时间研究你的问题后,差异归结为字符ö
的编码方式,并将其追溯到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可能非常令人困惑。
参考文献:
答案 1 :(得分:2)
Horray for 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
返回true
。在Objective-C(内置Firebase存储客户端)中,它完全不应该,因为它们是两个完全不同的字符(实际上,str1
的长度是{{1}虽然在Obj-C中2
的长度为str2
,而在Swift中我假设两者的答案都是1
。
Apple必须在Swift中进行比较之前对字符串进行规范化(这可能是一件合理的事情,否则会导致像this这样的错误,其中字符串是"相同"但是比较不同)。事实证明,这正是他们所做的(参见"扩展字形集群"他们的docs部分)。
因此,当您在Swift中提供两个不同的字符时,它们将作为不同的字符传播到Obj-C,因此编码方式不同。这不是一个错误,只是Swift的1
类型和Obj-C的String
类型之间的众多差异之一。如果有疑问,请选择您期望的规范表示并坚持使用它,但作为图书馆开发人员,我们很难为您选择该表示。
因此,在命名包含Unicode字符的文件时,请确保选择标准表示(C,D,KC或KD)并在创建引用时始终使用它。
NSString