-[NSKeyedUnarchiver decodeObjectForKey:]: value for key (NSAttributes) contains too many nested (NSDictionary)s 해결

서론

나는 아래와 같이 iOS 앱 개발할 때 UI 컴포넌트 실시간 편집, 핫 리로딩 등 도움이 되는 macOS 앱을 만들고 있었다.

그런데 프로퍼티들이 많이 생기다 보니까 제목과 같은 에러가 발생하기 시작했다.

본론

찾아보니 NSSecureCoding 을 사용하는 경우에만 발생하는 오류인데.. NSCoding은 문제가 없다고 한다..?

하지만 일부 제약 조건때문에 (다형성을 가진 객체들을 decode 해야함) 꼼수를 사용하기로 했다.

기존에 property들을 전부 Data 형태로 encode하고 받는 쪽에서 Data를 decode한 뒤 property들로 설정해주는 걸로..

Baseclass 에서 아래와 같이 본인에게 필요한 직렬화 함수와 함께 필수 initializer를 만든다.

import Foundation

class ElementInspectorDataSource: NSObject, NSSecureCoding {
    class var supportsSecureCoding: Bool { true }

    ...

    var properties: [String: Any] = [:]
    var data: Data = .init()

    func encode(with coder: NSCoder) {
        do {
            self.data = try serialize(properties)
        } catch {
            logger.error("Failed to serialize the properties DataSource: \(error)")
        }
    }

    func serialize(_ dict: [String: Any]) throws -> Data {
        return try JSONSerialization.data(withJSONObject: dict)
    }
}

그리고 자식 클래스에서는 그냥 아래와 같이 properties를 override해서 사용하면 끝.

class UILabelAttributeDataSource: ElementInspectorDataSource, NSSecureCodingKeySupportable {
    class override var supportsSecureCoding: Bool { true }

    override var properties: [String: Any] {
        get {
            guard let label else { return [:] }
            
            ⋯
        }
        set { }
    }
}

결론

애플이 NSCoding, NSSecureCoding 문서를 조금 더 추가해줬으면 좋겠다.

정보가 없어도 너무 없다..