SkillAgentSearch skills...

ESNetworkManager

ESNetworkManager is a network layer based on Alamofire 5 with response Mapping

Install / Use

/learn @MahmoudEissa/ESNetworkManager
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

<img src="https://github.com/MahmoudEissa/ESNetworkManager/blob/master/logo.png" height="400">

ESNetworkManager is a library that depenent on Alamofire that making new work request easly to made with response mappin.

Version Compatibility

Here is the current Swift compatibility breakdown:

| Swift Version | Network Version | | ------------- | ------------ | | 5.X | master |

Installation

CocoaPods

Add the following to your Podfile:

pod 'ESNetworkManager'
pod 'ESNetworkManager/Promise'
pod 'ESNetworkManager/Rx'
pod 'ESNetworkManager/ObjectMapper'

You will also need to make sure you're opting into using frameworks:

use_frameworks!

Then run pod install with CocoaPods 0.36 or newer.

Usage

Initializing Request

let request = ESNetworkRequest(url: "https://sample.com/api/path")
    request.parameters = [:]
    request.headers = [:]
    request.encoding = JSONEncoding.default
    request.method = .post
    request.selections = []
    print(request)

Execute request with completion

func login(email: String, password: String) {
    let request = ESNetworkRequest(url: "https://sample.com/api/login")
    request.parameters = ["email": email, "password": password]
    request.encoding = JSONEncoding.default
    request.method = .post
    ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<User>) in
        guard case .success(let user) = response else {
            return
        }
        print(user.name)
    }
}

Uploading MultiPartFile

func upload(avatar: UIImage) {
    let data = avatar.jpegData(compressionQuality: 0.5)!
    let file = MPFile(data: data, key: "file", name: "image.jpeg", memType: "image/jpeg")
    let request = ESNetworkRequest(url: "https://sample.com/api/upload")
    request.encoding = JSONEncoding.default
    request.method = .post
    ESNetworkManager.upload(data: .multipart([file]), request: request, progress: { progress in
        print(progress.fractionCompleted)
    }) { (response: ESNetworkResponse<String>) in
        guard case .success(let url) = response else {
            return
        }
        print(url)
    }
}

Download file

func downloadFile() {
    let request = ESNetworkRequest(url: "https://sample.com/api/file.mp4")
    ESNetworkManager.download(request: request, progress: { (progress) in
        print(progress.fractionCompleted)
    }) { (response) in
        guard case .success(let url) = response else {
            return
        }
        print(url.absoluteString)
    }
}

Session Manager

Overriding Session Manager

class NetworkManager: ESNetworkManager {
    static let session: Session = {
        let manager = ServerTrustManager(evaluators: ["serverurl.com": DisabledEvaluator()])
        let configuration = URLSessionConfiguration.af.default
        return Session(configuration: configuration, serverTrustManager: manager)
    }()
    
    override class var Manager: Session {
        return session
    }
}

DataResponse Mapping

DataResponse advanced Mapping if you have a base response with pre defined errors or an error server message such the following login responses cases

{
   "status":200,
   "message":"Welcom",
   "content":{
      "token":"2e13eer1rt13tvxcvz"
   }
}
{
   "status":1002,
   "message":"Wrong Email or password"
}

Simply override DataResponse Mapping

class NetworkManager: ESNetworkManager {
    override class func map(_ response: AFDataResponse<Any>) -> ESNetworkResponse<JSON> {
        if let error = response.error {
            return .failure(error)
        }
        let json = JSON(response.value)
        let status: Int = json.status.value() ?? 0
        switch status {
        case 200:
            return .success(json.content)
        case let code:
            return .failure(NSError.init(error: json.message.value() ?? "", code: code))
        }
    }
}

// Example For Wrong Email or password
login(email: "email", password: "password") { (response) in
   guard case .error(let error) = response else {
           return
   }
   print(error.localizedDescription) // --> Wrong Email or password
   print(error.statusCode) // --> 1002
}

