When you add a UIView
in Storyboard, you can assign its Custom Class. However, at run-time, you cannot change its class this way:
@IBOutlet var graphViewHolder: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// cannot do this
let v = View2Class()
graphViewHolder = v
}
One common approach, as you've done, is to add a UIView
in your Storyboard as a "holder" (or "container") view. Then, in code, instantiate an instance of your desired Custom Class and add it as a subview to the "holder" view.
However, if you do this:
selectedGraphView.frame = CGRect(x: 0, y: 0, width: graphView, height: graphView)
graphView.addSubview(selectedGraphView)
The newly added subview will have the size of the "holder" view, and you'll run into layout issues if / when the holder view changes size (such as on device rotation).
So, you can do it like this:
// let's name it "graphViewHolder" so we know we're using it as a "holder" view
@IBOutlet var graphViewHolder: UIView!
var currentChoice: Int = 1
override func viewDidLoad() {
super.viewDidLoad()
displayGraph(choice: 1)
}
func displayGraph(choice: Int) {
var selectedGraphView: UIView?
switch choice {
case 1: selectedGraphView = View1Class()
case 2: selectedGraphView = View2Class()
case 3: selectedGraphView = View3Class()
default: selectedGraphView = View1Class()
}
// unwrap optional
guard let sgv = selectedGraphView else { return }
// does the "holder" view already have any subviews?
// if so, remove them
graphViewHolder.subviews.forEach { v in
v.removeFromSuperview()
}
// add the new view as a subview of the "holder" view
graphViewHolder.addSubview(sgv)
// we need to give the new view auto-layout properties
sgv.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
// constrain it to all 4 sides of the "holder" view
sgv.topAnchor.constraint(equalTo: graphViewHolder.topAnchor),
sgv.leadingAnchor.constraint(equalTo: graphViewHolder.leadingAnchor),
sgv.trailingAnchor.constraint(equalTo: graphViewHolder.trailingAnchor),
sgv.bottomAnchor.constraint(equalTo: graphViewHolder.bottomAnchor),
])
}
Now the subview will follow the "holder" view's constraints.
Note that if you want to do something to the loaded view, you'll have to make sure it's the right class.
So, for example, if we want to call a custom func in View2Class
:
// make sure the "holder" view has a subview
guard let v = graphViewHolder.subviews.first else {
print("Graph View Holder has no subviews!")
return
}
// make sure the subview is a View2Class instance
guard let v2 = v as? View2Class else {
print("The Holder subview is not View2Class!")
return
}
// call a func in View2Class
v2.myFunc()
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…