我想知道是否有一种方法可以让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
}
}
一个非常简单的方法如下:
- 创建一个显示花哨的"没有互联网连接"文本的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>
实现以下
UIWebView
委托方法:- shouldStartLoadWithRequest:navigationType: - didFailLoadWithError:
在
viewDidLoad
方法中设置webView?.delegate = self
现在,当没有互联网连接时,将调用 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) } }