观察功能如何在SWIFT中工作的机制

时间:2018-05-05 12:47:06

标签: ios swift

我相信每个人都熟悉

select count(*) from some_view

只要将新的子视图添加到UIView,就会调用此函数。

我想知道如何实现?比如,实现这一目标的基本代码是什么?

谢谢

编辑:

我在这个问题中的意思是实现非客观c观察功能的代码。例如,我们可以构建一个通知,这样每当调用addSubView时,都会相应地调用didAddSuView,但显然,在这种情况下。它不是我们在正常实现中看到的object-c选择器。所以我想问我们如何实现这样的事情,这意味着,如果调用另一个函数而不是objc函数,我该如何触发函数。

不过,顺便进一步澄清一下。该函数是作为UIView(Extension UIView)的函数实现的,因此它不是一个协议,这意味着它没有作为委托优雅地实现。

所以再一次,我在问......我怎么能复制这样的东西?

1 个答案:

答案 0 :(得分:2)

“底层代码”是指在需要调用时只调用“观察函数”。 UIKit如何调用didAddSubview并没有什么神奇之处。它不使用Objective-C特有的任何功能。

iOS SDK有四种方法可以将子视图添加到视图中:

  • addSubview:
  • insertSubview:atIndex:
  • insertSubview:aboveSubview:
  • insertSubview:belowSubview:

所有这些方法都是私有方法_addSubview:positioned:relativeTo:的包装器。您可以使用反汇编程序检查这一点,或者在didAddSubview:中放置一个断点并查看堆栈跟踪以查看谁调用它。

私有方法使用普通的Objective-C消息调用[self didAddSubview:subview]。它没有“建立通知”。源代码可能看起来像这样:

- (void)_addSubview:(UIView *)newSubview position:(UIViewSubviewPosition)position relativeTo:(UIView *)sibling {
    // Lots of bookkeeping related to first responder status,
    // gesture recognizers, auto layout, visual effects,
    // and private implementation details…

    [newSubview removeFromSuperview];

    switch (position) {
        case UIViewSubviewPositionAtEnd:
            [self.layer addSublayer:newSubview.layer];
            break
        case UIViewSubviewPositionBelowSibling:
            [self.layer insertSublayer:newSubview.layer below:sibling.layer];
            break;
        case UIViewSubviewPositionAboveSibling:
            [self.layer insertSublayer:newSubview.layer above:sibling.layer];
            break;
        default:
            [self.layer insertSublayer:newSubview.layer atIndex:(unsigned int)position];
            break;
    }

    [newSubview didMoveToSuperview];
    [newSubview didMoveToWindow];
    [self didAddSubview:newSubview];

    // Lots more bookkeeping related to first responder status,
    // gesture recognizers, auto layout, visual effects,
    // and private implementation details…
}

在Swift中,它看起来像这样:

enum SubviewPosition {
    case atEnd
    case below(UIView)
    case above(UIView)
    case atIndex(UInt32)
}

func _addSubview(_ newSubview: UIView, position: SubviewPosition) {
    // Lots of bookkeeping related to first responder status,
    // gesture recognizers, auto layout, visual effects,
    // and private implementation details…

    newSubview.removeFromSuperview()

    switch position {
        case .atEnd: layer.addSublayer(newSubview.layer)
        case .below(let sibling):
            layer.insertSublayer(newSubview.layer, below:sibling.layer)
        case .above(let sibling)):
            layer.insertSublayer(newSubview.layer, above:sibling.layer)
        case .atIndex(let index):
            layer.insertSublayer(newSubview.layer at:index)
    }

    newSubview.didMoveToSuperview()
    newSubview.didMoveToWindow()
    didAddSubview(newSubview)

    // Lots more bookkeeping related to first responder status,
    // gesture recognizers, auto layout, visual effects,
    // and private implementation details…
}