Bạn có ứng dụng yêu cầu kết nối
mạng, để trước khi vào phần dùng mạng khỏi bị lỗi, ta sẽ kiểm tra xem đã có kết
nối mạng chưa, nếu có mới cho sang.
Tạo một class có tên Reachability, copy toàn bộ code dưới đây vào.
/*Copyright (c) 2014,
Ashley Mills
All rights reserved.
Redistribution and use in source and binary
forms, with or without
modification, are permitted provided that the
following conditions are met:
1. Redistributions of source code must retain
the above copyright notice, this
list of conditions and the following
disclaimer.
2. Redistributions in binary form must
reproduce the above copyright notice,
this list of conditions and the following
disclaimer in the documentation
and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT
HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
import Foundation
import SystemConfiguration
//import Foundation
publicenum ReachabilityError: ErrorType {
case FailedToCreateWithAddress(sockaddr_in)
case FailedToCreateWithHostname(String)
case UnableToSetCallback
case UnableToSetDispatchQueue
}
publiclet 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)
}
}
publicclass Reachability: NSObject {
publictypealias NetworkReachable = (Reachability) -> ()
publictypealias NetworkUnreachable = (Reachability) -> ()
publicenum NetworkStatus: CustomStringConvertible {
case NotReachable, ReachableViaWiFi, ReachableViaWWAN
publicvar description: String {
switchself {
case .ReachableViaWWAN:
return"Cellular"
case .ReachableViaWiFi:
return"WiFi"
case .NotReachable:
return"No Connection"
}
}
}
// MARK: - *** Public
properties ***
publicvar whenReachable: NetworkReachable?
publicvar whenUnreachable: NetworkUnreachable?
publicvar reachableOnWWAN: Bool
publicvar notificationCenter = NSNotificationCenter.defaultCenter()
publicvar currentReachabilityStatus: NetworkStatus {
ifisReachable() {
ifisReachableViaWiFi() {
return .ReachableViaWiFi
}
ifisRunningOnDevice {
return .ReachableViaWWAN
}
}
return .NotReachable
}
publicvar currentReachabilityString: String {
return"\(currentReachabilityStatus)"
}
privatevar previousFlags: SCNetworkReachabilityFlags?
// MARK: - *** Initialisation
methods ***
requiredpublicinit(reachabilityRef: SCNetworkReachability) {
reachableOnWWAN = true
self.reachabilityRef = reachabilityRef
}
publicconvenienceinit(hostname: String) throws {
let nodename = (hostname asNSString).UTF8String
guardlet ref = SCNetworkReachabilityCreateWithName(nil, nodename) else { throwReachabilityError.FailedToCreateWithHostname(hostname) }
self.init(reachabilityRef: ref)
}
publicclassfunc reachabilityForInternetConnection() throws ->Reachability {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
guardlet ref = withUnsafePointer(&zeroAddress, {
SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
}) else { throwReachabilityError.FailedToCreateWithAddress(zeroAddress) }
returnReachability(reachabilityRef: ref)
}
publicclassfunc reachabilityForLocalWiFi() throws ->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)
guardlet ref = withUnsafePointer(&localWifiAddress, {
SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
}) else { throwReachabilityError.FailedToCreateWithAddress(localWifiAddress) }
returnReachability(reachabilityRef: ref)
}
// MARK: - ***
Notifier methods ***
publicfunc startNotifier() throws {
guard !notifierRunningelse { return }
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) {
stopNotifier()
throwReachabilityError.UnableToSetCallback
}
if !SCNetworkReachabilitySetDispatchQueue(reachabilityRef!, reachabilitySerialQueue) {
stopNotifier()
throwReachabilityError.UnableToSetDispatchQueue
}
// Perform an intial
check
dispatch_async(reachabilitySerialQueue) { () ->Voidin
let flags = self.reachabilityFlags
self.reachabilityChanged(flags)
}
notifierRunning = true
}
publicfunc stopNotifier() {
defer { notifierRunning = false }
guardlet reachabilityRef = reachabilityRefelse { return }
SCNetworkReachabilitySetCallback(reachabilityRef, nil, nil)
SCNetworkReachabilitySetDispatchQueue(reachabilityRef, nil)
}
// MARK: - ***
Connection test methods ***
publicfunc isReachable() ->Bool {
let flags = reachabilityFlags
returnisReachableWithFlags(flags)
}
publicfunc isReachableViaWWAN() ->Bool {
let flags = reachabilityFlags
// Check we're not on
the simulator, we're REACHABLE and check we're on WWAN
returnisRunningOnDevice&&isReachable(flags) &&isOnWWAN(flags)
}
publicfunc isReachableViaWiFi() ->Bool {
let flags = reachabilityFlags
// Check we're
reachable
if !isReachable(flags) {
returnfalse
}
// Must be on WiFi if
reachable but not on an iOS device (i.e. simulator)
if !isRunningOnDevice {
returntrue
}
// Check we're NOT on
WWAN
return !isOnWWAN(flags)
}
// MARK: - *** Private
methods ***
privatevar isRunningOnDevice: Bool = {
#if (arch(i386) || arch(x86_64)) &&os(iOS)
returnfalse
#else
returntrue
#endif
}()
privatevar notifierRunning = false
privatevar reachabilityRef: SCNetworkReachability?
privatelet reachabilitySerialQueue = dispatch_queue_create("uk.co.ashleymills.reachability", DISPATCH_QUEUE_SERIAL)
privatefunc reachabilityChanged(flags: SCNetworkReachabilityFlags) {
guardpreviousFlags != flags else { return }
ifisReachableWithFlags(flags) {
iflet block = whenReachable {
block(self)
}
} else {
iflet block = whenUnreachable {
block(self)
}
}
notificationCenter.postNotificationName(ReachabilityChangedNotification, object:self)
previousFlags = flags
}
privatefunc isReachableWithFlags(flags: SCNetworkReachabilityFlags) ->Bool {
if !isReachable(flags) {
returnfalse
}
ifisConnectionRequiredOrTransient(flags) {
returnfalse
}
ifisRunningOnDevice {
ifisOnWWAN(flags) && !reachableOnWWAN {
// We don't want to
connect when on 3G.
returnfalse
}
}
returntrue
}
// WWAN may be
available, but not active until a connection has been established.
// WiFi may require a
connection for VPN on Demand.
privatefunc isConnectionRequired() ->Bool {
returnconnectionRequired()
}
privatefunc connectionRequired() ->Bool {
let flags = reachabilityFlags
returnisConnectionRequired(flags)
}
// Dynamic, on demand
connection?
privatefunc isConnectionOnDemand() ->Bool {
let flags = reachabilityFlags
returnisConnectionRequired(flags) &&isConnectionOnTrafficOrDemand(flags)
}
// Is user
intervention required?
privatefunc isInterventionRequired() ->Bool {
let flags = reachabilityFlags
returnisConnectionRequired(flags) &&isInterventionRequired(flags)
}
privatefunc isOnWWAN(flags: SCNetworkReachabilityFlags) ->Bool {
#ifos(iOS)
return flags.contains(.IsWWAN)
#else
returnfalse
#endif
}
privatefunc isReachable(flags: SCNetworkReachabilityFlags) ->Bool {
return flags.contains(.Reachable)
}
privatefunc isConnectionRequired(flags: SCNetworkReachabilityFlags) ->Bool {
return flags.contains(.ConnectionRequired)
}
privatefunc isInterventionRequired(flags: SCNetworkReachabilityFlags) ->Bool {
return flags.contains(.InterventionRequired)
}
privatefunc isConnectionOnTraffic(flags: SCNetworkReachabilityFlags) ->Bool {
return flags.contains(.ConnectionOnTraffic)
}
privatefunc isConnectionOnDemand(flags: SCNetworkReachabilityFlags) ->Bool {
return flags.contains(.ConnectionOnDemand)
}
func isConnectionOnTrafficOrDemand(flags: SCNetworkReachabilityFlags) ->Bool {
return !flags.intersect([.ConnectionOnTraffic, .ConnectionOnDemand]).isEmpty
}
privatefunc isTransientConnection(flags: SCNetworkReachabilityFlags) ->Bool {
return flags.contains(.TransientConnection)
}
privatefunc isLocalAddress(flags: SCNetworkReachabilityFlags) ->Bool {
return flags.contains(.IsLocalAddress)
}
privatefunc isDirect(flags: SCNetworkReachabilityFlags) ->Bool {
return flags.contains(.IsDirect)
}
privatefunc isConnectionRequiredOrTransient(flags: SCNetworkReachabilityFlags) ->Bool {
let testcase:SCNetworkReachabilityFlags = [.ConnectionRequired,
.TransientConnection]
return flags.intersect(testcase) == testcase
}
privatevar reachabilityFlags: SCNetworkReachabilityFlags {
guardlet reachabilityRef = reachabilityRefelse { returnSCNetworkReachabilityFlags() }
var flags = SCNetworkReachabilityFlags()
let gotFlags = withUnsafeMutablePointer(&flags) {
SCNetworkReachabilityGetFlags(reachabilityRef, UnsafeMutablePointer($0))
}
if gotFlags {
return flags
} else {
returnSCNetworkReachabilityFlags()
}
}
overridepublicvar description: String {
var W: String
ifisRunningOnDevice {
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
}
}
Đây là đoạn code
free trên mạng, người public yêu cầu giữ nguyên đoạn comment mô tả trên cùng. Bạn
đọc thử xem các lập trình viên chuyên nghiệp bài bản thế nào khi cho code free.
Tiếp theo trong
class mà bạn chuẩn bị cho sử dụng kết nối mạng, giả sử bạn sẽ bật sang class
second cần dùng mạng, trước đó sẽ kiểm tra, nếu không có mạng hiện Dialog thông
báo, nếu có cho sang.
Hàm đó cho nút bấm
nào đó như sau.
func next(sender: UIButton){
do {
let reachability: Reachability = tryReachability.reachabilityForInternetConnection()
let networkStatus: Int = reachability.currentReachabilityStatus.hashValue
if networkStatus == 0{
var alert = UIAlertView(title: "No Internet Connection", message: "Bật 3G
hoặc wifi.", delegate: nil, cancelButtonTitle: "OK")
alert.show()
}
else{
let vc = second()
self.presentViewController(vc, animated: true, completion: nil)
}
}
catch {
// Handle error
}
}
Sau đó bạn set hàm
cho nút bấm trong viewDidLoad là được.
No comments:
Post a Comment