微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

核心数据中的 NSSecureCoding 崩溃

如何解决核心数据中的 NSSecureCoding 崩溃

当我使用提取请求从我的 Core Data 实体中提取时,我收到了来自用户的崩溃报告。这是崩溃的样子:

SIGABRT:未处理的错误 (NSCocoaErrorDomain,4864) 发生在 错误并被抛出:错误域=NSCocoaErrorDomain 代码=4864 “无法读取数据,因为它的格式不正确。” UserInfo={NSUnderlyingError=0x2822582d0 {错误 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.framework]","NSGlyphInfo (0x1ffa906d8) [/System/Library/PrivateFrameworks/UIFoundation.framework]","NSArray (0x1ff352238) [/System/Library/Frameworks/CoreFoundation.framework]","NSParagraphStyle (0x1ff3bbec0) [/System/Library/PrivateFrameworks/UIFoundation.framework]","NSUUID (0x1ff35f290) [/System/Library/Frameworks/Foundation.framework]","NSDate (0x1ff3522b0) [/System/Library/Frameworks/CoreFoundation.framework]","NSColor (0x1ff3a67a8) [/System/Library/PrivateFrameworks/UIKitCore.framework]","NSNull (0x1ff3527b0) [/System/Library/Frameworks/CoreFoundation.framework]","NSData (0x1ff3519c8) [/System/Library/Frameworks/CoreFoundation.framework]","UIColor (0x1ff3a6a78) [/System/Library/PrivateFrameworks/UIKitCore.framework]","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=key 'NS.objects' 的值是 意外的类 'NSTextAlternatives (0x1ffa90890) [/System/Library/PrivateFrameworks/UIFoundation.framework]'。允许 类是 '{("NSTextAttachment (0x1ff3bc730) [/System/Library/PrivateFrameworks/UIFoundation.framework]","Nsstring (0x1ff35d170) [/System/Library/Frameworks/Foundation.framework]" )}'.}}}崩溃版本 5.6.8 (5.6.9)1 user1 报告

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

7 核心数据 0x00000001b48c1a94 __43-[NSFetchedResultsController performFetch:]_block_invoke + 572 8 CoreData 0x00000001b487c01c developerSubmittedBlockToNSManagedobjectContextPerform + 152 9
核心数据 0x00000001b474eda4 -[NSManagedobjectContext performBlockAndWait:] + 204 10 CoreData 0x00000001b475cae4 -[NSFetchedResultsController _recursivePerformBlockAndWait:withContext:] + 144 11 CoreData 0x00000001b475cc1c -[NSFetchedResultsController performFetch:] + 220

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

添加了以下转换器:

@objc(AttributedStringDictionaryTransformer)
final class AttributedStringDictionaryTransformer: NSSecureUnarchiveFromDataTransformer {

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

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

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

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

解决方法

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。