Wednesday, November 23, 2016

How to Isolate Client-Server Interaction Logic in iOS Applications

Nowadays most mobile applications rely heavily on client-server interactions. Not only does this mean that can they offload most of their heavy tasks to backend servers, but it also allows these mobile applications to offer all sorts of features and functionality that can only be made available through the Internet.
Backend servers are usually designed to offer their services through RESTful APIs. For simpler applications, we often feel tempted to get by creating spaghetti code; mixing code that invokes the API with rest of the application logic. However as applications grow complex and deal with more and more APIs, it can become a nuisance to interact with these APIs in an unstructured, unplanned manner.
Keep your iOS application code clutter-free with a well-designed REST client networking module.Keep your iOS application code clutter-free with a well-designed REST client networking module.
This article discusses an architectural approach for building a clean REST client networking module for iOS applications that allows you to keep all of your client-server interaction logic isolated from rest of your application code.

Client-Server Applications

A typical client-server interaction looks something like this:
  1. A user performs some action (e.g., tapping on some button or performing some other gesture on the screen).
  2. The application prepares and sends an HTTP/REST request in response to the user action.
  3. The server processes the request and responds accordingly to the application.
  4. The application receives the response and updates the user interface based on it.
At quick glance, the overall process may look simple, but we do have to think about the details.
Even assuming that a backend server API works as advertised (which is not always the case!), it can often be poorly designed making it inefficient, or even difficult, to use. One common annoyance is that all calls to the API require the caller to redundantly provide the same information (e.g., how request data is formatted, an access token that the server can use to identify the currently signed in user, and so on).
Mobile applications may also need to utilize multiple back-end servers concurrently for different purposes. One server may, for example, be dedicated to user authentication while another deals with collecting analytics only.
Furthermore, a typical REST client will need to do way more than just invoke remote APIs. The ability to cancel pending requests, or a clean and manageable approach to handling errors, are examples of functionality that needs to be built into any robust mobile application.

An Overview of the Architecture

The core of our REST client will be built on these following components:
  • Models: Classes that describe the data models of our application, reflecting the structure of data received from, or sent to, the backend servers.
  • Parsers: Responsible for decoding server responses and producing model objects.
  • Errors: Objects to represent erroneous server responses.
  • Client: Sends requests to backend servers and receives responses.
  • Services: Manage logically linked operations (e.g. authentication, managing user related data, analytics, etc).
This is how each of these components will interact with each other:
The arrows 1 through 10 in the image above show an ideal sequence of operations between the application invoking a service and the service eventually returning the requested data as a model object. Each component in that flow has a specific role ensuring separation of concerns within the module.

Implementation

We will implement our REST client as part of our imaginary social network application into which we will load a list of the currently logged in user’s friends. We will assume our remote server uses JSON for responses.
Let us begin by implementing our models and parsers.

From Raw JSON to Model Objects

Our first model, User, defines the structure of information for any user of the social network. To keep things simple, we will only include fields that are absolutely necessary for this tutorial (in a real application, the structure would typically have a lot more properties).
struct User {
    var id: String
    var email: String?
    var name: String?
}
Since we will receive all user data from the backend server via its API, we need a way to parse the API response into a valid User object. To do this, we will add a constructor to User that accepts a parsed JSON object (Dictionary) as a parameter. We will define our JSON object as an aliased type:
typealias JSON = [String: Any]
We will then add the constructor function to our User struct as follows:
extension User {
    init?(json: JSON) {
        guard let id = json["id"] as? String else {
            return nil
        }
        
        self.id = id
        self.email = json["email"] as? String
        self.name = json["name"] as? String
    }
}
To preserve the original default constructor of User, we add the constructor through an extension on the User type.
Next, to create a User object from a raw API response, we need to perform the following two steps:
// Transform raw JSON data to parsed JSON object using JSONSerializer (part of standard library)
let userObject = (try? JSONSerialization.jsonObject(with: data, options: [])) as? JSON
// Create an instance of `User` structure from parsed JSON object
let user = userObject.flatMap(User.init)

Streamlined Error Handling

We will define a type to represent different errors that may occur when attempting to interact with the backend servers. We can divide all such errors into three basic categories:
  • No Internet connectivity
  • Errors that reported as a part of the response (e.g. validation errors, insufficient access rights, etc.)
  • Errors that the server fails to report as a part of the response (e.g. server crash, responses timing out, etc.)
