Ios 在视图控制器中访问UIView子类
假设我有Ios 在视图控制器中访问UIView子类,ios,swift,uiview,uiviewcontroller,Ios,Swift,Uiview,Uiviewcontroller,假设我有SomeViewController:UIViewController,我有一个自定义视图CustomView:UIView,定义为XIB,我想显示它。此自定义视图将在其他视图控制器中重复使用,甚至在同一视图控制器中重复使用多次 class CustomView: UIView { @IBOutlet public var label: UILabel! } 我一直以来添加此视图的方式是: class UIExamples: UIViewController { @IBOutl
SomeViewController:UIViewController
,我有一个自定义视图CustomView:UIView
,定义为XIB,我想显示它。此自定义视图将在其他视图控制器中重复使用,甚至在同一视图控制器中重复使用多次
class CustomView: UIView {
@IBOutlet public var label: UILabel!
}
我一直以来添加此视图的方式是:
class UIExamples: UIViewController {
@IBOutlet private var myView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Assume makeViewFromNib returns the view [0] in the Nib.
let customView = makeViewFromNib(nib: "\(CustomView.self)", owner: self) as! CustomView
customView.frame = myView.bounds
myView.addSubview(customView)
}
}
假设稍后我想通过公共属性标签
修改有关CustomView
的内容
我可以在viewDidLoad
中执行此操作,只是因为我可以访问customView
,但是如果我想在其他功能中更改它呢?我所看到的是一个人必须要做的事
let customView = myView.subviews[0] as! CustomView
customView.label.text = "some text"
这看起来不对
因此,我认为正确的方法应该是:
class UIExamples: UIViewController {
@IBOutlet public var customView: CustomView! // Now this is always a CustomView type
override func viewDidLoad() {
super.viewDidLoad()
// Assume makeViewFromNib returns the view [0] in the Nib.
customView = makeViewFromNib(nib: "\(CustomView.self)", owner: self) as! CustomView
customView.label.text = "some text" // DOES NOT WORK!
}
}
最后一行customView.label.text无效。事实上,屏幕上甚至看不到标签。我做错了什么 好的,没有读到(或者可能在编辑之前读过)您使用的xib。如果ViewController是从xib中创建的,其中包含标签,则这将是正确的方式:
在xib中设置myView类,如下所示:
然后连接IB插座(此处从xib中移除当前插座:
然后从代码)
现在myView.label.text=“some text”
应该可以正常工作,不会出现进一步的问题。
祝你好运
如果从代码创建视图,请按以下方式执行:
class UIExamples: UIViewController {
@IBOutlet private var myView: CustomView!
override func viewDidLoad() {
super.viewDidLoad()
// Assume makeViewFromNib returns the view [0] in the Nib.
myView = makeViewFromNib(nib: "\(CustomView.self)", owner: self) as! CustomView
myView.frame = view.bounds
view.addSubview(myView)
}
}
因为已经有属性将此视图存储在视图控制器中,所以无需在子视图中挖掘,它将像这样工作
myView.label.text = "some text"
原因何在
customView = makeViewFromNib(nib: "\(CustomView.self)", owner: self) as! CustomView
customView.label.text = "some text"
不起作用是因为它是一个全新的视图,没有添加到视图控制器子视图中(顺便说一句,框架也没有设置)。而且,因为您更改了customView属性的值,所以它现在不会指向视图的旧实例,即子视图中的旧实例(您仍然可以看到“旧实例”,但不会更改它)
但我确实建议使用一次创建的指针作为正确的类来避免强制转换。(或者直接在xib/故事板中创建视图,否则不需要
@IBOutlet
)发布我自己的答案
...
/// Initializer used by Interface Builder.
required init?(coder: NSCoder) {
super.init(coder: coder)
configure()
}
/// Initializer used programmatically.
override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
...
func configure() {
let contentView = // here use many of the functions available on the internet to
// load a view from a nib.
// Then add this view to the view hierarchy.
addSubview(contentView)
}
您不需要显式地从nib调用
makeViewFromNib(nib:\(CustomView.self)”,所有者:self)
,因为如果在这种情况下使用IBOutlet
,您已经从情节提要加载了CustomView
。下一点你应该澄清——你使用的是故事板还是Xib。你想在不同的视图控制器中重用视图,还是专门针对那个视图?在第一句中添加了澄清。也许可以看看这里:你可以找到问题的答案我注意到了myView。子视图的类型是[UIView]
。这就是为什么我认为您不能执行customView.label.text
@anr是,但所有自定义视图(UIView子类)都是UIView类型。将CustomView添加为子视图甚至不需要强制转换到UIView。这是“向上投射”-投射到超类。在此上下文中,只有向下转换(转换为子类)需要显式。因此,您可以(也应该)以方便的方式使用属性,正如我在回答(@IBOutlet private var myView:CustomView!
)中所建议的那样,再次阅读答案时,我认为有点不对:我希望能够执行myView.label.text
(您使用的是CustomView.label.text)。事实上,我尝试了myView.label.text
,但它不起作用。请记住,我希望能够在myView.label.text
之外执行viewDidLoad
操作,这意味着我只能访问myView
而不能访问customView
。@anr稍微改变了我的答案。实际上没有必要将CustomView添加到另一个CustomView。如果myView是从storyboard/xib创建的,类设置为“CustomView”,则只需在代码中将myView设置为此类,并直接使用label(myView.label.text=“some text”
),而不必从nib创建视图all@anr为从xib创建的ViewController编辑了我的答案(对于故事板,它非常类似)