-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Carlos Pérez
committed
Apr 5, 2021
1 parent
f9cb23f
commit 2d77e29
Showing
18 changed files
with
701 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# Xcode | ||
# | ||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore | ||
|
||
## Build generated | ||
build/ | ||
DerivedData/ | ||
|
||
## Various settings | ||
*.pbxuser | ||
!default.pbxuser | ||
*.mode1v3 | ||
!default.mode1v3 | ||
*.mode2v3 | ||
!default.mode2v3 | ||
*.perspectivev3 | ||
!default.perspectivev3 | ||
xcuserdata/ | ||
|
||
## Other | ||
*.moved-aside | ||
*.xcuserstate | ||
|
||
## Obj-C/Swift specific | ||
*.hmap | ||
*.ipa | ||
*.dSYM.zip | ||
*.dSYM | ||
|
||
## Playgrounds | ||
timeline.xctimeline | ||
playground.xcworkspace | ||
|
||
# Swift Package Manager | ||
# | ||
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. | ||
# Packages/ | ||
.build/ | ||
|
||
# CocoaPods | ||
# | ||
# We recommend against adding the Pods directory to your .gitignore. However | ||
# you should judge for yourself, the pros and cons are mentioned at: | ||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control | ||
# | ||
Pods/ | ||
Podfile.lock | ||
|
||
# Carthage | ||
# | ||
# Add this line if you want to avoid checking in source code from Carthage dependencies. | ||
# Carthage/Checkouts | ||
|
||
Carthage/Build | ||
|
||
# fastlane | ||
# | ||
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the | ||
# screenshots whenever they are needed. | ||
# For more information about the recommended setup visit: | ||
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md | ||
|
||
fastlane/report.xml | ||
fastlane/Preview.html | ||
fastlane/screenshots | ||
fastlane/test_output |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import Foundation | ||
|
||
struct AlbumResponse: Codable { | ||
let resultCount: Int? | ||
let results: [Album]? | ||
} | ||
|
||
struct Album: Codable { | ||
let wrapperType: String? | ||
let collectionId: Int32? | ||
let collectionName: String? | ||
let artworkUrl60: String? | ||
let releaseDate: String? | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import Foundation | ||
|
||
struct ArtistResponse: Codable { | ||
let resultCount: Int? | ||
let results: [Artist]? | ||
} | ||
|
||
struct Artist: Codable { | ||
let artistId: Int32? | ||
let amgArtistId: Int32? | ||
let artistName: String? | ||
let primaryGenreName: String? | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import Foundation | ||
|
||
struct SongResponse: Codable { | ||
let resultCount: Int? | ||
let results: [Song]? | ||
} | ||
|
||
struct Song: Codable { | ||
let wrapperType: String? | ||
let trackId: Int32? | ||
let trackName: String? | ||
let previewUrl: String? | ||
let artworkUrl100: String? | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
//BY USING DATASOURCE EXTENSIONS, WE GET TO ISOLATE WHAT INTERACTORS CAN ACCESS AND ALSO | ||
//TO GET ESCALABILITY BY NOT CREATING MASSIVE DATA SOURCES WITH THE WHOLE CALLS IN A SINGLE FILE | ||
|
||
import Foundation | ||
|
||
protocol ArtistDataSource { | ||
func getArtists(searchTerm: String, | ||
page: String?, | ||
limit: String?, | ||
needsLoader: ((Bool) -> Void)?, | ||
completion: @escaping (([ArtistResponse]?) -> Void), | ||
failure: ((String?) -> Void)?) | ||
|
||
func getAlbums(amgArtistId: Int32, | ||
needsLoader: ((Bool) -> Void)?, | ||
completion: @escaping (([AlbumResponse]?) -> Void), | ||
failure: ((String?) -> Void)?) | ||
|
||
func getSongs(collectionId: Int32, | ||
needsLoader: ((Bool) -> Void)?, | ||
completion: @escaping (([SongResponse]?) -> Void), | ||
failure: ((String?) -> Void)?) | ||
} | ||
|
||
extension DataSource: ArtistDataSource { | ||
|
||
func getArtists(searchTerm: String, | ||
page: String? = nil, | ||
limit: String? = nil, | ||
needsLoader: ((Bool) -> Void)?, | ||
completion: @escaping (([ArtistResponse]?) -> Void), | ||
failure: ((String?) -> Void)?) { | ||
|
||
let serviceUrl = webServiceURLProvider.artistSearchURL | ||
.replacingOccurrences(of: "{{searchTerm}}", with: searchTerm) | ||
|
||
let request = Request(serviceUrl: serviceUrl, | ||
contentType: .queryString, | ||
method: .get) | ||
|
||
performRequest(requestParams: request, | ||
needsLoader: needsLoader, | ||
completion: completion, | ||
failure: failure) | ||
} | ||
|
||
func getAlbums(amgArtistId: Int32, | ||
needsLoader: ((Bool) -> Void)?, | ||
completion: @escaping (([AlbumResponse]?) -> Void), | ||
failure: ((String?) -> Void)?) { | ||
|
||
let serviceUrl = webServiceURLProvider.albumsURL | ||
.replacingOccurrences(of: "{{amgArtistId}}", with: "\(amgArtistId)") | ||
|
||
let request = Request(serviceUrl: serviceUrl, | ||
contentType: .queryString, | ||
method: .get) | ||
|
||
performRequest(requestParams: request, | ||
needsLoader: needsLoader, | ||
completion: completion, | ||
failure: failure) | ||
} | ||
|
||
func getSongs(collectionId: Int32, | ||
needsLoader: ((Bool) -> Void)?, | ||
completion: @escaping (([SongResponse]?) -> Void), | ||
failure: ((String?) -> Void)?) { | ||
|
||
let serviceUrl = webServiceURLProvider.songsURL | ||
.replacingOccurrences(of: "{{collectionId}}", with: "\(collectionId)") | ||
|
||
let request = Request(serviceUrl: serviceUrl, | ||
contentType: .queryString, | ||
method: .get) | ||
|
||
performRequest(requestParams: request, | ||
needsLoader: needsLoader, | ||
completion: completion, | ||
failure: failure) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import Foundation | ||
|
||
protocol DataSourceProtocol { | ||
} | ||
|
||
class DataSource: DataSourceProtocol { | ||
|
||
internal let repository: Repository | ||
internal let webServiceURLProvider: WebServiceURLProvider | ||
typealias T = Codable | ||
|
||
init(repository: Repository, webServiceURLProvider: WebServiceURLProvider) { | ||
self.repository = repository | ||
self.webServiceURLProvider = webServiceURLProvider | ||
} | ||
|
||
// MARK: Internal Methods | ||
|
||
internal func performRequest<T>(requestParams: Request, | ||
needsLoader: ((Bool) -> Void)?, | ||
completion: @escaping (([T]?) -> Void), | ||
failure: ((String?) -> Void)?) where T: Codable { | ||
|
||
repository.request(requestParams: requestParams, | ||
completion: completion, | ||
failure: failure) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import Foundation | ||
|
||
struct Request{ | ||
public var serviceUrl: String? | ||
public var params: [String: Any]? | ||
public var contentType: RequestType | ||
public var method: RequestMethod | ||
|
||
public init(serviceUrl: String? = nil, | ||
params: [String: Any]? = nil, | ||
contentType: RequestType, | ||
method: RequestMethod) { | ||
|
||
self.serviceUrl = serviceUrl | ||
self.params = params | ||
self.contentType = contentType | ||
self.method = method | ||
} | ||
|
||
public func getId() -> String { | ||
var output = serviceUrl | ||
|
||
if let params = params, params.count > 0 { | ||
for (key, value) in params { | ||
output?.append(contentsOf: "_\(key)_\(value)") | ||
} | ||
} | ||
|
||
return output ?? "" | ||
} | ||
|
||
public func description() -> String { | ||
return "\(serviceUrl != nil ? "ServiceURL: \(serviceUrl!)\n" : "")" + | ||
"\(params != nil ? "Params: \(params!)\n" : "")" | ||
} | ||
} | ||
|
||
public enum RequestType: String { | ||
case urlEncoded | ||
case json | ||
case queryString | ||
} | ||
|
||
public enum RequestMethod: String { | ||
case get | ||
case post | ||
case delete | ||
case put | ||
case patch | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
//REPOSITORY IS A FEATURE WE USE FOR BOTH READ OR WRITE FROM OR TO WHEREVER, GIVEN | ||
//THAT MOST OF THE TIME, WE WILL BE READING DATA FROM REMOTE SERVERS, DATABASES, ETC | ||
//AND SAVING THEM TO LOCAL STORAGES OR SIMPLY USING DATA TO BE SHOWN IN APP. | ||
|
||
//IN THIS CASE, IT IS PROVIDED A RESTREPOSITORY THAT WILL BE USING THE WEBSERVICE | ||
//LAYER, IN CHARGE OF THE NETWORK CONNECTIONS | ||
|
||
import Foundation | ||
|
||
protocol Repository { | ||
func request<T>(requestParams: Request, | ||
completion: @escaping (_ result: [T]) -> Void, | ||
failure: ((_ error: String?) -> Void)?) where T: Codable | ||
} | ||
|
||
class RestRepository: Repository { | ||
private let webService: WebServiceProtocol | ||
|
||
init(webService: WebService) { | ||
self.webService = webService | ||
} | ||
|
||
func request<T>(requestParams: Request, | ||
completion: @escaping (_ result: [T]) -> Void, | ||
failure: ((_ error: String?) -> Void)?) where T: Codable { | ||
|
||
webService.get(request: requestParams, completion: {(result) in | ||
|
||
print("GET FROM REMOTE 👍: \n\(requestParams.description())") | ||
|
||
if let parsed: T = try? JSONDecoder().decode(T.self, from: result) { | ||
completion([parsed]) | ||
return | ||
|
||
} else if let parsed: [T] = try? JSONDecoder().decode([T].self, from: result) { | ||
completion(parsed) | ||
return | ||
} | ||
|
||
completion([]) | ||
|
||
}, failure: {(error) in | ||
failure?(error.localizedDescription) | ||
}) | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import Alamofire | ||
|
||
protocol WebServiceProtocol: class { | ||
func get(request: Request, | ||
completion : @escaping (_ result : Data) -> Void, | ||
failure : @escaping (_ result : AnyObject) -> Void) | ||
} | ||
|
||
class WebService: WebServiceProtocol { | ||
|
||
func get(request: Request, | ||
completion: @escaping (Data) -> Void, | ||
failure: @escaping (AnyObject) -> Void) { | ||
|
||
guard let serviceUrl = request.serviceUrl, | ||
let trimmed = serviceUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), | ||
let finalUrl = URL(string: trimmed) else { | ||
|
||
failure("NO_REQUEST" as AnyObject) | ||
return | ||
} | ||
|
||
Alamofire.request(finalUrl, | ||
method: request.alamofireMethod, | ||
parameters: request.params, | ||
encoding: request.alamofireEncondingType, | ||
headers: nil) | ||
|
||
.responseData(completionHandler: { response in | ||
if response.result.isSuccess, | ||
let data = response.result.value { | ||
completion(data) | ||
|
||
} else { | ||
failure((response.result.error?.localizedDescription ?? "NO_DATA") as AnyObject) | ||
} | ||
} | ||
) | ||
} | ||
|
||
} |
Oops, something went wrong.