Search code examples
swiftmacosframeworksaccess-controltype-alias

Property cannot be declared open because its type uses an internal type (Typealias)


I have seen this trick to implement a platform-agnostic interface to (say) the image classes UIImage/NSImage:

#if os(iOS)
    import UIKit
    typealias Image = UIImage

#elseif os(macOS)
    import Cocoa
    typealias Image = NSImage

#endif

Now I am trying to adopt it in a framework. Let's say I have a class like this:

public final class MyClass {

    public var image: Image // < Compiler Error (see below)

    init?(imageURL: URL) {
        guard let image = Image(contentsOf: imageFileURL) else {
        return nil
        }
        self.image = image
    }
}

I get the error:

Property cannot be declared open because its type uses an internal type

Is the "internal type" refering to NSImage? How do I get around this?


Note: I don't think this a duplicate of this question: I am using a typealias, it is not evident what declaration I sould mark as "public".


Solution

  • In this specific case (when used within a framework target), making the typealias public will not solve the issue. You need to use the platform condition check also when declaring the image property, as follows:

    #if os(iOS)
        import UIKit
        typealias Image = UIImage
    #elseif os(macOS)
        import Cocoa
        typealias Image = NSImage
    #endif
    
    public final class MyClass {
    
        #if os(iOS)
            public var image: UIImage
        #elseif os(macOS)
            public var image: NSImage
        #endif
    
        init?(imageURL: URL) {
            guard let image = Image(contentsOf: imageFileURL) else {
                return nil
            }
            self.image = image
        }
    }
    

    The same applies for any public methods that use this type, whether it is a parameter or the return type of a function.

    Offtopic: Make sure to initialize this class on a background queue/thread to avoid blocking the main thread and freezing the UI while the image is being downloaded.