IB — 根据条件初始化特定的自定义 UIView
Posted
技术标签:
【中文标题】IB — 根据条件初始化特定的自定义 UIView【英文标题】:IB — Initialize specific custom UIView depending on conditions 【发布时间】:2020-11-18 10:18:16 【问题描述】:我有以下课程:
/**
* This is basically an empty class and exists for the purpose of being able to
* define IBOutlets as BaseHeading, regardless of which specific heading is used in IB.
*/
class BaseHeading: UIView
/**
* This class has a .xib where the layout is defined.
* This view should be used as navigationBar for modally-presented ViewControllers.
*/
class HeadingIconRight: BaseHeading // This class has a .xib.
/**
* This class has a .xib where the layout is defined.
* This view should be used as navigationBar for pused ViewControllers.
*/
class HeadingIconLeft: BaseHeading // This class has a .xib.
在MyViewController
的.xib 中,我有一个BaseHeading
类型的自定义UIView
。在它的 Swift 文件中,我有一个 @IBOutlet private weak var heading: BaseHeading!
,连接到这个。
在 Swift 文件中,我知道应该使用哪个特定的标头 (HeadingIconRight
/ HeadingIconLeft
),我只是不确定如何在代码中实现这一点。
我想要什么:
初始化特定的 HeadingIconXXX 将IBOutlet
的引用替换为该视图
替换视图层次结构中的视图
它需要具有相同的约束(通常是 0 到 leading/ trailing/ superview.top, 0 到它下面的第一个视图)
到目前为止我已经尝试过:
let headingIndex = self.view.subviews.firstIndex $0 == self.heading
let newHeading = HeadingIconRight()
// Loop through 'old' heading's constraints and convert them to the new heading.
self.heading.constraints.forEach constraint in
let firstItem: AnyObject? = constraint.firstItem as! AnyHashable == self.heading as AnyHashable ? newHeading : constraint.firstItem
let secondItem: AnyObject? = constraint.secondItem as! AnyHashable == self.heading as AnyHashable ? newHeading : constraint.secondItem
newHeading.addConstraint(
NSLayoutConstraint(item: firstItem,
attribute: constraint.firstAttribute,
relatedBy: constraint.relation,
toItem: secondItem,
attribute: constraint.secondAttribute,
multiplier: constraint.multiplier,
constant: constraint.constant)
)
self.heading.removeFromSuperview()
self.view.insertSubview(newHeading, at: headingIndex!)
self.heading = newHeading
当然,我会尝试更多,但我不想构建非常复杂的东西,我希望在正确的方向上得到一些指导,以找到一个好的解决方案。
如果有可能以某种方式覆盖初始化 Xib 视图的生命周期函数,并将其替换为特定的标头,那将是一个不错的解决方案(如果它不违反 UIViewController API)。
【问题讨论】:
全部添加并隐藏,根据需要安装? 如果我知道它们不会被使用,我不想不必要地添加视图,并以这种方式混乱 ViewController.. 为此使用 IBOutlet 毫无意义。您可以拥有一个属性,然后在运行时创建并分配正确的视图。您无法更改笔尖加载过程。 感谢您的意见。我会调查的。 【参考方案1】:我选择了@Paulw11 的suggestion 并在运行时用代码创建了视图。
我没有在 IB 中添加 BaseHeading
-view,而是将下一个最顶层视图约束到 ViewController
的顶部,并引用此约束(例如 topMostConstraint
)。
我给BaseHeading
添加了如下函数:
public func constrainToTop(in container: UIView, above otherView: UIView, bottomMargin: CGFloat = 0, disableConstraint: NSLayoutConstraint? = nil)
container.addSubview(self)
self.translatesAutoresizingMaskIntoConstraints = false
self.topAnchor.constraint(equalTo: container.topAnchor).isActive = true
self.leadingAnchor.constraint(equalTo: container.leadingAnchor).isActive = true
self.trailingAnchor.constraint(equalTo: container.trailingAnchor).isActive = true
self.bottomAnchor.constraint(equalTo: otherView.topAnchor, constant: -bottomMargin).isActive = true
disableConstraint?.isActive = false
这是做什么的:
将self
添加到containerView
创建必要的约束
如果需要,在下一个(下方)视图中添加 bottomMargin
禁用旧约束,它将另一个视图约束到屏幕顶部
在我的ViewController
的viewDidLoad()
中,我现在可以执行以下操作:
public class MyViewController: UIViewController
private var heading: BaseHeading?
@IBOutlet private weak var topMostConstraint: NSLayoutConstraint!
@IBOutlet private weak var anyOtherView: UIStackView!
override func viewDidLoad()
super.viewDidLoad()
self.heading = HeadingIconRight() // Or any other BaseHeading-subclass.
self.heading?.constrainToTop(in: self.view,
above: self.anyOtherView,
bottomMargin: 16,
disableConstraint: self.topMostConstraint)
这似乎完成了这项工作,并且最终没有我预期的那么复杂。
【讨论】:
以上是关于IB — 根据条件初始化特定的自定义 UIView的主要内容,如果未能解决你的问题,请参考以下文章
Objective C - 带有动画的自定义 UIView 类初始化