We can define our error objects as an enumeration type. And while we are at it, it is a good idea to make our ServiceError type conform to the Error protocol. This will allow us to use and handle these error values using standard mechanisms provided by Swift (such as using throw to throw an error).
enum ServiceError: Error {
    case noInternetConnection
    case custom(String)
    case other
}
Unlike noInternetConnection and other errors, the custom error has a value associated with it. This will allow us to use the error response from the server as an associated value for the error itself, thereby giving the error more context.
Now, let’s add a errorDescription property to the ServiceError enumartion to make the errors more descriptive. We will add hardcoded messages for the noInternetConnection and other errors and use the associated value as the message for custom errors.
extension ServiceError: LocalizedError {
    var errorDescription: String? {
        switch self {
        case .noInternetConnection:
            return "No Internet connection"
        case .other:
            return "Something went wrong"
        case .custom(let message):
            return message
        }
    }
}
There is just one more thing we need to implement in our ServiceError enumeration. In the case of a customerror, we need to transform the server JSON data into an error object. To do this, we use the same approach we used in the case of models:
extension ServiceError {
    init(json: JSON) {
        if let message =  json["message"] as? String {
            self = .custom(message)
        } else {
            self = .other
        }
    }
}

Bridging the Gap Between the Application and Backend Server

The client component will be an intermediary between the application and the backend server. It’s a critical component that will define how the application and the server will communicate, yet it will know nothing about the data models and their structures. The client will be responsible for invoking specific URLs with provided parameters and returning incoming JSON data parsed as JSON objects.
enum RequestMethod: String {
    case get = "GET"
    case post = "POST"
    case put = "PUT"
    case delete = "DELETE"
}


final class WebClient {
    private var baseUrl: String
    
    init(baseUrl: String) {
        self.baseUrl = baseUrl
    }
    
    func load(path: String, method: RequestMethod, params: JSON, completion: @escaping (Any?, ServiceError?) -> ()) -> URLSessionDataTask? {
        // TODO: Add implementation 
    }
}
Let’s examine what’s happening in the above code…
First, we declared an enumeration type, RequestMethod, that describes four common HTTP methods. These are among the methods used in REST APIs.
The WebClient class contains the baseURL property which will be used to resolve all relative URLs that it receives. In case our application needs to interact with multiple servers, we can create multiple instances of WebClient each with a different value for baseURL.
The Client has a single method load, which takes a path relative to baseURL as a parameter, request method, request parameters, and completion closure. The completion closure is invoked with the parsed JSON and ServiceError as parameters. For now, the method above lacks an implementation, which we will get to shortly.
Before implementing the load method, we need a way to create a URL from all the information available to the method. We will extend the URL class for this purpose:
extension URL {
    init(baseUrl: String, path: String, params: JSON, method: RequestMethod) {
        var components = URLComponents(string: baseUrl)!
        components.path += path
        
        switch method {
        case .get, .delete:
            components.queryItems = params.map {
                URLQueryItem(name: $0.key, value: String(describing: $0.value))
            }
        default:
            break
        }
        
        self = components.url!
    }
}
Here we simply add the path to the base URL. For GET and DELETE HTTP methods, we also add the query parameters to the URL string.
Next, we need to be able to create instances of URLRequest from given parameters. To do this we will do something similar to what we did for URL:
extension URLRequest {
    init(baseUrl: String, path: String, method: RequestMethod, params: JSON) {
        let url = URL(baseUrl: baseUrl, path: path, params: params, method: method)
        self.init(url: url)
        httpMethod = method.rawValue
        setValue("application/json", forHTTPHeaderField: "Accept")
        setValue("application/json", forHTTPHeaderField: "Content-Type")
        switch method {
        case .post, .put:
            httpBody = try! JSONSerialization.data(withJSONObject: params, options: [])
        default:
            break
        }
    }
}
Here, we first create a URL using the constructor from the extension. Then we initialize an instance of URLRequest with this URL, set a few HTTP headers as necessary, and then in case of POST or PUT HTTP methods, add parameters to the request body.
Now that we have covered all the prerequisites, we can implement the load method:
final class WebClient {
    private var baseUrl: String
    
    init(baseUrl: String) {
        self.baseUrl = baseUrl
    }
    
    func load(path: String, method: RequestMethod, params: JSON, completion: @escaping (Any?, ServiceError?) -> ()) -> URLSessionDataTask? {
        // Checking internet connection availability
        if !Reachability.isConnectedToNetwork() {
            completion(nil, ServiceError.noInternetConnection)
            return nil
        }




        // Adding common parameters
        var parameters = params
        
        if let token = KeychainWrapper.itemForKey("application_token") {
            parameters["token"] = token
        }




        // Creating the URLRequest object
        let request = URLRequest(baseUrl: baseUrl, path: path, method: method, params: params)




        // Sending request to the server.
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            // Parsing incoming data
            var object: Any? = nil
            if let data = data {
                object = try? JSONSerialization.jsonObject(with: data, options: [])
            }
            
            if let httpResponse = response as? HTTPURLResponse, (200..<300) ~= httpResponse.statusCode {
                completion(object, nil)
            } else {
                let error = (object as? JSON).flatMap(ServiceError.init) ?? ServiceError.other
                completion(nil, error)
            }
        }
        
        task.resume()
        
        return task
    }
}
The load method above performs the following steps:
  1. Check availability of the Internet connection. If Internet connectivity is not available, we call the completion closure immediately with noInternetConnection error as a parameter. (Note: Reachability in the code is a custom class, which uses one of the common approaches to check the Internet connection.)
  2. Add common parameters.. This can include common parameters such as an application token or user id.
  3. Create the URLRequest object, using the constructor from the extension.
  4. Send the request to the server. We use the URLSession object to send data to the server.
  5. Parse incoming data. When the server responds, we first parse the response payload into a JSON object using JSONSerialization. Then we check the status code of the response. If it is a success code (i.e., in the range between 200 and 299), we call the completion closure with the JSON object. Otherwise, we transform the JSON object into a ServiceError object and call the completion closure with that error object.

Defining Services for Logically Linked Operations

In the case of our application, we need a service that will deal with tasks related to friends of a user. For this, we create a FriendsService class. Ideally, a class like this will be in charge of operations such as getting a list of friends, adding a new friend, removing a friend, grouping some friends into a category, etc. For simplicity in this tutorial, we will implement just one method:
final class FriendsService {
    private let client = WebClient(baseUrl: "https://your_server_host/api/v1")
    
    @discardableResult
    func loadFirends(forUser user: User, completion: @escaping ([User]?, ServiceError?) -> ()) -> URLSessionDataTask? {


        let params: JSON = ["user_id": user.id]
        
        return client.load(path: "/friends", method: .get, params: params) { result, error in
            let dictionaries = result as? [JSON]
            completion(dictionaries?.flatMap(User.init), error)
        }
    }
}
The FriendsService class contains a client property of type WebClient. It is initialized with the base URL of the remote server which is in charge of managing friends. As previously mentioned, in other service classes, we can have a different instance of WebClient initialized with a different URL if necessary.
In the case of an application that works with only one server, the WebClient class can be given a constructor that initializes with that server’s URL:
final class WebClient {
    // ...
    init() {
        self.baseUrl = "https://your_server_base_url"
    }
    // ...
}
The loadFriends method, when invoked, prepares all the necessary parameters and uses FriendService’s instance of WebClient to make an API request. After it receives the response from the server through the WebClient, it transforms the JSON object into User models and calls the completion closure with them as a parameter.
A typical usage of the FriendService may look something like the following:
let friendsTask: URLSessionDataTask!
let activityIndicator: UIActivityIndicatorView!
var friends: [User] = []


func friendsButtonTapped() {
 
       friendsTask?.cancel() //Cancel previous loading task.




       activityIndicator.startAnimating() //Show loading indicator


 friendsTask = FriendsService().loadFriends(forUser: currentUser) {[weak self] friends, error in
DispatchQueue.main.async {
      self?.activityIndicator.stopAnimating() //Stop loading indicators 
            if let error = error {
                print(error.localizedDescription) //Handle service error
            } else if let friends = friends {
                 self?.friends = friends //Update friends property
                 self?.updateUI() //Update user interface
            }
}
      }
}
In the above example, we are assuming that the function friendsButtonTapped is invoked whenever the user taps on a button intended to show them a list of their friends in the network. We also keep a reference to the task in the friendsTask property so that we can cancel the request at any time by calling friendsTask?.cancel().
This allows us to have a greater control of the lifecycle of pending requests, enabling us to terminate them when we determine that they have become irrelevant.

Conclusion

In this article, I have shared a simple architecture of a networking module for your iOS application that is both trivial to implement and can be adapted to the intricate networking needs of most iOS applications. However, the key takeaway from this is that a properly designed REST client and components accompanying it – that are isolated from the rest of your application logic – can help keep your application’s client-server interaction code simple, even as the application itself becomes increasingly complex.
I hope you find this article helpful in building your next iOS application. You can find the source code of this networking module on GitHub. Check out the code, fork it, change it, play with it.
If you find some other architecture more preferable for you and your project, please do share the details in the comments section below.
This article was originally posted on Toptal

