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 Feedable
s 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.
You can not create an instance of protocol.
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.
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.
Swift 4 allows multiple protocols to be called at once with the help of protocol composition.
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() {
}
}
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 ModelType
s, 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With