0

I am currently building a framework, and would like to conform SwiftUI Color to the RawRepresentable protocol only for iOS 14. I have the following code:

@available(iOS 14.0, *)
extension Color: RawRepresentable {
    public init?(rawValue: Data) {
        let uiColor = try? NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: rawValue)
        if let uiColor = uiColor {
            self = Color(uiColor)
        } else {
            return nil
        }
    }
    
    public var rawValue: Data {
        let uiColor = UIColor(self)
        return (try? NSKeyedArchiver.archivedData(withRootObject: uiColor, requiringSecureCoding: false)) ?? Data()
    }
}

However, this results in two similar errors:

Protocol 'RawRepresentable' requires 'init(rawValue:)' to be available in iOS 13.0.0 and newer
Protocol 'RawRepresentable' requires 'rawValue' to be available in iOS 13.0.0 and newer

Is this not possible? I am able to modify the code to:

extension Color: RawRepresentable {
    public init?(rawValue: Data) {
        let uiColor = try? NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: rawValue)
        if let uiColor = uiColor {
            self = Color(uiColor)
        } else {
            return nil
        }
    }

    public var rawValue: Data {
        if #available(iOS 14, *) {
            let uiColor = UIColor(self)
            return (try? NSKeyedArchiver.archivedData(withRootObject: uiColor, requiringSecureCoding: false)) ?? Data()
        }
        fatalError("do not use Color.rawValue on iOS 13")
    }
}

This fixes the error, but it seems wrong and hack-y to call a fatalError.

Thank you for any help!

YulkyTulky
  • 886
  • 1
  • 6
  • 20
  • Is your project's minimum deployment target version 13.0? – Sweeper Mar 16 '21 at 01:17
  • @Sweeper yes, it is a framework that targets iOS 13, but I want to add this for people using it on iOS 14 – YulkyTulky Mar 16 '21 at 01:18
  • @YulkyTulky your issue is not iOS14. Your issue is that there is no conventional way to convert from Color to UIColor in iOS 13. There is some hackie solutions but it is probably not worth using them. – Leo Dabus Mar 16 '21 at 02:17

1 Answers1

0

It seems Swift hasn't officially(or fully) supported this feature at the moment (Swift 5.3).

Your codes can be reduced to the following lines:

// for example: in project with minimum deploy target of iOS 13.0

struct A {}

protocol B {
  var val: Int { get }
}

@available(iOS 14.0, *)
extension A: B {   
  var val: Int {  // <- Compiler Error 
    0
  }
}

// The compiler says: Protocol 'B' requires 'val' to be available in iOS 13.0.0 and newer.

The related feature was discussed in Swift forums: https://forums.swift.org/t/availability-checking-for-protocol-conformances/42066.

And hopefully when it lands in Swift 5.4 ( https://github.com/apple/swift/blob/main/CHANGELOG.md#swift-54), your problem would be solved.

CrystDragon
  • 131
  • 1
  • 5