Swift 固有任务
Swift inherence task
几天前,我在 objc 之后转向 swift 编码。当我用 MVVM 模式编写适配器时,我混淆了下一个案例,这可以在 objc 中完成而没有任何问题。
所以在 Objc 中:我们有 IDTableViewController 和 presenter (viewModel) 属性
@interface IDTableViewController : UITableViewController
@property (nonatomic, strong) id<IDCollectionPresenterProtocol> presenter;
@end
而我们在继承IDTableViewController的时候,在extension中重写了presenter的class(当然符合上面提到的协议)
UsersViewController.h
@interface UsersViewController : IDTableViewController
UsersViewController.m
@interface UsersViewController ()
@property (nonatomic, strong) UsersPresenter *presenter;
@end
@implementation UsersViewController
@dynamic presenter;
一切都很好...但是在 swift 我不能做同样的事情。我无法在 UsersViewController
中覆盖 属性 的 class
class IDTableViewController: UITableViewController {
var viewModel : IDCollectionPresenterProtocol?
}
class UsersViewController: IDTableViewController {
var viewModel : UsersPresenter?
}
我可以这样做吗?如果它不合法,我该如何实施?
您可能想要这样的东西:
protocol MyProtocol {
}
class ImplementedProtocol : MyProtocol {
}
class MyBaseClass<T : MyProtocol> {
var viewModel : T?
}
class MyDerivedClass : MyBaseClass<ImplementedProtocol> {
}
现在,当您实例化 MyDerivedClass
时,viewModel
的类型将是 ImplementedProtocol
。
一句警告:Xcode 7.3 没有在自动完成中正确推断出 viewModel
的类型,而是将其分配给一个固定的变量 - 所以它只是一个 Xcode 错误,希望会很快就会修复。
有几种方法:
您可以使用计算 属性 覆盖存储 属性,这是您自己的私有存储 属性 的前端,例如:
class UsersViewController: IDTableViewController {
private var usersViewModel: UsersPresenter?
override var viewModel: IDCollectionPresenterProtocol? {
get { return usersViewModel }
set { usersViewModel = newValue as! UsersPresenter }
}
}
您根本无法覆盖 viewModel
,如果您需要一个 UsersPresenter
接口,只需将 usersViewModel
实现为计算的 属性 本身UsersViewController
:
中的视图模型
class UsersViewController: IDTableViewController {
private var usersViewModel: UsersPresenter? {
get { return viewModel as? UsersPresenter }
set { viewModel = newValue }
}
}
另一种更自然的 Swifty 处理方法(例如,在协议扩展中使用 UITableViewDataSource
方法的默认实现的泛型或协议)在 Objective-C 中表现不佳,因此将它们用作视图控制器或 UITableViewDataSource
.
时会遇到问题
几天前,我在 objc 之后转向 swift 编码。当我用 MVVM 模式编写适配器时,我混淆了下一个案例,这可以在 objc 中完成而没有任何问题。
所以在 Objc 中:我们有 IDTableViewController 和 presenter (viewModel) 属性
@interface IDTableViewController : UITableViewController
@property (nonatomic, strong) id<IDCollectionPresenterProtocol> presenter;
@end
而我们在继承IDTableViewController的时候,在extension中重写了presenter的class(当然符合上面提到的协议)
UsersViewController.h
@interface UsersViewController : IDTableViewController
UsersViewController.m
@interface UsersViewController ()
@property (nonatomic, strong) UsersPresenter *presenter;
@end
@implementation UsersViewController
@dynamic presenter;
一切都很好...但是在 swift 我不能做同样的事情。我无法在 UsersViewController
中覆盖 属性 的 classclass IDTableViewController: UITableViewController {
var viewModel : IDCollectionPresenterProtocol?
}
class UsersViewController: IDTableViewController {
var viewModel : UsersPresenter?
}
我可以这样做吗?如果它不合法,我该如何实施?
您可能想要这样的东西:
protocol MyProtocol {
}
class ImplementedProtocol : MyProtocol {
}
class MyBaseClass<T : MyProtocol> {
var viewModel : T?
}
class MyDerivedClass : MyBaseClass<ImplementedProtocol> {
}
现在,当您实例化 MyDerivedClass
时,viewModel
的类型将是 ImplementedProtocol
。
一句警告:Xcode 7.3 没有在自动完成中正确推断出 viewModel
的类型,而是将其分配给一个固定的变量 - 所以它只是一个 Xcode 错误,希望会很快就会修复。
有几种方法:
您可以使用计算 属性 覆盖存储 属性,这是您自己的私有存储 属性 的前端,例如:
class UsersViewController: IDTableViewController { private var usersViewModel: UsersPresenter? override var viewModel: IDCollectionPresenterProtocol? { get { return usersViewModel } set { usersViewModel = newValue as! UsersPresenter } } }
您根本无法覆盖
中的视图模型viewModel
,如果您需要一个UsersPresenter
接口,只需将usersViewModel
实现为计算的 属性 本身UsersViewController
:class UsersViewController: IDTableViewController { private var usersViewModel: UsersPresenter? { get { return viewModel as? UsersPresenter } set { viewModel = newValue } } }
另一种更自然的 Swifty 处理方法(例如,在协议扩展中使用 UITableViewDataSource
方法的默认实现的泛型或协议)在 Objective-C 中表现不佳,因此将它们用作视图控制器或 UITableViewDataSource
.