视图控制器之间的共享UI功能

时间:2016-09-30 01:56:13

标签: ios swift

我有一些与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仍然能够达到这些功能呢?

2 个答案:

答案 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
        }
    }
}