如果调用者传入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'转换为预期的参数类型'() - > Bool'“。我怎样才能解决这个问题?我试过添加?而且!但仍然没有完全理解Swift的可选概念。
我正在使用Xcode 8.2.1和Swift 3(?)。
答案 0 :(得分:2)
- 这样做的方法有点复杂吗?
醇>
您可以在访问self
成员时忽略delegates
,并将index(where:)
来电的结果索引烘焙到对map
的调用中} Optional
的方法:
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
} type requirement)使用MyDelegate
作为具体类型(仅作为例如通用的类型约束)。
如果您的具体委托对象是引用对象(class
),并且您希望测试对象相等性,如果两者都引用相同的对象(对象引用),则可以使用ObjectIdentifier
可用于类实例。约束MyDelegate
(在您将其显示为协议之后的编辑)仅限于类
protocol MyDelegate: class { /* ... */ }
并测试上面ObjectIdentifier
调用中index(where:)
的相等性:
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在上述问题的评论中提到的那样,您也可以直接使用ObjectIdentifier
身份运算符来处理类实例,而不是通过===
。
func removeDelegate(_ delegate: MyDelegate) {
delegates.index(where: { $0 === delegate })
.map { delegates.remove(at: $0) }
}
为了完整起见,我们可以通过查看{{3}来验证===
是否使用与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
}
}
}:
class SamplePage { public IWebDriver Driver; private By waitForLocator = By.Id("sampleId"); // please put the variable declarations in alphabetical order private By sampleElementLocator = By.Id("sampleId"); public SamplePage(IWebDriver webDriver) { this.Driver = webDriver; // wait for page to finish loading new WebDriverWait(Driver, TimeSpan.FromSeconds(10)).Until(ExpectedConditions.PresenceOfAllElementsLocatedBy(waitForLocator)); // see if we're on the right page if (!Driver.Url.Contains("samplePage.jsp")) { throw new InvalidOperationException("This is not the Sample page. Current URL: " + Driver.Url); } } public void ClickSampleElement() { Driver.FindElement(sampleElementLocator).Click(); } }