脱机时在 UIWebView 后面显示文本



我想知道是否有一种方法可以让UIWebView在离线时透视。我想在其后面显示"此应用程序需要互联网"文本,以便在您无法访问互联网时显示它。这可能吗?

任何帮助不胜感激! :)

使用可达性在网络连接脱机时继续监视。当它处于脱机状态时,隐藏 UIWebView 并在其后面显示相同大小的 UILabel。反之亦然,当网络连接时。

通常你可以直接从苹果官方网站下载Reachability,但我更喜欢Ashley Mills对他的github页面的快速翻译(在Rechability的副本下方.swift以防万一)。必须在项目中导入此文件。

如您所见,线条很少。我举个例子给一个UIViewController但你可以在你的UIWebViewController或任何你想要的地方实现它:

let reachability = Reachability.reachabilityForInternetConnection()
    override func viewDidLoad() {
        super.viewDidLoad()
        NSNotificationCenter.defaultCenter().addObserver(self, selector:#selector(ViewController.checkReachability(_:)), name: ReachabilityChangedNotification, object: reachability)
        reachability?.startNotifier()
    }
    func checkReachability(note: NSNotification) {
        reachability?.startNotifier()
        if reachability!.isReachable() {
            if reachability!.isReachableViaWiFi() {
                print("∙ reachability via WIFI enabled")
            } else {
                print("∙ reachability via 3G/4G enabled")
            }
        } else {
            print("∙ network is unreachable..")
            let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
            let alert = UIAlertController(title: "No internet", message:"No internet connection available!", preferredStyle: .Alert)
            alert.addAction(UIAlertAction(title: "OK", style: .Default) { _ in })
            appDelegate.window?.rootViewController?.presentViewController(alert, animated: true){}
            // Here you can put also a label, or an HTML page to show "no internet connection", do whatever you want to alert your connection status
        }
    }

可访问性的副本.swift :

import SystemConfiguration
import Foundation
public let ReachabilityChangedNotification = "ReachabilityChangedNotification"
func callback(reachability:SCNetworkReachability, flags: SCNetworkReachabilityFlags, info: UnsafeMutablePointer<Void>) {
    let reachability = Unmanaged<Reachability>.fromOpaque(COpaquePointer(info)).takeUnretainedValue()
    dispatch_async(dispatch_get_main_queue()) {
        reachability.reachabilityChanged(flags)
    }
}

public class Reachability: NSObject {
    public typealias NetworkReachable = (Reachability) -> ()
    public typealias NetworkUnreachable = (Reachability) -> ()
    public enum NetworkStatus: CustomStringConvertible {
        case NotReachable, ReachableViaWiFi, ReachableViaWWAN
        public var description: String {
            switch self {
            case .ReachableViaWWAN:
                return "Cellular"
            case .ReachableViaWiFi:
                return "WiFi"
            case .NotReachable:
                return "No Connection"
            }
        }
    }
    // MARK: - *** Public properties ***
    public var whenReachable: NetworkReachable?
    public var whenUnreachable: NetworkUnreachable?
    public var reachableOnWWAN: Bool
    public var notificationCenter = NSNotificationCenter.defaultCenter()
    public var currentReachabilityStatus: NetworkStatus {
        if isReachable() {
            if isReachableViaWiFi() {
                return .ReachableViaWiFi
            }
            if isRunningOnDevice {
                return .ReachableViaWWAN
            }
        }
        return .NotReachable
    }
    public var currentReachabilityString: String {
        return "(currentReachabilityStatus)"
    }
    // MARK: - *** Initialisation methods ***
    required public init?(reachabilityRef: SCNetworkReachability?) {
        reachableOnWWAN = true
        self.reachabilityRef = reachabilityRef
    }
    public convenience init?(hostname: String) {
        let nodename = (hostname as NSString).UTF8String
        let ref = SCNetworkReachabilityCreateWithName(nil, nodename)
        self.init(reachabilityRef: ref)
    }
    public class func reachabilityForInternetConnection() -> Reachability? {
        var zeroAddress = sockaddr_in()
        zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)
        let ref = withUnsafePointer(&zeroAddress) {
            SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
        }
        return Reachability(reachabilityRef: ref)
    }
    public class func reachabilityForLocalWiFi() -> Reachability? {
        var localWifiAddress: sockaddr_in = sockaddr_in(sin_len: __uint8_t(0), sin_family: sa_family_t(0), sin_port: in_port_t(0), sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
        localWifiAddress.sin_len = UInt8(sizeofValue(localWifiAddress))
        localWifiAddress.sin_family = sa_family_t(AF_INET)
        // IN_LINKLOCALNETNUM is defined in <netinet/in.h> as 169.254.0.0
        let address: UInt32 = 0xA9FE0000
        localWifiAddress.sin_addr.s_addr = in_addr_t(address.bigEndian)
        let ref = withUnsafePointer(&localWifiAddress) {
            SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
        }
        return Reachability(reachabilityRef: ref)
    }
    // MARK: - *** Notifier methods ***
    public func startNotifier() -> Bool {
        if notifierRunning { return true }
        var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
        context.info = UnsafeMutablePointer(Unmanaged.passUnretained(self).toOpaque())
        if SCNetworkReachabilitySetCallback(reachabilityRef!, callback, &context) {
            if SCNetworkReachabilitySetDispatchQueue(reachabilityRef!, reachabilitySerialQueue) {
                notifierRunning = true
                return true
            }
        }
        stopNotifier()
        return false
    }

    public func stopNotifier() {
        if let reachabilityRef = reachabilityRef {
            SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil)
        }
        notifierRunning = false
    }
    // MARK: - *** Connection test methods ***
    public func isReachable() -> Bool {
        return isReachableWithTest({ (flags: SCNetworkReachabilityFlags) -> (Bool) in
            return self.isReachableWithFlags(flags)
        })
    }
    public func isReachableViaWWAN() -> Bool {
        if isRunningOnDevice {
            return isReachableWithTest() { flags -> Bool in
                // Check we're REACHABLE
                if self.isReachable(flags) {
                    // Now, check we're on WWAN
                    if self.isOnWWAN(flags) {
                        return true
                    }
                }
                return false
            }
        }
        return false
    }
    public func isReachableViaWiFi() -> Bool {
        return isReachableWithTest() { flags -> Bool in
            // Check we're reachable
            if self.isReachable(flags) {
                if self.isRunningOnDevice {
                    // Check we're NOT on WWAN
                    if self.isOnWWAN(flags) {
                        return false
                    }
                }
                return true
            }
            return false
        }
    }
    // MARK: - *** Private methods ***
    private var isRunningOnDevice: Bool = {
        #if (arch(i386) || arch(x86_64)) && os(iOS)
            return false
            #else
            return true
        #endif
        }()
    private var notifierRunning = false
    private var reachabilityRef: SCNetworkReachability?
    private let reachabilitySerialQueue = dispatch_queue_create("uk.co.ashleymills.reachability", DISPATCH_QUEUE_SERIAL)
    private func reachabilityChanged(flags: SCNetworkReachabilityFlags) {
        if isReachableWithFlags(flags) {
            if let block = whenReachable {
                block(self)
            }
        } else {
            if let block = whenUnreachable {
                block(self)
            }
        }
        notificationCenter.postNotificationName(ReachabilityChangedNotification, object:self)
    }
    private func isReachableWithFlags(flags: SCNetworkReachabilityFlags) -> Bool {
        let reachable = isReachable(flags)
        if !reachable {
            return false
        }
        if isConnectionRequiredOrTransient(flags) {
            return false
        }
        if isRunningOnDevice {
            if isOnWWAN(flags) && !reachableOnWWAN {
                // We don't want to connect when on 3G.
                return false
            }
        }
        return true
    }
    private func isReachableWithTest(test: (SCNetworkReachabilityFlags) -> (Bool)) -> Bool {
        if let reachabilityRef = reachabilityRef {
            var flags = SCNetworkReachabilityFlags(rawValue: 0)
            let gotFlags = withUnsafeMutablePointer(&flags) {
                SCNetworkReachabilityGetFlags(reachabilityRef, UnsafeMutablePointer($0))
            }
            if gotFlags {
                return test(flags)
            }
        }
        return false
    }
    // WWAN may be available, but not active until a connection has been established.
    // WiFi may require a connection for VPN on Demand.
    private func isConnectionRequired() -> Bool {
        return connectionRequired()
    }
    private func connectionRequired() -> Bool {
        return isReachableWithTest({ (flags: SCNetworkReachabilityFlags) -> (Bool) in
            return self.isConnectionRequired(flags)
        })
    }
    // Dynamic, on demand connection?
    private func isConnectionOnDemand() -> Bool {
        return isReachableWithTest({ (flags: SCNetworkReachabilityFlags) -> (Bool) in
            return self.isConnectionRequired(flags) && self.isConnectionOnTrafficOrDemand(flags)
        })
    }
    // Is user intervention required?
    private func isInterventionRequired() -> Bool {
        return isReachableWithTest({ (flags: SCNetworkReachabilityFlags) -> (Bool) in
            return self.isConnectionRequired(flags) && self.isInterventionRequired(flags)
        })
    }
    private func isOnWWAN(flags: SCNetworkReachabilityFlags) -> Bool {
        #if os(iOS)
            return flags.contains(.IsWWAN)
        #else
            return false
        #endif
    }
    private func isReachable(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.Reachable)
    }
    private func isConnectionRequired(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.ConnectionRequired)
    }
    private func isInterventionRequired(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.InterventionRequired)
    }
    private func isConnectionOnTraffic(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.ConnectionOnTraffic)
    }
    private func isConnectionOnDemand(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.ConnectionOnDemand)
    }
    func isConnectionOnTrafficOrDemand(flags: SCNetworkReachabilityFlags) -> Bool {
        return !flags.intersect([.ConnectionOnTraffic, .ConnectionOnDemand]).isEmpty
    }
    private func isTransientConnection(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.TransientConnection)
    }
    private func isLocalAddress(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.IsLocalAddress)
    }
    private func isDirect(flags: SCNetworkReachabilityFlags) -> Bool {
        return flags.contains(.IsDirect)
    }
    private func isConnectionRequiredOrTransient(flags: SCNetworkReachabilityFlags) -> Bool {
        let testcase:SCNetworkReachabilityFlags = [.ConnectionRequired, .TransientConnection]
        return flags.intersect(testcase) == testcase
    }
    private var reachabilityFlags: SCNetworkReachabilityFlags {
        if let reachabilityRef = reachabilityRef {
            var flags = SCNetworkReachabilityFlags(rawValue: 0)
            let gotFlags = withUnsafeMutablePointer(&flags) {
                SCNetworkReachabilityGetFlags(reachabilityRef, UnsafeMutablePointer($0))
            }
            if gotFlags {
                return flags
            }
        }
        return []
    }
    override public var description: String {
        var W: String
        if isRunningOnDevice {
            W = isOnWWAN(reachabilityFlags) ? "W" : "-"
        } else {
            W = "X"
        }
        let R = isReachable(reachabilityFlags) ? "R" : "-"
        let c = isConnectionRequired(reachabilityFlags) ? "c" : "-"
        let t = isTransientConnection(reachabilityFlags) ? "t" : "-"
        let i = isInterventionRequired(reachabilityFlags) ? "i" : "-"
        let C = isConnectionOnTraffic(reachabilityFlags) ? "C" : "-"
        let D = isConnectionOnDemand(reachabilityFlags) ? "D" : "-"
        let l = isLocalAddress(reachabilityFlags) ? "l" : "-"
        let d = isDirect(reachabilityFlags) ? "d" : "-"
        return "(W)(R) (c)(t)(i)(C)(D)(l)(d)"
    }
    deinit {
        stopNotifier()
        reachabilityRef = nil
        whenReachable = nil
        whenUnreachable = nil
    }
}

一个非常简单的方法如下:

  1. 创建一个显示花哨的"没有互联网连接"文本的HTML文件。我创建了简单的html文件来显示这一点。HTML 文件名为 nointernet.html ,将此文件添加到您的项目中。

<html>
    <body>
        </br></br></br></br></br></br>
        <p>You need internet connection to use this application.</p>
    </body>
</html>
  1. 实现以下UIWebView委托方法:

    - shouldStartLoadWithRequest:navigationType:
    - didFailLoadWithError:
    
  2. viewDidLoad方法中设置webView?.delegate = self

  3. 现在,当没有互联网连接时,将调用 webView 的didFailLoadWithError委托方法。编写下面的代码以显示来自HTML文件的"无互联网连接"消息。

    func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
        return true
    }
    func webView(webView: UIWebView, didFailLoadWithError error: NSError?) {
        print("Did fail to load")
        let htmlFilePath : String! = NSBundle.mainBundle() .pathForResource("nointernet", ofType: "html")
        if let htmlString = try? String(contentsOfFile: htmlFilePath!) {
            webView.loadHTMLString(htmlString, baseURL: NSBundle.mainBundle().bundleURL)
        }
    }
    

最新更新