Array of Protocol instances won't work with contains method

1k views Asked by At

I have a protocol that I am using to define what makes up the content of a note. A note can have many different content types, so a protocol seemed like the best way to go.

public protocol Content {
    var contentType: String { get }
}

I then have an implementation of that protocol

public class PlainTextContent: Content {
    public var contentType: String {
        return "Plain Text"
    }

    public var text: String = String()

    public init(content: String) {
        self.text = content
    }
}

This is a simplified example of the two objects. Next I have a Note class that holds an Array of Content protocol implementations.

public class Note {
    public private(set) var noteContent: [Content] = []
    public var title: String = String()
    public var date: NSDate

    public init() {
        self.date = NSDate()
    }

    func insertContent(content: Content) -> Bool {
        if contains(self.noteContent, content) {
            return false
        }

        self.noteContent.append(content)
        return true
    }

    func deleteContent(content: Content) -> Bool {
        return false
    }
}

The problem that I have is that when I do

if contains(self.noteContent, content) {}

the compiler tells me

Note.swift:21:12: Cannot find an overload for 'contains' that accepts an argument list of type '([Content], Content)'

I have looked a few examples on Stackoverflow and I'm doing as they show. Is there an issue with how I am defining my protocol in order for me to use it as an array and the associated global functions?

Edit

I have also tried to make the protocol inherit from Equatable, at which point I get the following compiler error

Protocol 'Content' can only be used as a generic constraint because it has Self or associated type requirements

I'm a little confused as to how I can perform equality checks against the array of protocols. Is that something that Swift doesn't support? I'm coming from a C# background, so not sure how Swift handles protocols fully.

1

There are 1 answers

5
Matteo Piombo On

You might use map in order to unbox your equatable value:

func insertContent(content: Content) -> Bool {
        if contains(self.noteContent.map({$0.contentType}), content.contentType) {
            return false
        }

        self.noteContent.append(content)
        return true
    }

Hope this helps.