如何在Swift中对自定义UIViewController进行子类化? [英] How to subclass custom UIViewController in Swift?

查看:181
本文介绍了如何在Swift中对自定义UIViewController进行子类化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个可重用的视图控制器UsersViewControllerBase.

I'd like to create a reusable view controller UsersViewControllerBase.

UsersViewControllerBase扩展了UIViewController,实现了两个委托(UITableViewDelegateUITableViewDataSource),并且具有两个视图(UITableViewUISegmentedControl)

UsersViewControllerBase extends UIViewController, and implements two delegates (UITableViewDelegate, UITableViewDataSource), and has two views (UITableView, UISegmentedControl)

目标是继承UsersViewControllerBase的实现并自定义UsersViewController类中的分段控件的分段项.

The goal is to inherit the implementation of the UsersViewControllerBase and customise the segmented items of segmented control in UsersViewController class.

class UsersViewControllerBase: UIViewController, UITableViewDelegate, UITableViewDataSource{
  @IBOutlet weak var segmentedControl: UISegmentedControl!
  @IBOutlet weak var tableView: UITableView!
  //implementation of delegates
}

class UsersViewController: UsersViewControllerBase {
}

情节提要中存在UsersViewControllerBase,并且所有插座均已连接,已指定标识符.

The UsersViewControllerBase is present in the storyboard and all outlets are connected, the identifier is specified.

问题是我如何初始化UsersViewController来继承UsersViewControllerBase

The question is how can I init the UsersViewController to inherit all the views and functionality of UsersViewControllerBase

当我创建UsersViewControllerBase的实例时,一切正常

When I create the instance of UsersViewControllerBase everything works

let usersViewControllerBase = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("UsersViewControllerBase") as? UsersViewControllerBase

但是当我创建UsersViewController的实例时,会得到nil出口 (我创建了一个简单的UIViewController,并在情节提要中为其分配了UsersViewController类)

But when I create the instance of UsersViewController I get nil outlets (I created a simple UIViewController and assigned the UsersViewController class to it in the storyboard )

let usersViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("UsersViewController") as? UsersViewController

似乎没有继承视图.

我希望UsersViewControllerBase中的init方法可以从情节提要中获取具有视图和出口的控制器:

I would expect init method in UsersViewControllerBase that gets controller with views and outlets from storyboard:

  class UsersViewControllerBase: UIViewController, UITableViewDelegate, UITableViewDataSource{
      @IBOutlet weak var segmentedControl: UISegmentedControl!
      @IBOutlet weak var tableView: UITableView!
      init(){
        let usersViewControllerBase = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("UsersViewControllerBase") as? UsersViewControllerBase
        self = usersViewControllerBase //but that doesn't compile
      }
    }

然后我会初始化UsersViewController:

let usersViewController = UsersViewController()

但不幸的是,这不起作用

But unfortunately that doesn't work

推荐答案

通过instantiateViewControllerWithIdentifier实例化视图控制器时,该过程实质上如下:

When you instantiate a view controller via instantiateViewControllerWithIdentifier, the process is essentially as follows:

  • 找到具有该标识符的场景;
  • 它确定该场景的基类;和
  • 它返回该类的实例.

然后,当您首次访问view时,它将:

And then, when you first access the view, it will:

  • 创建该情节提要场景中概述的视图层次结构;和
  • 连接网点.

(该过程实际上比这复杂得多,但我正在尝试将其简化为该工作流中的关键元素.)

(The process is actually more complicated than that, but I'm trying to reduce it to the key elements in this workflow.)

此工作流程的含义是,出口和基类由传递给instantiateViewControllerWithIdentifier的唯一情节提要标识符确定.因此,对于基类的每个子类,您都需要一个单独的情节提要场景,并已将出口连接到该特定子类.

The implication of this workflow is that the outlets and the base class are determined by the unique storyboard identifier you pass to instantiateViewControllerWithIdentifier. So for every subclass of your base class, you need a separate storyboard scene and have hooked up the outlets to that particular subclass.

不过,有一种方法可以满足您的要求.可以使用视图控制器实现loadView(不要与viewDidLoad混淆),而可以通过编程方式创建视图控制器类所需的视图层次结构,而不是使用视图控制器的情节提要场景. Apple曾经在他们的《 iOS的View Controller编程指南》 中对此过程进行了很好的介绍,但此后已经取消了该讨论,但仍然可以在他们的

There is an approach that will accomplish what you've requested, though. Rather than using storyboard scene for the view controller, you can instead have the view controller implement loadView (not to be confused with viewDidLoad) and have it programmatically create the view hierarchy needed by the view controller class. Apple used to have a nice introduction to this process in their View Controller Programming Guide for iOS, but have since retired that discussion, but it can still be found in their legacy documentation.

话虽如此,除非有非常令人信服的理由,否则我个人不会被迫回到以编程方式创建视图的旧世界.我可能更倾向于放弃视图控制器子类方法,而采用类似单个类的方法(这意味着我回到了故事板的世界),然后向其传递了一些标识符,该标识符指示了我希望从该特定实例获取的行为那一幕. 如果要对此保持某种OO优雅,则可以实例化数据源的自定义类并根据在此视图控制器类中设置的某些属性进行委托.

Having said that, I personally would not be compelled to go back to the old world of programmatically created views unless there was a very compelling case for that. I might be more inclined to abandon the view controller subclass approach, and adopt something like a single class (which means I'm back in the world of storyboards) and then pass it some identifier that dictates the behavior I want from that particular instance of that scene. If you want to keep some OO elegance about this, you might instantiate custom classes for the data source and delegate based upon some property that you set in this view controller class.

如果您需要真正的动态视图控制器行为,而不是以编程方式创建视图层次结构,那么我会更倾向于走这条路. 或更简单的说,继续采用原始的视图控制器子类化方法,只是接受对于每个子类在情节提要中需要单独的场景.

I'd be more inclined to go down this road if you needed truly dynamic view controller behavior, rather than programmatically created view hierarchies. Or, even simpler, go ahead and adopt your original view controller subclassing approach and just accept that you'll need separate scenes in the storyboard for each subclass.

这篇关于如何在Swift中对自定义UIViewController进行子类化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