1

Let's take a look at a theoretical example:

protocol Text {} //Protocol in the external Framework
extension String: Text {} //Implementing the protocol in the app  

protocol A { //Another protocol in the external Framework
    var text: Text { get }
}

class B { //Existing class in the app, I'd like to pass where Framework expects protocol A
    let text: String = ""
}

I tried doing this:

//ERROR: Type 'B' does not conform to protocol 'A'
extension B: A {}

Trying to use solve function in XCode does the following:

extension B: A {
    //ERROR: Invalid redeclaration of 'text'
    var text: Text {
        ...
    }
}

What else can I do? I'd like to avoid changing variable name in the class B, as it's already wideley used and would be a big refactor.

What I ended up with is some kind of a wrapper:

//1) Wrapper
class C: A {
    let b: B

    var text: Text {
        return b.text
    }

    init(b: B) {
        self.b = b
    }
}

extension B {
   var wrapper: A {
      return C(b: self)
   }
}

and now everywhere where external Framwork expects type A, instead of passing b I pass b.wrapper.

Is there any other way to achieve same thing? Creating wrapper doesn't seem like an ideal solution to me.

  • So the original `text` in `B` and the `text` needed in the conforming of `A` are different values right? – Papershine Nov 20 '19 at 11:40
  • Yes, in `B` we have a variable of type String, which conforms to `Text`, and in protocol `A` we have variable directly of type `Text`. I would expect this to work fine, as basically both `text` variables have conformance to `Text` protocol, only direct type is different. – Mariusz Wiśniewski Nov 20 '19 at 11:43
  • `let` is a problem, make value in class B `var` – Lu_ Nov 20 '19 at 11:52
  • @MariuszWiśniewski You could just define text as `let text: Text = ""`? – Papershine Nov 20 '19 at 11:55
  • @paper1111 I could, but this would hide all functionality of a String from user of class B, which is not ideal (it's widely used in the app right now) (or I would end up. with casting and dealing with optionals if I tried in other placees casting `(Text as? String)`) – Mariusz Wiśniewski Nov 20 '19 at 12:07
  • 1
    https://stackoverflow.com/questions/42561685/why-cant-a-get-only-property-requirement-in-a-protocol-be-satisfied-by-a-proper Does this answer? It seems that there is just no other way and it is a limitation of Swift. This can be done if `A` has an `associatedtype` only. – Papershine Nov 20 '19 at 12:31
  • 1
    @paper1111 Thanks, link to the other question and to the bug report https://bugs.swift.org/browse/SR-522 helped -- it's a shame this is still not supported by Swift – Mariusz Wiśniewski Nov 20 '19 at 13:38

0 Answers0