简体   繁体   English

Swift 3无法将符合协议的对象数组附加到该协议的集合

[英]Swift 3 unable to append array of objects, which conform to a protocol, to a collection of that protocol

Below I have pasted code which you should be able to paste into a Swift 3 playground and see the error. 下面我粘贴了你应该能够粘贴到Swift 3游乐场的代码并查看错误。

I have a protocol defined and create an empty array of that type. 我定义了一个协议,并创建一个该类型的空数组。 I then have a class which conforms to the protocol which I try to append to the array but I get the below error. 然后我有一个类符合我尝试附加到数组的协议,但我收到以下错误。

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'

Note that collection += myClassCollection returns the following error: 请注意,collection + = myClassCollection会返回以下错误:

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

This was working in earlier versions of Swift. 这在早期版本的Swift中有效。

The only solution I have found so far is to iterate and add each element to the new array like so: 到目前为止我找到的唯一解决方案是迭代并将每个元素添加到新数组中,如下所示:

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

Any help appreciated, thanks! 任何帮助表示感谢,谢谢!

EDIT 编辑

The solution as show below is: 如下所示的解决方案是:

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

The real issue is a misleading compiler error when you are missing "as [MyProtocol]" 当您缺少“as [MyProtocol]”时,真正的问题是误导性的编译器错误

The compiler error reads: 编译器错误如下:

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

This error causes users to remove contentsOf: from the code which then causes the error I first mentioned. 此错误导致用户从代码中删除contentsOf:然后导致我第一次提到的错误。

append(_ newElement: Element) appends a single element. append(_ newElement: Element)追加单个元素。 What you want is append(contentsOf newElements: C) . 你想要的是append(contentsOf newElements: C)

But you have to convert the [MyClass] array to [MyProtocol] explicitly: 但是你必须明确地 [MyClass]数组转换[MyProtocol]

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

As explained in Type conversion when using protocol in Swift , this wraps each array element into a box which holds "something that conforms to MyProtocol ", it is not just a reinterpretation of the array. 正如在Swift中使用协议时的类型转换中所解释的那样,这将每个数组元素包装成一个包含“符合MyProtocol东西”的框,它不仅仅是对数组的重新解释。

The compiler does this automatically for a single value (that is why 编译器会自动为单个值执行此操作(这就是原因

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

compiles) but not for an array. 编译)但不是数组。 In earlier Swift versions, you could not even cast an entire array with as [MyProtocol] , you had to cast each individual element. 在早期的Swift版本中,您甚至无法使用as [MyProtocol]整个数组,您必须转换每个单独的元素。

Your trying to append an array when collection is only expecting individual items. 当集合只期望单个项目时,您尝试附加数组。 For example, changing collection to this compiles: 例如,将集合更改为此编译:

var collection = [[MyProtocol]]()

here is a way you can go about adding two arrays together: 这里有一种方法可以将两个数组加在一起:

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM