|
| 1 | +## **Getting Started** |
| 2 | + |
| 3 | +- When you develop an app usually you have to fetch data from server/s. |
| 4 | +- due to this you will want to use a Networking framework but you want to keep the code clean, independent and mantainable. |
| 5 | +- You may want to use libraries like Alamofire, Malibu or your own implementation using URLSession or URLConnection. |
| 6 | +- What QuickHatch provides is a set of protocols that allows you to follow clean code standards, SOLID principles and allows you to be flexible when it comes to Networking. |
| 7 | +- First of all, your app will use a NetworkClient (this can be Alamofire, etc), and QuickHatch provides a protocol called NetworkRequestFactory that sets what a network client should respond when making a request. |
| 8 | + |
| 9 | + |
| 10 | + |
| 11 | +The name of this networkLayer interface in QuickHatchHTTP is NetworkRequestFactory :). |
| 12 | +```swift |
| 13 | + |
| 14 | +public protocol NetworkRequestFactory { |
| 15 | + func data(request: URLRequest, |
| 16 | + dispatchQueue: DispatchQueue, |
| 17 | + completionHandler completion: @Sendable @escaping (Result<HTTPResponse, Error>) -> Void) -> DataTask |
| 18 | + func dataPublisher(request: URLRequest) -> AnyPublisher<HTTPResponse,Error> |
| 19 | + func data(request: URLRequest) async throws -> HTTPResponse |
| 20 | +} |
| 21 | +``` |
| 22 | + |
| 23 | +The very base protocol of the RequestFactory provides 2 functions to get Data out of a network request, one is using a ***completionHandler*** with a ***Request*** type return and the other one is using ***Combine's AnyPublisher*** if you choose to use Reactive Programming |
| 24 | + |
| 25 | +Now lets say your app is using a MVP (Model-View-Presenter) pattern and you want to use QuickHatch to map your networking layer. |
| 26 | +Lets show a sample of how that would be: |
| 27 | + |
| 28 | +First we have our presenter, class in charge of connecting View and Models. |
| 29 | +Keep in mind these its just a sample, you should always use clean code principles such as SOLID or KISS. |
| 30 | + |
| 31 | + |
| 32 | +```swift |
| 33 | + class ViewPresenter: Presenter { |
| 34 | + private var requestFactory: NetworkRequestFactory |
| 35 | + var view: View? |
| 36 | + |
| 37 | + init(requestFactory: NetworkRequestFactory) { |
| 38 | + self.requestFactory = requestFactory |
| 39 | + } |
| 40 | + |
| 41 | + func fetchData(username: String) { |
| 42 | + view?.showLoading() |
| 43 | + // Here you initialize the URLRequest object, for now we will use a quickHatch get request |
| 44 | + let yourRequest = URLRequest.get(url: URL("www.google.com", |
| 45 | + parameters: ["username": username], |
| 46 | + parameterEncoding: URLEncoding.queryString) |
| 47 | + requestFactory.data(request: yourRequest, dispatch: .main) { result in |
| 48 | + view?.stopLoading() |
| 49 | + switch result { |
| 50 | + case .success(let data): |
| 51 | + view?.showSuccessAlert(data) |
| 52 | + case .failure(let error): |
| 53 | + view?.showErrorAlert(error) |
| 54 | + } |
| 55 | + |
| 56 | + }.resume() |
| 57 | + } |
| 58 | + } |
| 59 | +``` |
| 60 | +Here we have a View type (protocol), a fetchData method that is going to use the NetworkFactory to get the data from somewhere using a data response and we have the initializer where we are injecting the networkFactory. |
| 61 | +Now previously if we used some NetworkClient framework here we would be using the implementation class instead of the protocol and we would be attached to that framework, |
| 62 | +but with QuickHatch you are attaching yourself to a protocol, and the implementation can change anytime. |
| 63 | + |
| 64 | +And now we have the code of our view and the dependency injector: |
| 65 | + |
| 66 | +```swift |
| 67 | + struct DependencyInjector { |
| 68 | + func initializeSampleView() { |
| 69 | + let presenter = ViewPresenter(requestFactory: QHRequestFactory(urlSession: URLSession.shared) |
| 70 | + let sampleView = SampleView(presenter: presenter) |
| 71 | + application.rootView = sampleView |
| 72 | + } |
| 73 | + } |
| 74 | +``` |
| 75 | + |
| 76 | +```swift |
| 77 | + class SampleView: View { |
| 78 | + |
| 79 | + private var presenter: ViewPresenter |
| 80 | + private var textField: TextField |
| 81 | + |
| 82 | + init(presenter: Presenter) { |
| 83 | + self.presenter = presenter |
| 84 | + self.presenter.view = self |
| 85 | + } |
| 86 | + |
| 87 | + @IBAction buttonTapped() { |
| 88 | + presenter.fetchData(textField.text) |
| 89 | + } |
| 90 | + |
| 91 | + func stopLoading() { |
| 92 | + // stop spinner |
| 93 | + } |
| 94 | + |
| 95 | + func showLoading() { |
| 96 | + // start spinner |
| 97 | + } |
| 98 | + |
| 99 | + func showSuccessAlert(data: Data) { |
| 100 | + // show alert for success case |
| 101 | + } |
| 102 | + |
| 103 | + func showErrorAlert(error: Error) { |
| 104 | + // show alert for error case |
| 105 | + } |
| 106 | + } |
| 107 | +``` |
| 108 | + |
| 109 | +Great! now we have a presenter that uses an abstract networking layer, and we can switch the implementation by changing the code in the dependencyInjector, |
| 110 | +in this case we used the NetworkFactory implementation that QuickHatch provides, this one is initizalized with a URLSession object. |
| 111 | +If we want to use an Alamofire Implementation: |
| 112 | +you go to the dependency injector and set the new implementation. |
| 113 | + |
| 114 | +```swift |
| 115 | + let presenter = ViewPresenter(requestFactory: AlamofireRequestFactory()) |
| 116 | +``` |
| 117 | + |
| 118 | +--- |
0 commit comments