MarkerData icon indicating copy to clipboard operation
MarkerData copied to clipboard

Update Codebase for Xcode 26

Open IAmVigneswaran opened this issue 3 months ago • 2 comments

@milanvarady For our build I have switched from Xcode 16.4 to Xcode 26.

It was able to build without errors. However, we are getting the following warnings.

Warning: extension declares a conformance of imported type 'AnyRole' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'DAWFileKit' introduce this conformance in the future
extension FinalCutPro.FCPXML.AnyRole: Codable {}
^
Warning: extension declares a conformance of imported type 'DeltaEFormula' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'DominantColors' introduce this conformance in the future
extension DeltaEFormula: Codable {}
^
Warning: extension declares a conformance of imported type 'ExportFolderFormat' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension ExportFolderFormat: Codable {
^
Warning: extension declares a conformance of imported type 'MarkerIDMode' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension MarkerIDMode: Codable {
^
Warning: extension declares a conformance of imported type 'AlignHorizontal' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension MarkerLabelProperties.AlignHorizontal: Codable {
^
Warning: extension declares a conformance of imported type 'AlignVertical' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension MarkerLabelProperties.AlignVertical: Codable {
^
Warning: extension declares a conformance of imported type 'ExportField' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension ExportField: Codable {}
^
Warning: extension declares a conformance of imported type 'MarkersSource' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension MarkersSource: Codable {}
^
Warning: extension declares a conformance of imported type 'ExportProfileFormat' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension ExportProfileFormat: Codable {
^
Warning: extension declares a conformance of imported type 'Color' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'SwiftUICore' introduce this conformance in the future
extension Color: Codable {
^
Warning: extension declares a conformance of imported type 'ExportFolderFormat' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension ExportFolderFormat: Codable {
^
Warning: extension declares a conformance of imported type 'MarkerIDMode' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension MarkerIDMode: Codable {
^
Warning: extension declares a conformance of imported type 'AlignHorizontal' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension MarkerLabelProperties.AlignHorizontal: Codable {
^
Warning: extension declares a conformance of imported type 'AlignVertical' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension MarkerLabelProperties.AlignVertical: Codable {
^
Warning: extension declares a conformance of imported type 'ExportField' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension ExportField: Codable {}
^
Warning: extension declares a conformance of imported type 'MarkersSource' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension MarkersSource: Codable {}
^
Warning: extension declares a conformance of imported type 'ExportProfileFormat' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'MarkersExtractor' introduce this conformance in the future
extension ExportProfileFormat: Codable {
^
Warning: extension declares a conformance of imported type 'Color' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'SwiftUICore' introduce this conformance in the future
extension Color: Codable {
^
Warning: extension declares a conformance of imported type 'DeltaEFormula' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'DominantColors' introduce this conformance in the future
extension DeltaEFormula: Codable {}
^
Warning: extension declares a conformance of imported type 'AnyRole' to imported protocols 'Decodable', 'Encodable'; this will not behave correctly if the owners of 'DAWFileKit' introduce this conformance in the future
extension FinalCutPro.FCPXML.AnyRole: Codable {}
^

@orchetect The warning indicates about conformance for both MarkersExtractor and DAWFileKit?

IAmVigneswaran avatar Sep 19 '25 00:09 IAmVigneswaran

These are all being emitted from the Marker Data codebase.

These warnings show up when you add a conformance to a type you "don't own" - meaning the type is defined in a module outside of your app but you are adding a protocol conformance to it.

In this case, they are all custom Codable implementations. They're fine to ignore, but if in future those types gain their own Codable implementation in the framework/package where they are defined, then their implementation will replace yours automatically.

This is fine as long as you are not storing the encoded data persistently (on disk, in UserDefaults, etc.). If the types are only being encoded and decoded ephemerally (only encoded in memory while the app is running, for example to facilitate copy & paste or drag & drop within the app) then you don't have to worry about it. But if you're storing the encoded data somewhere, then it's a bit of an issue. The hypothetical problem is: you store the data somewhere, then a 3rd-party module adds Codable conformance for one or more of these types, then you recompile Marker Data and run it, the encoding format may be different and the app may fail to decode the user's stored data.

One way to ensure your custom Codable implementation will always be used is to create wrapper objects only for the purpose of encoding or decoding the types. You make the wrapper Codable instead of making the actual type Codable. Unfortunately it involves requiring custom implementation to avoid the wrapper itself being encoded (which would happen if you allow Codable to synthesize its implementation on the wrapper), so as to treat the wrapper as being a stand-in for the type. For example, for ExportProfileFormat which is a String enum:

extension ExportProfileFormat {
    public struct CodableWrapper: Codable {
        public let wrapped: ExportProfileFormat
        
        public init(wrapped: ExportProfileFormat) {
            self.wrapped = wrapped
        }
        
        public init(from decoder: any Decoder) throws {
            let c = try decoder.singleValueContainer()
            let rawValue = try c.decode(ExportProfileFormat.RawValue.self) // a.k.a. String.self
            guard let value = ExportProfileFormat(rawValue: rawValue) else { throw CocoaError(.coderInvalidValue) }
            wrapped = value
        }
        
        public func encode(to encoder: any Encoder) throws {
            var c = encoder.singleValueContainer()
            try c.encode(wrapped.rawValue)
        }
    }
}

Then when you encode/decode, use ExportProfileFormat.CodableWrapper in place of the ExportProfileFormat instance.

let profile: ExportProfileFormat = .airtable
let encoder = JSONEncoder()
let wrapper = ExportProfileFormat.CodableWrapper(wrapped: profile)
let encoded = try encoder.encode(wrapper) // single string value "airtable"

let decoder = JSONDecoder()
let wrapper = try decoder.decode(ExportProfileFormat.CodableWrapper.self, from: encoded)
let profile: ExportProfileFormat = wrapper.wrapped // .airtable case

orchetect avatar Sep 19 '25 01:09 orchetect

Thanks for the insights!

IAmVigneswaran avatar Sep 19 '25 01:09 IAmVigneswaran