Swift:对UIViewController的根视图进行子类化

时间:2014-06-10 01:47:57

标签: ios uiview uiviewcontroller swift

tl;博士:我如何告诉Swift我正在覆盖MyViewController view属性UIView的子类?


我想做什么

我非常喜欢为UIView视图提供UIViewController的子类。例如:

// MyView --------------------------------------------------------

@interface MyView: UIView
@property (nonatomic, strong) UITableView *tableView;    
@end

@implementation MyView

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        _tableView = [[UITableView alloc] initWithFrame:frame];
    }
    return self;
}

@end

// MyViewController ----------------------------------------------

@interface MyViewController: UIViewController <UITableViewDataSource>
@property (nonatomic, retain) MyView *view;
@end

@implementation MyViewController

- (void)loadView {
    self.view = [[MyView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
}

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.tableView.dataSource = self;
    // etc.
}

@end

这很好,因为它将视图创建和布局逻辑与视图控制器分开。好的,很好。

我可以想象,这就像这样转换成Swift:

// MyView --------------------------------------------------------

class MyView: UIView {
    let tableView: UITableView!

    init(frame: CGRect) {
        super.init(frame: frame)
        tableView = UITableView(frame: frame)
    }
}

// MyViewController ----------------------------------------------

class MyViewController: UIViewController, UITableViewDataSource {
    override func loadView() {
        view = MyView(frame: UIScreen.mainScreen().bounds)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // this causes the compiler to complain with:
        // 'UIView' does not have a member named 'tableView'
        self.view.tableView.dataSource = self
    }
}

麻烦的是我似乎无法弄清楚如何告诉视图控制器它的viewMyView的实例,而不是UIView本身。

尝试失败

这是我到目前为止所尝试的内容:

我在MyViewController的顶部尝试过此操作,但出现以下错误:

override var view: MyView!
// error: Cannot override mutable property 'view' of
//        type 'UIView' with covariant type 'MyView!'

我在loadView尝试了这个,但没有运气:

view = MyView(frame: UIScreen.mainScreen().bounds) as MyView
// this produces the same error as in the original code:
// 'UIView' does not have a member named 'tableView'

所以这是问题

如何告诉Swift我用MyViewController子类覆盖view的{​​{1}}属性?这甚至可能吗?如果没有,为什么不呢?

3 个答案:

答案 0 :(得分:24)

我认为在Swift中可能无法实现完全相同的实现。从Swift书中有关覆盖属性的部分:

  

“您必须始终说明您的财产的名称和类型   覆盖,以使编译器检查您的覆盖   匹配具有相同名称和类型的超类属性。“

但是,您可以使用一个计算属性来返回视图控制器的view属性的类型转换版本,它几乎一样干净:

class MyViewController: UIViewController, UITableViewDataSource {
    var myView: MyView! { return self.view as MyView }

    override func loadView() {
        view = MyView(frame: UIScreen.mainScreen().bounds)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.myView.tableView.dataSource = self
    }
}

答案 1 :(得分:0)

我们可以使用这样的东西吗?

class MyViewController: UIViewController, UIScrollViewDelegate {

weak var viewAlias: UIScrollView!

override func loadView() {
    let scrollView = UIScrollView(frame: UIScreen.mainScreen().bounds)
    viewAlias = scrollView

    view = scrollView
}

override func viewDidLoad() {
    //super.viewDidLoad()
    viewAlias.delegate = self
    viewAlias.contentSize = view.frame.size

    // Do any additional setup after loading the view.

}

答案 2 :(得分:0)

[Apple Developer]这样做1

  

以下显示了如何覆盖视图控制器   viewDidLoad()方法将其视图转换为SKView:

override func viewDidLoad() {
    super.viewDidLoad()
    view = SKView()
}
var skView: SKView {
    return view as! SKView
}

或者,Xcode的新项目游戏模板就是这样做的:

override func viewDidLoad() {
    super.viewDidLoad()

    if let view = self.view as! SKView? {
        // Can now set up view as if it were a SKView.
    }
}