get Users up
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright (c) 2014, Ashley Mills
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source, with or without modification, is permitted provided that the following condition is met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
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.
|
||||
*/
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
# Reachability.swift
|
||||
|
||||
Replacement for Apple's Reachability re-written in Swift with closures
|
||||
|
||||
Inspired by https://github.com/tonymillion/Reachability
|
||||
|
||||
**NOTES:**
|
||||
|
||||
- As of Swift 1.2, you cannot convert Swift closures into C-function pointers, meaning we can't set an `SCNetworkReachabilityCallBack`. To get around this, this reachability replacement uses a `dispatch_source` firing at 1/2 second intervals.
|
||||
|
||||
- If an application has the privacy option “Use cellular data” turned off, the Reachability class still reports isReachable() to be true. There is currently no (non-private) API to detect this. If you need this feature, please raise file a [bug report](https://bugreport.apple.com) with Apple to get this fixed. See devforums thread for details: https://devforums.apple.com/message/1059332#1059332
|
||||
|
||||
## Installation
|
||||
### CocoaPods
|
||||
[CocoaPods][] is a dependency manager for Cocoa projects. To install Reachability.swift with CocoaPods:
|
||||
|
||||
1. Make sure CocoaPods is [installed][CocoaPods Installation].
|
||||
|
||||
2. Update your Podfile to include the following:
|
||||
|
||||
``` ruby
|
||||
use_frameworks!
|
||||
pod 'ReachabilitySwift', git: 'https://github.com/ashleymills/Reachability.swift'
|
||||
```
|
||||
|
||||
3. Run `pod install`.
|
||||
|
||||
[CocoaPods]: https://cocoapods.org
|
||||
[CocoaPods Installation]: https://guides.cocoapods.org/using/getting-started.html#getting-started
|
||||
|
||||
### Manual
|
||||
Just drop the **Reachability.swift** file into your project. That's it!
|
||||
|
||||
## Example - closures
|
||||
|
||||
let reachability = Reachability.reachabilityForInternetConnection()
|
||||
|
||||
reachability.whenReachable = { reachability in
|
||||
if reachability.isReachableViaWiFi() {
|
||||
println("Reachable via WiFi")
|
||||
} else {
|
||||
println("Reachable via Cellular")
|
||||
}
|
||||
}
|
||||
reachability.whenUnreachable = { reachability in
|
||||
println("Not reachable")
|
||||
}
|
||||
|
||||
reachability.startNotifier()
|
||||
|
||||
## Example - notifications
|
||||
|
||||
let reachability = Reachability.reachabilityForInternetConnection()
|
||||
|
||||
NSNotificationCenter.defaultCenter().addObserver(self, selector: "reachabilityChanged:", name: ReachabilityChangedNotification, object: reachability)
|
||||
|
||||
reachability.startNotifier()
|
||||
|
||||
and
|
||||
|
||||
func reachabilityChanged(note: NSNotification) {
|
||||
|
||||
let reachability = note.object as! Reachability
|
||||
|
||||
if reachability.isReachable() {
|
||||
if reachability.isReachableViaWiFi() {
|
||||
println("Reachable via WiFi")
|
||||
} else {
|
||||
println("Reachable via Cellular")
|
||||
}
|
||||
} else {
|
||||
println("Not reachable")
|
||||
}
|
||||
}
|
||||
|
||||
## Want to help?
|
||||
|
||||
Got a bug fix, or a new feature? Create a pull request and go for it!
|
||||
|
||||
## Let me know!
|
||||
|
||||
If you use **Reachability.swift**, please let me know about your app and I'll put a link [here…](https://github.com/ashleymills/Reachability.swift/wiki/Apps-using-Reachability.swift) and tell your friends!
|
||||
|
||||
Cheers,
|
||||
Ash
|
||||
|
||||
+373
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
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 SystemConfiguration
|
||||
import Foundation
|
||||
|
||||
public let ReachabilityChangedNotification = "ReachabilityChangedNotification"
|
||||
|
||||
public class Reachability: NSObject, Printable {
|
||||
|
||||
public typealias NetworkReachable = (Reachability) -> ()
|
||||
public typealias NetworkUnreachable = (Reachability) -> ()
|
||||
|
||||
public enum NetworkStatus: Printable {
|
||||
|
||||
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 ***
|
||||
|
||||
public required init(reachabilityRef: SCNetworkReachability) {
|
||||
reachableOnWWAN = true
|
||||
self.reachabilityRef = reachabilityRef
|
||||
}
|
||||
|
||||
public convenience init(hostname: String) {
|
||||
let ref = SCNetworkReachabilityCreateWithName(nil, (hostname as NSString).UTF8String).takeRetainedValue()
|
||||
self.init(reachabilityRef: ref)
|
||||
}
|
||||
|
||||
public class func reachabilityForInternetConnection() -> Reachability {
|
||||
|
||||
var zeroAddress = 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))
|
||||
zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
|
||||
zeroAddress.sin_family = sa_family_t(AF_INET)
|
||||
|
||||
let ref = withUnsafePointer(&zeroAddress) {
|
||||
SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, UnsafePointer($0)).takeRetainedValue()
|
||||
}
|
||||
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: Int64 = 0xA9FE0000
|
||||
localWifiAddress.sin_addr.s_addr = in_addr_t(address.bigEndian)
|
||||
|
||||
let ref = withUnsafePointer(&localWifiAddress) {
|
||||
SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, UnsafePointer($0)).takeRetainedValue()
|
||||
}
|
||||
return Reachability(reachabilityRef: ref)
|
||||
}
|
||||
|
||||
// MARK: - *** Notifier methods ***
|
||||
public func startNotifier() -> Bool {
|
||||
|
||||
reachabilityObject = self
|
||||
let reachability = self.reachabilityRef!
|
||||
|
||||
previousReachabilityFlags = reachabilityFlags
|
||||
if let timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, timer_queue) {
|
||||
dispatch_source_set_timer(timer, dispatch_walltime(nil, 0), 500 * NSEC_PER_MSEC, 100 * NSEC_PER_MSEC)
|
||||
dispatch_source_set_event_handler(timer, { [unowned self] in
|
||||
self.timerFired()
|
||||
})
|
||||
|
||||
dispatch_timer = timer
|
||||
dispatch_resume(timer)
|
||||
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public func stopNotifier() {
|
||||
|
||||
reachabilityObject = nil
|
||||
|
||||
if let timer = dispatch_timer {
|
||||
dispatch_source_cancel(timer)
|
||||
dispatch_timer = nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 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 reachabilityRef: SCNetworkReachability?
|
||||
private var reachabilityObject: AnyObject?
|
||||
private var dispatch_timer: dispatch_source_t?
|
||||
private lazy var timer_queue: dispatch_queue_t = {
|
||||
return dispatch_queue_create("uk.co.joylordsystems.reachability_timer_queue", nil)
|
||||
}()
|
||||
private var previousReachabilityFlags: SCNetworkReachabilityFlags?
|
||||
|
||||
func timerFired() {
|
||||
let currentReachabilityFlags = reachabilityFlags
|
||||
if let _previousReachabilityFlags = previousReachabilityFlags {
|
||||
if currentReachabilityFlags != previousReachabilityFlags {
|
||||
dispatch_async(dispatch_get_main_queue(), { [unowned self] in
|
||||
self.reachabilityChanged(currentReachabilityFlags)
|
||||
self.previousReachabilityFlags = currentReachabilityFlags
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
var flags: SCNetworkReachabilityFlags = 0
|
||||
let gotFlags = SCNetworkReachabilityGetFlags(reachabilityRef, &flags) != 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 & SCNetworkReachabilityFlags(kSCNetworkReachabilityFlagsIsWWAN) != 0
|
||||
#else
|
||||
return false
|
||||
#endif
|
||||
}
|
||||
private func isReachable(flags: SCNetworkReachabilityFlags) -> Bool {
|
||||
return flags & SCNetworkReachabilityFlags(kSCNetworkReachabilityFlagsReachable) != 0
|
||||
}
|
||||
private func isConnectionRequired(flags: SCNetworkReachabilityFlags) -> Bool {
|
||||
return flags & SCNetworkReachabilityFlags(kSCNetworkReachabilityFlagsConnectionRequired) != 0
|
||||
}
|
||||
private func isInterventionRequired(flags: SCNetworkReachabilityFlags) -> Bool {
|
||||
return flags & SCNetworkReachabilityFlags(kSCNetworkReachabilityFlagsInterventionRequired) != 0
|
||||
}
|
||||
private func isConnectionOnTraffic(flags: SCNetworkReachabilityFlags) -> Bool {
|
||||
return flags & SCNetworkReachabilityFlags(kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0
|
||||
}
|
||||
private func isConnectionOnDemand(flags: SCNetworkReachabilityFlags) -> Bool {
|
||||
return flags & SCNetworkReachabilityFlags(kSCNetworkReachabilityFlagsConnectionOnDemand) != 0
|
||||
}
|
||||
func isConnectionOnTrafficOrDemand(flags: SCNetworkReachabilityFlags) -> Bool {
|
||||
return flags & SCNetworkReachabilityFlags(kSCNetworkReachabilityFlagsConnectionOnTraffic | kSCNetworkReachabilityFlagsConnectionOnDemand) != 0
|
||||
}
|
||||
private func isTransientConnection(flags: SCNetworkReachabilityFlags) -> Bool {
|
||||
return flags & SCNetworkReachabilityFlags(kSCNetworkReachabilityFlagsTransientConnection) != 0
|
||||
}
|
||||
private func isLocalAddress(flags: SCNetworkReachabilityFlags) -> Bool {
|
||||
return flags & SCNetworkReachabilityFlags(kSCNetworkReachabilityFlagsIsLocalAddress) != 0
|
||||
}
|
||||
private func isDirect(flags: SCNetworkReachabilityFlags) -> Bool {
|
||||
return flags & SCNetworkReachabilityFlags(kSCNetworkReachabilityFlagsIsDirect) != 0
|
||||
}
|
||||
private func isConnectionRequiredOrTransient(flags: SCNetworkReachabilityFlags) -> Bool {
|
||||
let testcase = SCNetworkReachabilityFlags(kSCNetworkReachabilityFlagsConnectionRequired | kSCNetworkReachabilityFlagsTransientConnection)
|
||||
return flags & testcase == testcase
|
||||
}
|
||||
|
||||
private var reachabilityFlags: SCNetworkReachabilityFlags {
|
||||
var flags: SCNetworkReachabilityFlags = 0
|
||||
let gotFlags = SCNetworkReachabilityGetFlags(reachabilityRef, &flags) != 0
|
||||
if gotFlags {
|
||||
return flags
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user