Xcode 15.2b Transformable Properties Crash App

This possibly seems like a regression but from iOS 17.1.0+, I'm having issues from Xcode 15.2 Beta &where when using a transformable property I'm getting a crash when trying to create a model container. This worked fine for me in Xcode 15.1 Beta when testing on iOS OS 17.0.1 and below.

I have a simple model where I'm trying to save a UIColor, below is an example of this model.

class Category: Codable {
        
        @Attribute(.unique)
        var title: String
        
        var items: [Item]?
        
        @Attribute(.transformable(by: ColorValueTransformer.self))
        var color: UIColor?

        init(title: String = "",
             color: UIColor) {
            self.title = title
            self.color = color
        }
        
        enum CodingKeys: String, CodingKey {
            case title
        }
        
        required init(from decoder: Decoder) throws { ... }
        
        func encode(to encoder: Encoder) throws { ... }
    }

Within my value transformer, I'm handling setting and getting the value.

final class ColorValueTransformer: ValueTransformer {

    static let name = NSValueTransformerName(rawValue: String(describing: ColorValueTransformer.self))

    override func transformedValue(_ value: Any?) -> Any? {
        guard let color = value as? UIColor else { return nil }
        do {
            let data = try NSKeyedArchiver.archivedData(withRootObject: color, requiringSecureCoding: true)
            return data
        } catch {
            return nil
        }
    }
    
    override func reverseTransformedValue(_ value: Any?) -> Any? {
        guard let data = value as? Data else { return nil }
        
        do {
            let color = try NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: data)
            return color
        } catch {
            return nil
        }
    }
    public static func register() {
        let transformer = ColorValueTransformer()
        ValueTransformer.setValueTransformer(transformer, forName: name)
    }
}

Then within my root app entry point, I register this transformer.

@main
struct ToDosApp: App {

......

    init() {
        ColorValueTransformer.register()
    }

......

Unfortunately in my custom container object I get a crash on this line


let container = try ModelContainer(for:  ....)

With an error of Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)

Like i said before previously this was working fine but now it's not... I have a feedback open also FB13471979 but it would be great if someone on the SwiftData team at Apple could look into this issue since it's a pretty big regression...

Here is an image of the crash I'm getting on app launch. A few things I've tried with no luck:

  • Removing Migration Plan, this has no effect and the issue is still there
  • Removing the model container when setting up the app, has no effect and the issue is still there

I'm convinced this is linked to using non-default types like Date with transformable. Since I've tested out a project where I have a Date as a transformable property, this doesn't crash. But if I use something from UIKit or my own custom type it crashes.

I’m seeing the same behavior on the released version of Xcode 15.2. It works just fine on the iOS 17.0 simulator, but 17.2 crashes on launch with "EXC_BAD_ACCESS".

hey it's actually quite easy you just have to override transformedValueClass() -> AnyClass as

    override class func transformedValueClass() -> AnyClass {
        return NSData.self
    }

and then simply return NSData from transformedValue(_ value: Any?) -> Any? as shown below

 override func transformedValue(_ value: Any?) -> Any? {
    guard let color = value as? UIColor else { return nil }
    do {
        let data = try NSKeyedArchiver.archivedData(withRootObject: color, requiringSecureCoding: true)
        return data as NSData
    } catch {
        return nil
    }
}

and while doing reverse transform you have to do one additional casting from NSData to Data then you good to go

override func reverseTransformedValue(_ value: Any?) -> Any? {
    guard let nsData = value as? NSData else { return nil }
    let data = nsData as Data
    do {
        let color = try NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: data)
        return color
    } catch {
        return nil
    }
}

Actually now I'm facing the problem described here https://developer.apple.com/forums/thread/743142

Try to add override class func transformedValueClass() to final class ColorValueTransformer. It works for me.

override class func transformedValueClass() -> AnyClass {
    return UIColor.self
}

https://developer.apple.com/documentation/foundation/valuetransformer

Xcode 15.2b Transformable Properties Crash App
 
 
Q