我正在尝试提取一些代码库以供重用。我的方法是使用Protocol
和Protocol
Extension
而不是一般的BaseClass
。
我在下面创建了protocol
和protocol extension
protocol MovieDisplay {
var collectionView: UICollectionView! { get set }
var refreshControl: UIRefreshControl! { get set }
}
extension MovieDisplay where Self: UIViewController {
var refreshControl: UIRefreshControl {
let rc = UIRefreshControl()
rc.backgroundColor = .clear
rc.tintColor = .lightGray
if #available(iOS 10.0, *) {
collectionView.refreshControl = rc
} else {
// Fallback on earlier versions
collectionView.addSubview(rc)
}
return rc
}
}
在采用协议的主类中,我这样声明(使用refreshcontrol
的默认实现)
class PopularMovieVC: UIViewController, MovieDisplay {
@IBOutlet weak var collectionView: UICollectionView!
}
问题是涉及refreshcontrol
的函数不起作用。仅当我在主类中显式声明refreshcontrol
变量并将扩展名转换为函数并在主类内进行调用(如波纹管)时,它才起作用
func setupRefreshControl() {
refreshControl.backgroundColor = .clear
refreshControl.tintColor = .lightGray
if #available(iOS 10.0, *) {
collectionView.refreshControl = refreshControl
} else {
// Fallback on earlier versions
collectionView.addSubview(refreshControl)
}
}
如何为默认实施正确配置protocol
和protocol extension
?
答案 0 :(得分:1)
它不起作用,因为没有隐式调用计算所得的属性。
在viewDidLoad
中添加此行应初始化刷新控件
_ = refreshControl
在这种情况下,我真的更喜欢基类
答案 1 :(得分:1)
您的协议需要一个可获取和可设置的refreshControl
(返回UIRefreshControl!
),但是您的默认实现仅提供一个getter(该getter返回一种不同的类型UIRefreshControl
)。您的默认实现在每次访问时也会返回不同的UIRefreshControl
,并在每次访问时修改collectionView
。我想这些都不是你的意思。
正如vadian所说,如果您想自动修改collectionView.refreshControl
,我想这里就是基类。遵守协议绝不应引起其他属性的隐式更改,并且在大多数情况下不会。想象一下PopularMovieVC
是否与另一个模块的扩展名中的MovieDisplay
相符。充其量只会导致混乱。
协议一致性扩展了类型的使用方式,例如添加新方法。它不会改变类型本身。如果您想更改类型本身,则需要继承或组合之类的东西,而不是协议一致性。
如果您要这样做,我就不会以这种方式使用协议。我只会创建这样的扩展程序:
extension UIRefreshControl {
static func makeStandard(attachedTo collectionView: UICollectionView) -> UIRefreshControl {
let rc = UIRefreshControl()
rc.backgroundColor = .clear
rc.tintColor = .lightGray
if #available(iOS 10.0, *) {
collectionView.refreshControl = rc
} else {
// Fallback on earlier versions
collectionView.addSubview(rc)
}
return rc
}
}
extension UIActivityIndicatorView {
static func makeStandard() -> UIActivityIndicatorView {
return UIActivityIndicatorView(style: .gray)
}
}
然后您的视图控制器可能如下所示:
class MyViewController: UIViewController {
private var refreshController: UIRefreshControl!
@IBOutlet var collectionView: UICollectionView!
let activityIndicator = UIActivityIndicatorView.makeStandard()
override func viewDidLoad() {
refreshController = .makeStandard(attachedTo: collectionView)
}
}
不需要协议,这使您可以在同一视图控制器或任何其他异常情况下处理多个集合视图。这也使调用此方法将修改集合视图更加清楚。