以编程方式将类分配给在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()
}
}

但我不知道如何运行类的内容。

我可以这样做吗?如果是,缺少什么?

EDIT:实际上,有3个UIViews:IB中的一个,保存图形的一个和类本身创建的一个。

如果说class1除了print("entered class1")什么都没有,在第一种情况下(displayGraph(,我看到";进入类1";打印。在第二个(displayGraph2(中,我一无所获。

第2版:我可以在IB中将任何一个类分配给graphView,并从该类中获得打印消息。如何以编程方式将类分配给graphView(因为我在displayGraph2中尝试的操作不起作用(?

在Storyboard中添加UIView时,可以分配其自定义类。然而,在运行时,您不能以这种方式更改其类:

@IBOutlet var graphViewHolder: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// cannot do this
let v = View2Class()
graphViewHolder = v
}

正如您所做的,一种常见的方法是在Storyboard中添加一个UIView作为";支架";(或"容器"(视图。然后,在代码中,实例化所需自定义类的实例,并将其作为子视图添加到"中;支架";看法

然而,如果你这样做:

selectedGraphView.frame = CGRect(x: 0, y: 0, width: graphView, height: graphView)
graphView.addSubview(selectedGraphView)

新添加的子视图将具有"0"的大小;支架";视图,如果/当支架视图更改大小(例如在设备旋转时(,您将遇到布局问题。

所以,你可以这样做:

// 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()

最新更新