patternswiftMinor
C Socket API Call with Swift
Viewed 0 times
swiftwithapicallsocket
Problem
I have a small function in Objective-C which uses the C Socket API to check if the device has an active internet connection:
I have rewritten this function in Swift, using an
Is there a better way to check for network connectivity in Swift without using the C API? How can I improve this function, possibly removing the need to manually retain and release an
#include
- (BOOL)isNetworkAvailable {
char *hostname;
struct hostent *hostinfo;
hostname = "youtube.com";
hostinfo = gethostbyname(hostname);
if (hostinfo == NULL) {
return NO;
} else {
return YES;
}
}I have rewritten this function in Swift, using an
UnsafeMutablePointer type for the hostent struct:func isNetworkAvailable() -> Bool {
var hostinfo: UnsafeMutablePointer
let hostString: String = "youtube.com"
var hostname = (hostString.cStringUsingEncoding(NSUTF8StringEncoding))!
hostinfo = gethostbyname(hostname)
if (hostinfo == nil) {
hostinfo.destroy()
return false
} else {
hostinfo.destroy()
return true
}
}Is there a better way to check for network connectivity in Swift without using the C API? How can I improve this function, possibly removing the need to manually retain and release an
UnsafeMutablePointer?Solution
Wrong memory management
have initialized that memory and don't own it, therefore you must not
call
Things that can be improved
can be combined to
There is no need to declare the variable in advance, and the type
can be inferred automatically. Also you can define it as a constant
with
can be simplified to
because a Swift string is automatically converted to a C string when
passed to a C API taking a
Finally, since the
can be simplified to
So your function is now
BUT: This does not what you expect it to do!
That does not necessarily involve any network communication, as
the local DNS resolver might have cached the information.
Better: Use the SCNetworkReachability framework.
From the documentation:
The SCNetworkReachability programming interface allows an application
to determine the status of a system's current network configuration
and the reachability of a target host. A remote host is considered
reachable when a data packet, sent by an application into the network
stack, can leave the local device. Reachability does not guarantee
that the data packet will actually be received by the host.
Other Resources:
gethostbyname() returns a pointer to an internal structure. You don'thave initialized that memory and don't own it, therefore you must not
call
destroy().Things that can be improved
var hostinfo: UnsafeMutablePointer
// ...
hostinfo = gethostbyname(...)can be combined to
let hostinfo = gethostbyname(...)There is no need to declare the variable in advance, and the type
can be inferred automatically. Also you can define it as a constant
with
let because it is not modified subsequently.let hostString: String = "youtube.com"
var hostname = (hostString.cStringUsingEncoding(NSUTF8StringEncoding))!
let hostinfo = gethostbyname(hostname)can be simplified to
let hostname = "youtube.com"
let hostinfo = gethostbyname(hostname)because a Swift string is automatically converted to a C string when
passed to a C API taking a
const char * parameter.Finally, since the
destroy() has been removed,if (hostinfo == nil) {
return false
} else {
return true
}can be simplified to
return hostinfo != nilSo your function is now
func isNetworkAvailable() -> Bool {
let hostname = "youtube.com"
let hostinfo = gethostbyname(hostname)
return hostinfo != nil
}BUT: This does not what you expect it to do!
gethostbyname() "only" resolves a host name to an IP address.That does not necessarily involve any network communication, as
the local DNS resolver might have cached the information.
Better: Use the SCNetworkReachability framework.
From the documentation:
The SCNetworkReachability programming interface allows an application
to determine the status of a system's current network configuration
and the reachability of a target host. A remote host is considered
reachable when a data packet, sent by an application into the network
stack, can leave the local device. Reachability does not guarantee
that the data packet will actually be received by the host.
Other Resources:
- Apple provides Objective-C sample code at https://developer.apple.com/library/ios/samplecode/Reachability/Introduction/Intro.html
- A Swift wrapper can be found here: https://github.com/ashleymills/Reachability.swift
- And perhaps you can use the code from https://stackoverflow.com/questions/25623272/working-with-c-structs-in-swift.
Code Snippets
var hostinfo: UnsafeMutablePointer<hostent>
// ...
hostinfo = gethostbyname(...)let hostinfo = gethostbyname(...)let hostString: String = "youtube.com"
var hostname = (hostString.cStringUsingEncoding(NSUTF8StringEncoding))!
let hostinfo = gethostbyname(hostname)let hostname = "youtube.com"
let hostinfo = gethostbyname(hostname)if (hostinfo == nil) {
return false
} else {
return true
}Context
StackExchange Code Review Q#92579, answer score: 8
Revisions (0)
No revisions yet.