如何从数组中删除特定对象? [复制]
Posted
技术标签:
【中文标题】如何从数组中删除特定对象? [复制]【英文标题】:How to remove specific object from array? [duplicate] 【发布时间】:2017-04-08 14:55:04 【问题描述】:如果调用者传入一个 MyDelegate 类型的对象并且它在数组中,我想将它从数组中移除。
protocol MyDelegate
private var delegates = [MyDelegate]()
...
...
func removeDelegate(_ delegate: MyDelegate)
if let index = self.delegates.index(where: $0 == delegate )
log.trace("Removing delegate \(delegate)");
self.delegates.remove(at: index)
有没有更简单的方法来做到这一点?
此条件“ $0 == delegate ”导致错误“无法将类型 '(OptionalNilComparisonType) -> Bool' 的值转换为预期的参数类型 '( ) -> 布尔'"。我怎样才能解决这个问题?我试过添加?和 !但仍然没有完全理解 Swift 的可选概念。
我正在使用 Xcode 8.2.1 和 Swift 3(?)。
【问题讨论】:
代理应该是类的实例吗? 然后你可以定义一个“类协议”protocol MyDelegate: class
并使用身份运算符进行比较:index(where: $0 === delegate )
。
【参考方案1】:
有没有更简单的方法来做到这一点?
您可以在访问delegates
成员时忽略self
,并将index(where:)
调用的结果索引烘焙到对Optional
的map
方法的调用中:
func removeDelegate(_ delegate: MyDelegate)
delegates.index(where: $0 == delegate)
.map delegates.remove(at: $0)
如果没有找到这样的delegate
对象,则上面的表达式只会返回nil
(未捕获的结果)。
这个条件“
$0 == delegate
”给出导致错误, “无法将 '(OptionalNilComparisonType) -> Bool
' 类型的值转换为 预期的参数类型'() -> Bool
'”。我该如何解决这个问题?我试过了 添加?
和!
,但仍不能完全理解Swift 的可选 概念。
这是 Swift 中一种模糊错误消息的又一个例子。核心错误是MyDelegate
没有定义==
操作符(不符合Equatable
)。
但是,在您进行编辑后,您显示MyDelegate
是一个协议,因此如果您让它符合Equatable
,您将无法(因为它将包含Self
类型要求)使用@ 987654345@ 作为具体类型(仅作为泛型上的类型约束)。
如果您的具体委托对象是引用对象 (class
),并且您想在测试的意义上测试对象相等性是否都引用同一个对象(对象引用),您可以使用 @987654321 @ 可用于类实例。将MyDelegate
(在您的编辑后将其显示为协议)限制为仅类,
protocol MyDelegate: class /* ... */
并在上面的index(where:)
调用中测试ObjectIdentifier
的相等性:
func removeDelegate(_ delegate: MyDelegate)
delegates.index(where: ObjectIdentifier($0) == ObjectIdentifier(delegate) )
.map delegates.remove(at: $0)
查看ObjectIdentifier
的源代码,我们看到这将比较两个delegate
实例的底层原始ptr 值;来自swift/stdlib/public/core/ObjectIdentifier.swift:
public static func == (x: ObjectIdentifier, y: ObjectIdentifier) -> Bool return Bool(Builtin.cmp_eq_RawPointer(x._value, y._value))
正如@MartinR 在上述问题的 cmets 中所提到的,您也可以直接将 ===
标识运算符用于类实例,而不是通过 ObjectIdentifier
。
func removeDelegate(_ delegate: MyDelegate)
delegates.index(where: $0 === delegate )
.map delegates.remove(at: $0)
为了完整起见,我们可以通过查看swift/stdlib/public/core/Equatable.swift 来验证===
使用与==
运算符相同的Builtin
方法ObjectIdentifier
:
public func === (lhs: AnyObject?, rhs: AnyObject?) -> Bool switch (lhs, rhs) case let (l?, r?): return Bool(Builtin.cmp_eq_RawPointer( Builtin.bridgeToRawPointer(Builtin.castToUnknownObject(l)), Builtin.bridgeToRawPointer(Builtin.castToUnknownObject(r)) )) case (nil, nil): return true default: return false
【讨论】:
没有像 java 和 c# 中的默认对象相等的 Swift 概念吗? @RichAmberale 一般来说,没有。ObjectIdentifier
可用于类实例,因此如果您将 MyDelegate
(在编辑后将其显示为协议)限制为仅类,您可以测试 ObjectIdentifier
:s 的 $0
的相等性和上面的delegate
。这实质上是测试两者是否引用(对象引用)到同一个对象,而不是在某些预定义的==
运算符的意义上它们是否相等。
@MartinR 感谢您的链接!我在ObjectIdentifier
的源代码中看到了相同的评论部分,但正在四处寻找===
的实际实现(以验证它很可能调用相同的Builtin
方法)。
@RichAmberale 乐于提供帮助。这可能是个人喜好,但我自己在使用 Swift 时通常会避免使用 Obj-C 功能,所以我自己可能更喜欢 ===
/ ObjectIdentifier
而不是 NSObjectProtocol
:s isEqual(...)
方法。跨度>
感谢您的链接,我已经更新了其他答案。 - 我不知道。从github.com/apple/swift/blob/master/include/swift/AST/… 看来,似乎没有必要:“CastToUnknownObject 具有类型 (T) -> Builtin.UnknownObject。”和“BridgeToRawPointer 具有类型 (T) -> Builtin.RawPointer”——但我对“内置 SIL 操作”没有更深入的了解 :)以上是关于如何从数组中删除特定对象? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 ES6 扩展运算符和剩余运算符从数组或对象中删除特定元素