- 有没有更简单的方法来做到这一点?
您可以在访问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
}
}