使用可选返回值访问UIDynamicItemBehavior中的项目

时间:2014-07-18 14:06:53

标签: objective-c swift

我想在Swift中重写这个Objective-C方法。 我试图找到最佳方法。

- (UIDynamicItemBehavior*) itemBehaviourForView:(UIView*)view
{
    for (UIDynamicItemBehavior* behaviour in _animator.behaviors)
    {
        if (behaviour.class == [UIDynamicItemBehavior class] && [behaviour.items firstObject] == view)
        {
            return behaviour;
        }
    }
    return nil;
}
我写了类似的东西:

func itemBehaviorForView(view :UIView)->UIDynamicItemBehavior
{
    for dynamicItemBehavior in animator.behaviors
    {
        if dynamicItemBehavior is UIDynamicItemBehavior  && dynamicItemBehavior.items.firstObject == view
        {
            return dynamicItemBehavior as UIDynamicItemBehavior
        }

    }
    return nil
}

我看到两个问题:

  1. dynamicItemBehavior.items.firstObject不是Array,因此没有firstObject方法

  2. 我无法退回nil

  3. 我该怎么办?

3 个答案:

答案 0 :(得分:1)

如果函数有可能返回nil,则函数的返回类型必须是可选。在您的情况下,将函数声明为:

func itemBehaviorForView (view:UIView) -> UIDynamicItemBehavior?

UIDynamicItemBehavior的文档将items声明为数组:

var items: [AnyObject]! { get }

因此您将使用数组下标表示法引用第一个对象:

dynamicItemBehavior.items[0]

当然,items可能是空的。要在惯用的Swift中使用:

    if dynamicItemBehavior is UIDynamicItemBehavior {
      if let firstView = dynamicItemBehavior.items?[0] {
        if firstView == view {
          return dynamicItemBehavior as UIDynamicItemBehavior
        }
      }
    }

如果if let <var>的结果不是<var>...items?的使用将绑定nil

答案 1 :(得分:0)

转换后的更多功能方法:

let r = (animator.behaviors.filter { $0 is UIDynamicItemBehavior } as [UIDynamicItemBehavior])
    .filter({ $0.items?[0] === view })

return r.count > 0 ? r[0] : nil

如果我们bridgeToObjectiveC()结果可以利用firstObject属性,我们甚至可以将其缩小为一行回报:

return (animator.behaviors.filter { $0 is UIDynamicItemBehavior } as [UIDynamicItemBehavior])
    .filter({ $0.items?[0] === view }).bridgeToObjectiveC().firstObject as? UIDynamicItemBehavior

<强>说明:

Objective-C ==将Swift中的引用与===进行比较。

我知道最初的Objective-C算法非常渴望并且在找到匹配后立即返回。展示功能方法的表现力。

答案 2 :(得分:0)

我认为Keenle使用功能风格走在正确的轨道上。但这不是filter的工作,这是find的工作。它会在遇到的第一场比赛中提早停止。不幸的是,Swift目前没有为我们实现find(与filter不同),但我们可以添加扩展名!

与此处的其他答案不同,我不知道动画师或行为的类型。我假设行为是NSArray,如果这个假设不正确,请告诉我。

extension NSArray {
    func find(predicate: (AnyObject) -> Bool) -> AnyObject? {
        for element: AnyObject in self {
            if predicate(element) {
                return element
            }
        }
        return nil
    }
}

现在我们只需要更新你的功能就可以使用它了!

func itemBehaviorForView(view: UIView) -> UIDynamicItemBehavior?
{
    func predicate(object: AnyObject) -> Bool {
        if let dynamicItemBehavior = object as? UIDynamicItemBehavior {
            return view === dynamicItemBehavior.items?[0]
        }
        return false
    }

    return animator.behaviors.find(predicate) as? UIDynamicItemBehavior
}

我承认,最后一句话上的演员有点难看。如果知道animator.behaviors只包含可接受返回类型的对象,我们可以避免这种情况,但是由于obj-c代码,你很可能会坚持使用它。