Friday, November 18, 2016

The Mistakes Most Swift Developers Don't Know They're Making

Coming from an Objective-C background, in the beginning, I felt like Swift was holding me back. Swift was not allowing me to make progress because of its strongly typed nature, which used to be infuriating at times.
Unlike Objective-C, Swift enforces many requirements at the compile time. Things that are relaxed in Objective-C, such as the id type and implicit conversions, are not a thing in Swift. Even if you have an Intand a Double, and you want to add them up, you will have to convert them to a single type explicitly.
Also, optionals are a fundamental part of the language, and even though they are a simple concept, it takes some time to get used to them.
In the beginning, you might want to force unwrap everything, but that will eventually lead to crashes. As you get acquainted with the language, you start to love how you hardly have runtime errors since many mistakes are caught at compile time.
Most Swift programmers have significant previous experience with Objective-C, which, among other things, might lead them to write Swift code using the same practices they are familiar with in other languages. And that can cause some bad mistakes.
In this article, we outline the most common mistakes that Swift developers make and ways to avoid them.
Top Swift Development MistakesMake no mistake - Objective-C best practices are not Swift best practices

1. Force-Unwrapping Optionals

A variable of an optional type (e.g. String?) might or might not hold a value. When they don’t hold a value, they’re equal to nil. To obtain the value of an optional, first you have to unwrap them, and that can be made in two different ways.
One way is optional binding using an if let or a guard let, that is:
  var optionalString: String?
  //...
  if let s = optionalString {
      // if optionalString is not nil, the test evaluates to
      // true and s now contains the value of optionalString
  }
  else {
      // otherwise optionalString is nil and the if condition evaluates to false
  }
Second is forcing unwrap using the ! operator, or using an implicitly unwrapped optional type (e.g. String!). If the optional is nil, forcing an unwrap will cause a runtime error and terminate the application. Further, attempting to access the value of an implicitly unwrapped optional will cause the same.
We sometimes have variables that we can’t (or don’t want to) initialize in the class/struct initializer. Thus, we have to declare them as optionals. In some cases, we assume they won’t be nil in certain parts of our code, so we force unwrap them or declare them as implicitly unwrapped optionals because that’s easier than having to do optional binding all the time. This should be done with care.
This is similar to working with IBOutlets, which are variables that reference an object in a nib or storyboard. They won’t be initialized upon the parent object’s initialization (usually a view controller or custom UIView), but we can be sure they won’t be nil when viewDidLoad (in a view controller) or awakeFromNib (in a view) is called, and so we can access them safely.
In general, the best practice is to avoid forcing unwrap and using implicitly unwrapped optionals. Always consider the optional could be nil and handle it appropriately either using optional binding, or checking if it’s not nil before forcing an unwrap, or accessing the variable in case of an implicitly unwrapped optional.

2. Not Knowing Pitfalls of Strong Reference Cycles

A strong reference cycle exists when a pair of objects keeps a strong reference to each other. This is not something new to Swift, since Objective-C has the same issue, and seasoned Objective-C developers are expected to properly manage this. It’s important to pay attention to strong references and what references what. The Swift documentation has a section dedicated to this topic.
It’s particularly important to manage your references when using closures. By default, closures (or blocks), keep a strong reference to every object that is referenced inside of them. If any of these objects has a strong reference to the closure itself, we have a strong reference cycle. It’s necessary to make use of capture lists to properly manage how your references are captured.
If there’s the possibility that the instance captured by the block will be deallocated before the block gets called, you have to capture it as a weak reference, which will be optional since it can be nil. Now, if you’re sure the captured instance will not be deallocated during the lifetime of the block, you can capture it as an unowned reference. The advantage of using unowned instead of weak is that the reference won’t be an optional and you can use the value directly without the need to unwrap it.
In the following example, which you can run in the Xcode Playground, the Container class has an array and an optional closure that is invoked whenever its array changes (it uses property observers to do so). The Whatever class has a Container instance, and in its initializer, it assigns a closure to arrayDidChange and this closure references self, thus creating a strong relationship between the Whatever instance and the closure.
    struct Container<T> {
        var array: [T] = [] {
            didSet {
                arrayDidChange?(array: array)
            }
        }

        var arrayDidChange: ((array: [T]) -> Void)?
    }

    class Whatever {
        var container: Container<String>

        init() {
            container = Container<String>()


            container.arrayDidChange = { array in
                self.f(array)
            }
        }

        deinit {
            print("deinit whatever")
        }

        func f(s: [String]) {
            print(s)
        }
    }

    var w: Whatever! = Whatever()
    // ...
    w = nil
