Networking Flashcards

1
Q

What is HTTP?

A

<strong>HTTP</strong> stands for Hypertext Transfer Protocol and is the foundation of today’s internet. What it means for us iOS developers is that when we build client-side applications we connect with backend APIs via HTTP.

When we send requests to HTTP APIs we use “verbs” such as HEAD, GET, POST, PATCH, PUT, DELETE, etc. Each verb represents a different type of action you’d like the backend to do. You’d typically work with the following verbs in a properly implemented API:

  • <strong>HEAD</strong> returns header information about a resource. Typically it has a status code (200, 300, 400, etc.) and caching details.
  • <strong>GET</strong> returns actual data for the resource you requested. Typically it’s your domain model data.
  • <strong>POST</strong> is used to, well, post something to your server. Typically used to submit data only.
  • <strong>PATCH</strong> is used to change a resource’s data. Unlike PUT, it changes only certain values for the resource instead of overriding the whole thing.
  • <strong>PUT</strong> is like PATCH, but instead of altering only certain values in a re- source, it is supposed to replace everything about the resource with the data you submit leaving only the unique ID intact.
  • <strong>DELETE</strong>, not surprisingly, destroys a resource on the backend. iOS applications that communicate with server APIs using the above verbs can achieve most of the networking goals, except real-time connection/sockets, as long as the APIs adhere to HTTP standards and respect the meaning of those verbs. It is incredibly difficult to work with a backend that does some data changes on POST requests and returns some data on PUT requests and so on. Contracts between server and client were made for the purpose of not only convenience but consistency and predictability.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What is REST?

A

REST stands for Representational State Transfer. REST is an API architecture built on top of HTTP protocol.

Its main focus is resources and the ability of client applications to access, write, delete, and alter them. REST is an API architecture that revolves around resources and HTTP verbs. Each resource is represented by a set of endpoints that can receive some of the HTTP verb requests to do various CRUD(Create, Read, Update, Destroy) operations.

For example, let’s say you have an API that lets you manage posts users create in your app. A typical CRUD REST API for it would look like this:

  • <strong>https://yourawesomeproduct.com/posts</strong> accepts GET requestsand returns a list of posts available on the server.
  • <strong>https://yourawesomeproduct.com/posts/123</strong> accepts GET requests and returns a single post with given ID (123) available on the server.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

How do you typically implement networking on iOS?

A

Networking falls into the service layer of your ap- plication since it deals with external communication. In general, you should decouple everything HTTP/network-related in your app into a set of service and client objects that handle all the nitty-gritty of HTTP connection. Those objects would perform requests and API calls for your application, decoupling it from other layers of responsibility (like storage, business logic, UI, etc.) of the app. A typical small “starter” implementation of a service layer in your app could look like this:

  • a networking/HTTP manager of some kind (either NSURLSession or AFNetworking/Alamofire manager).
  • an APIClient object that can be configured with a networking manager to actually perform HTTP requests against your API domain. APIClient usually is responsible for signing every request with authentication to- ken/credentials.
  • a set of service objects that work with individual resources of your RESTful API such as PostsService, UsersService, etc. These ser- vice objects use shared APIClient to issue specific concrete HTTP requests to their respective /posts and /users endpoints. They compose params and other necessary data for requests. At the end of the day, all other parts of the app are working directly only with service objects and never touch low-level implementation such as APIClient or NSURLSession/AFNetworking/Alamofire. That separation of concerns ensures that if your authentication or individual endpoints change they won’t affect each other in your codebase.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

What are the concerns and limitations of net- working on iOS?

A

The main networking constraints on iOS are battery and bandwidth. iOS devices have limited battery capacity and sporadic network connection that can drop in and out frequently. When developing the network- ing layer of the app, you should always issue as few HTTP requests as possible and retry requests if they suddenly fail due to a poor connection or other issues. There’s also a bandwidth issue; it is not a good idea to upload or download large files and chunks of information when using a cellular connection and it is advised to use Wi-Fi instead.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What should go into the networking/service layer?

A

