Code Monkey home page Code Monkey logo

networklayer's Introduction

NetWorkLayer Useing ALamofire , Codable & Generic

First of all I want thank Eng: Ahmed-Masoud


OK we need to implement some of classes and enums like below :

1- create file with name >> TargetType

  • create inside this file 2 enums and one protocol like below :
     //HTTPMethod specify what is type of request {get|post|delete}
    enum HTTPMethod:String {
        case get  = "GET"
        case post = "POST"
        case put  = "PUT"
        case delete = "DELETE"
    }
        //Task specify what is type of request have parameters or Not
    enum Task{
           case requestPlain
           case requestParameters(parameters: [String:Any],encoding:ParameterEncoding)
            }
            // define the informations of any request
    protocol TargetType {
        var baseURL:String {get}
        var path:String {get}
        var method:HTTPMethod {get}
        var task:Task {get}
        var headers: [String:String]? {get}
      }
      

2- create file with name >> BaseAPI in this File we will implement the main function for fetch data

 import Foundation
 import Alamofire

 class BaseAPI<T:TargetType> {

     func fetchData<M:Decodable>(target:T,responseClass:M.Type,completion: @escaping (Result<M?,NSError>) -> Void) {
         let method = Alamofire.HTTPMethod(rawValue:target.method.rawValue)
         let headers = Alamofire.HTTPHeaders(target.headers ?? [:])
         let params = buildParameters(task: target.task)

         AF.request(target.baseURL + target.path , method: method,parameters:params.0 , encoding: params.1,headers: headers).responseJSON { response in
             guard let statusCode = response.response?.statusCode else {
                 //ADD Custom error
                 let error = NSError(domain: target.baseURL, code:response.response?.statusCode ?? 0 , userInfo: [NSLocalizedDescriptionKey:ErrorMessages.genericError])
                 completion(.failure(error))
                 return
             }
             if statusCode == 200 {
                 //SuccessFul request
                 guard let jsonResponse = try? response.result.get() else {
                     //ADD Custom Error
                     let error = NSError(domain: target.baseURL, code:response.response?.statusCode ?? 0 , userInfo: [NSLocalizedDescriptionKey:ErrorMessages.genericError])
                     completion(.failure(error))
                     return
                 }
                 guard let theJsonData = try? JSONSerialization.data(withJSONObject: jsonResponse, options: []) else {
                     //ADD Custom Error
                     let error = NSError(domain: target.baseURL, code:response.response?.statusCode ?? 200 , userInfo: [NSLocalizedDescriptionKey:ErrorMessages.genericError])
                     completion(.failure(error))
                     return
                 }

                 guard let responseObj = try? JSONDecoder().decode(M.self, from: theJsonData) else {
                     //ADD Custom Error
                     let error = NSError(domain: target.baseURL, code:response.response?.statusCode ?? 200 , userInfo: [NSLocalizedDescriptionKey:ErrorMessages.decodingError])
                     completion(.failure(error))
                     return
                 }
                 //Successful Decode Data
                 completion(.success(responseObj))
             }else if statusCode == 404 {
                 //ADD Custom Error
                 let error = NSError(domain: target.baseURL, code:response.response?.statusCode ?? 200 , userInfo: [NSLocalizedDescriptionKey:ErrorMessages.notFoundError])
                 completion(.failure(error))
             }else if statusCode == 401 {
                 //ADD Custom Error
                 let error = NSError(domain: target.baseURL, code:response.response?.statusCode ?? 200 , userInfo: [NSLocalizedDescriptionKey:ErrorMessages.unAuthorizedError])
                 completion(.failure(error))
             }
         }

     }


     private func buildParameters(task:Task) -> ([String:Any],ParameterEncoding){
         switch task {
         case .requestPlain:
             return ([:],URLEncoding.default)
         case .requestParameters(let parameters, let encoding):
             return (parameters,encoding)
         }

     }

 }

3- create file with name BaseResponse in this file we can map any response from back end by passing the Model of Data

    class BaseResponse<T:Codable>:Codable {
        let status:Bool?
        let message:String?
        let data:T?

        enum CodingKeys:String,CodingKey {
            case data = "data"
            case message
            case status 
        }
    }

Now we can use our Network layer to fetch some of data

create userNetwork

    import Foundation
   import Alamofire

   enum UsersNetworking {

       case loginUsers(email:String,password:String)
       case creatUser(name:String,email:String,phone:String,password:String,image:String)
   }

   extension UsersNetworking :TargetType {
       var baseURL: String {
           switch self {
           default:
               return Constants.BaseURL.rawValue
           }
       }

       var path: String{
           switch self {
       case .loginUsers:
               return Constants.LoginPath.rawValue
       case .creatUser:
           return Constants.RegisterPath.rawValue
       }
       }
       var method: HTTPMethod {
           switch self {

           case .loginUsers:
               return .post
           case .creatUser:
               return .post
           }
       }
       var task: Task {
           switch self {

           case .loginUsers(email: let email, password: let password):
               return .requestParameters(parameters: ["email":email,"password":password], encoding: JSONEncoding.default)
           case .creatUser(name: let name, email: let email, phone: let phone, password: let password, image: let image):
               return .requestParameters(parameters: ["name":name, "email":email,"password":password,"phone":phone,"image":image], encoding: JSONEncoding.default)
           }
       }

       var headers: [String : String]? {
           switch self {
           default:
               return ["lang":AppLanguage.lang,"Content-Type":"application/json"]
           }
       }


   }

Create UserAPI the main function that we use it to login user

    import Foundation

   protocol UserAPIProtocol {
       func loginUsers(email:String,password:String,completion: @escaping (Result<BaseResponse<UserModel>?,NSError>) -> Void)
   }

   class UserAPI:BaseAPI<UsersNetworking>,UserAPIProtocol{
       func loginUsers(email:String,password:String,completion: @escaping (Result<BaseResponse<UserModel>?,NSError>) -> Void) {
           fetchData(target: .loginUsers(email: email, password: password), responseClass: BaseResponse<UserModel>.self) { result in
               completion(result)
           }
       }

   }

Now we can call our function in viewController to login user .

     func login() {
           let userAPI:UserAPIProtocol = UserAPI()

           AppLanguage.lang = "ar"
           userAPI.loginUsers(email: "[email protected]", password: "123456") { result in
               switch result {
               case .success(let response):
                   if response?.status ?? true {
                       guard let user = response?.data else {return}
                       print(user.email , user.name)
                       print("\(response?.message)")
                   }else {
                       print("\(response?.message)")
                   }
               case .failure(let error):
                       print(error)
               }
           }
       }

   }

๐Ÿ”‘ Note

you can find BaseURL & endpoints inside the constants File

GoodLuck โค๏ธ

networklayer's People

Contributors

iosayedahmed avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.