If you run this example, you’ll notice that deinit whatever never gets printed, which means our instance wdoesn’t get deallocated from memory. To fix this, we have to use a capture list to not capture self strongly:
    struct Container<T> {
        var array: [T] = [] {
            didSet {
                arrayDidChange?(array: array)
            }
        }

        var arrayDidChange: ((array: [T]) -> Void)?
    }


    class Whatever {
        var container: Container<String>

        init() {
            container = Container<String>()

            container.arrayDidChange = { [unowned self] array in
                self.f(array)
            }
        }

        deinit {
            print("deinit whatever")
        }

        func f(s: [String]) {
            print(s)
        }
    }

    var w: Whatever! = Whatever()
    // ...
    w = nil
In this case, we can use unowned, because self will never be nil during the lifetime of the closure.
It’s a good practice to nearly always use capture lists to avoid reference cycles, which will reduce memory leaks, and a safer code in the end.

3. Using self Everywhere

Unlike in Objective-C, with Swift, we are not required to use self to access a class’ or struct’s properties inside a method. We are only required to do so in a closure because it needs to capture self. Using selfwhere it’s not required is not exactly a mistake, it works just fine, and there will be no errors and no warnings. However, why write more code than you have to? Also, it is important to keep your code consistent.

4. Not Knowing the Type of Your Types

Swift uses value types and reference types. Moreover, instances of a value type exhibit a slightly different behavior of instances of reference types. Not knowing what category each of your instances fit in will cause false expectations on the behavior of the code.
In the most object oriented languages, when we create an instance of a class and pass it around to other instances and as an argument to methods, we expect this instance to be the same everywhere. That means any change to it will be reflected everywhere, because in fact, what we have are just a bunch of references to the exact same data. Objects that exhibit this behavior are reference types, and in Swift, all types declared as class are reference types.
Next, we have value types which are declared using struct or enum. Value types are copied when they’re assigned to a variable or passed as an argument to a function or method. If you change something in the copied instance, the original one will not be modified. Value types are immutable. If you assign a new value to a property of an instance of a value type, such as CGPoint or CGSize, a new instance is created with the changes. That’s why we can use property observers on an array (as in the example above in the Containerclass) to notify us of changes. What’s actually happening, is that a new array is created with the changes; it is assigned to the property, and then didSet gets invoked.
Thus, if you don’t know the object you’re dealing with is of a reference or value type, your expectations about what your code is going to do, might be entirely wrong.

5. Not Using the Full Potential of Enums

When we talk about enums, we generally think of the basic C enum, which is just a list of related constants that are integers underneath. In Swift, enums are way more powerful. For example, you can attach a value to each enumeration case. Enums also have methods and read-only/computed properties that can be used to enrich each case with more information and details.
The official documentation on enums is very intuitive, and the error handling documentation presents a few use cases for enums’ extra power in Swift. Also, check out following extensive exploration of enums in Swift to learn pretty much everything you can do with them.

6. Not Using Functional Features

The Swift Standard Library provides many methods that are fundamental in functional programming and allow us to do a lot with just one line of code, such as mapreduce, and filter, among others.
Let’s examine few examples.
Say, you have to calculate the height of a table view. Given you have a UITableViewCell subclass such as the following:
  class CustomCell: UITableViewCell {
      // Sets up the cell with the given model object (to be used in tableView:cellForRowAtIndexPath:)
      func configureWithModel(model: Model)
      // Returns the height of a cell for the given model object (to be used in tableView:heightForRowAtIndexPath:)
      class func heightForModel(model: Model) -> CGFloat
  }
Consider, we have an array of model instances modelArray; we can compute the height of the table view with one line of code:
  let tableHeight = modelArray.map { CustomCell.heightForModel($0) }.reduce(0, combine: +)
The map will output an array of CGFloat, containing the height of each cell, and the reduce will add them up.
If you want to remove elements from an array, you might end up doing the following:
  var supercars = ["Lamborghini", "Bugatti", "AMG", "Alfa Romeo", "Koenigsegg", "Porsche", "Ferrari", "McLaren", "Abarth", "Morgan", "Caterham", "Rolls Royce", "Audi"]

  func isSupercar(s: String) -> Bool {
      return s.characters.count > 7
  }

  for s in supercars {
      if !isSupercar(s), let i = supercars.indexOf(s) {
          supercars.removeAtIndex(i)
      }
  }
