ESNetworkManager
ESNetworkManager is a network layer based on Alamofire 5 with response Mapping
Install / Use
/learn @MahmoudEissa/ESNetworkManagerREADME
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
node-connect
345.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
104.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
345.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
345.4kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
