我有一些与UI相关的功能,例如显示警告弹出窗口,在屏幕中间显示一个活动指示器,或者在屏幕上显示一个带有自定义消息的动画UIView。我想在多个viewControllers中使用( VC1和VC2在这种情况下)所以我不重复自己。
最初,我有以下代码,可以使用两个VC继承BaseVC,负责这些功能。
VC1是一个嵌入了tablelView的UIViewController,VC2是一个嵌入了collectionView的UIViewController。
class VC1: BaseVC {
func viewDidAppear(animated: Bool) {
activityIndicatorBegin()
}
func btnPressed() {
activityIndicatorEnd()
}
}
class VC2: BaseVC {
func viewDidAppear(animated: Bool) {
activityIndicatorBegin()
}
func btnPressed() {
activityIndicatorEnd()
}
}
class BaseVC: UIViewController {
var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView()
var isCustomViewOnScreen = false
func activityIndicatorBegin() {
if activityIndicator.isAnimating() == false {
activityIndicator = UIActivityIndicatorView(frame: CGRectMake(0,0,20,20))
activityIndicator.center = view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.WhiteLarge
activityIndicator.color = UIColor.blackColor()
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
}
}
func activityIndicatorEnd() {
if activityIndicator.isAnimating() == true {
activityIndicator.stopAnimating()
activityIndicator.removeFromSuperview()
}
}
func animateACustomViewOnScreen() {
if isCustomViewOnScreen == false {
// Some animation code
}
}
func removeCustomView() {
if isCustomViewOnScreen == true {
// Some removal code
}
}
}
但是,由于某些原因,我决定从UICollectionViewController直接为UITableViewController和VC2创建VC1。
这意味着它们不再能从这个UIViewController类的BaseVC中出现。我怎么能这样做才能让两个VC仍然能够达到这些功能呢?
答案 0 :(得分:4)
答案是Protocol Extensions
。您将BaseVC
定义为协议,然后通过添加将在实现它的类中使用的共享逻辑来扩展它:
(在以下示例中,BaseVC重命名为ActivityIndicatorDisplaying
。)
protocol ActivityIndicatorDisplaying {
var activityIndicator: UIActivityIndicatorView { get set }
var showsCustomView: Bool { get }
func showActivityIndicator()
func dismissActivityIndicator()
}
extension ActivityIndicatorDisplaying where Self: UIViewController {
func showActivityIndicator() {
if activityIndicator.isAnimating() { return }
activityIndicator.center = CGPointMake(view.bounds.width / 2, view.bounds.height / 2)
activityIndicator.hidesWhenStopped = true
activityIndicator.activityIndicatorViewStyle = .WhiteLarge
activityIndicator.color = UIColor.blackColor()
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
}
func dismissActivityIndicator() {
activityIndicator.stopAnimating()
activityIndicator.removeFromSuperview()
}
func animateACustomViewOnScreen() {
if !showsCustomView {
// Some animation code
}
}
func removeCustomView() {
if showsCustomView {
// Some removal code
}
}
}
class VC1: UITableViewController, ActivityIndicatorDisplaying {
var activityIndicator = UIActivityIndicatorView()
var showsCustomView: Bool = false
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
showActivityIndicator()
}
func btnPressed() {
dismissActivityIndicator()
}
}
class VC2: UICollectionViewController, ActivityIndicatorDisplaying {
var activityIndicator = UIActivityIndicatorView()
var showsCustomView: Bool = true
...
}
答案 1 :(得分:0)
为什么不将UIActivityViewController本身子类化? 这将更合乎逻辑,更清晰。
class VC1: UIViewController {
var customActivityIndicatorView: CustomActivityIndicatorView? = nil
func viewDidAppear(animated: Bool) {
if let view = view {
customActivityIndicatorView = CustomActivityIndicatorView(parentView: view)
}
}
func btnPressed() {
customActivityIndicatorView?.end()
}
}
class VC2: UITableViewController {
var customActivityIndicatorView: CustomActivityIndicatorView? = nil
func viewDidAppear(animated: Bool) {
if let view = view {
customActivityIndicatorView = CustomActivityIndicatorView(parentView: view)
}
}
func btnPressed() {
customActivityIndicatorView?.end()
}
}
class CustomActivityIndicatorView: UIActivityIndicatorView {
var isCustomViewOnScreen = false
convenience init?(parentView: UIView) {
if isAnimating == false {
self.init(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
center = parentView.center
hidesWhenStopped = true
activityIndicatorViewStyle = UIActivityIndicatorViewStyle.whiteLarge
color = UIColor.black
parentView.addSubview(self)
startAnimating()
} else {
return nil
}
}
func end() {
if isAnimating == true {
stopAnimating()
removeFromSuperview()
}
}
func animateACustomViewOnScreen() {
if isCustomViewOnScreen == false {
// Some animation code
}
}
func removeCustomView() {
if isCustomViewOnScreen == true {
// Some removal code
}
}
}