{"id":1666,"url":"https://github.com/emadhegab/MHNetwork","last_synced_at":"2025-08-02T04:32:14.722Z","repository":{"id":62446791,"uuid":"141154824","full_name":"emadhegab/MHNetwork","owner":"emadhegab","description":"Say goodbye to the Fat ugly singleton Network Manager with this Network Layer","archived":false,"fork":false,"pushed_at":"2019-11-25T16:23:02.000Z","size":353,"stargazers_count":19,"open_issues_count":2,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-08T02:16:59.814Z","etag":null,"topics":["network-layer","protocol-oriented","swift4","viper"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emadhegab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-07-16T15:05:04.000Z","updated_at":"2022-11-19T20:56:43.000Z","dependencies_parsed_at":"2022-11-01T23:07:56.150Z","dependency_job_id":null,"html_url":"https://github.com/emadhegab/MHNetwork","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emadhegab%2FMHNetwork","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emadhegab%2FMHNetwork/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emadhegab%2FMHNetwork/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emadhegab%2FMHNetwork/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emadhegab","download_url":"https://codeload.github.com/emadhegab/MHNetwork/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228439074,"owners_count":17920017,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["network-layer","protocol-oriented","swift4","viper"],"created_at":"2024-01-05T20:15:52.788Z","updated_at":"2024-12-06T08:31:24.578Z","avatar_url":"https://github.com/emadhegab.png","language":"Swift","funding_links":[],"categories":["Networking"],"sub_categories":["Video"],"readme":"# MHNetwork\nProtocol Oriented Network Layer Aim to avoid having bloated singleton NetworkManager\n\n[![Build Status](https://travis-ci.org/emadhegab/MHNetwork.svg?branch=master)](https://travis-ci.org/emadhegab/MHNetwork)\n[![Coverage Status](https://codecov.io/gh/emadhegab/MHNetwork/branch/master/graphs/badge.svg)](https://codecov.io/gh/emadhegab/MHNetwork/branch/master)\n\n\n ## Philosophy\nthe main philosophy behind MHNetwork is to have a single responsibility. it makes it much easier to determine where is the problem located in your code if every class in your code have only one task and one task only to do.\nso in the beginning..\n\n#### install\n\n```\n$ pod install MHNetwork\n```\nor in your podfile\n```\npod 'MHNetwork'\n```\n\nalso you can use `Swift Package Manager`\n\n#### usage\n\nlet's say you have movies API .. and you need to make a request call to get the movies list..\n\nyou will need to create two files for your feature\n`MoviesRequests.swift` and `MoviesTasks.swift`\n\nin the request it should be something like this\n\n```\n\nimport Foundation\nimport MHNetwork\n\nenum MoviesRequests: Request {\n    case getMoviesList\n\n    var path: String {\n        return \"movies/list/\"\n    }\n\n    var method: HTTPMethod {\n        switch self {\n        case .getRandomQuote:\n            return .get\n        }\n    }\n\n    var parameters: RequestParams {\n        return .url([\"year\" : \"2018\"])\n        // can use .body([\"year\": \"20018\"]) if the api require body parameters\n    }\n\n    var headers: [String : Any]? {\n        return [\"Authorization\": \"xyz\"]\n    }\n}\n```\n\nthen add your task\n\n```\n\nclass MovieTasks \u003cT: Codable\u003e: Operations {\n\n    var request: Request {\n        return MoviesRequests.getMoviesList\n    }\n\n    func execute(in dispatcher: Dispatcher, completed: @escaping (Result\u003cT, NetworkError\u003e) -\u003e Void) {\n\n        do {\n            try dispatcher.execute(request: self.request, completion: { (result) in\n               switch result {\n                               case .success(let response):\n                                   switch response {\n                                       case .data(let data):\n                                           do {\n\n                        let decoder = JSONDecoder()\n                        //                        decoder.keyDecodingStrategy = .convertFromSnakeCase\n                        //                        uncomment this in case you have some json properties in Snake Case and you just want to decode it to camel Case... workes only for swift 4.1 or higher\n                        let object = try decoder.decode(T.self, from: data)\n                                               completed(.success(object))\n                                           } catch let error {\n                                               print(\"error Parsing with Error: \\(error.localizedDescription)\")\n                                           }\n                                           break\n                                       case .error(let error):\n                                           completed(.failure(error))\n                                           break\n                                       }\n                               case .failure(let error):\n                                   completed(.failure(error))\n                               }\n            })\n        } catch {\n          completed(.failure(.error(code: nil, error: error, data: nil)))\n        }\n    }\n}\n\n```\n\nthat's it you finished your basic setup for the request.. now you can call it from your code like that\n\n```\nfunc getMoviesList(onComplete: @escaping (Movie) -\u003e Void, onError: @escaping (Error) -\u003e Void) {\n    let environment = Environment(host: \"https://imdb.com/api\")\n    let networkDispatcher = NetworkDispatcher(environment: environment, session: URLSession(configuration: .default))\n    let moviesTask = MoviesTasks\u003cMovie\u003e() // Movie Model should be codable\n    moviesTask.execute(in: networkDispatcher) { (result) in\n          switch result {\n            case .success(let users):\n                onCompletion(movies)\n            case .failure(let error):\n                onError(error)\n            }\n         })\n}\n```\n\nthat's it..\none last note.. when creating the instance of MoviesTask you noticed the comment that `Movie Model should be Codable` well.. it's not a must but my preferable way.. just suit yourself in the task itself and make it less restricted if you like but you'll need to handle the returned data in another way.\n\n\n### TODO://\n- [ ] need to support JSON return type without depending on any 3rd party\n- [x] need to fix \u0026 clean the example test cases and code\n\n\n### Contribute://\n fork / edit / and Pull request to Develop Branch... you know what to do ;)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femadhegab%2FMHNetwork","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femadhegab%2FMHNetwork","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femadhegab%2FMHNetwork/lists"}