ios - 如何通过协议(protocol)展示 View ?

标签 ios swift

我想检测网络状态,当网络状态发生变化时,在当前 Controller 中显示错误 View 。但是使用协议(protocol)有一个问题。 这是代码:

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)

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() {

}

}

谁能告诉我怎么解决?这真的让我抓狂。非常感谢。

最佳答案

您的设置问题在于,使 UIViewController 符合您的协议(protocol)不允许您在子类中接收该调用。如果您尝试重写子类中的协议(protocol)函数,您将收到编译器错误:来自扩展的声明还不能被重写

首先,关于通知中心的说明。如果您需要应用程序的多个部分收到更改通知,这将是一个好方法。如果您只需要告诉一个 Controller ,这是委托(delegate)的经典用法。

这里有两种获得所需功能的方法:使用委托(delegate)模式和不使用委托(delegate)模式。 假设 Manager 是进行监视的类:

使用委托(delegate)模式

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)
        }
    }
}

同样的 Manager 没有委托(delegate)模式。这将是解决当前实现问题的最简单的方法。

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)
        }
    }
}

然后是你的 View Controller

class MyController : UIViewController, NetworkStatusDelegate {

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

此外,与您的问题没有直接关系,但在这个示例中,我使用了稍微不同的协议(protocol)设计方法,这对于面向“状态”的协议(protocol)很有帮助。随着协议(protocol)变得越来越大,拥有多个功能通常会变得更加繁琐。

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

关于ios - 如何通过协议(protocol)展示 View ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43648801/

相关文章:

regex - 解码正则表达式以了解它是否仅允许数字

ios - 如何在调用索引后从数组中永久删除项目?

ios - 在 iOS 中与服务器保持持续连接

ios - (Swift 3)我需要向用户发送通知以在特定时间打开应用程序。使用本地通知还是推送通知更好?

iphone - 具有多个参数的 performSelectorOnMainThread

ios - uitablviewcell 动态高度与 systemLayoutSizeFittingSize 不正确

ios - 将 CocoaPods 与 Xcode 一起使用时出现 Apple Mach-O 链接器错误

ios - UITableView 中的可变高度单元格仅在单元格不在 View 中时才有效

ios - 如何使用 UIKit 更快地渲染具有效果的图像

ios - 如何在 XCode 中更有效地复制 objective-c 方法名称?