This Project will display the implementation of GitHub Public API's using SOLID principles and Design patterns (MVVM+R) with Reactive Combine framework
- Design Pattern MVVM + Repository (Using SOLID Principles)
- Combine Framework
- iOS Environments
- Unit Test Cases
- Api Implementation
- IQKeyboard
- Custom Fonts
- CI/CD Using FastLane (In Progress)
GET https://api.github.com/users/{username}
Parameter | Type | Description |
---|---|---|
username |
string |
Required. Username Github Profile |
UIViewController only responsible for updating Views
ViewModel contain all the business logic
Model contain Codable Struct
Repository is responsible for data from (Database or WebSerice)
The Combine framework provides a declarative Swift API for processing values over time. These values can represent many kinds of asynchronous events. Combine declares publishers to expose values that can change over time, and subscribers to receive those values from the publishers
We were using completion handler to receive result after getting asynchronous response but combine is really flexiable and also provide to modify data using operator and thraed managment to update views.
Every new Xcode project comes with two default configurations, Debug and Release.
When things get more complicated, these two configurations are no longer enough. If your app needs to communicate with an external service, you can't afford to develop and test your app in the same environment that your users use, where one mistake can harm your users. That's why we need multiple environments for our development (Assume your external service also has a separate environment for testing).
These configurations capture a build configuration that matches their intention. For example, Debug configuration set Optimization Level to None because we want to debug our code without the compiler interfering. In comparison, the Release configuration set this value to Fastest, Smallest to let the compiler optimize our code for performance and space.
I Have created three environments
- Development
- Staging
- Production
Creating multiple scheme with with difference configuration can reduce our workload and by changing scheme will be updated.
Difference Scheme have:
- Multiple Identifers
- Multiple Provision profiles
- Multiple App Icons
- Multiple App Names
- Multiple environment will have e.g (baseUrl,Auth Keys etc)
For detail documentation Please click here
For functional automation testing. We have Model-View-ViewModel (MVVM) architecture, we separate the business logic and presentational logic from the view logic. The separation of concerns (SoC) makes writing unit tests easier than ever. Even though the idea of the MVVM is simple, writing unit tests for its various use cases is still worth mentioning
In short, I will cover two techniques:
- How to design a mock to simulate different network states.
- How to use stubs to test user interaction.
For detail documentation Please click here
For all the network calls we have created the base call
class APIClientHandler {
static var shared = APIClientHandler()
private let session: URLSession
private var cancellable = Set<AnyCancellable>()
init(session: URLSession = URLSession(configuration: URLSessionConfiguration.default)) {
self.session = session
}
To send request using datapublisher
func sendRequest(urlString: String, parameters: [String: Any?],method: HTTPMethods) -> AnyPublisher<Data, Error> {
guard let request = self.makeRequest(urlString: urlString, parameters: parameters, method: method) else {
return .fail(NetworkError.invalidRequest)
}
return session.dataTaskPublisher(for: request)
.mapError { _ in NetworkError.invalidRequest }
.flatMap { data, response -> AnyPublisher<Data, Error> in
guard let httpResponse = response as? HTTPURLResponse else {
if let httpResponse = response as? HTTPURLResponse {
self.showRequestDetailForFailure(responseObject: httpResponse, data: data)
}
return .fail(NetworkError.invalidURL)
}
guard 200..<300 ~= httpResponse. statusCode else {
self.showRequestDetailForFailure(responseObject: httpResponse, data: data)
return .fail(NetworkError.invalidResponse)
}
self.showRequestDetailForSuccess(responseObject: httpResponse, data: data)
return .just(data)
}
.eraseToAnyPublisher()
}
Implemented IQkeyboard Pod to handle keyboard
For detail documentation Please click here
Implemented Custom fonts
For detail documentation Please click here
CI/CD Implementation (In Progress)
For detail documentation Please click here
Distributed under the MIT License.
Any contribution is more than welcome! You can contribute through pull requests and issues on GitHub.
If you have any feedback, please reach out to us at [email protected]