JSON

JSON is an enum used like javaScrip object insteed of Dictionary ex

let dictionary: [String: Any] = ["name": "Demo User",
                                 "age": 41,
                                 "type": 1,
                                 "verified": 0,
                                 "activated": true,
                                 "phones": ["134234", "532412"],
                                 "adddress": ["title": "Cairo", "latitude": "12.23123", "logintude": "41.12323"],
                                 "family": [["name": "Demo Son", "age": 19, "activated": false]]]

let json = JSON(dictionary)

json.name.value() // --> Demo User
json.phones.0.value() // --> 134234
json.adddress.title.value() // --> Cairo
json.family.0.name.value() // -->  Demo Son

Request Selections

Selections used for if you want to select a certian response as the following suppose you have json response below after user has logged in successfully

{
    "staus": 200
    "messase" : "Success"
    "content": {
        "id": 12,
        "name": "Demo User",
        "email": "demo@user.com",
        "token": "Token"
        "phones": ["01000000000", "02000000000"]
    }
}

There is no need to create a model like

class Model: Codable {
    var status: Int?
    var messase: Int?
    var content: User?
}

just set the Request Selections ( key or index ) e.x

func login(email: String, password: String) {
    request.selection = [.key("content")]
    ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<User>) in
        guard case .success(let user) = response else {
            return
        }
        print(user.name)
    }
}

Or

func login(email: String, password: String) {
    request.selection = [.key("content"), .key("token")]
    ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<String>) in
        guard case .success(let token) = response else {
            return
        }
        print(token) // --> Token
    }
}

Or

func login(email: String, password: String) {
    request.selection = [.key("content"), .key("phones"), .index(0)]
    ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<String>) in
        guard case .success(let phone) = response else {
            return
        }
        print(phone) // --> 01000000000
    }
}

Request Wrappers

A convenient wrappers implemented to use other frameworks as a return type for better usage & concurrency

PromiseKit

func login(email: String, password: String) -> Promise<User> {
    return ESNetworkManager.execute(request: request)
}

RxSwift

func login(email: String, password: String) -> Single<User> {
    return ESNetworkManager.execute(request: request)
}

Swift Combine

func login(email: String, password: String) -> AnyPublisher<User, Error> {
    return ESNetworkManager.execute(request: request)
}

Swift Async/await

func login(email: String, password: String) async throws -> User {
    return ESNetworkManager.execute(request: request)
}

Resposne Mapping

  • Default Mapping implemented for Codable, ObjectMapper and RawRepresentable

  • In such case api response

{
   "name":"Demo User",
   "age":41,
   "type":1,
   "verified":0,
   "activated":true,
   "phones":[
      "134234",
      "532412"
   ],
   "adddress":{
      "title":"Cairo",
      "latitude":"12.23123",
      "logintude":"41.12323"
   },
   "family":[
      {
         "name":"Demo Son",
         "age":19,
         "activated":false
      }
   ]
}

Codable

Codable

func login(email: String, password: String) {
    ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<User>) in
        guard case .success(let user) = response else {
            return
        }
        print(user.name) // --> Demo User
    }
}

struct User: Codable {
    let name: String
    let age: Int
    let activated: Bool 
}

String

func login(email: String, password: String) {
    request.selection = [.key("name")]
    ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<String>) in
        guard case .success(let name) = response else {
            return
        }
        print(name) // --> Demo User
    }
}

Array

func login(email: String, password: String) {
    request.selection = [.key("phones")]
    ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<[String]>) in
        guard case .success(let phones) = response else {
            return
        }
        print(phones) // --> ["134234", "532412"]
    }
}

ObjectMapper

func login(email: String, password: String) {
    ESNetworkManager.execute(request: request) { (response: ESNetworkResponse<Us

Related Skills

View on GitHub
GitHub Stars9
CategoryDevelopment
Updated2y ago
Forks2

Languages

Swift

Security Score

70/100

Audited on Oct 18, 2023

No findings