Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a Swift Array conform to a Protocol

Let's say that certain items can appear in a Feed, so long as they implement the necessary properties defined by the Feedable protocol. Let's also say that the Photo object is feed-worthy:

extension Photo: Feedable { }

Is it possible to say that an Array of these photos might also be Feedable?

extension [Photo] : Feedable

Or do I always need some kind of wrapper object, such as a PhotoAlbum, to conform to Feedable?

Edit

To re-iterate, I was curious whether I can make only arrays of Photo objects Feedable. Not making Array of any content type Feedable, not making an array of Feedables itself Feedable (both of which are offered as solutions below if that's what you need).

In other words, a solution (which I doubt exists) would allow me to define a variable of type Feedable with the following outcomes:

var feedable: Feedable

//photo is feedable, so this is fine
feedable = Photo() //ok

//arrays of photos are feedable
let photo1 = Photo()
let photo2 = Photo()
feedable = [photo1, photo2]

//arrays of other things are not
feedable = ["no", "dice"] //nope

//even if the contents of an array are themselves Feedable, that's not sufficient. E.g. Video is Feedable, but Array of Videos is not.
let video1 = Video()
let video2 = Video()
feeble = video1 //fine
feedable = [video1, video2] //nope

Perhaps this gist (which doesn't compile of course) shows the intention more clearly.

like image 306
Ben Packard Avatar asked Mar 31 '16 02:03

Ben Packard


People also ask

Can you create instance of protocol in Swift?

You can not create an instance of protocol.

How do I add a protocol in Swift?

To create a protocol, use the protocol keyword followed by the name you want and defined by the curly braces. Protocols can be of 2 types: read-only/read-write. Read-only means you can only get the variable, but you cannot set it. Read-write means you can both set and get properties.

What is conform in Swift?

Any type that satisfies the requirements of a protocol is said to conform to that protocol. In addition to specifying requirements that conforming types must implement, you can extend a protocol to implement some of these requirements or to implement additional functionality that conforming types can take advantage of.

How many protocols can a Swift class adopt?

Swift 4 allows multiple protocols to be called at once with the help of protocol composition.


2 Answers

You can achieve your goal in this way:

Swift 4:

protocol Feedable {
    func foo()
}

extension String: Feedable {
    func foo() {    
    }
}

extension Array: Feedable where Element: Feedable {
    func foo() {    
    }
}
// or in more generic way to support Array, Set and other collection types
extension Collection: Feedable where Element: Feedable {
    func foo() {    
    }
}
like image 108
Vitalii Gozhenko Avatar answered Oct 29 '22 23:10

Vitalii Gozhenko


I think this is currently not possible. In my project I have the same issue with a ModelProducer.

protocol M: ModelType {}
protocol ModelProducerType {
    associatedtype M: ModelType
    var model: M? { get }
    func produce()
}

struct Test: ModelType {}
class TestProducer: ModelProducerType {
    var model: Test?
    func produce() {
        model = Test()
    }
}

I use ModelType as a ghost protocol. The problem is I cannot make a model producer that produces multiple ModelTypes, because of the same reason you discovered. The solution in this case was the following:

protocol M: ModelType {}
protocol ModelProducerType {
    associatedtype M: ModelType
    var model: [M] { get }
    func produce()
}

struct Test: ModelType {}
class TestProducer: ModelProducerType {
    var model: [Test] = []
    func produce() {
        model = [Test()]
    }
}

This is more flexible from the start. I get rid of the optional variable and single model producers just have one item in the array. Maybe you can use a similar approach.

like image 39
fruitcoder Avatar answered Oct 29 '22 22:10

fruitcoder