Firebase或Swift没有检测到变音符号
我在Firebase
数据库/存储中发现了一些最古怪的东西。 问题是,我不知道Firebase或Swift是否没有检测到变音器,例如(ä,ö,ü)。
我使用Firebase做了一些简单的事情,例如将图片上传到Firebase存储,然后将其下载到tableview
。 例如,我的一些.png
文件在标题中有元音变音( Röda.png
)。
所以现在如果我下载它们,问题就会出现。 只有当我的下载url
是nil
,如果文件名包含我所说的变音符号。
所以我尝试了一些替代方法,如HTML
ö - ö
。 但是这不起作用。 你们可以给我一些build议吗? 我不能用ö - o
, ü - u
等
这是在尝试将某些值设置为Firebase时, url
nil
时的代码:
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)
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存储客户端是内置的)中,它们完全不应该是两个完全不同的字符(实际上,在Obj-C中str1
的长度是2
而str2
的长度是1
,而在Swift中我假设两者的答案都是1
)。
苹果必须在Swift比较之前对string进行规范化(可能是一个合理的做法,否则会导致像这样的错误,即string“相同”,但是比较不同)。 原来,这正是他们所做的(参见他们的文档的“扩展字形集群”部分)。
所以,当你在Swift中提供两个不同的字符时,它们被传播到Obj-C作为不同的字符,因此编码方式不同。 不是一个错误,只是Swift的String
types和Obj-C的NSString
types之间的许多区别之一。 如果有疑问,请select您希望遵循的规范表示forms,但作为图书馆开发人员,我们很难为您select该表示forms。
因此,在命名包含Unicode字符的文件时,请确保select标准表示(C,D,KC或KD),并在创build引用时始终使用它。
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
花了一段时间研究你的问题后,差异归结为字符ö
是如何编码的,我把它追溯到Unicode规范化forms。
字母ö
可以用两种方式写, 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
我的猜测是,谷歌/ Firebaseselect分解的forms,而苹果更喜欢在其文本input系统中的其他。 您可以将文件名称转换为其分解forms以与Firebase匹配:
let str3 = str2.decomposedStringWithCanonicalMapping print(str3.stringByAddingPercentEncodingWithAllowedCharacters(.URLPathAllowedCharacterSet())) // o%CC%88
这与ASCII范围的字符无关。 Unicode可能非常混乱。
参考文献:
- 绝对最小每个软件开发人员绝对积极地必须了解Unicode和字符集 (强烈推荐)
- Swift中的string2
- NSString和Unicode