1

当我通过获取请求从我的核心数据实体获取时,我收到了来自用户的崩溃报告。这是崩溃的样子:

SIGABRT:故障期间发生未处理的错误(NSCocoaErrorDomain,4864)并被抛出:错误域 = NSCocoaErrorDomain Code = 4864“无法读取数据,因为它的格式不正确。” UserInfo = {NSUnderlyingError = 0x2822582d0 {Error Domain = NSCocoaErrorDomain Code = 4864“键'NS.objects'的值是意外类'NSTextAlternatives(0x1ffa90890)[/System/Library/PrivateFrameworks/UIFoundation.framework]'。允许的类是' {("NSTextAttachment (0x1ff3bc730) [/System/Library/PrivateFrameworks/UIFoundation.framework]", "NSNumber (0x1ff35d8c8) [/System/Library/Frameworks/Foundation.framework]", "NSDictionary (0x1ff352418) [/System/Library /Frameworks/CoreFoundation.framework]”、“NSFont (0x1ff3bc3e8) [/System/Library/PrivateFrameworks/UIFoundation. NSAttributedString (0x1ff359c00) [/System/Library/Frameworks/Foundation.framework]", "NSURL (0x1ff352e18) [/System/Library/Frameworks/CoreFoundation.framework]", "NSSet (0x1ff352878) [/System/Library/Frameworks/ CoreFoundation.framework]”、“NSValue (0x1ff35d940) [/System/Library/Frameworks/Foundation.framework]”、“UIFont (0x1ff3bc780) [/System/Library/PrivateFrameworks/UIFoundation.framework]”、“NSString (0x1ff35d170) [ /System/Library/Frameworks/Foundation.framework]" )}'。" UserInfo={NSDebugDescription=键“NS.objects”的值属于意外类“NSTextAlternatives (0x1ffa90890) [/System/Library/PrivateFrameworks/UIFoundation.framework]”。允许的类是 '{("NSTextAttachment (0x1ff3bc730) [/System/Library/PrivateFrameworks/UIFoundation.

它崩溃的那一行NSFetchedResultsController是调用的performFetch时间:

7 CoreData 0x00000001b48c1a94 __43-[NSFetchedResultsController performFetch:]_block_invoke + 572 8 CoreData 0x00000001b487c01c developerSubmittedBlockToNSManagedObjectContextPerform + 152 9
CoreData 0x00000001b474eda4 -[NSManagedObjectContext performBlockAndWait:] + 204 10 CoreData 0x00000001b475cae4 -[NSFetchedResultsController _recursivePerformBlockAndWait:withContext:] + 144 11 CoreData 0x00000001b475cc1c -[NSFetchedResultsController performFetch :] + 220

这几乎肯定会发生,因为我最近将一个没有任何转换器集(因此基本上使用NSKeyedUnarchiveFromDataTransformerName)的 Transformable 属性更改为使用NSSecureUnarchiveFromDataTransformer. 该属性存储NSAttributedString来自UITextViewiOS 应用程序中的 a 。我还将“粗体”和“斜体”项目的 NSRange 保存为 NSValue。

我添加了以下变压器:

@objc(AttributedStringDictionaryTransformer)
final class AttributedStringDictionaryTransformer: NSSecureUnarchiveFromDataTransformer {

    override static var allowedTopLevelClasses: [AnyClass] {
        return super.allowedTopLevelClasses + [NSValue.self]
    }
}

这个“转换器”用于核心数据模型中的可转换属性。它将NSValue类添加到允许的类列表中。

当它说“键'NS.objects'的值是意外类'NSTextAlternatives”时......我不确定是什么NSTextAlternatives。我从来没有(明确地)在我的代码中使用过这个。任何想法可能来自哪里?

编辑:在进一步调查中,事实证明 NSAttributedString 可以附加各种对象,例如NSTextAlternativesand的对象,_UITextInputDictationResultMetadata如果用户在 UITextView 上使用听写,则可能存在这些对象。因此NSSecureUnarchiveFromDataTransformer,在技术上支持 NSAttributedString 的 ,实际上并没有正确支持它。这些类来自私有框架,所以不确定如何将它们添加到我的自定义转换器中。除了提交错误之外,不确定是否有解决方法。如果有,请告诉我。

4

1 回答 1

2

事实上,NSAttributedString这可能有点像文本系统相关的属性:文本视图中的各种操作会导致文本系统(CoreText、UIKit 等)使用元数据位注释范围以改善 iOS 体验,但这确实意味着任何给定NSAttributedString的结果都可能会带来一些您可能不知道的包袱。(从概念上讲,如果你斜视恰到好处,NSAttributedString它就像NSString一个关联的NSDictionary,它可以包含任何东西。)经常使用文本视图可能会导致这种情况,当你考虑粘贴来自其他属性字符串源的文本时,你最终会得到许多您不期望的属性值。这是按预期工作的文本系统。

不幸的是,这种设计与. 冲突NSSecureCoding,它要求您在解码之前列出您希望从存档中解码的类型。您正确地将对象NSAttributedStringNSValue对象列入白名单,并且NSAttributedString它本身将它知道的几种类型列入白名单(并且NSSecureUnarchiveFromDataTransformer还允许一些已知的 Foundation 类型),但问题是该字符串最终包含您也不知道的类型,并且没有将这些类型列入白名单 NSAttributedString解码将被阻止。

由于这些类型确实是私有的,因此您将很难找到文本系统可以抛出的所有可能的私有类型。最简单的方法是在编码方面:在对 进行编码之前NSAttributedString,遍历其所有属性范围并删除其类型不符合您的白名单标准的任何属性。在编码时使用与解码时相同的标准将允许您成功解码。

于 2021-03-05T14:25:27.440 回答