This example doesn’t look elegant, nor very efficient since we’re calling indexOf for each item. Consider the following example:
  var supercars = ["Lamborghini", "Bugatti", "AMG", "Alfa Romeo", "Koenigsegg", "Porsche", "Ferrari", "McLaren", "Abarth", "Morgan", "Caterham", "Rolls Royce", "Audi"]

  func isSupercar(s: String) -> Bool {
      return s.characters.count > 7
  }

  for (i, s) in supercars.enumerate().reverse() { // reverse to remove from end to beginning
      if !isSupercar(s) {
          supercars.removeAtIndex(i)
      }
  }
Now, the code is more efficient, but it can be further improved by using the filter:
  var supercars = ["Lamborghini", "Bugatti", "AMG", "Alfa Romeo", "Koenigsegg", "Porsche", "Ferrari", "McLaren", "Abarth", "Morgan", "Caterham", "Rolls Royce", "Audi"]

  func isSupercar(s: String) -> Bool {
      return s.characters.count > 7
  }

  supercars = supercars.filter(isSupercar)
The next example illustrates how you can remove all subviews of a UIView that meet certain criteria, such as the frame intersecting a particular rectangle. You can use something like:
  for v in view.subviews {
    if CGRectIntersectsRect(v.frame, rect) {
      v.removeFromSuperview()
    }
  }
  ```
  We can do that in one line using `filter`
  ```
  view.subviews.filter { CGRectIntersectsRect($0.frame, rect) }.forEach { $0.removeFromSuperview() }
We have to be careful, though, because you might be tempted to chain a couple of calls to these methods to create fancy filtering and transforming, which may end up with one line of unreadable spaghetti code.

7. Staying in the Comfort-Zone and Not Trying Protocol-Oriented Programming

Swift is claimed to be the first protocol-oriented programming language, as mentioned in the WWDC Protocol-Oriented Programming in Swift session. Basically, that means we can model our programs around protocols and add behavior to types simply by conforming to protocols and extending them. For example, given we have a Shape protocol, we can extend CollectionType (which is conformed by types such as ArraySetDictionary), and add a method to it that calculates the total area accounting for intersections
  protocol Shape {
      var area: Float { get }
      func intersect(shape: Shape) -> Shape?
  }

  extension CollectionType where Generator.Element: Shape {
      func totalArea() -> Float {
          let area = self.reduce(0) { (a: Float, e: Shape) -> Float in
              return a + e.area
          }

          return area - intersectionArea()
      }

      func intersectionArea() -> Float {
          /*___*/
      }
  }
The statement where Generator.Element: Shape is a constraint that states the methods in the extension will only be available in instances of types that conform to CollectionType, which contains elements of types that conform to Shape. For example, these methods can be invoked on an instance of Array<Shape>, but not on an instance of Array<String>. If we have a class Polygon that conforms to the Shape protocol, then those methods will be available for an instance of Array<Polygon> as well.
With protocol extensions, you can give a default implementation to methods declared in the protocol, which will then be available in all types that conform to that protocol without having to make any changes to those types (classes, structs or enums). This is done extensively throughout the Swift Standard Library, for example, the mapand reduce are defined in an extension of CollectionType, and this same implementation is shared by types such as Array and Dictionary without any extra code.
This behavior is similar to mixins from other languages, such as Ruby or Python. By simply conforming to a protocol with default method implementations, you add functionality to your type.
Protocol oriented programming might look quite awkward and not very useful at first sight, which could make you ignore it and not even give it a shot. This post gives a good grasp of using protocol-oriented programming in real applications.

As We Learned, Swift Is Not a Toy Language

Swift was initially received with a lot of skepticism; people seemed to think that Apple was going to replace Objective-C with a toy language for kids or with something for non-programmers. However, Swift has proven to be a serious and powerful language that makes programming very pleasant. Since it is strongly typed, it is hard to make mistakes, and as such, it’s difficult to list mistakes you can make with the language.
When you get used to Swift and go back to Objective-C, you will notice the difference. You’ll miss nice features Swift offers and will have to write tedious code in Objective-C to achieve the same effect. Other times, you’ll face runtime errors that Swift would have caught during compilation. It is a great upgrade for Apple programmers, and there’s still a lot more to come as the language matures.
This article was originally posted on Toptal