Details
xCode 9.1, Swift 4
Features:
- Easy readable code
 
- Ready templates (it's easy to add more requests)
 
- Embedded solution with asynchronous data processing
 
- Full examples
 
Sample 1
Return data using closure
Data1.searchRequest(term: "jack johnson") { json, error  in
     print(error ?? "nil")
     print(json ?? "nil")
     print("Update views")
}
Full sample 1
Data class
import Alamofire
class Data1 {
    static fileprivate let queue = DispatchQueue(label: "requests.queue", qos: .utility)
    static fileprivate let mainQueue = DispatchQueue.main
    fileprivate class func make(request: DataRequest, closure: @escaping (_ json: [String: Any]?, _ error: Error?)->()) {
        request.responseJSON(queue: Data1.queue) { response in
            // print(response.request ?? "nil")  // original URL request
            // print(response.response ?? "nil") // HTTP URL response
            // print(response.data ?? "nil")     // server data
            //print(response.result ?? "nil")   // result of response serialization
            switch response.result {
            case .failure(let error):
                Data1.mainQueue.async {
                    closure(nil, error)
                }
            case .success(let data):
                Data1.mainQueue.async {
                    closure((data as? [String: Any]) ?? [:], nil)
                }
            }
        }
    }
    class func searchRequest(term: String, closure: @escaping (_ json: [String: Any]?, _ error: Error?)->()) {
        let request = Alamofire.request("https://itunes.apple.com/search?term=\(term.replacingOccurrences(of: " ", with: "+"))")
        Data1.make(request: request) { json, error in
            closure(json, error)
        }
    }
}
UIViewController
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        Data1.searchRequest(term: "jack johnson") { json, error  in
            print(error ?? "nil")
            print(json ?? "nil")
            print("Update views")
        }
    }
}
Sample 2
Return data using delegate
// ....
var data = Data2()
data.delegate = self
data.searchRequest(term: "jack johnson")
// ....
extension ViewController: Data2Delegate {
    func searchRequest(response json: [String : Any]?, error: Error?) {
        print(error ?? "nil")
        print(json ?? "nil")
        print("Update views")
    }
}
Full sample 2
Data class
import Alamofire
protocol Data2Delegate: class {
    func searchRequest(response json: [String: Any]?, error: Error?)
}
class Data2 {
    fileprivate let queue = DispatchQueue(label: "requests.queue", qos: .utility)
    fileprivate let mainQueue = DispatchQueue.main
    weak var delegate: Data2Delegate?
    fileprivate func make(request: DataRequest, closure: @escaping (_ json: [String: Any]?, _ error: Error?)->()) {
        request.responseJSON(queue: queue) { response in
            // print(response.request ?? "nil")  // original URL request
            // print(response.response ?? "nil") // HTTP URL response
            // print(response.data ?? "nil")     // server data
            //print(response.result ?? "nil")   // result of response serialization
            switch response.result {
            case .failure(let error):
                self.mainQueue.async {
                    closure(nil, error)
                }
            case .success(let data):
                self.mainQueue.async {
                    closure((data as? [String: Any]) ?? [:], nil)
                }
            }
        }
    }
    func searchRequest(term: String) {
        let request = Alamofire.request("https://itunes.apple.com/search?term=\(term.replacingOccurrences(of: " ", with: "+"))")
        make(request: request) { json, error in
            self.delegate?.searchRequest(response: json, error: error)
        }
    }
}
UIViewController
import UIKit
class ViewController: UIViewController {
    private var data = Data2()
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        data.delegate = self
        data.searchRequest(term: "jack johnson")
    }
}
extension ViewController: Data2Delegate {
    func searchRequest(response json: [String : Any]?, error: Error?) {
        print(error ?? "nil")
        print(json ?? "nil")
        print("Update views")
    }
}
Sample 3
Return data using PromiseKit
_ = data.searchRequest(term: "jack johnson").then { response in
      print(response.error ?? "nil")
      print(response.json ?? "nil")
      print("Update views")
      return .void
}
Full sample 3
Data class
      import Alamofire
      import PromiseKit
class Data3 {
    fileprivate let queue = DispatchQueue(label: "requests.queue", qos: .utility)
    fileprivate let mainQueue = DispatchQueue.main
    fileprivate func make(request: DataRequest) -> Promise<(json:[String: Any]?, error: Error?)> {
         return Promise { fulfill, reject in
            request.responseJSON(queue: queue) { response in
                // print(response.request ?? "nil")  // original URL request
                // print(response.response ?? "nil") // HTTP URL response
                // print(response.data ?? "nil")     // server data
                //print(response.result ?? "nil")   // result of response serialization
                switch response.result {
                    case .failure(let error):
                        self.mainQueue.async {
                            fulfill((nil, error))
                        }
                    case .success(let data):
                        self.mainQueue.async {
                            fulfill(((data as? [String: Any]) ?? [:], nil))
                        }
                }
            }
        }
    }
    func searchRequest(term: String) -> Promise<(json:[String: Any]?, error: Error?)> {
        let request = Alamofire.request("https://itunes.apple.com/search?term=\(term.replacingOccurrences(of: " ", with: "+"))")
        return make(request: request)
    }
}
extension AnyPromise {
    class var void: AnyPromise {
        return AnyPromise(Promise<Void>())
    }
}
UIViewController
import UIKit
import PromiseKit
class ViewController: UIViewController {
    private var data = Data3()
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        _ = data.searchRequest(term: "jack johnson").then { response in
            print(response.error ?? "nil")
            print(response.json ?? "nil")
            print("Update views")
            return .void
        }
    }
}