In this article by Jon Hoffman, author of the book Mastering Swift, you will learn how to use Apple's system configuration API to figure out what type of network connection we have. If we are developing applications for a mobile device (iPhone, iPod, or iPad), it is e essential to know if we have a network connection and what type of connection it is.
(For more resources related to this topic, see here.)
What is network development?
Network development is writing code that will allow our application to send and receive data from remote services or devices. The large majority of these bulletin board services used a single modem, which meant that only one user could connect to them at any one time. These bulletin boards would seem very strange and archaic for those that grew up with the Internet; however, back then, they were how computers shared information. At that time, being able to connect to a computer across town and upload/download files was amazing. Today, however, we communicate with services and devices all over the world without thinking twice about it.
Back when I first started writing applications, it was rare to develop an application that communicated over a standard network, and it was also hard to find developers with experience in network development. In today's world, just about every application has a requirement for some sort of network communication.
In this article, we will show you how to connect to Representational State Transfer (REST) based services like the one Apple supplies that lets developers search the iTunes Store. Apple has documented this service very well. The documentation can be found at https://www.apple.com/itunes/affiliates/resources/documentation/itunes-store-web-service-search-api.html.
Before we look at how to connect to REST services, let's look at the classes in Apple's networking API that we will be using. These classes are part of Apple's powerful URL loading system.
An overview of the URL session classes
Apple's URL loading system is a framework of classes available to interact with URLs. Using these classes together lets us communicate with services that use standard Internet protocols. The classes that we will be using in this article to connect to and retrieve information from REST services are as follows:
NSURLSession: This is the main session object. It was written as a replacement for the older NSURLConnection API.
NSURLSessionConfiguration: This is used to configure the behavior of the NSURLSession object.
NSURLSessionTask: This is a base class to handle the data being retrieved from the URL. Apple provides three concrete subclasses of the NSURLSessionTask class.
NSURL: This is an object that represents the URL to connect to.
NSMutableURLRequest: This class contains information about the request that we are making and is used by the NSURLSessionTask service to make the request.
NSHTTPURLResponse: This class contains the response to our request.
Now, let's look at each of these classes a little more in depth so we have a basic understanding of what each does.
NSURLSession
Prior to iOS 7 and OS X 10.9, when a developer wanted to retrieve contents from a URL, they used the NSURLConnection API. Starting with iOS 7 and OS X 10.9, the preferred API became NSURLSession. The NSURLSession API can be thought of as an improvement to the older NSURLConnection API.
An NSURLSession object provides an API for interacting with various protocols such as HTTP and HTTPS. The session object, which is an instance of the NSURLSession, manages this interaction. These session objects are highly configurable, which allows us to control how our requests are made and how we handle the data that is returned.
Like most networking API, NSURLSession is asynchronous. This means that we have to provide a way to return the response from the service back to the code that needs it. The most popular way to return the results from a session is to pass a completion handler block (closure) to the session. This completion handler is then called when the service successfully responds or we receive an error. All of the examples in this article use completion handlers to process the data that is returned from the services.
NSURLSessionConfiguration
The NSURLSessionConfiguration class defines the behavior and policies to use when using the NSURLSession object to connect to a URL. When using the NSURLSession object, we usually create an NSURLSessionConfiguration instance first because an instance of this class is required when we create an instance of the NSURLSession class.
The NSURLSessionConfiguration class defines three session types. These are:
Default session configuration: This configuration behaves similar to the NSURLConnection API.
Ephemeral Session configuration: This configuration behaves similar to the default session configuration, except it does not cache anything to disk.
Background Session configuration: This session allows for uploads and downloads to be performed, even when the app is running in the background.
It is important to note that we should make sure that we configure the NSURLSessionConfiguration object appropriately before we use it to create an instance of the NSURLSession class. When the session object is created, it creates a copy of the configuration object that we provided it. Any changes made to the configuration object once the session object is created are ignored by the session. If we need to make changes to the configuration, we must create another instance of the NSURLSession class.
NSURLSessionTask
The NSURLSession service uses an instance of the NSURLSessionTask classes to make the call to the service that we are connecting to. The NSURLSessionTask class is a base class, and Apple has provided three concrete subclasses that we can use, and they are as follows:
NSURLSessionDataTask: This returns the response, in memory, directly to the application as one or more NSData objects. This is the task that we generally use most often.
NSURLSessionDownloadTask: This writes the response directly to a temporary file.
NSURLSessionUploadTask: This is used for making requests that require a request body such as a POST or PUT request.
It is important to note that a task will not send the request to the service until we call the resume() method.
Using the NSURL class
The NSURL object represents the URL that we are going to connect to. The NSURL class is not limited to URLs that represent remote servers but it can also be used to represent a local file on disk. In this article, we will be using the NSURL class exclusively to represent the URL of the remote service that we are connecting to.
NSMutableURLRequest
The NSMutableURLRequest class is a mutable subclass of the NSURLRequest class, which represents a URL load request. We use the NSMutableRequest class to encapsulate our URL and the request properties.
It is important to understand that the NSMutableURLRequest class is used to encapsulate the necessary information to make our request but it does not make the actual request. To make the request, we use instances of the NSURLSession and NSURLSessionTask classes.
NSURLHTTPResponse
NSURLHTTPResponse is a subclass of the NSURLResponse class that encapsulates the metadata associated with the response to a URL request. The NSURLHTTPResponse class provides methods for accessing specific information associated with an HTTP response. Specifically, this class allows us to access the HTTP header fields and the response status codes.
We briefly covered a number of classes in this section and it may not be clear how they all actually fit together; however, once you see the examples a little further in this article, it will become much clearer. Before we go into our examples, let's take a quick look at the type of service that we will be connecting to.
REST web services
REST has become one of the most important technologies for stateless communications between devices. Due to the lightweight and stateless nature of the REST base services, its importance is likely to continue to grow as more devices are connected to the Internet.
REST is an architecture style for designing networked applications. The idea behind REST is instead of using complex mechanisms, such as SOAP or CORBA to communicate between devices, we use simple HTTP requests for the communication. While, in theory, REST is not dependent on the Internet protocols, it is almost always implemented using them. Therefore, when we are accessing REST services, we are almost always interacting with web servers in the same way that our web browsers interact with these servers.
REST web services use the HTTP POST, GET, PUT, or DELETE methods. If we think about a standard CRUD (create/read/update/delete) application, we would use a POST request to create or update data, a GET request to read data, and a DELETE request to delete data.
When we type a URL into our browser's address bar and hit Enter, we are generally making a GET request to the server and asking it to send us the web page associated with that URL. When we fill out a web form and click the the submit button, we are generally making a POST request to the server. We then include the parameters from the web form in the body of our POST request.
Now, let's look at how to make an HTTP GET request using Apple's networking API.
Making an HTTP GET request
In this example, we will make a GET request to Apple's iTunes search API to get a list of items related to the search term Jimmy Buffett. Since we are retrieving data from the service, by REST standards, we should use a GET request to retrieve the data.
While the REST standard is to use GET requests to retrieve data from a service, there is nothing stopping a developer of a web service from using a GET request to create or update a data object. It is not recommended to use a GET request in this manner, but just be aware that there are services out there that do not adhere to the REST standards.
The following code makes a request to Apple's iTunes search API and then prints the results to the console:
public typealias DataFromURLCompletionClosure = (NSURLResponse!, NSData!) -> Void public func sendGetRequest(handler: DataFromURLCompletionClosure) { var queue = NSOperationQueue() var sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration(); var urlString = "https://itunes.apple.com/search?term=jimmy+buffett" if let encodeString = urlString.stringByAddingPercentEscapesUsingEncoding (NSUTF8StringEncoding) { if let url = NSURL(string: encodeString) { var request = NSMutableURLRequest(URL: url) request.HTTPMethod = "GET" var urlSession = NSURLSession(configuration: sessionConfiguration, delegate: nil, delegateQueue: queue) var sessionTask = urlSession.dataTaskWithRequest(request) { (data, response, error) in handler(response, data) } sessionTask.resume() } }}
We start off by creating a type alias named DataFromURLCompletionClosure. The DataFromURLCompletionClosure type will be used for both the GET and POST examples of this `. If you are not familiar with using a typealias object to define a closure type.
We then create a function named sendGetRequest() that will be used to make the GET request to Apple's iTunes API. This function accepts one argument named handler, which is a closure that conforms to the DataFromURLCompletionClosure type. The handler closure will be used to return the results from our request.
Within our sendGetRequest() method, we begin by creating an instance of the NSOperationQueue class. This queue will be used by our NSURLSession instance for scheduling the delegate calls and completion handlers.
We then create an instance of the NSURLSessionConfiguration class using the defaultSessionConfiguration() method, which creates a default session configuration instance. If we need to, we can modify the session configuration properties after we create it, but in this example, the default configuration is what we want.
After we create our session configuration, we create our URL string. This is the URL of the service we are connecting to. With a GET request, we put our parameters in the URL itself. In this specific example, https://itunes.apple.com/search is the URL of the web service. We then follow the web service URL with a question mark (?), which indicates that the rest of the URL string consists of parameters for the web service. Parameters take the form of key/value pairs, which means that each parameter has a key and a value. The key and the value of a parameter, in a URL, are separated by an equals sign (=). In our example, the key is term and the value is jimmy+buffett. Next, we run the URL string that we just created through the stringByAddingPercentEscapesUsingEncoding() method to make sure our URL string is encoded properly.
Next, we use the URL string that we just built to create an NSURL instance named url. Since we are making a GET request, this NSURL instance will represent both the location of the web service and the parameters that we are sending to it.
We create an instance of the NSMutableURLRequest class using the NSURL instance that we just created. We use the NSMutableURLRequest class, instead of the NSURLRequest class, so we can set the properties needed for our request. In this example, we set the HTTPMethod property; however, we can also set other properties like the timeout interval, or add items to our HTTP header.
Now, we use the sessionConfiguration variable (instance of the NSURLSessionConfiguration) and the queue (instance of NSOperationQueue) that we created at the beginning of the sendGetRequest() function to create an instance of the NSURLSession class. The NSURLSession class provides the API that we will use to connect to Apple's iTunes search API. In this example, we use the dataTaskWithRequest() method of the NSURLSession instance to return an instance of the NSURLSessionDataTask instance named sessionTask.
The sessionTask instance is what makes the request to the iTunes search API. When we receive the response from the service, we use the handler callback to return both the NSURLResponse object and the NSData object. The NSURLResponse contains information about the response, and the NSData instance contains the body of the response.
Finally, we call the resume() method of the NSURLSessionDataTask instance to make the request to the web service. Remember, as we mentioned earlier, an NSURLSessionTask instance will not send the request to the service until we call the resume() method.
Now, let's look at how we would call the sendGetRequest() function. The first thing we need to do is to create a closure that will be passed to the sendGetRequest() function and called when the response from the web service is received. In this example, we will simply print the response to the console. Here is the code:
var printResultsClosure: HttpConnect.DataFromURLCompletionClosure = {
if let data = $1 {
var sString = NSString(data: data, encoding: NSUTF8StringEncoding)
println(sString)
}
}
We define this closure, named printResultsClosure, to be an instance of the DataFromURLCompletionClosure type. Within the closure, we unwrap the first parameter and set the value to a constant named data. If the first parameter is not nil, we convert the data constant to an instance of the NSString class, which is then printed to the console.
Now, let's call the getConnection() method with the following code:
let aConnect = HttpConnect()
aConnect.sendGetRequest(printResultsClosure)
This code creates an instance of the HttpConnect class and then calls the sendGetRequest() method, passing the printResultsClosure closure as the only parameter. If we run this code while we are connected to the Internet, we will receive a JSON response that contains a list of items related to Jimmy Buffett on iTunes.
Now that we have seen how to make a simple HTTP GET request, let's look at how we would make an HTTP Post POST request to a web service.
Making an HTTP POST request
Since Apple's iTunes, APIs use GET requests to retrieve data. In this section, we will use the free httpbin.org service to show you how to make a POST request. The POST service that httpbin.org provides can be found at http://httpbin.org/post. This service will echo back the parameters that it receives so we can verify our request was made properly.
When we make a POST request, we generally have some data that we want to send or post to the server. This data takes the form of key-value pairs. These pairs are separated by an ampersand (&) symbol and each key is separated from its value by an equals sign (=). As an example, let's say that we want to submit the following data to our service:
firstname: Jon
lastname: Hoffman
age: 47 years
The body of the POST request would take the following format:
firstname=Jon&lastname=Hoffman&age=47
Once we have the data in the proper format, we will then use the dataUsingEncoding() method, like we did with the GET request to properly encode the POST data.
Since the data going to the server is in the key-value format, the most appropriate way to store this data, prior to sending it to the service, is with a Dictionary object. With this in mind, we will need to create a method that will take a Dictionary object and return a string object that can be used for the POST request. The following code will do that:
func dictionaryToQueryString(dict: [String : String]) -> String {
var parts = [String]()
for (key, value) in dict {
var part: String = key + "=" + value
parts.append(part);
}
return join("&", parts)
}
This function loops though each key-value pair of the Dictionary object and creates a String object that contains the key and the value separated by the equals sign (=). We then use the join() function to join each item in the array separated by the specified sting. In our case, we want to separate each string with the ampersand symbol (&). We then return this newly created string to the code that called it.
Now, let's create our sendPostRequest() function that will send the POST request to the httpbin.org post service. We will see a lot of similarities between this sendPostRequest() function and the sendGetRequest() function that we showed you in the Making an HTTP GET request section of this article. Let's take a look at the following code:
public func sendPostRequest(handler: DataFromURLCompletionClosure) {
var queue = NSOperationQueue()
var sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
var urlString = "http://httpbin.org/post"
if let encodeString = urlString.stringByAddingPercentEscapesUsingEncoding (NSUTF8StringEncoding){
if let url: NSURL = NSURL(string: encodeString) {
var request = NSMutableURLRequest(URL: url)
request.HTTPMethod = "POST"
var params = dictionaryToQueryString(["One":"1 and 1", "Two" : "2 and 2"])
request.HTTPBody = params.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
var urlSession = NSURLSession(configuration: sessionConfiguration, delegate: nil, delegateQueue: queue)
var sessionTask = urlSession.dataTaskWithRequest(request) {
(data, response, error) in
handler(response, data)
}
sessionTask.resume()
}
}
}
Now, let's walk though this code. Notice that we are using the same type alias, named DataFromURLCompletionClosure, that we used with the sendGetRequest() function. If you are not familiar with using a typealias object to define a closure type.
The sendPostRequest() function accepts one argument named handler, which is a closure that conforms to the DataFromURLCompletionClosure type. The handler closure will be used to process the data from the httpbin.org service once the service responds to our request.
Within our sendPostRequest() method, we start off by creating an instance of the NSOperationQueue named queue. This queue will be used by our NSURLSession instance to schedule the delegate calls and completion handlers.
We then create an instance of the NSURLSessionConfiguration class using the defaultSessionConfiguration() method, which creates a default session configuration instance. We are able to modify the session configuration properties after we create it, but, in this example, the default configuration is what we want.
After we created our session configuration, we create our URL string. This is the URL of the service we are connecting to. In this example, the URL is http://httpbin.org/post. Next, we run the URL string through the stringByAddingPercentEscapesUsingEncoding() method to make sure that our URL string is encoded properly.
Next, we use the URL string that we just built to create an instance of the NSURL class named url. Since this is a POST request, this NSURL instance will represent the location of the web service that we are connecting to.
We now create an instance of the NSMutableURLRequest class using the NSURL instance that we just created. We use the NSMutableURLRequest class, instead of the NSURLRequest class, so that we can set the properties needed for our request. In this example, we set the HTTPMethod property; however, we can also set other properties like the timeout interval, or add items to our HTTP header.
Now, we use our dictionaryToQueryString() function, that we showed you at the beginning of this section, to build the data that we are going to post to the server. We then use the dataUsingEncoding() function to make sure that our data is properly encoded prior to sending it to the server, and finally, the data is added to the HTTPBody property of the NSMutableURLRequest instance.
Next, we use the sessionConfiguration variable (instance of the NSURLSessionConfiguration) and the queue (NSOperationQueue) that we created at the beginning of the function to create an instance of the NSURLSession class. The NSURLSession class provides the API that we will use to connect to the post on httpbin.org's post service. In this example, we use the dataTaskWithRequest() method of the NSURLSession instance to return an instance of the NSURLSessionDataTask named sessionTask.
The sessionTask instance is what makes the request to the httpbin.org's POST service. When we receive the response from the service, we use the handler callback to return both the NSURLResponse object and the NSData object. The NSURLResponse contains information about the response and the NSData instance contains the body of the response.
Finally, we call the resume() method of the NSURLSessionDataTask instance to make the request to the web service. Remember, as we mentioned earlier, an NSURLSessionTask class will not send the request to the service until we call the resume() method.
We can then call the sendPostRequest() method in exactly the same way that we called the sendGetRequest() method.
When developing applications that communicate to other devices and services over the Internet, it is also good practice to verify that we have a network connection. When developing mobile applications, it is also good practice to verify that we are not using a mobile connection (3G, 4G, and so on) to transfer large amounts of data. Let's look at how to verify that we have a network connection and what type of connection we have.
Encoding a URL
In both the sendGetRequest and sendPostRequest examples, we used the stringByAddingPercentEscapesUsingEncoding() function to make sure that we had a valid URL. While this function does make sure that we have a valid URL, it does not always return the URL that we expect. In Apple's documentation of this function, it notes the following issue, in Apple's documentation of this function, it notes that it may be difficult to use this function to clean up unescaped or partially escaped URL strings where sequences are unpredictable.
With this in mind, the following function is a much better way to convert a standard string to a valid URL:
private func urlEncode(s: String) -> String {
return CFURLCreateStringByAddingPercentEscapes(nil, s, nil, "!*'"();:@&=+$,/?%#[]", CFStringBuiltInEncodings.UTF8.rawValue) as! String
}
Within this function, we use the CFURLCreateStringByAddingPercentEscapes() function to replace the characters listed with the equivalent percent escape sequence as defined by the encoding. This is a much better function for converting a string instance to a valid URL than the stringByAddingPercentEscapesUsingEncoding() function.
Checking network connection
As we create applications that communicate with other devices and services over the Internet, eventually, we will want to verify that we have a network connection prior to making the network calls. Another thing to consider when we are writing mobile applications is the type of network connection that the user has. As mobile application developers, we need to keep in mind that our users probably have a mobile data plan that limits the amount of data they can send/receive in a month. If they exceed that limit, they may have to pay an extra fee. If our application sends large amounts of data, it might be appropriate to warn our user prior to sending this data.
This next example will show how we can verify that we have a network connection and also tells us what type of connection we have. We will begin by importing the system configuration API and also defining an enum that contains the different connection types. We will import the system configuration API like this:
import SystemConfiguration
The ConnectionType enum is then defined like this:
public enum ConnectionType {
case NONETWORK
case MOBILE3GNETWORK
case WIFINETWORK
}
Now, let's look at the code to check the network connection type:
public func networkConnectionType(hostname: NSString) -> ConnectionType {
var reachabilityRef = SCNetworkReachabilityCreateWithName (nil,hostnamehostnamehostnamehostname.UTF8String)
var reachability = reachabilityRef.takeUnretainedValue()
var flags: SCNetworkReachabilityFlags = 0
SCNetworkReachabilityGetFlags (reachabilityRef.takeUnretainedValue(), &flags)
var reachable: Bool = (flags & UInt32(kSCNetworkReachabilityFlagsReachable) != 0)
var needsConnection: Bool = (flags & UInt32(kSCNetworkReachabilityFlagsConnectionRequired) != 0)
if reachable && !needsConnection {
// what type of connection is available
var isCellularConnection = (flags & UInt32(kSCNetworkReachabilityFlagsIsWWAN) != 0)
if isCellularConnection {
// cellular Cellular connection available
return ConnectionType.MOBILE3GNETWORK;
}
else {
// wifi Wifi connection available
return ConnectionType.WIFINETWORK;
}
}
//No or unknown connection
return ConnectionType.NONETWORK
}
The networkConnectionType() function begins by creating a SCNetworkReachability reference. To create the SCNetworkRechabilityRef reference, we use the SCNetworkReachabilityCreateWithName() function, which creates a reachability reference to the host provided.
In Swift, when we receive an unmanaged object, we should immediately convert it to a memory-managed object before we work with it. This allows Swift to manage the memory for us. For this, we use the takeUnretainedValue() function.
After we get our SCNetworkReachabilityRef reference, we need to retrieve the SCNetworkReachabilityFlags enum from the reference. This is done with the SCNetworkReachabilityGetFlags() function.
Once we have the network reachability flags, we can begin testing our connection. We use the bitwise AND (&) operator to see if the host is reachable and if we need to establish a connection before we can connect to the host (needsConnection). If the reachable flag is false (we cannot currently connect to the host), or if needsConnection is true (we need to establish a connection before we can connect), we return NONETWORK, which means the host is currently not reachable.
If we are able to connect to the host, we then check to see if we have a cellular connection by checking the network reachability flags again. If we have a cellular connection, we return MOBILE3GNETWORK; otherwise, we assume we have a Wi-Fi connection and return WIFINETWORK.
If you are writing applications that connect to other devices or services over the Internet, I would recommend putting this function in a standard library to use because you will want to check for networking connectivity, and also the type of connection that you have pretty regularly.
Now that we have seen how to use Apple's networking APIs to connect to remote services, I would like to demonstrate a network library that you can use in your own applications. This network library makes it very easy and simple to connect to various types of services on the Internet. This is a library that I created and maintained, but I would definitely welcome anyone that would like to contribute to the code base. This library is called RSNetworking.
RSNetworking
You can find RSNetworking on GitHub with this URL https://github.com/hoffmanjon/RSNetworking.
RSNetworking is a network library written entirely in the Swift programming language. RSNetworking is built using Apple's powerful URL loading system (https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html), which features the NSURLSession class that we used earlier in this article. The main design goal of RSNetworking is to make it easy and quick for developers to add powerful asynchronous networking requests to their applications that are written in Swift.
There are three ways that we can use RSNetworking, which are as follows:
RSURLRequest: This API provides a very simple and easy interface to make single GET requests to a service.
RSTransaction and RSTransactionRequest: These APIs provide a very powerful and flexible way to make both GET and POST requests to a service. This API also makes it very easy to make multiple requests to a service.
Extensions: RSNetworking provides extensions to both the UIImageView and the UIButton classes to dynamically load images from a URL and insert them into the UIImageView or UIButton classes after they are loaded.
Let's look at each of these APIs in greater detail and then provide some examples of how to use them.
RSURLRequest
With the RSURLRequest API, we can make a GET request to a service and the only thing we need to provide is the URL and the parameters we wish to send to the service. The RSURLRequest API exposes four functions. These functions are as follows:
dataFromURL(url: NSURL, completionHandler handler: RSNetworking.dataFromURLCompletionClosure): This retrieves an NSData object from a URL. This is the main function and is used by the other three functions to retrieve an NSData object prior to converting it to the requested format.
stringFromURL(url: NSURL, completionHandler handler: RSNetworking.stringFromURLCompletionClosure): This retrieves an NSString object from a URL. This function uses the dataFromURL() function to retrieve an NSData object and then converts it to an NSString object.
dictionaryFromJsonURL(url: NSURL, completionHandler handler: RSNetworking.dictionaryFromURLCompletionClosure): This retrieves an NSDictionary object from a URL. This function uses the dataFromURL() function to retrieve an NSData object and then converts it to an NSDictionary object. The data returned from the URL should be in the JSON format for this function to work properly.
imageFromURL(url: NSURL, completionHandler handler: RSNetworking.imageFromURLCompletionClosure): This retrieves a UIImage object from a URL. This function uses the dataFromURL() function to retrieve an NSData object and then converts it to a UIImage object.
Now, let's look at an example on how to use the RSURLRequest API. In this example, we will make a request to Apple's iTunes search API, as we did in the Making an HTTP GET request section of this article:
func rsURLRequestExample() {
var client = RSURLRequest()
if let testURL = NSURL(string:"https://itunes.apple.com/search?term=jimmy+buffett&media=music") {
client.dictionaryFromJsonURL(testURL, completionHandler: resultsHandler)
}
}
Let's walk through this code. We begin by creating an instance of the RSURLRequest class and an instance of the NSURL class. The NSURL instance represents the URL of the service that we wish to connect to and since we are making a GET request, it also contains the parameters that we are sending to the service. If we recall from the previous Making an HTTP GET Request section, when we make a HTTP GET request, the parameters that we are sending to the service are contained within the URL itself.
Apple's iTunes search API returns the results of the search in the JSON format. We can see that in the API documentation and also by printing out the results of the search to the console; therefore, we will use the dictionaryFromJsonURL() method of the RSURLRequest class to make our request to the service. We could also use the dataFromURL() or stringFromURL() methods to retrieve the data if we wanted to, but this method is specifically written to handle JSON data that is returned form a REST-based web service.
The dictionaryFromJsonURL() method will take the data that is returned from the NSURLSession request and convert it to an NSDictionary object. We use the NSDictionary object here rather that Swift's Dictionary object because the web service could return multiple types (Strings, Arrays, Numbers, and so on), and if we recall, a Swift Dictionary object can have only a single type for the key and a single type for the value.
When we call the dictionaryFromJsonURL() method, we pass the URL that we want to connect to and also a completion handler that will be called once the information from the service is returned and converted to an NSDicationary object.
Now, let's look at our completion handler;
var resultsHandler:RSURLRequestRSURLRequestRSURLRequestRSURLRequest.dictionaryFromURLCompletionClosure = {
var response = $0
var responseDictionary = $1
var error = $2
if error == nil {
var res = "results"
if let results = responseDictionary[res] as? NSArray {
println(results[0])
}
else {
println("Problem")
}
}
else {
//If there was an error, log it
println("Error : (error)")
}
}
Our completion handler is of the RSURLRequest.dictionaryFromURLCompletionClosure type. This type is defined in the same way as the RSTransactionRequest.dictionaryFromRSTransactionCompletionClosure type, which allows us to use this same closure for RSURLRequests and RSTransactionRequest requests.
We begin the completion handler by retrieving the three parameters that were passed and assign them to the response, the responseDictionary and error variables. We then check the error variable to see if it is nil. If it is nil, then we received a valid response and can retrieve values for the NSDictionary object.
In this example, we retrieve the NSArray value that is associated with the results key in the NSDictionary object that was returned from the service. This NSArray value will contain a list of items in the iTunes store that are associated with our search term. Once we have the NSArray value, we print out the first element of the array to the console.
The RSURLRequest API is very good for making single GET requests to a service. Now, let's look at the RSTransaction and RSTransactionRequest API, which can be used for both POST and GET requests and should be used when we need to make multiple requests to the same service.
Summary
In today's world, it is essential that a developer has a good working knowledge of network development. In this article, we showed you how to use Apple's NSURLSession API, with other classes, to connect to REST-based web services. The NSURLSession API was written as a replacement for the older NSURLConnection API and is now the recommended API to use when making network requests.
We ended the discussion with RSNetworking, which is an open source network library, written entirely in Swift, that I maintain. RSNetworking allows us to very quickly and easily add network functionality to our applications.
Resources for Article:
Further resources on this subject:
Flappy Swift [article]
Installing OpenStack Swift [article]
Dragging a CCNode in Cocos2D-Swift [article]
Read more