2016-08-18 56 views
2

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

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

所以现在的问题是如果我下载它们。我的下载url的唯一时间是nil是如果文件名包含我在说的变音符号。

所以我尝试了一些替代品,如HTMLö - ö。但是这不起作用。你们可以给我一些建议吗?我不能使用ö - oü - u

这是代码的时候urlnil试图设置一些值火力地堡时:

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) 
+1

您是否检查过网址已被转义? 'Röda.png'应该在URL路径中变成'R%C3%B6da.png'。 –

+0

@Code不同实际在Firebase存储中的网址路径是'Ro%CC%88da' –

回答

2

Horray对Unicode的!

简短的回答是,不,我们其实并没有在这里做任何特别的事情。基本上所有我们在引擎盖下做的是:

// This is the list at https://cloud.google.com/storage/docs/json_api/ without the & because query parameters 
NSString *const kGCSObjectAllowedCharacterSet = 
    @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-._~!$'()*+,;=:@"; 

- (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的长度为2,而0123'的长度为,对象C ,而在Swift中,我假设两者的答案都是1)。

Apple在Swift比较之前必须正常化字符串(可能是一个合理的事情,否则会导致像this这样的字符串“相同”但比较不同的错误)。原来,这正是他们所做的(请参阅他们的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 
+0

那么我的选择是什么?据我所知,没有必要像“代码不同”一样再次做同样的事情,因为你已经在“在你的引擎盖下”做了。 –

+0

你的选择是选择一个Unicode标准化(我编辑我的答案以显示D),并坚持所有操作。 Swift和Objective-C以不同的方式处理事情,所以你使用哪一个很重要。复制和粘贴随机的Unicode字符可能不起作用,因为它们会被区别对待(很可能)。 –

+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 

我猜测是谷歌/ Firebase选择了分解形式,而苹果更倾向于在其文本输入系统中使用另一种形式。您可以将文件名转换为其分解形式以与Firebase匹配:

let str3 = str2.decomposedStringWithCanonicalMapping 
print(str3.stringByAddingPercentEncodingWithAllowedCharacters(.URLPathAllowedCharacterSet())) 

// o%CC%88 

这与ASCII范围字符无关。 Unicode可能非常混乱。

参考文献: