如何从 ViewController 中的 xib (nib) 实例化 UIView / UITableView

How do I instantiate a UIView / UITableView from a xib (nib) in a ViewController

我想显示一个具有分段控件的用户界面,以及分段控件的每个部分的不同 table 视图;因此,可以在 2 table 视图(好友和群)之间切换。 为了实现这一点,我做了以下工作

  1. 在 Storyboard 中创建 ViewController
  2. 从 ViewController
  3. 中删除视图
  4. 创建一个新的 UIViewController swift class 和一个关联的 xib 文件
  5. 将分段控件放在main中UI在xib中查看
  6. 在主 UIView 中放置一个内部 UIView 元素,以将 space 替换为 table 视图
  7. 创建了 UITableView 和对应的 xib 文件的两个子classes

我想到的一些方案:

** 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()
}