Firebase或Swift没有检测到变音符号

我在Firebase数据库/存储中发现了一些最古怪的东西。 问题是,我不知道Firebase或Swift是否没有检测到变音器,例如(ä,ö,ü)。

我使用Firebase做了一些简单的事情,例如将图片上传到Firebase存储,然后将其下载到tableview 。 例如,我的一些.png文件在标题中有元音变音( Röda.png )。

所以现在如果我下载它们,问题就会出现。 只有当我的下载urlnil ,如果文件名包含我所说的变音符号。

所以我尝试了一些替代方法,如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的长度是2str2的长度是1 ,而在Swift中我假设两者的答案都是1 )。

苹果必须在Swift比较之前对string进行规范化(可能是一个合理的做法,否则会导致像这样的错误,即string“相同”,但是比较不同)。 原来,这正是他们所做的(参见他们的文档的“扩展字形集群”部分)。

所以,当你在Swift中提供两个不同的字符时,它们被传播到Obj-C作为不同的字符,因此编码方式不同。 不是一个错误,只是Swift的Stringtypes和Obj-C的NSStringtypes之间的许多区别之一。 如果有疑问,请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