ios - 以编程方式将类分配给在 Storyboard (Swift) 中创建的 UIView
问题描述
问题:如何以编程方式将类分配给在 Storyboard 中创建的 UIView?
我在 IB ( graphView
) 中创建了一个 UIView,我想在其中显示几个图形之一,它们的定义在各自的类中创建。
为此,我以编程方式创建了另一个视图,然后将所选图形的类分配给该视图,然后将其添加到原始视图中:
@IBOutlet weak var graphView: UIView!
func displayGraph(choice: Int) {
var selectedGraphView = UIView()
switch choice {
case 1: selectedGraphView = class1()
case 2: selectedGraphView = class2()
case 3: selectedGraphView = class3()
default: selectedGraphView = class1()
}
selectedGraphView.frame = CGRect(x: 0, y: 0, width: graphView, height: graphView)
graphView.addSubview(selectedGraphView)
}
事情似乎奏效了,但我真的需要第二个 UIView ( selectedGraphView
) 吗?
我尝试将其更改为:
func displayGraph2(choice: Int) {
switch choice {
case 1: graphView = class1()
case 2: graphView = class2()
case 3: graphView = class3()
default: graphView = class1()
}
}
但我不知道如何让类的内容运行。
我可以这样做吗?如果是这样,缺少什么?
编辑:实际上,有 3 个 UIView:IB 中的一个,保存图形的一个,类本身创建一个。
如果 sayclass1
只有print("entered class1")
,在第一种情况下 ( displayGraph
),我看到打印了“进入的 class1”。在第二个(displayGraph2
)中,我什么也没得到。
EDIT2:我可以将任何课程分配给graphView
IB 并从课程中获取打印消息。如何以graphView
编程方式分配一个类(因为我尝试的方法displayGraph2
不起作用)?
解决方案
当您UIView
在 Storyboard 中添加一个时,您可以分配它的自定义类。但是,在运行时,您不能以这种方式更改其类:
@IBOutlet var graphViewHolder: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// cannot do this
let v = View2Class()
graphViewHolder = v
}
正如您所做的那样,一种常见的方法是UIView
在您的故事板中添加一个作为“持有者”(或“容器”)视图。然后,在代码中,实例化所需自定义类的实例并将其作为子视图添加到“持有人”视图。
但是,如果您这样做:
selectedGraphView.frame = CGRect(x: 0, y: 0, width: graphView, height: graphView)
graphView.addSubview(selectedGraphView)
新添加的子视图将具有“持有人”视图的大小,如果/当持有人视图改变大小时(例如设备旋转),您将遇到布局问题。
所以,你可以这样做:
// 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),
])
}
现在子视图将遵循“持有人”视图的约束。
请注意,如果您想对加载的视图执行某些操作,则必须确保它是正确的类。
因此,例如,如果我们想在 中调用自定义函数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()
推荐阅读
- c# - 如何在计算器程序中添加第二个参数(数字)?
- c++ - 使用 Makefile 编译时,如何纠正对 `MPI::Comm::Comm()' 的未定义引用?
- javascript - 我可以在这个元素中有两个 onclick 事件吗?
- react-native - React Native 的组合包
- c# - 无法解析资源项 SvgImage
- sql - SQL概述表,不同数据库之间的存储过程依赖关系
- r - 为什么rgee不能使用正确版本的python?
- c++ - 如何在 CMake 中创建静态库(不可执行)?
- javascript - 使用 jquery each 方法访问 JavaScript 数组字符串
- kotlin - 如何使用 BottomNavigationBar 设置自定义工具栏