如何从 ViewController 中的 xib (nib) 实例化 UIView / UITableView
How do I instantiate a UIView / UITableView from a xib (nib) in a ViewController
我想显示一个具有分段控件的用户界面,以及分段控件的每个部分的不同 table 视图;因此,可以在 2 table 视图(好友和群)之间切换。
为了实现这一点,我做了以下工作
- 在 Storyboard 中创建 ViewController
- 从 ViewController
中删除视图
- 创建一个新的 UIViewController swift class 和一个关联的 xib 文件
- 将分段控件放在main中UI在xib中查看
- 在主 UIView 中放置一个内部 UIView 元素,以将 space 替换为 table 视图
- 创建了 UITableView 和对应的 xib 文件的两个子classes
我想到的一些方案:
- 我可以将 Interface Builder 中内部 UI 视图的 class 设置为 table 视图之一,但我不知道如何实例化另一个代替第一个。如果我创建了重叠的内部 UI 视图,每个视图都与一个 table 视图相关联,并在切换分段控件时隐藏其中一个视图,这实际上是可行的,但是视图的重叠性质使布局变得困难并且不直观。
- 我想知道如何做:实例化 table 视图代替单个主要 UIView 元素
- 备选方案:有一个 UITableView subclass,它的条件基于分段控件的状态,用于显示哪些数据。我不太喜欢这个,因为它会将 table 视图的代码混合在一起。在这种情况下,我什至不需要再使用 xibs,我可以在情节提要中用一个 table 视图来做到这一点。
** ViewController代码**
@objc(BuddiesBunchesViewController) class BuddiesBunchesViewController: UIViewController {
@IBOutlet weak var segmentedControl: UISegmentedControl!
@IBOutlet weak var tableView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Instantiate tableView here to BuddiesTableView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func segmentedControlIndexChanged(sender: AnyObject) {
switch segmentedControl.selectedSegmentIndex {
case 0: // Buddies
// Set tableview to the buddies table view
case 1: // Bunches
// Set tableview to the buddies table view
default:
break;
}
}
}
** Table 查看 **
@IBDesignable class BuddiesTableView: UITableView, UITableViewDataSource, UITableViewDelegate {
var view: UIView!
var nibName: String = "BuddiesTableView"
//init
override init(frame: CGRect) {
// set properties
super.init(frame: frame)
// Set anything that uses the view or visible bounds
setup()
}
required init(coder aDecoder: NSCoder) {
//set properties
super.init(coder: aDecoder)
// Setup
setup()
}
func setup() {
view = loadViewFromNib()
view.frame = self.bounds
view.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: nibName, bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
return view
}
// MARK: - Table View
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestCell")
cell.textLabel?.text = "\(indexPath.row)"
return cell
}
}
我的解决方案如下。
您有一个包含两个段的段控件,因此您可以只有一个 UITableView
对象并根据段控件 selectedSegmentIndex
编号更改数据源,而不是有两个 table 视图然后重新加载 table 视图。在情节提要中,将 table 视图放在 UIVIewController
之上,并为此创建一个 @IBOutlet
。
我个人不会创建两个 table 视图并将它们交换出来。两者之间唯一的显着区别是它们是不同的实例,您可以在数据源代码中对此进行测试。他们会指向不同的数据源吗?为什么不直接更改数据源而不是 table 视图?
创建一个 table 视图。创建两个(或更多)classes 作为数据源(和可能的代表)。如果它们有任何共同的行为,它们可以基于一个共同的超级class。
当分段控件值发生变化时,只需将 table 视图的数据源 属性 更改为指向带有该状态代码的 class。如果更改数据源不会自动重新加载它,您可能还需要使用 -reloadData 调用。
@IBOutlet private weak var tableView: UITableView!
let moviesDataSource = MyMoviesDataSource()
let tvShowsDataSource = MyTVShowsDataSource()
@IBAction func segmentedControlTouched(sender: UISegmentedControl) {
switch sender.selectedSegmentIndex {
case 0:
self.tableView.dataSource = self.moviesDataSource
self.tableView.delegate = self.moviesDataSource
case 1:
self.tableView.dataSource = self.tvShowsDataSource
self.tableView.delegate = self.tvShowsDataSource
}
self.tableView.reloadData()
}
我想显示一个具有分段控件的用户界面,以及分段控件的每个部分的不同 table 视图;因此,可以在 2 table 视图(好友和群)之间切换。 为了实现这一点,我做了以下工作
- 在 Storyboard 中创建 ViewController
- 从 ViewController 中删除视图
- 创建一个新的 UIViewController swift class 和一个关联的 xib 文件
- 将分段控件放在main中UI在xib中查看
- 在主 UIView 中放置一个内部 UIView 元素,以将 space 替换为 table 视图
- 创建了 UITableView 和对应的 xib 文件的两个子classes
我想到的一些方案:
- 我可以将 Interface Builder 中内部 UI 视图的 class 设置为 table 视图之一,但我不知道如何实例化另一个代替第一个。如果我创建了重叠的内部 UI 视图,每个视图都与一个 table 视图相关联,并在切换分段控件时隐藏其中一个视图,这实际上是可行的,但是视图的重叠性质使布局变得困难并且不直观。
- 我想知道如何做:实例化 table 视图代替单个主要 UIView 元素
- 备选方案:有一个 UITableView subclass,它的条件基于分段控件的状态,用于显示哪些数据。我不太喜欢这个,因为它会将 table 视图的代码混合在一起。在这种情况下,我什至不需要再使用 xibs,我可以在情节提要中用一个 table 视图来做到这一点。
** ViewController代码**
@objc(BuddiesBunchesViewController) class BuddiesBunchesViewController: UIViewController {
@IBOutlet weak var segmentedControl: UISegmentedControl!
@IBOutlet weak var tableView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Instantiate tableView here to BuddiesTableView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func segmentedControlIndexChanged(sender: AnyObject) {
switch segmentedControl.selectedSegmentIndex {
case 0: // Buddies
// Set tableview to the buddies table view
case 1: // Bunches
// Set tableview to the buddies table view
default:
break;
}
}
}
** Table 查看 **
@IBDesignable class BuddiesTableView: UITableView, UITableViewDataSource, UITableViewDelegate {
var view: UIView!
var nibName: String = "BuddiesTableView"
//init
override init(frame: CGRect) {
// set properties
super.init(frame: frame)
// Set anything that uses the view or visible bounds
setup()
}
required init(coder aDecoder: NSCoder) {
//set properties
super.init(coder: aDecoder)
// Setup
setup()
}
func setup() {
view = loadViewFromNib()
view.frame = self.bounds
view.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
addSubview(view)
}
func loadViewFromNib() -> UIView {
let bundle = NSBundle(forClass: self.dynamicType)
let nib = UINib(nibName: nibName, bundle: bundle)
let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
return view
}
// MARK: - Table View
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestCell")
cell.textLabel?.text = "\(indexPath.row)"
return cell
}
}
我的解决方案如下。
您有一个包含两个段的段控件,因此您可以只有一个 UITableView
对象并根据段控件 selectedSegmentIndex
编号更改数据源,而不是有两个 table 视图然后重新加载 table 视图。在情节提要中,将 table 视图放在 UIVIewController
之上,并为此创建一个 @IBOutlet
。
我个人不会创建两个 table 视图并将它们交换出来。两者之间唯一的显着区别是它们是不同的实例,您可以在数据源代码中对此进行测试。他们会指向不同的数据源吗?为什么不直接更改数据源而不是 table 视图?
创建一个 table 视图。创建两个(或更多)classes 作为数据源(和可能的代表)。如果它们有任何共同的行为,它们可以基于一个共同的超级class。
当分段控件值发生变化时,只需将 table 视图的数据源 属性 更改为指向带有该状态代码的 class。如果更改数据源不会自动重新加载它,您可能还需要使用 -reloadData 调用。
@IBOutlet private weak var tableView: UITableView!
let moviesDataSource = MyMoviesDataSource()
let tvShowsDataSource = MyTVShowsDataSource()
@IBAction func segmentedControlTouched(sender: UISegmentedControl) {
switch sender.selectedSegmentIndex {
case 0:
self.tableView.dataSource = self.moviesDataSource
self.tableView.delegate = self.moviesDataSource
case 1:
self.tableView.dataSource = self.tvShowsDataSource
self.tableView.delegate = self.tvShowsDataSource
}
self.tableView.reloadData()
}