2016-08-18 52 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可能非常混亂。

參考文獻: