UTF16 存储的字符串在从 CoreData 检索回来后不匹配
UTF16 stored string doesn't match once retrieved back from CoreData
所以我使用 CoreStore 在 CoreData 中保存一个字符串 identifier
。
该字符串可能包含一些瑞典语 UTF16 字符。从调试器控制台检查:
> po identifier
"/EXTERNAL/Gemensam RUN/FileCloud Test/Test folder åäö/Test with Swedish characters - åäö.xlsx"
保存回 CoreData 后立即:
>po record
<File: 0x281e140a0> (entity: File; id: 0xdcac6620f1e9eb63 <x-coredata://BA0168AF-92CE-4AC2-A934-1020E41C5C20/File/p615>; data: {
// ...
identifier = "filecloud.test@run.se@files.runcloud.se/EXTERNAL/Gemensam RUN/FileCloud Test/Test folder \U00e5\U00e4\U00f6/Test with Swedish characters - \U00e5\U00e4\U00f6.xlsx";
// ...
})
看起来 UTF16 字符串已存储为 UTF8 字符串。但仍然是有效的:
> po record.identifier == identifier
true
稍后尝试使用 UTF16 瑞典语 identifier
字符串检索 record
时出现问题,因为它不再匹配了。
CoreStore.fetchOne(From<Record>().where(\.identifier == identifier)) // Fails
如何将 identifier
转换为与存储的 CoreData 值匹配的表示形式?
更新
更奇怪的是,硬编码标识符确实成功了:
CoreStore.fetchOne(From<Record>().where(\.identifier == "filecloud.test@run.se@files.runcloud.se/EXTERNAL/Gemensam RUN/FileCloud Test/Test folder åäö/Test with Swedish characters - åäö.xlsx")) // Works
并且 identifer
和这个硬编码字符串匹配:
po identifier == "filecloud.test@run.se@files.runcloud.se/EXTERNAL/Gemensam RUN/FileCloud Test/Test folder åäö/Test with Swedish characters - åäö.xlsx"
true
但是使用 identifier
而不是硬编码的则不会。
更新 2
比较 identifier
的 .unicodeScalars
和硬编码字符串确实表明它们确实不同:
CoreData确实保存和return字符串完全一样。
尝试使用复杂字符检索值的问题是 CoreData(很可能是它背后的 SQLite)不认为我的句子相等,因为它们有不同 grapheme clusters。两个句子都是有效的,并且在 Swift 中比较相等,但在 CoreData 中不相等作为检索对象的值。
在 Swift 中似乎没有合适的方法来转换字素簇,所以我的解决方法是重新创建最初导致原始字素簇的过程。这涉及首先从字符串中创建一个 URL
,然后让 FileProvider
框架通过调用 persistentIdentifierForItem(at: url)!.rawValue
创建相同的字素簇。然后使用这个值来检索我保存的对象。
所以我使用 CoreStore 在 CoreData 中保存一个字符串 identifier
。
该字符串可能包含一些瑞典语 UTF16 字符。从调试器控制台检查:
> po identifier
"/EXTERNAL/Gemensam RUN/FileCloud Test/Test folder åäö/Test with Swedish characters - åäö.xlsx"
保存回 CoreData 后立即:
>po record
<File: 0x281e140a0> (entity: File; id: 0xdcac6620f1e9eb63 <x-coredata://BA0168AF-92CE-4AC2-A934-1020E41C5C20/File/p615>; data: {
// ...
identifier = "filecloud.test@run.se@files.runcloud.se/EXTERNAL/Gemensam RUN/FileCloud Test/Test folder \U00e5\U00e4\U00f6/Test with Swedish characters - \U00e5\U00e4\U00f6.xlsx";
// ...
})
看起来 UTF16 字符串已存储为 UTF8 字符串。但仍然是有效的:
> po record.identifier == identifier
true
稍后尝试使用 UTF16 瑞典语 identifier
字符串检索 record
时出现问题,因为它不再匹配了。
CoreStore.fetchOne(From<Record>().where(\.identifier == identifier)) // Fails
如何将 identifier
转换为与存储的 CoreData 值匹配的表示形式?
更新
更奇怪的是,硬编码标识符确实成功了:
CoreStore.fetchOne(From<Record>().where(\.identifier == "filecloud.test@run.se@files.runcloud.se/EXTERNAL/Gemensam RUN/FileCloud Test/Test folder åäö/Test with Swedish characters - åäö.xlsx")) // Works
并且 identifer
和这个硬编码字符串匹配:
po identifier == "filecloud.test@run.se@files.runcloud.se/EXTERNAL/Gemensam RUN/FileCloud Test/Test folder åäö/Test with Swedish characters - åäö.xlsx"
true
但是使用 identifier
而不是硬编码的则不会。
更新 2
比较 identifier
的 .unicodeScalars
和硬编码字符串确实表明它们确实不同:
CoreData确实保存和return字符串完全一样。
尝试使用复杂字符检索值的问题是 CoreData(很可能是它背后的 SQLite)不认为我的句子相等,因为它们有不同 grapheme clusters。两个句子都是有效的,并且在 Swift 中比较相等,但在 CoreData 中不相等作为检索对象的值。
在 Swift 中似乎没有合适的方法来转换字素簇,所以我的解决方法是重新创建最初导致原始字素簇的过程。这涉及首先从字符串中创建一个 URL
,然后让 FileProvider
框架通过调用 persistentIdentifierForItem(at: url)!.rawValue
创建相同的字素簇。然后使用这个值来检索我保存的对象。