redent84
redent84

Reputation: 19239

Extension property conflicting subclass declaration in Swift

I have a Swift 2 project in XCode 7.3 where I use two different third party frameworks.

'FrameworkA' declares a public UIView extension declaring cornerRadius property like this:

extension UIView {
    var cornerRadius: CGFloat {
        get { return self.layer.cornerRadius }
        set(cornerRadius) {
            self.layer.masksToBounds = true
            self.layer.cornerRadius = cornerRadius
        }
    }
}

'FrameworkB' declares a UIView subclass with a cornerRadius property:

class TagView: UIView {
    var cornerRadius: CGFloat = 0 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = cornerRadius > 0
        }
    }
}

Both frameworks compile perfectly fine as they don't know each other. However, when trying to use the 'FrameworkB' property in my code:

let view = UIView()
view.cornerRadius = 10    // FrameworkA: Ok

let tagView = TagView(title: "")
tagView.cornerRadius = 10    // Compilation error
(tagView as UIView).cornerRadius = 10    // FrameworkA: Ok

It fails with the error:

Ambiguous use of 'cornerRadius'

I'm able to call the 'FrameworkA' extension property type-casting to UIView, but I am not able to call the 'FrameworkB' class property even if I don't import 'FrameworkA' in this file. As soon as I import 'FrameworkA' somewhere in the project, it starts failing.

Is there any way to explicitly telling the compiler to use 'FrameworkB' method or avoid importing 'FrameworkA' in a Swift file?

Edit: To reproduce it you can use Wakup and TagListView pods (FrameworkA and FrameworkB respectively) and try to execute the code above.

Upvotes: 4

Views: 1435

Answers (2)

Alain T.
Alain T.

Reputation: 42143

If you're using these different classes in unrelated places, perhaps you could import specific symbols only in source files that actually need them.

 import class FrameworkA.TagView

Upvotes: 0

redent84
redent84

Reputation: 19239

My current solution is to create a dynamic framework target 'ProxyFramework' in the same project. I add the 'FrameworkB' dependency using Cocoapods and declare a new property that doesn't conflicts with the extension method declared in 'FrameworkA':

public extension TagList {
    public dynamic var cornerRadius_: CGFloat {
        get { return cornerRadius }
        set { cornerRadius = newValue }
    }
}

In my application target, I add the newly created framework target to 'Target Dependencies', so I'm now able to use the 'FrameworkB' property through this proxy framework:

let view = UIView()
view.cornerRadius = 10    // FrameworkA: Ok

let tagView = TagView(title: "")
tagView.cornerRadius_ = 10    // ProxyFramework -> FrameworkB: Ok
(tagView as UIView).cornerRadius = 10    // FrameworkA: Ok

I'd love to see a cleaner solution.

Upvotes: 1

Related Questions