2017-04-27 54 views
0

我想侦测网络状态,当网络状态改变时,在当前控制器中显示错误视图。但是使用协议存在问题。 这里是代码:如何通过协议显示视图?

private func networkingDetection() { 
    //This is the detective method in appdelegate 
    try! reachability.startNotifier() 

    reachability.whenReachable = { [weak self] _ in 
     DispatchQueue.main.async { 
      self?.currentViewController().hideNetworkingErrorView() 
     } 
    } 

    reachability.whenUnreachable = { [weak self] _ in 
     DispatchQueue.main.async { 
      self?.currentViewController().showNetworkingErrorView() 
     } 
    } 

} 

这里是协议

protocol NetworkingErrorProtocol { 
// I want to show the default view if there is no networkingErrorView, and 
when declare a custom view in controller, show the custom view. 
//var networkingErrorView: UIView? { get } 

func showNetworkingErrorView() 
func hideNetworkingErrorView() 

} 


extension UIViewController: NetworkingErrorProtocol { 
func showNetworkingErrorView() { 

} 
func hideNetworkingErrorView() { 

} 

}

谁能告诉我如何计算出来?这真的让我发疯。非常感谢。

+1

为什么您使用协议而不是NSNotification中心? – KKRocks

+0

什么是'currentViewController()'定义为? 'UIViewController'? – WCByrne

+0

我同意。 'NSNotificationCenter'会是一个更干净的方式 – Paulw11

回答

0

您的设置的问题是,符合UIViewController您的协议不允许您在您的子类中接收该调用。如果您尝试覆盖子类中的协议功能,您将收到编译器错误:Declarations from extensions cannot be overridden yet

首先,关于NotificationCenter的注意事项。如果您需要应用程序的多个部分才能收到变更通知,那么这将是一个好方法。如果你只需要告诉一个控制器,这是一个代表的经典用法。

以下是获得所需功能的两种方法:使用委托模式而不使用。 比方说Manager是其中监视正在发生的事情类:

使用委托模式

class Manager { 

    weak var networkDelegate : NetworkStatusListener? 

    func monitorNetworkStatus() { 

     var reachable = true; 
     if reachable { 
      // We can call the delegate directly 
      networkDelegate?.networkStatusChanged(.connected) 
     } 
     else { 
      networkDelegate?.networkStatusChanged(.disconnected) 
     } 
    } 
} 

而同样的经理没有代理模式。这将是解决当前实施问题的最简单方法。

class Manager { 

    func currentViewController() -> UIViewController { return vc } 

    func monitorNetworkStatus() { 
     var maybeAtListener = currentViewController() 

     // DON't SHIP THIS, but it can be helpful during development to make sure you didn't forget to conform one of your classes 
     assert(maybeAtListener is NetworkStatusListener, "Oops, did you mean to conform \(currentVC) to NetworkStatusListener") 

     var reachable = true; 
     if reachable { 
      // We can't be sure the controller conforms to the protocol but we can try 
      (maybeAtListener as? NetworkStatusListener)?.networkStatusChanged(.connected) 
     } 
     else { 
      (maybeAtListener as? NetworkStatusListener)?.networkStatusChanged(.connected) 
     } 
    } 
} 

那么对于您的视图控制器

class MyController : UIViewController, NetworkStatusDelegate { 

    func networkStatusChanged(_ status: NetworkStatus) { 
     switch status { 
     case .connected: 
      // Normal UI 
      break 
     case .disconnected: 
      // No network connect 
      break; 
     } 
    } 
} 

此外,不直接关系到你的问题,但在这个例子中我使用了一个稍微不同的方法,以该协议的设计,可以是“状态”乐于助人为本协议。随着协议变得越来越大,拥有多个功能通常会变得更加单调乏味。

enum NetworkStatus { 
    case connected 
    case disconnected 
} 
protocol NetworkStatusListener : class { 
    func networkStatusChanged(_ status: NetworkStatus) 
} 
0

使用可达性类的NSNotificationCenter

尝试的appdelegate的didFinishLaunchingWithOptions如果你想添加这个对整个应用程序

或在您的特定视图 - 控制,如果你想这个特定的ViewController

NotificationCenter.default.addObserver(self, selector:Selector(("checkForReachability:")), name: NSNotification.Name.reachabilityChanged, object: nil); 
let reachability: Reachability = Reachability.forInternetConnection(); 
reachability.startNotifier(); 
添加

在网络状态改变时调用此方法。

func checkForReachability(notification:NSNotification) 
     { 

      let networkReachability = notification.object as! Reachability; 
      _ = networkReachability.currentReachabilityStatus() 
      // do yor additional work here 
    }