编写具有一些网络活动的应用程序我发现自己一遍又一遍地为多个视图控制器编写相同的代码,只是为了显示一个活动指示器。
class SomeViewController: UIViewController {
let indicator: UIActivityIndicatorView = UIActivityIndicatorView(frame: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0))
override func viewDidLoad() {
super.viewDidLoad()
// customize indicator
self.indicator.layer.cornerRadius = 10
self.indicator.center = self.view.center
self.indicator.hidesWhenStopped = true
self.indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.whiteLarge
self.indicator.backgroundColor = UIColor(red: 1/255, green: 1/255, blue: 1/255, alpha: 0.5)
}
// MARK: - Acitivity Indicator
func startIndicatingActivity() {
DispatchQueue.main.async {
self.view.addSubview(self.indicator)
self.indicator.startAnimating()
}
}
func stopIndicatingActivity() {
DispatchQueue.main.async {
self.indicator.stopAnimating()
}
}
}
在同一SomeViewController
课程中,我可以按如下方式使用它:
@IBAction func startHeavyNetworkStuffButtonPressed(_ sender: UIButton) {
startIndicatingActivity()
doHeavyNetworkStuff() { success in
// heavy networking has finished
stopIndicatingActivity()
}
}
只要我只需要在单个视图控制器中显示活动指示器,这就可以正常工作。但是,对于需要此功能的每个视图控制器来说,一遍又一遍地执行它是很繁琐的。当我 讨厌一遍又一遍地编写相同的代码时,我正在寻找一个我可以简单地调用的解决方案
任何视图控制器中都有startIndicatingActivity()
(和stopIndicatingActivity()
)。
我明显的第一个想法是为UIViewController
类写一个扩展名。因为我需要存储UIActivityIndicatorView
的实例,但我收到了Extensions may not contain stored properties
错误。
接下来:继承UIViewController
。这适用于任何简单的视图控制器。但是,如果我需要MyCustomTableViewController
的相同功能,我会再次需要先从UITableViewController
继承,然后复制/粘贴现有代码。
是否有一种优雅的方法可以在任何视图控制器中调用startIndicatingActivity()
/ stopIndicatingActivity()
,同时避免复制/粘贴大量代码?我假设一个优雅的解决方案涉及extension
,protocol
或某种多继承方法。
答案 0 :(得分:2)
This SO thread是解决方案!毕竟, 有一种方法可以用extension
和模拟属性来解决这个问题。
为感兴趣的读者发布完整的解决方案:
UIViewController
extension UIViewController {
// see ObjectAssociation<T> class below
private static let association = ObjectAssociation<UIActivityIndicatorView>()
var indicator: UIActivityIndicatorView {
set { UIViewController.association[self] = newValue }
get {
if let indicator = UIViewController.association[self] {
return indicator
} else {
UIViewController.association[self] = UIActivityIndicatorView.customIndicator(at: self.view.center)
return UIViewController.association[self]!
}
}
}
// MARK: - Acitivity Indicator
public func startIndicatingActivity() {
DispatchQueue.main.async {
self.view.addSubview(self.indicator)
self.indicator.startAnimating()
//UIApplication.shared.beginIgnoringInteractionEvents() // if desired
}
}
public func stopIndicatingActivity() {
DispatchQueue.main.async {
self.indicator.stopAnimating()
//UIApplication.shared.endIgnoringInteractionEvents()
}
}
}
// source: https://stackoverflow.com/questions/25426780/how-to-have-stored-properties-in-swift-the-same-way-i-had-on-objective-c
public final class ObjectAssociation<T: AnyObject> {
private let policy: objc_AssociationPolicy
/// - Parameter policy: An association policy that will be used when linking objects.
public init(policy: objc_AssociationPolicy = .OBJC_ASSOCIATION_RETAIN_NONATOMIC) {
self.policy = policy
}
/// Accesses associated object.
/// - Parameter index: An object whose associated object is to be accessed.
public subscript(index: AnyObject) -> T? {
get { return objc_getAssociatedObject(index, Unmanaged.passUnretained(self).toOpaque()) as! T? }
set { objc_setAssociatedObject(index, Unmanaged.passUnretained(self).toOpaque(), newValue, policy) }
}
}
我还使用自定义的静态函数扩展了UIActivityIndicatorView
类。
extension UIActivityIndicatorView {
public static func customIndicator(at center: CGPoint) -> UIActivityIndicatorView {
let indicator = UIActivityIndicatorView(frame: CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0))
indicator.layer.cornerRadius = 10
indicator.center = center
indicator.hidesWhenStopped = true
indicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.whiteLarge
indicator.backgroundColor = UIColor(red: 1/255, green: 1/255, blue: 1/255, alpha: 0.5)
return indicator
}
}
答案 1 :(得分:1)
示例在任何视图中显示完全加载
extension UIView{
/**
ShowLoader: loading view ..
- parameter Color: ActivityIndicator and view loading color .
*/
func showLoader(_ color:UIColor?){
let LoaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height))
LoaderView.tag = -888754
LoaderView.backgroundColor = color
let Loader = UIActivityIndicatorView(frame: CGRect(x: 0, y: 0, width: 60, height: 30))
Loader.center = LoaderView.center
Loader.activityIndicatorViewStyle = .whiteLarge
Loader.color = Color.primaryColor
Loader.startAnimating()
LoaderView.addSubview(Loader)
self.addSubview(LoaderView)
}
/**
dismissLoader: hidden loading view ..
*/
func dismissLoader(){
self.viewWithTag(-888754)?.removeFromSuperview()
}
}
调用此函数
UIViewController
中的
self.view.showLoader(nil) //you can set background color nil or any color
// dismiss
self.view.dismissLoader()
我更喜欢这种方法,因为您可以在
中使用任何视图button , tableview , cell ...etc