2016-12-12 6 views
3

Ниже я вставил код, который вы можете вставить в игровую площадку Swift 3 и увидеть ошибку.Swift 3 не может добавить массив объектов, соответствующих протоколу, в коллекцию этого протокола

У меня есть определенный протокол и создайте пустой массив этого типа. Тогда у меня есть класс, который соответствует протоколу, который я пытаюсь добавить к массиву, но получаю следующую ошибку.

protocol MyProtocol { 
    var text: String { get } 
} 

class MyClass: MyProtocol { 
    var text = "Hello" 
} 
var collection = [MyProtocol]() 
var myClassCollection = [MyClass(), MyClass()] 
collection.append(myClassCollection) 

argument type '[MyClass]' does not conform to expected type 'MyProtocol' 

Обратите внимание, что сбор + = myClassCollection возвращает следующую ошибку:

error: cannot convert value of type '[MyProtocol]' to expected argument type 'inout _' 

Это работает в более ранних версиях Swift.

Единственное решение, которое я нашел до сих пор является для перебора и добавить каждый элемент в новый массив так:

for item in myClassCollection { 
    collection.append(item) 
} 

Любая помощь приветствуется, спасибо!

EDIT

Решение, как показано ниже:

collection.append(contentsOf: myClassCollection as [MyProtocol]) 

Реальная проблема заключается в заблуждение ошибка компилятора, когда вам не хватает "как [MyProtocol]" ошибка

компилятор гласит:

error: extraneous argument label 'contentsOf:' in call 
collection.append(contentsOf: myClassCollection) 

Эта ошибка заставляет пользователей удалять contentsOf: из кода, который затем вызывает ошибку, о которой я впервые упоминал.

ответ

9

append(_ newElement: Element) присоединяет один элемент. Что вы хотите, это append(contentsOf newElements: C).

Но вы к преобразовать[MyClass] массив [MyProtocol] явно:

collection.append(contentsOf: myClassCollection as [MyProtocol]) 
// or: 
collection += myClassCollection as [MyProtocol] 

Как объяснены в Type conversion when using protocol in Swift, это компрессов каждого элемент массива в ящик, который держит «что-то, которое соответствует MyProtocol», это не просто переинтерпретация массива.

Компилятор делает это автоматически для одного значения (именно поэтому

for item in myClassCollection { 
    collection.append(item) 
} 

компилирует), но не для массива. В более ранних версиях Swift вы не могли даже отличить весь массив с as [MyProtocol], вам пришлось бросать каждый отдельный элемент.

+0

Это работает. collection.append (contentsOf: myClassCollection as [MyProtocol]) Ошибка вводит в заблуждение, если вы отсутствовали как [MyProtocol]. Ошибка читает посторонний аргумент label 'contentsOf:' при вызове. –

0

Ваша попытка добавить массив, когда коллекция ожидает только отдельные элементы. Например, изменение коллекции в этой компиляции:

var collection = [[MyProtocol]]() 

здесь, как вы можете идти о добавлении двух массивов вместе:

func merge<T: MyProtocol>(items: inout [T], with otherItems: inout [T]) -> [T] { 
return items + otherItems 

}

var myClassCollection = [MyClass(), MyClass()] 

var myClassCollection2 = [MyClass(), MyClass()] 

let combinedArray = merge(items: &myClassCollection, with: &myClassCollection2)