Every iOS app that works with external data has a service layer that is responsible for communication with things like HTTP APIs, GPS location, BLE peripherals, Gyroscope, iCloud, sockets, and so on. They are all external to your app resources, and to work with them, you need a set of objects that can communicate with those resources (for example, HTTP Client or BLE manager) and can serialize/deserialize data sent to or received from those resources. Here is a typical service layer that does networking with some kind of API:

  • APIClient object that has an HTTP manager
  • PostsService object that owns API Client and issues requests to specific endpoints to POST and GET posts. PostsService maps JSON data to your custom domain model objects.
  • Post class that subclasses from MTLModel to map JSON received by PostsService to your custom Post objects And here’s what will go in the same service layer for Bluetooth Low Energy (BLE):
  • BLEClient object that owns and manages CBCentralManager and executes low-level connection to BLE peripherals
  • PeripheralsClient object that discovers peripheral services, charac- teristics, and executes low-level stuff to get and send values to and from peripherals
  • SpecificDeviceService that uses both BLEClient and Peripherals- Client to orchestrate a connection to BLE, discovery, and communi- cation with the specific device/peripheral you’re trying to connect to. SpecificDeviceService is also responsible for mapping data received from Characteristic to your custom objects.
  • CustomCharacteristicData is just like Post. In the case of JSON API it is a domain model object that is mapped from raw data received from BLE to conveniently work with that piece of data throughout your application. As you can see, both the HTTP and BLE examples are similar in what they do. Both of those examples wrap some kind of external service (HTTP or BLE respectively) and make it convenient and easy to work with those exter- nal services.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What is NSURLSession? How is it used?

A

Since iOS 7, NSURLConnection became obsolete and the new Apple standard for implementing HTTP networking is NSURLSession. NSURLSession and related classes do a lot of heavy lifting for basic HTTP connection and authentication for you. It allows you to send HTTP verb (GET, POST, etc.) requests, connect to FTP, and to download files. You can optionally configure cache and execute your requests in a background/app suspended state.

The way you typically work with it is to use NSURLSessionDownloadTask objects to execute requests against given urls. It has a block-based and delegate based API, which means there are two ways you can issue HTTP requests with NSURLSession: either by receiving a completion handler block callback or by implementing delegate methods and receiving notifications as the data comes in. Either way is fine and has a different purpose depending on your use case (for example, if you’d like to receive download progress notification you would want to implement delegate callbacks rather than a completion block). Also NSURLSession allows you to resume, cancel, or pause networking task.

All and all, NSURLSession is a very robust way of doing HTTP and other networking but in reality, it is a bit too low level, and in the majority of the cases, you’re better off using a wrapper library like AFNetworking or Alamofire. Both of them are the de facto standard for networking on iOS, and use NSURLSession under the hood to run HTTP requests for you.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

What is AFNetworking/Alamofire? How do you use it?

A

AFNetworking and Alamofire became the de facto standard for networking on iOS. AFNetworking and Alamofire are wrappers around standard Apple iOS technologies for networking such as NSURLSession that make working with it more convenient and reduce the boilerplate setup you have to do when you work with NSURLSession directly.

Nowadays, AFNetworking and Alamofire are the de facto standard of how you do HTTP networking on iOS and probably the most commonly used third-party library. As a wrapper around Apple’s NSURLSession, it has access to pretty much every feature it provides and more. Overall it takes care of HTTP requests, JSON data serialization into Dictionary objects, response caching, and status code response validation. With it, you can setup HTTP request headers, params, issue HTTP GET/POST/PUT/etc. requests, serialize JSON response, do basic HTTP authentication, upload and download files, and more.

Alamofire has a block-based API. You use it either directly with minimal setup by creating requests using Alamofire class methods or by creating a session manager object (and providing it with URLSessionConfiguration) that can take callback blocks. Here’s an example of a typical minimal setup request:

<strong>Alamofire.request(“https://httpbin.org/get”).responseJSON { response in </strong>

<strong>print(response.request) // original URL request </strong>

<strong>print(response.response) // HTTP URL response </strong>

<strong>print(response.data) // server data </strong>

<strong>print(response.result) // result of response serialization </strong>

<strong>if let JSON = response.result.value { </strong>

<strong>print(“JSON: (JSON)”) </strong>

<strong>} </strong>

<strong>} </strong>

And this is how you’d set up a session manager and use it to send requests:

<strong>let configuration = URLSessionConfiguration.default </strong>

<strong>let sessionManager = Alamofire.SessionManager(configuration: configuration)</strong>

<strong>sessionManager.request(urlString, method: .post, parameters: parameters, encoding: JSONEncoding.default) .responseJSON { [weak self] response in </strong>

<strong>if let json = response.result.value as? [String: String] { </strong>

<strong>// do something if it was success </strong>

<strong>} else {</strong>

<strong>// do something if it was failure </strong>

<strong>} </strong>

<strong>}</strong>

Alamofire and AFNetworking are the workhorses for today’s HTTP networking on iOS and every developer should be familiar with it.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

How do you handle multi-threading with networking on iOS?

A

Multi-threading is very important when you work with networking on mobile devices. Blocking the main thread, making your UI unresponsive for the duration of HTTP requests for a long time, is not an option.

