Ios Firebase或Swift未检测到umlauts
我在Ios Firebase或Swift未检测到umlauts,ios,swift,firebase,firebase-realtime-database,firebase-storage,Ios,Swift,Firebase,Firebase Realtime Database,Firebase Storage,我在Firebase数据库/存储中发现了一些最奇怪的东西。问题是,我不知道Firebase或Swift是否没有检测到umlauts,例如(ä,ö,ü) 我用Firebase做了一些简单的事情,比如将图像上传到Firebase存储,然后下载到tableview。例如,我的一些.png文件的标题中有umlauts(Röda.png) 因此,如果我下载它们,问题就出现了。我唯一的下载url是nil的时间是文件名是否包含我所说的umlauts 所以我尝试了一些替代方法,比如在HTMLö-ö。但这
Firebase
数据库/存储中发现了一些最奇怪的东西。问题是,我不知道Firebase或Swift是否没有检测到umlauts,例如(ä,ö,ü)
我用Firebase做了一些简单的事情,比如将图像上传到Firebase存储,然后下载到tableview
。例如,我的一些.png
文件的标题中有umlauts(Röda.png
)
因此,如果我下载它们,问题就出现了。我唯一的下载url
是nil
的时间是文件名是否包含我所说的umlauts
所以我尝试了一些替代方法,比如在HTML
ö-ö代码>。但这是行不通的。你们能给我提个建议吗?我不能使用ö-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)
在花了相当多的时间研究您的问题之后,差异可以归结为字符ö
的编码方式,我将其追溯到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在其文本输入系统中选择了分解形式,而苹果则更喜欢另一种。您可以将文件名转换为其分解形式以匹配Firebase:
let str3 = str2.decomposedStringWithCanonicalMapping
print(str3.stringByAddingPercentEncodingWithAllowedCharacters(.URLPathAllowedCharacterSet()))
// o%CC%88
这与ASCII范围字符无关。Unicode可能非常令人困惑
参考资料:
- (强烈推荐)
用于Unicode的Horray
简单的回答是不,我们实际上没有做任何特别的事情。基本上,我们在引擎盖下所做的就是:
// 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 Storage client内置)中,它完全不应该这样做,因为它们是两个完全不同的字符(实际上,str1
的长度是2
,而在Obj-C中str2
的长度是1
,而在Swift中,我假设两者的答案都是1
)
苹果必须在使用Swift进行比较之前对字符串进行规范化(这可能是一个合理的做法,因为否则会导致诸如字符串“相同”但比较不同之类的错误)。事实证明,这正是他们所做的(请参阅他们文章中的“扩展石墨烯簇”一节)
因此,当您在Swift中提供两个不同的字符时,它们将作为不同的字符传播到Obj-C,因此编码不同。这不是一个bug,只是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
您是否检查过URL是否已转义Röda.png
应该成为URL路径中的R%C3%B6da.png
。@code不同的是Firebase存储中实际的URL路径是Ro%CC%88da
那么我的选项是什么?据我所知,没有必要像回答“Code Different”那样再次这样做,因为您已经在“您的引擎盖下”这样做了。您的选择是选择一个Unicode规范化(我将答案编辑为显示D),并在所有操作中都坚持使用它。快速和客观-C处理事情的方式不同,所以使用哪一种方式很重要。复制和粘贴随机Unicode字符可能不起作用,因为它们将被不同的对待(很可能)。非常感谢:)这么多混乱,但现在它工作得很好。我只想说,这并不是问题的结束。对于分解的路径,这些是唯一没有缓存的图像。所以我想我得把它们去掉。