当我创建一个数组并向其中添加一些对象(引用类型(时:
let myArray = [UILabel(), UIButton(), UIView()]
我可以通过复制数组的所有项目来创建数组的副本:
let myCopiedArray = myArray.map{ $0.copy() }
当我修改myCopiedArray
中的任何项目时,它不会对原始myArray
产生任何影响。
由于map(_:)
函数总是有点难以阅读,我想将此复制操作包装到一个具有更具表现力的名称的单独函数中:
extension Array where Element: AnyObject {
/// Creates a new array that contains a copy of each of the receiver's items.
func newArrayByCopyingItems() -> Array {
return map{ $0.copy() }
}
}
这不是工作,编译器也无助于我理解我做错了什么:
Cannot convert value of type '(_) -> _' to expected argument type '(_) -> _'
有没有人可以给我更有用的建议? ;)
(我怀疑编译器无法以某种方式推断参数AnyObject
的类型$0
尽管它在扩展声明中显式定义。
AnyObject
没有为其声明copy()
方法。
我将解释我用来提出答案的步骤。也许这会有所帮助。
开头:let copiedArray = myArray.map { $0.copy() }
我首先寻找了一个声明了copy()
方法的协议,但我没有找到。我发现使用该方法的最通用类是 NSObject,所以看起来我必须使用它。然后我通过单击选项查看copiedArray
的类型。我发现这是一个[Any]
.所以这意味着我最终会得到:
extension Array where Element: NSObject {
func newArrayByCopyingItems() -> [Any] {
return self.map { $0.copy() }
}
}
不是很愉快,但就是这样。我可以通过创建自己的协议使其更有用。这样做的好处是我可以维护复制数组的类型。缺点是我必须确保我想与之一起使用的所有类型都符合扩展......
使用下面的代码,我现在可以做到:
let myArray = [UILabel(), UIButton(), UIView()]
let myCopiedArray = myArray.newArrayByCopyingItems()
myCopiedArray
将是一组 UIViews,而无需我投射它们。
protocol Copying {
associatedtype Copied
func makeCopy() -> Copied
}
extension Array where Element: Copying, Element.Copied == Element {
func newArrayByCopyingItems() -> [Element] {
return self.map { $0.makeCopy() }
}
}
extension UIView: Copying {
func makeCopy() -> UIView {
return self.copy() as! Copied
}
}