The general idea with any kind of multi-threading on iOS is that you don’t want to block the main UI thread. That means that every HTTP or other service/networking layer request should be executed on a back- ground thread. In fact, some of the iOS system frameworks will complain and print logs or crash if you use them outside of the main thread (Autolayout for example). There are various mechanics in iOS and third-party libraries to help you with this but the most common solutions are GCD and NSOperation. Most of the third-party libraries (i.e., Alamofire and AFNetworking) and NSURLSession already have threading mechanics built in and execute their requests on a background thread and call completion blocks on the main thread.

GCD is a low-level library for managing threading and queues on iOS. It has a C-based interface (with Swift 3 it has finally become an object-based API) and is very powerful. You’d use it in conjunction with NSURLSession, for example. All the HTTP requests the NSURLSession makes are executed on a background thread, and it could be either configured to execute completion callback on the main thread or on a background thread. Also, if your comple- tion callback is executed on a background thread but you need to do some UI updates, you can use GCD blocks like this:

<strong>dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{</strong>

<strong>NSURLRequest *request = [NSURLRequest requestWithURL: [NSURL URLWithString:@”http://smartcloud.io/”]];</strong>

<strong>NSURLResponse *response;</strong>

<strong>NSError *error;</strong>

<strong>NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];</strong>

<strong>if (error) {<br></br> // handle error</strong>

<strong> return; </strong>

<strong>}</strong>

<strong>dispatch_async(dispatch_get_main_queue(), ^{ </strong>

<strong>// update your UI safely</strong>

<strong>}); </strong>

<strong>});</strong>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

How do you serialize and map JSON data coming from the backend?

A

JSON serialization and mapping are common tasks when you’re doing HTTP networking with an API on iOS.

Every time you receive JSON or XML or any other kind of response from a backend API, you most likely get it in a JSON or binary or other “inconvenient” format. The first thing you need to do to be able to work with the data you’ve received is to serialize it in something your app understands. At the most simplest and basic level that would be a dictionary or array of objects containing other dictionaries, arrays, and primitives from that response. So let’s say if your JSON response looks like this:

<strong>{ </strong>

<strong>post: { </strong>

<strong>title: ‘This is an awesome post!’, </strong>

<strong>body: ‘loads of text …..’, </strong>

<strong>tags: [‘Awesomeness’, ‘Coolness’, ‘Greatness!’], </strong>

<strong>} </strong>

<strong>}</strong>

Then a serialized object from it is going to look like this:

<strong>var post = Dictionary(); </strong>

<strong>post[“title”] = “This is an awesome post!” as AnyObject? </strong>

<strong>post[“body”] = “loads of text …..” as AnyObject? </strong>

<strong>post[“tags”] = [“Awesomeness”, “Coolness”, “Greatness!”] as AnyObject? </strong>

<strong>print(post) </strong>

<strong>========== print output </strong>

<strong>[“tags”: (Awesomeness, Coolness, Greatness!), </strong>

<strong>“body”: loads of text ….., </strong>

<strong>“title”: This is an awesome post!]</strong>

Obviously in the example above we’ve manually created the dictionary our- selves but this is exactly what something like NSJSONSerialization would do for you. NSJSONSerialization is the go-to tool for JSON dictionar- ies/arrays/primitives serialization.

Data serialization is only the first piece of the puzzle when working with JSON data. The other piece is data mapping.

A better solution for this would be a library such as Mantle or ObjectMapper. Both of those help you declare your key/property mapping and automate the process. As a result you’d get your custom domain model objects crafted specifically for the tasks your application does, reducing errors.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

How do you download images on iOS?

A

There are two main things you need to worry about when working with images fetched from the web on iOS: <strong>downloading and caching</strong>. Downloading involves actually issuing an HTTP request to get the raw image data from a server. Caching is concerned with storing downloaded images to disk, database, or in-memory cache (or any combination of the three). At the end of the day you’re better off using a library that takes care of a lot image downloading and caching boilerplate for you. Typical options to pick from are AFNetworking or Alamofire themselves or a powerhouse when it comes to image download and caching, SDWebImage. SDWebImage gives you a lot of flexibility with your image downloading and caching and provides a set of UIImageView extension methods that you can call on to download images for given URLs, along with placeholder images and download progress reporting.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How would you cache images?

A

Image caching is important for every iOS application that fetches graphics from the web. Due to mobile device constraints on memory, battery, and bandwidth, it is important to cache images and be efficient when doing it.

When it comes to caching images, there are really three ways you can go about it: in-memory cache, database storage, and disk storage.

<strong>In-memory cache</strong> could be as simple as a Dictionary that keeps a reference to UIImage objects and uses the URLs they were downloaded from as unique keys or it could actually be NSCache that performs similar stuff for you and also can be configured.

<strong>Database storage</strong> is used for image caching when you save downloaded image binary to Core Data or Realm or a similar database. Typically this is used for images of a very small size because databases were not necessarily made to handle large files. The best use case for that is small thumbnail images.

