如何从数组中删除特定对象?

时间:2017-04-08 14:55:05

标签: arrays swift xcode8 optional

如果调用者传入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)
    }
}
  1. 是否有一种不那么复杂的方法呢?

  2. 此条件“{$ 0 == delegate}”导致错误“无法将类型的值'( OptionalNilComparisonType) - > Bool'转换为预期的参数类型'() - > Bool'“。我怎样才能解决这个问题?我试过添加?而且!但仍然没有完全理解Swift的可选概念。

  3. 我正在使用Xcode 8.2.1和Swift 3(?)。

1 个答案:

答案 0 :(得分:2)

  
      
  1. 这样做的方法有点复杂吗?
  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),并且您希望测试对象相等性,如果两者都引用相同的对象(对象引用),则可以使用Object​Identifier可用于类实例。约束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();
    }
}