1

I'm doing this for testing purposes. It helps with dependency injection.

I have an Objective-C library that I've imported into my Swift 3 project. One of the classes in the Objective-C library is defined this way:

@interface Auth : NSObject
@property (strong, readwrite) NSString *clientId;
@property (strong, readwrite) NSArray *scopes;
@end

In my Swift project, I want to define a protocol. The protocol should define 4 methods: 2 setters and 2 getters.

I want the protocol to be defined in a way so that I can reopen the Auth class in Swift with an extension and declare that Auth conforms to my protocol without putting anything in the body of the extension because the Objective-C class already conforms.

Here's my protocol:

protocol AuthProtocol {
    var clientID: String! { get set }
}

Here's the extension:

extension Auth: AuthProtocol {}

This works fine. Now I can treat Auth objects as AuthProtocols and have access to setting and getting their clientID property.

The problem arises when I try to make the protocol define the setter and getter for the scopes array. I believe NSArray is Array<AnyObject> in Swift. Here's what I tried:

protocol AuthProtocol {
    var clientID: String! { get set }
    var scopes: Array<AnyObject> { get set }
}

Now the line which reopens Auth for extension complains that

Type Auth does not conform to protocol AuthProtocol

Xcode suggests a solution when I click on the error, which adds this code to the body of the exention:

extension Auth: AuthProtocol {
    internal var scopes: Array<AnyObject> {
        get {
            <#code#>
        }
        set {
            <#code#>
        }
    }
}

This code now has an error on the internal line:

scopes used within its own type

How do I define AuthProtocol with a getter and setter for the scopes array so that this line:

extension Auth: AuthProtocol {}

Doesn't complain?

All this indicates to me that the problem has to do with the NSArray type.

pachun
  • 926
  • 2
  • 10
  • 26

1 Answers1

1

you can use Xcode to show you exactly what the protocol should be by using the "Generated Interface" command:

Generated Interface Prompt

this jumps you to the generated code:

open class Auth : NSObject {
    open var clientId: String!
    open var scopes: [Any]!
}

transform this generated class definition into the correct protocol definition:

protocol AuthProtocol {
    var clientId: String! { get set }
    var scopes: [Any]! { get set }
}

// doesn't complain anymore
extension Auth: AuthProtocol {}
Casey
  • 6,531
  • 24
  • 43
  • That's a great tool! Wish I'd known about it earlier. Thank you. Your solution works. I am having trouble getting xcode to generate interfaces for me, though. When I click `Generated Interface`, xcode shows me this http://i.imgur.com/w8BJqdw.png and just hangs there. I am using Xcode 8.1 on Mac OSX Sierra 10.12.1. Any thought on that? Thanks for your help. – pachun Oct 31 '16 at 22:06
  • sadly the view is pretty buggy. a lot of the time you need to restart Xcode or clear derived data before it'll work. – Casey Oct 31 '16 at 22:39
  • Good enough. That worked. I'd had Xcode open since last night. You've helped a bunch. Thanks Casey! – pachun Oct 31 '16 at 23:19