我相信每个人都熟悉
select count(*) from some_view
只要将新的子视图添加到UIView,就会调用此函数。
我想知道如何实现?比如,实现这一目标的基本代码是什么?
谢谢
编辑:
我在这个问题中的意思是实现非客观c观察功能的代码。例如,我们可以构建一个通知,这样每当调用addSubView时,都会相应地调用didAddSuView,但显然,在这种情况下。它不是我们在正常实现中看到的object-c选择器。所以我想问我们如何实现这样的事情,这意味着,如果调用另一个函数而不是objc函数,我该如何触发函数。
不过,顺便进一步澄清一下。该函数是作为UIView(Extension UIView)的函数实现的,因此它不是一个协议,这意味着它没有作为委托优雅地实现。所以再一次,我在问......我怎么能复制这样的东西?
答案 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…
}