<strong>Disk storage</strong> is what you expect it to be - storing downloaded files to the disk for quick retrieval later instead of doing another fetch from the server. Files are usually stored with a unique name identifier to make it easy to look them up quickly.

Ultimately the best solution for caching is going to vary case by case, but a lot of apps either use SDWebImage or a similar library or roll their own solution using a combination of in-memory, database storage, and disk storage.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

How do you download files on iOS?

A

File download is a common task for iOS apps. It could be a PDF or image or video file that you need your app to download. At the very basic level, file download is just fetching a bunch of bytes from a URL over HTTP somewhere on the web. Either NSURLSession’s NSURLSessionDataTask or Alamofire’s download GET request will do the trick. When you get the data there are three ways you can deal with it. You either:

  1. work with received data right there in-memory in the callback where you received it,
  2. store the received file in a temporary folder for later use, or
  3. store the received file permanently on the disk.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Have you used sockets and/or pubsub systems?

A

Pub/sub sys- tems are growing in popularity for solving problems other than chat/messaging on iOS though, so it is beneficial for iOS developers to be at least familiar with the topic.

Sockets is a specific technology for persistent connection communication and you can think of it as a subset of pub/sub systems. Sockets and pub/sub systems such as Pubnub allow you to build apps that can connect and observe external data streams and react and process received data in nearly real time.

Consider this example: you’re building an app similar to Facebook Messenger. In that app you have your normal view controller with a list of chats you have open and when you open a specific chat it will open another view controller for that chat. This new view controller with a specific chat then subscribes to a channel using sockets or Pubnub or another pubsub system. As soon as it’s subscribed to its chat channel, it will receive the latest batch of messages since the last connection and then will start receiving and sending new messages in real time as participants of that chat type them. That is the general idea of how chat/message applications work.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What is RestKit? What is it used for? What are the advantages and disadvantages?

A

RestKit used to be a very popular data synchronization framework used by many companies, especially with legacy codebases.

RestKit is a framework that was made for the purpose of data synchronization between client iOS applications and RESTful web services. RestKit has several responsibilities it takes onto itself such as

  • HTTP url composition and building (routing),
  • HTTP GET/POST/etc. request sending and enqueueing,
  • JSON request and response serialization,
  • JSON response parsing and mapping,
  • Core Data synchronization with mapping from JSON domain models received from the backend,
  • POSTing/PUTing/etc. domain models created locally and synced with Core Data with a remote RESTful service.
  • At the end of the day the reason RestKit became obsolete and is virtually not used anymore on new projects is because it was doing too much for you and forced you into its convoluted API.

As an alternative to RestKit, you’re better off rolling your own solution for data synchronization. RestKit’s downfall was that it broke SRP. Choose wisely what features and functionality you need from your libraries and how they should be used in your applications.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

What could you use instead of RestKit?

A

Since RestKit is practically obsolete these days, you could be asked about al- ternatives you could use instead of RestKit to synchronize data with backend APIs. You have several options instead of RestKit to use for data synchronization with backend APIs:

  • Overcoat
  • Roll-Your-Own-Solution

Overcoat is another library that takes care of a lot of things for you like RestKit, but unlike RestKit its API is way easier to use. It takes care of routing, HTTP requests, JSON response parsing, object mapping from JSON to custom objects, object mapping from custom objects to Core Data, and promises API out of the box. It takes on a lot of responsibilities just like RestKit and therefore is not advisable to use for every app.

But the better option is to roll your own solution. If you think about it, every- thing that RestKit does is more or less necessary for any complex enough iOS application. Things that it does can be implemented using other libraries and tools available. For example:

  • HTTP URL composition/routing can be implemented as a simple custom URL builder.
  • HTTP GET/POST/etc. requests sending and enqueueing can be handled by AFNetworking and Alamofire.
  • JSON request and response serialization is taken care of by NSJSONSerialization and/or Alamofire/AFNetworking.
  • JSON response parsing and mapping can be handled by a library like Mantle.
  • Core Data synchronization and mapping from/to custom domain models can be taken care of by Mantle.

And that’s everything you need. Rolling your own solution, and only when you need to, will also help you evolve your codebase gradually without introducing things with unnecessary functionality and baggage. You just need to know what you need.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

How do you test network requests?

A

Unit and integration testing are becoming more and more popular as tools for testing evolve in the iOS ecosystem.

In general client-side applications do not integrate test network requests, they only do unit-testing or mock them if really necessary. The reason is that it is not common to have a dedicated server for unit-testing that can receive and adequately respond to those test requests. And also there’s a challenge of keeping it in sync with the current client-side codebase.

Typically OCMock-based libraries like Cedar, Quick, Specta, and Expecta are the go-to tools for unit-testing on iOS.