(This answer was extended repeatedly due to changes in the Swift language, which made it a bit confusing. I have now rewritten it and removed everything which refers to Swift 1.x. The older code can
be found in the edit history if somebody needs it.)
This is how you would do it in Swift 2.0 (Xcode 7):
import SystemConfiguration
func connectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
zeroAddress.sin_family = sa_family_t(AF_INET)
guard let defaultRouteReachability = withUnsafePointer(&zeroAddress, {
SCNetworkReachabilityCreateWithAddress(nil, UnsafePointer($0))
}) else {
return false
}
var flags : SCNetworkReachabilityFlags = []
if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
return false
}
let isReachable = flags.contains(.Reachable)
let needsConnection = flags.contains(.ConnectionRequired)
return (isReachable && !needsConnection)
}
Explanations:
-
As of Swift 1.2 (Xcode 6.3), imported C structs have a default initializer in Swift, which initializes all of the struct’s fields to zero, so the socket address structure can be initialized with
var zeroAddress = sockaddr_in()
-
sizeofValue()
gives the size of this structure, this has
to be converted toUInt8
forsin_len
:zeroAddress.sin_len = UInt8(sizeofValue(zeroAddress))
-
AF_INET
is anInt32
, this has to be converted to the correct type forsin_family
:zeroAddress.sin_family = sa_family_t(AF_INET)
-
withUnsafePointer(&zeroAddress) { ... }
passes the address of the
structure to the closure where it is used as argument for
SCNetworkReachabilityCreateWithAddress()
. TheUnsafePointer($0)
conversion is needed because that function expects a pointer to
sockaddr
, notsockaddr_in
. -
The value returned from
withUnsafePointer()
is the return value
fromSCNetworkReachabilityCreateWithAddress()
and that has the
typeSCNetworkReachability?
, i.e. it is an optional.
Theguard let
statement (a new feature in Swift 2.0) assigns the unwrapped value to thedefaultRouteReachability
variable if it is
notnil
. Otherwise theelse
block is executed and the function
returns. - As of Swift 2,
SCNetworkReachabilityCreateWithAddress()
returns
a managed object. You don’t have to release it explicitly. -
As of Swift 2,
SCNetworkReachabilityFlags
conforms to
OptionSetType
which has a set-like interface. You create an
empty flags variable withvar flags : SCNetworkReachabilityFlags = []
and check for flags with
let isReachable = flags.contains(.Reachable) let needsConnection = flags.contains(.ConnectionRequired)
-
The second parameter of
SCNetworkReachabilityGetFlags
has the type
UnsafeMutablePointer<SCNetworkReachabilityFlags>
, which means that you have to
pass the address of the flags variable.
Note also that registering a notifier callback is possible as of
Swift 2, compare Working with C APIs from Swift and Swift 2 – UnsafeMutablePointer<Void> to object.
Update for Swift 3/4:
Unsafe pointers cannot be simply be converted to a pointer of a
different type anymore (see – SE-0107 UnsafeRawPointer API). Here the updated code:
import SystemConfiguration
func connectedToNetwork() -> Bool {
var zeroAddress = sockaddr_in()
zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
zeroAddress.sin_family = sa_family_t(AF_INET)
guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
SCNetworkReachabilityCreateWithAddress(nil, $0)
}
}) else {
return false
}
var flags: SCNetworkReachabilityFlags = []
if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
return false
}
let isReachable = flags.contains(.reachable)
let needsConnection = flags.contains(.connectionRequired)
return (isReachable && !needsConnection)
}