9

I'd like to do something like this, but can't get the syntax right or find anywhere on the web that gives the right way to write it:

protocol JSONDecodeable {
    static func withJSON(json: NSDictionary) -> Self?
}

protocol JSONCollectionElement: JSONDecodeable {
    static var key: String { get }
}

extension Array: JSONDecodeable where Element: JSONCollectionElement {
    static func withJSON(json: NSDictionary) -> Array? {
        var array: [Element]?
        if let elementJSON = json[Element.key] as? [NSDictionary] {
            array = [Element]()
            for dict in elementJSON {
                if let element = Element.withJSON(dict) {
                    array?.append(element)
                }
            }
        }
        return array
    }
}

So I want to conform Array to my protocol JSONDecodeable only when the elements of this array conform to JSONCollectionElement.

Is this possible? If so, what's the syntax?

1
  • Use generics something like Array<JSONCollectionElement> Commented Oct 19, 2015 at 16:43

4 Answers 4

5

This isn't possible yet in Swift. You can see the same thing happen in the standard library: Array doesn't gain Equatable conformance when it's declared with Equatable elements.

Sign up to request clarification or add additional context in comments.

1 Comment

@OrkhanAlikhanov still not possible. I am getting a Extension of type 'Array' with constraints cannot have an inheritance clause build time error from XCode.
1

Swift 4.2

In Swift 4.2 I was able to extend an array with the elements conforming to a protocol like this:

public extension Array where Element: CustomStringConvertible{
    public var customDescription: String{
        var description = ""
        for element in self{
            description += element.description + "\n"
        }

        return description
    }
}

2 Comments

Confirmed! Thank you! I had a quick look around for some info on this change in Swift 4.2, but couldn't find any. If anyone's got it please share!
And for optional array? Where Element must conform some protocol
1

I would suggest using a wrapper. For instance

struct ArrayContainer<T: Decodable>: Container {
    let array: [T]
}

Comments

1

I don't know if this is the best approach or if apple intended it to be used this way. I used this once and it worked well for me:

Say you have the following protocol

protocol MyProtocol {
    var test: Bool { get }
}

You can do this for Arrays

extension Array: MyProtocol where Element: MyProtocol {
    var test: Bool {
        return self.allSatisfy({ $0.test })
    }
}

And this for Dictionaries

extension Dictionary: MyProtocol where Value: MyProtocol {
    var test: Bool {
        return self.values.allSatisfy({ $0.test })
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.