From 4f3277f1dec2ed08dc211b0eef133fec6b32134d Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Fri, 4 Oct 2019 19:49:09 -0500 Subject: [PATCH 01/23] Implement basic client --- fakestagram.xcodeproj/project.pbxproj | 24 +++++++ .../xcdebugger/Breakpoints_v2.xcbkptlist | 6 ++ fakestagram/Credentials.swift | 24 +++++++ fakestagram/DataSource/Client.swift | 70 +++++++++++++++++++ fakestagram/DataSource/HttpResponse.swift | 25 +++++++ fakestagram/DataSource/StatusCode.swift | 36 ++++++++++ 6 files changed, 185 insertions(+) create mode 100644 fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 fakestagram/Credentials.swift create mode 100644 fakestagram/DataSource/Client.swift create mode 100644 fakestagram/DataSource/HttpResponse.swift create mode 100644 fakestagram/DataSource/StatusCode.swift diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index e876e02..39bdf3d 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -15,6 +15,10 @@ E084FAE6233A8735009AC50D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E084FAE4233A8735009AC50D /* LaunchScreen.storyboard */; }; E084FAF1233A8735009AC50D /* fakestagramTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAF0233A8735009AC50D /* fakestagramTests.swift */; }; E084FAFC233A8888009AC50D /* PostsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAFB233A8888009AC50D /* PostsTableViewController.swift */; }; + E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9642348018200DA9D1A /* Credentials.swift */; }; + E0E8B9682348036D00DA9D1A /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9672348036D00DA9D1A /* Client.swift */; }; + E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96923481D5A00DA9D1A /* StatusCode.swift */; }; + E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96B23481E1700DA9D1A /* HttpResponse.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -40,6 +44,10 @@ E084FAF0233A8735009AC50D /* fakestagramTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = fakestagramTests.swift; sourceTree = ""; }; E084FAF2233A8735009AC50D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E084FAFB233A8888009AC50D /* PostsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostsTableViewController.swift; sourceTree = ""; }; + E0E8B9642348018200DA9D1A /* Credentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Credentials.swift; sourceTree = ""; }; + E0E8B9672348036D00DA9D1A /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; + E0E8B96923481D5A00DA9D1A /* StatusCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCode.swift; sourceTree = ""; }; + E0E8B96B23481E1700DA9D1A /* HttpResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HttpResponse.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -81,6 +89,7 @@ E084FAD8233A8734009AC50D /* fakestagram */ = { isa = PBXGroup; children = ( + E0E8B9662348035800DA9D1A /* DataSource */, E084FAD9233A8734009AC50D /* AppDelegate.swift */, E084FADB233A8734009AC50D /* SceneDelegate.swift */, E084FAFB233A8888009AC50D /* PostsTableViewController.swift */, @@ -89,6 +98,7 @@ E084FAE2233A8735009AC50D /* Assets.xcassets */, E084FAE4233A8735009AC50D /* LaunchScreen.storyboard */, E084FAE7233A8735009AC50D /* Info.plist */, + E0E8B9642348018200DA9D1A /* Credentials.swift */, ); path = fakestagram; sourceTree = ""; @@ -102,6 +112,16 @@ path = fakestagramTests; sourceTree = ""; }; + E0E8B9662348035800DA9D1A /* DataSource */ = { + isa = PBXGroup; + children = ( + E0E8B9672348036D00DA9D1A /* Client.swift */, + E0E8B96923481D5A00DA9D1A /* StatusCode.swift */, + E0E8B96B23481E1700DA9D1A /* HttpResponse.swift */, + ); + path = DataSource; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -203,8 +223,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */, E038FCED233FC78600E28571 /* PostViewController.swift in Sources */, E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */, + E0E8B9682348036D00DA9D1A /* Client.swift in Sources */, + E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */, + E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */, E084FAFC233A8888009AC50D /* PostsTableViewController.swift in Sources */, E084FADC233A8734009AC50D /* SceneDelegate.swift in Sources */, ); diff --git a/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 0000000..d88cf55 --- /dev/null +++ b/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,6 @@ + + + diff --git a/fakestagram/Credentials.swift b/fakestagram/Credentials.swift new file mode 100644 index 0000000..c8e8926 --- /dev/null +++ b/fakestagram/Credentials.swift @@ -0,0 +1,24 @@ +// +// Credentials.swift +// fakestagram +// +// Created by LuisE on 10/4/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +enum Credentials { + case apiToken + + func get() -> String? { + switch self { + case .apiToken: + return "f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e" + } + } + + func set(value: String) -> Bool { + return true + } +} diff --git a/fakestagram/DataSource/Client.swift b/fakestagram/DataSource/Client.swift new file mode 100644 index 0000000..08a7be7 --- /dev/null +++ b/fakestagram/DataSource/Client.swift @@ -0,0 +1,70 @@ +// +// Client.swift +// fakestagram +// +// Created by LuisE on 10/4/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +class Client { + let session: URLSession + let baseUrl: URL + let contentType: String + + init(session: URLSession, baseUrl: URL, contentType: String) { + self.session = session + self.baseUrl = baseUrl + self.contentType = contentType + } + + typealias successfulResponse = (Data?) -> Void + + func get(path: String, success: @escaping successfulResponse) { + request(method: "get", path: path, body: nil, success: success) + } + + func post(path: String, body: Data?, success: @escaping successfulResponse) { + request(method: "post", path: path, body: body, success: success) + } + + func put(path: String, body: Data?, success: @escaping successfulResponse) { + request(method: "put", path: path, body: body, success: success) + } + + func delete(path: String, success: @escaping successfulResponse) { + request(method: "delete", path: path, body: nil, success: success) + } + + private func request(method: String, path: String, body: Data?, success: @escaping successfulResponse) { + let req = buildRequest(method: method, path: path, body: body) + + session.dataTask(with: req) { (data, response, error) in + if let error = error { + debugPrint(error) + return + } + + let response = HttpResponse(response: response) + if response.isSuccessful() { + success(data) + } + }.resume() + } + + private func buildRequest(method: String, path: String, body: Data?) -> URLRequest { + var urlComponents = URLComponents(url: self.baseUrl, resolvingAgainstBaseURL: true)! + urlComponents.path = path + var request = URLRequest(url: urlComponents.url!) + request.setValue(contentType, forHTTPHeaderField: "Accept") + request.setValue(contentType, forHTTPHeaderField: "Content-Type") + request.httpMethod = method + if let token = Credentials.apiToken.get() { + request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization") + } + request.httpBody = body + + return request + } +} diff --git a/fakestagram/DataSource/HttpResponse.swift b/fakestagram/DataSource/HttpResponse.swift new file mode 100644 index 0000000..6ea1dfa --- /dev/null +++ b/fakestagram/DataSource/HttpResponse.swift @@ -0,0 +1,25 @@ +// +// HttpResponse.swift +// fakestagram +// +// Created by LuisE on 10/4/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +class HttpResponse { + let httpUrlResponse: HTTPURLResponse + + init(response: URLResponse?) { + self.httpUrlResponse = response as! HTTPURLResponse + } + + lazy var status: StatusCode = { + return StatusCode(rawValue: self.httpUrlResponse.statusCode) + }() + + func isSuccessful() -> Bool { + return status == StatusCode.success + } +} diff --git a/fakestagram/DataSource/StatusCode.swift b/fakestagram/DataSource/StatusCode.swift new file mode 100644 index 0000000..2432e92 --- /dev/null +++ b/fakestagram/DataSource/StatusCode.swift @@ -0,0 +1,36 @@ +// +// StatusCode.swift +// fakestagram +// +// Created by LuisE on 10/4/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +enum StatusCode: Int { + case unkown = 0 + case info + case success + case redirection + case clientError + case serverError + + public init(rawValue: Int) { + switch rawValue { + case 100, 101, 102: + self = .info + case 200, 201, 202, 203, 204, 205, 206, 207, 208, 226: + self = .success + case 300, 301, 302, 303, 304, 305, 306, 307, 308: + self = .redirection + case 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 421, 422, 423, 424, 426, 428, 429, 431, 451: + self = .clientError + case 500, 501, 502, 503, 504, 505, 506, 507, 510, 511: + self = .serverError + default: + self = .unkown + } + } +} From b235a3f66563b7befa0a22a1ba15860b9b962593 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Sat, 5 Oct 2019 13:16:12 -0500 Subject: [PATCH 02/23] Implement RequestBuilder with TDD --- fakestagram.xcodeproj/project.pbxproj | 12 ++-- fakestagram/Credentials.swift | 4 +- fakestagram/DataSource/Client.swift | 50 ++++++++-------- fakestagram/DataSource/HttpResponse.swift | 6 +- fakestagram/DataSource/RequestBuilder.swift | 62 ++++++++++++++++++++ fakestagram/DataSource/StatusCode.swift | 2 +- fakestagramTests/RequestBuilderTests.swift | 65 +++++++++++++++++++++ fakestagramTests/fakestagramTests.swift | 34 ----------- 8 files changed, 165 insertions(+), 70 deletions(-) create mode 100644 fakestagram/DataSource/RequestBuilder.swift create mode 100644 fakestagramTests/RequestBuilderTests.swift delete mode 100644 fakestagramTests/fakestagramTests.swift diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index 39bdf3d..bc77121 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -13,12 +13,13 @@ E084FAE1233A8734009AC50D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E084FADF233A8734009AC50D /* Main.storyboard */; }; E084FAE3233A8735009AC50D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E084FAE2233A8735009AC50D /* Assets.xcassets */; }; E084FAE6233A8735009AC50D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E084FAE4233A8735009AC50D /* LaunchScreen.storyboard */; }; - E084FAF1233A8735009AC50D /* fakestagramTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAF0233A8735009AC50D /* fakestagramTests.swift */; }; + E084FAF1233A8735009AC50D /* RequestBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAF0233A8735009AC50D /* RequestBuilderTests.swift */; }; E084FAFC233A8888009AC50D /* PostsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAFB233A8888009AC50D /* PostsTableViewController.swift */; }; E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9642348018200DA9D1A /* Credentials.swift */; }; E0E8B9682348036D00DA9D1A /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9672348036D00DA9D1A /* Client.swift */; }; E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96923481D5A00DA9D1A /* StatusCode.swift */; }; E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96B23481E1700DA9D1A /* HttpResponse.swift */; }; + E0E8B96E2348203B00DA9D1A /* RequestBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96D2348203B00DA9D1A /* RequestBuilder.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -41,13 +42,14 @@ E084FAE5233A8735009AC50D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; E084FAE7233A8735009AC50D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E084FAEC233A8735009AC50D /* fakestagramTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = fakestagramTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - E084FAF0233A8735009AC50D /* fakestagramTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = fakestagramTests.swift; sourceTree = ""; }; + E084FAF0233A8735009AC50D /* RequestBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestBuilderTests.swift; sourceTree = ""; }; E084FAF2233A8735009AC50D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E084FAFB233A8888009AC50D /* PostsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostsTableViewController.swift; sourceTree = ""; }; E0E8B9642348018200DA9D1A /* Credentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Credentials.swift; sourceTree = ""; }; E0E8B9672348036D00DA9D1A /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; E0E8B96923481D5A00DA9D1A /* StatusCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCode.swift; sourceTree = ""; }; E0E8B96B23481E1700DA9D1A /* HttpResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HttpResponse.swift; sourceTree = ""; }; + E0E8B96D2348203B00DA9D1A /* RequestBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestBuilder.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -106,7 +108,7 @@ E084FAEF233A8735009AC50D /* fakestagramTests */ = { isa = PBXGroup; children = ( - E084FAF0233A8735009AC50D /* fakestagramTests.swift */, + E084FAF0233A8735009AC50D /* RequestBuilderTests.swift */, E084FAF2233A8735009AC50D /* Info.plist */, ); path = fakestagramTests; @@ -118,6 +120,7 @@ E0E8B9672348036D00DA9D1A /* Client.swift */, E0E8B96923481D5A00DA9D1A /* StatusCode.swift */, E0E8B96B23481E1700DA9D1A /* HttpResponse.swift */, + E0E8B96D2348203B00DA9D1A /* RequestBuilder.swift */, ); path = DataSource; sourceTree = ""; @@ -226,6 +229,7 @@ E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */, E038FCED233FC78600E28571 /* PostViewController.swift in Sources */, E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */, + E0E8B96E2348203B00DA9D1A /* RequestBuilder.swift in Sources */, E0E8B9682348036D00DA9D1A /* Client.swift in Sources */, E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */, E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */, @@ -238,7 +242,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - E084FAF1233A8735009AC50D /* fakestagramTests.swift in Sources */, + E084FAF1233A8735009AC50D /* RequestBuilderTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/fakestagram/Credentials.swift b/fakestagram/Credentials.swift index c8e8926..2e81160 100644 --- a/fakestagram/Credentials.swift +++ b/fakestagram/Credentials.swift @@ -10,14 +10,14 @@ import Foundation enum Credentials { case apiToken - + func get() -> String? { switch self { case .apiToken: return "f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e" } } - + func set(value: String) -> Bool { return true } diff --git a/fakestagram/DataSource/Client.swift b/fakestagram/DataSource/Client.swift index 08a7be7..2b9852a 100644 --- a/fakestagram/DataSource/Client.swift +++ b/fakestagram/DataSource/Client.swift @@ -9,62 +9,60 @@ import Foundation class Client { + static let fakestagram = Client(session: URLSession.shared, baseUrl: "https://fakestagram-api.herokuapp.com") let session: URLSession - let baseUrl: URL - let contentType: String - - init(session: URLSession, baseUrl: URL, contentType: String) { + let baseUrl: String + + init(session: URLSession, baseUrl: String) { self.session = session self.baseUrl = baseUrl - self.contentType = contentType } - + typealias successfulResponse = (Data?) -> Void - + func get(path: String, success: @escaping successfulResponse) { request(method: "get", path: path, body: nil, success: success) } - + func post(path: String, body: Data?, success: @escaping successfulResponse) { request(method: "post", path: path, body: body, success: success) } - + func put(path: String, body: Data?, success: @escaping successfulResponse) { request(method: "put", path: path, body: body, success: success) } - + func delete(path: String, success: @escaping successfulResponse) { request(method: "delete", path: path, body: nil, success: success) } - + private func request(method: String, path: String, body: Data?, success: @escaping successfulResponse) { - let req = buildRequest(method: method, path: path, body: body) - + guard let req = buildRequest(method: method, path: path, body: body) else { + debugPrint("Invalid request") + return + } + session.dataTask(with: req) { (data, response, error) in if let error = error { debugPrint(error) return } - + let response = HttpResponse(response: response) if response.isSuccessful() { success(data) } }.resume() } - - private func buildRequest(method: String, path: String, body: Data?) -> URLRequest { - var urlComponents = URLComponents(url: self.baseUrl, resolvingAgainstBaseURL: true)! - urlComponents.path = path - var request = URLRequest(url: urlComponents.url!) - request.setValue(contentType, forHTTPHeaderField: "Accept") - request.setValue(contentType, forHTTPHeaderField: "Content-Type") - request.httpMethod = method + + private func buildRequest(method: String, path: String, body: Data?) -> URLRequest? { + var builder = RequestBuilder(baseUrl: self.baseUrl) + builder.method = method + builder.path = path + builder.body = body if let token = Credentials.apiToken.get() { - request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization") + builder.headers = ["Authorization": "Bearer \(token)"] } - request.httpBody = body - - return request + return builder.request() } } diff --git a/fakestagram/DataSource/HttpResponse.swift b/fakestagram/DataSource/HttpResponse.swift index 6ea1dfa..cd7b4aa 100644 --- a/fakestagram/DataSource/HttpResponse.swift +++ b/fakestagram/DataSource/HttpResponse.swift @@ -10,15 +10,15 @@ import Foundation class HttpResponse { let httpUrlResponse: HTTPURLResponse - + init(response: URLResponse?) { self.httpUrlResponse = response as! HTTPURLResponse } - + lazy var status: StatusCode = { return StatusCode(rawValue: self.httpUrlResponse.statusCode) }() - + func isSuccessful() -> Bool { return status == StatusCode.success } diff --git a/fakestagram/DataSource/RequestBuilder.swift b/fakestagram/DataSource/RequestBuilder.swift new file mode 100644 index 0000000..0fb17dd --- /dev/null +++ b/fakestagram/DataSource/RequestBuilder.swift @@ -0,0 +1,62 @@ +// +// RequestBuilder.swift +// fakestagram +// +// Created by LuisE on 10/4/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +struct RequestBuilder { + enum ContentMode { + case jsonApp + + func accept() -> String { + switch self { + case .jsonApp: + return "application/json" + } + } + + func contentType() -> String { + switch self { + case .jsonApp: + return "application/json" + } + } + } + private let urlComponents: URLComponents + public var scheme: String = "https" + public var method: String = "get" + public var path: String = "/" + public var body: Data? + public var headers: [String: String]? + public var contentMode: ContentMode = .jsonApp + + init(baseUrl: String) { + self.urlComponents = URLComponents(string: baseUrl)! + } + + func url() -> URL? { + var comps = self.urlComponents + comps.scheme = scheme + comps.path = path + return comps.url + } + + func request() -> URLRequest? { + guard let url = url() else { return nil } + var req = URLRequest(url: url) + req.httpMethod = method + req.httpBody = body + req.addValue(contentMode.accept(), forHTTPHeaderField: "Accept") + req.addValue(contentMode.contentType(), forHTTPHeaderField: "Content-Type") + if let headers = self.headers { + for (key, value) in headers { + req.addValue(value, forHTTPHeaderField: key) + } + } + return req + } +} diff --git a/fakestagram/DataSource/StatusCode.swift b/fakestagram/DataSource/StatusCode.swift index 2432e92..cdc5e29 100644 --- a/fakestagram/DataSource/StatusCode.swift +++ b/fakestagram/DataSource/StatusCode.swift @@ -15,7 +15,7 @@ enum StatusCode: Int { case redirection case clientError case serverError - + public init(rawValue: Int) { switch rawValue { case 100, 101, 102: diff --git a/fakestagramTests/RequestBuilderTests.swift b/fakestagramTests/RequestBuilderTests.swift new file mode 100644 index 0000000..01606ed --- /dev/null +++ b/fakestagramTests/RequestBuilderTests.swift @@ -0,0 +1,65 @@ +// +// RequestBuilderTests.swift +// RequestBuilderTests +// +// Created by LuisE on 9/24/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import XCTest +@testable import fakestagram + +class RequestBuilderTests: XCTestCase { + func testBuildValidURL() { + var builder = RequestBuilder(baseUrl: "https://example.com/") + builder.path = "/api/v1/accounts" + XCTAssertEqual(builder.scheme, "https") + XCTAssertEqual(builder.method, "get") + XCTAssertEqual(builder.url(), URL(string: "https://example.com/api/v1/accounts")!) + } + + func testBuildInvalidURL() { + var builder = RequestBuilder(baseUrl: "example.com") + builder.path = "//@3`-" + XCTAssertNil(builder.url()) + } + + func testBuildForceSchemeURL() { + let builder = RequestBuilder(baseUrl: "http://example.com/") + XCTAssertEqual(builder.url(), URL(string: "https://example.com/")!) + } + + func testBuildOverrideSchemeURL() { + var builder = RequestBuilder(baseUrl: "http://example.com/") + builder.scheme = "ftp" + XCTAssertEqual(builder.url(), URL(string: "ftp://example.com/")!) + } + + func testBuildInvalidRequest() { + var builder = RequestBuilder(baseUrl: "example.com") + builder.path = "//@3`-" + XCTAssertNil(builder.request()) + } + + func testBuildValidRequest() { + var builder = RequestBuilder(baseUrl: "https://example.com/") + builder.path = "/api/v1/accounts" + builder.method = "post" + builder.body = "{\"a\": 1}".data(using: .utf8) + builder.headers = ["test": "example"] + + let result = builder.request() + XCTAssertNotNil(result) + XCTAssertEqual(result!.httpMethod!, "POST") + XCTAssertEqual(result!.httpBody!, "{\"a\": 1}".data(using: .utf8)) + XCTAssertEqual(result!.allHTTPHeaderFields!, ["Accept": "application/json", "Content-Type": "application/json", "test": "example"]) + } + + func testBuildValidRequestWithDefaults() { + let result = RequestBuilder(baseUrl: "https://example.com/").request() + XCTAssertNotNil(result) + XCTAssertEqual(result!.httpMethod!, "GET") + XCTAssertNil(result!.httpBody) + XCTAssertEqual(result!.allHTTPHeaderFields!, ["Accept": "application/json", "Content-Type": "application/json"]) + } +} diff --git a/fakestagramTests/fakestagramTests.swift b/fakestagramTests/fakestagramTests.swift deleted file mode 100644 index f022cfd..0000000 --- a/fakestagramTests/fakestagramTests.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// fakestagramTests.swift -// fakestagramTests -// -// Created by LuisE on 9/24/19. -// Copyright © 2019 3zcurdia. All rights reserved. -// - -import XCTest -@testable import fakestagram - -class fakestagramTests: XCTestCase { - - override func setUp() { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - } - - func testPerformanceExample() { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } - -} From 55f061fe484554e7d5c55f8f6b119d9225c1c3b6 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Fri, 11 Oct 2019 17:54:46 -0500 Subject: [PATCH 03/23] RestClient basic implementations --- fakestagram.xcodeproj/project.pbxproj | 30 +++++- fakestagram/DataSource/RestClient.swift | 99 +++++++++++++++++++ fakestagram/Models/Account.swift | 16 +++ fakestagram/Models/Post.swift | 38 +++++++ .../{DataSource => Network}/Client.swift | 0 .../HttpResponse.swift | 0 .../RequestBuilder.swift | 0 .../{DataSource => Network}/StatusCode.swift | 0 fakestagram/PostsTableViewController.swift | 28 ------ 9 files changed, 182 insertions(+), 29 deletions(-) create mode 100644 fakestagram/DataSource/RestClient.swift create mode 100644 fakestagram/Models/Account.swift create mode 100644 fakestagram/Models/Post.swift rename fakestagram/{DataSource => Network}/Client.swift (100%) rename fakestagram/{DataSource => Network}/HttpResponse.swift (100%) rename fakestagram/{DataSource => Network}/RequestBuilder.swift (100%) rename fakestagram/{DataSource => Network}/StatusCode.swift (100%) diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index bc77121..fb14047 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -20,6 +20,9 @@ E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96923481D5A00DA9D1A /* StatusCode.swift */; }; E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96B23481E1700DA9D1A /* HttpResponse.swift */; }; E0E8B96E2348203B00DA9D1A /* RequestBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96D2348203B00DA9D1A /* RequestBuilder.swift */; }; + E0E8B971234916D100DA9D1A /* RestClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B970234916D100DA9D1A /* RestClient.swift */; }; + E0E8B974234918FF00DA9D1A /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B973234918FF00DA9D1A /* Account.swift */; }; + E0E8B9762349197100DA9D1A /* Post.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9752349197100DA9D1A /* Post.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -50,6 +53,9 @@ E0E8B96923481D5A00DA9D1A /* StatusCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCode.swift; sourceTree = ""; }; E0E8B96B23481E1700DA9D1A /* HttpResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HttpResponse.swift; sourceTree = ""; }; E0E8B96D2348203B00DA9D1A /* RequestBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestBuilder.swift; sourceTree = ""; }; + E0E8B970234916D100DA9D1A /* RestClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestClient.swift; sourceTree = ""; }; + E0E8B973234918FF00DA9D1A /* Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = ""; }; + E0E8B9752349197100DA9D1A /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -91,6 +97,8 @@ E084FAD8233A8734009AC50D /* fakestagram */ = { isa = PBXGroup; children = ( + E0E8B972234918ED00DA9D1A /* Models */, + E0E8B96F234916AA00DA9D1A /* Network */, E0E8B9662348035800DA9D1A /* DataSource */, E084FAD9233A8734009AC50D /* AppDelegate.swift */, E084FADB233A8734009AC50D /* SceneDelegate.swift */, @@ -115,6 +123,14 @@ sourceTree = ""; }; E0E8B9662348035800DA9D1A /* DataSource */ = { + isa = PBXGroup; + children = ( + E0E8B970234916D100DA9D1A /* RestClient.swift */, + ); + path = DataSource; + sourceTree = ""; + }; + E0E8B96F234916AA00DA9D1A /* Network */ = { isa = PBXGroup; children = ( E0E8B9672348036D00DA9D1A /* Client.swift */, @@ -122,7 +138,16 @@ E0E8B96B23481E1700DA9D1A /* HttpResponse.swift */, E0E8B96D2348203B00DA9D1A /* RequestBuilder.swift */, ); - path = DataSource; + path = Network; + sourceTree = ""; + }; + E0E8B972234918ED00DA9D1A /* Models */ = { + isa = PBXGroup; + children = ( + E0E8B973234918FF00DA9D1A /* Account.swift */, + E0E8B9752349197100DA9D1A /* Post.swift */, + ); + path = Models; sourceTree = ""; }; /* End PBXGroup section */ @@ -227,13 +252,16 @@ buildActionMask = 2147483647; files = ( E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */, + E0E8B974234918FF00DA9D1A /* Account.swift in Sources */, E038FCED233FC78600E28571 /* PostViewController.swift in Sources */, + E0E8B9762349197100DA9D1A /* Post.swift in Sources */, E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */, E0E8B96E2348203B00DA9D1A /* RequestBuilder.swift in Sources */, E0E8B9682348036D00DA9D1A /* Client.swift in Sources */, E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */, E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */, E084FAFC233A8888009AC50D /* PostsTableViewController.swift in Sources */, + E0E8B971234916D100DA9D1A /* RestClient.swift in Sources */, E084FADC233A8734009AC50D /* SceneDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/fakestagram/DataSource/RestClient.swift b/fakestagram/DataSource/RestClient.swift new file mode 100644 index 0000000..473fba6 --- /dev/null +++ b/fakestagram/DataSource/RestClient.swift @@ -0,0 +1,99 @@ +// +// RestClient.swift +// fakestagram +// +// Created by LuisE on 10/5/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +class RestClient { + private let client: Client + let basePath: String + let encoder: JSONEncoder = { + let encoder = JSONEncoder() + encoder.keyEncodingStrategy = .convertToSnakeCase + return encoder + }() + + let decoder: JSONDecoder = { + let decoder = JSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + return decoder + }() + + init(client: Client, basePath: String) { + self.client = client + self.basePath = basePath + } + + // eg. POST /posts/ + func create(_ data: T, success: @escaping (T?) -> Void) { + let payload = try? encoder.encode(data) + client.post(path: basePath, body: payload) { [unowned self] data in + guard let data = data else { + success(nil) + return + } + do { + let json = try self.decoder.decode(T.self, from: data) + success(json) + } catch let err { + print("Invalid JSON format: \(err.localizedDescription)") + } + } + + } + + // eg. GET /posts/ + // eg. GET /posts/:id + func show(id: String, success: @escaping (T?) -> Void) { // aka read + client.get(path: "\(basePath)/\(id)") { [unowned self] data in + guard let data = data else { + success(nil) + return + } + do { + let json = try self.decoder.decode(T.self, from: data) + success(json) + } catch let err { + print("Invalid JSON format: \(err.localizedDescription)") + } + } + } + // eg. PUT /posts/:id + func update(id: String, data: T, success: @escaping (T?) -> Void) { + let payload = try? encoder.encode(data) + client.put(path: "\(basePath)/\(id)", body: payload) { [unowned self] data in + guard let data = data else { + success(nil) + return + } + do { + let json = try self.decoder.decode(T.self, from: data) + success(json) + } catch let err { + print("Invalid JSON format: \(err.localizedDescription)") + } + } + } + + + // eg. DELETE /posts/:id + func delete(id: String, success: @escaping (T?) -> Void) { + client.delete(path: "\(basePath)/\(id)") { [unowned self] data in + guard let data = data else { + success(nil) + return + } + do { + let json = try self.decoder.decode(T.self, from: data) + success(json) + } catch let err { + print("Invalid JSON format: \(err.localizedDescription)") + } + } + } + +} diff --git a/fakestagram/Models/Account.swift b/fakestagram/Models/Account.swift new file mode 100644 index 0000000..bb66fde --- /dev/null +++ b/fakestagram/Models/Account.swift @@ -0,0 +1,16 @@ +// +// Account.swift +// fakestagram +// +// Created by LuisE on 10/5/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +struct Account: Codable { + let id: String? + let name: String + let deviceNumber: String + let deviceModel: String +} diff --git a/fakestagram/Models/Post.swift b/fakestagram/Models/Post.swift new file mode 100644 index 0000000..c7e6397 --- /dev/null +++ b/fakestagram/Models/Post.swift @@ -0,0 +1,38 @@ +// +// Post.swift +// fakestagram +// +// Created by LuisE on 10/5/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation +import UIKit + +struct Post: Codable { + let id: Int? + let title: String + let imageUrl: String? + var likesCount: Int + var commentsCount: Int + let createdAt: String + var liked: Bool + let location: String + + func likesCountText() -> String { + return "\(likesCount) likes" + } + + func commentsCountText() -> String { + return "\(commentsCount) comments" + } + + func load(_ image: @escaping (UIImage) -> Void) { + guard let urlString = imageUrl, let url = URL(string: urlString) else { return } + DispatchQueue.global(qos: .background).async { + if let data = try? Data(contentsOf: url), let img = UIImage(data: data) { + DispatchQueue.main.async { image(img) } + } + } + } +} diff --git a/fakestagram/DataSource/Client.swift b/fakestagram/Network/Client.swift similarity index 100% rename from fakestagram/DataSource/Client.swift rename to fakestagram/Network/Client.swift diff --git a/fakestagram/DataSource/HttpResponse.swift b/fakestagram/Network/HttpResponse.swift similarity index 100% rename from fakestagram/DataSource/HttpResponse.swift rename to fakestagram/Network/HttpResponse.swift diff --git a/fakestagram/DataSource/RequestBuilder.swift b/fakestagram/Network/RequestBuilder.swift similarity index 100% rename from fakestagram/DataSource/RequestBuilder.swift rename to fakestagram/Network/RequestBuilder.swift diff --git a/fakestagram/DataSource/StatusCode.swift b/fakestagram/Network/StatusCode.swift similarity index 100% rename from fakestagram/DataSource/StatusCode.swift rename to fakestagram/Network/StatusCode.swift diff --git a/fakestagram/PostsTableViewController.swift b/fakestagram/PostsTableViewController.swift index 2bb0b63..7be52f3 100644 --- a/fakestagram/PostsTableViewController.swift +++ b/fakestagram/PostsTableViewController.swift @@ -8,34 +8,6 @@ import UIKit -struct Post: Codable { - let id: Int? - let title: String - let imageUrl: String? - var likesCount: Int - var commentsCount: Int - let createdAt: String - var liked: Bool - let location: String - - func likesCountText() -> String { - return "\(likesCount) likes" - } - - func commentsCountText() -> String { - return "\(commentsCount) comments" - } - - func load(_ image: @escaping (UIImage) -> Void) { - guard let urlString = imageUrl, let url = URL(string: urlString) else { return } - DispatchQueue.global(qos: .background).async { - if let data = try? Data(contentsOf: url), let img = UIImage(data: data) { - DispatchQueue.main.async { image(img) } - } - } - } -} - class PostsTableViewController: UITableViewController { static let cellId = "PostCell" var posts = [Post]() From ed41a35db1b86311165dd817498d70e708808278 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Fri, 11 Oct 2019 18:04:28 -0500 Subject: [PATCH 04/23] Include gitignore into proyect --- .gitignore | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dffc1ac --- /dev/null +++ b/.gitignore @@ -0,0 +1,140 @@ + +# Created by https://www.gitignore.io/api/osx,swift,xcode,cocoapods +# Edit at https://www.gitignore.io/?templates=osx,swift,xcode,cocoapods + +### CocoaPods ### +## CocoaPods GitIgnore Template + +# CocoaPods - Only use to conserve bandwidth / Save time on Pushing +# - Also handy if you have a large number of dependant pods +# - AS PER https://guides.cocoapods.org/using/using-cocoapods.html NEVER IGNORE THE LOCK FILE +Pods/ + +### OSX ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Swift ### +# 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 +*.xccheckout +*.xcscmblueprint + +## 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/ +# Package.pins +# Package.resolved +.build/ +# Add this line if you want to avoid checking in Xcode SPM integration. +# .swiftpm/xcode + +# 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/ +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# Accio dependency management +Dependencies/ +.accio/ + +# 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://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ + +### Xcode ### +# Xcode +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) + +## Xcode Patch +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcworkspace/contents.xcworkspacedata +/*.gcno + +### Xcode Patch ### +**/xcshareddata/WorkspaceSettings.xcsettings + +# End of https://www.gitignore.io/api/osx,swift,xcode,cocoapods From 011a0d51a3988fa74363f1767aa551326332ec34 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Fri, 11 Oct 2019 18:06:24 -0500 Subject: [PATCH 05/23] Add cocoapods with DVR pod --- Podfile | 13 +++ Podfile.lock | 16 +++ fakestagram.xcodeproj/project.pbxproj | 104 ++++++++++++++++++ .../contents.xcworkspacedata | 10 ++ 4 files changed, 143 insertions(+) create mode 100644 Podfile create mode 100644 Podfile.lock create mode 100644 fakestagram.xcworkspace/contents.xcworkspacedata diff --git a/Podfile b/Podfile new file mode 100644 index 0000000..9363ece --- /dev/null +++ b/Podfile @@ -0,0 +1,13 @@ +# Uncomment the next line to define a global platform for your project +platform :ios, '13.0' + +target 'fakestagram' do + # Comment the next line if you don't want to use dynamic frameworks + use_frameworks! + # Pods for fakestagram + + target 'fakestagramTests' do + inherit! :search_paths + pod 'DVR' + end +end diff --git a/Podfile.lock b/Podfile.lock new file mode 100644 index 0000000..918107b --- /dev/null +++ b/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - DVR (2.0.0) + +DEPENDENCIES: + - DVR + +SPEC REPOS: + trunk: + - DVR + +SPEC CHECKSUMS: + DVR: 062c287b9dc613a84120e44640176e4ef3ecf943 + +PODFILE CHECKSUM: 841e7401a398ccd6377f6b0c60295e943d9532bd + +COCOAPODS: 1.8.3 diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index fb14047..9e6d3cd 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 05D8E963168944918FFCC7FF /* Pods_fakestagram.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FFAA8B9133CEE464C903FDF5 /* Pods_fakestagram.framework */; }; + D3D164DC7444072103DE027D /* Pods_fakestagramTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E669E31C92D68155914FC99D /* Pods_fakestagramTests.framework */; }; E038FCED233FC78600E28571 /* PostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E038FCEC233FC78600E28571 /* PostViewController.swift */; }; E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAD9233A8734009AC50D /* AppDelegate.swift */; }; E084FADC233A8734009AC50D /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FADB233A8734009AC50D /* SceneDelegate.swift */; }; @@ -36,6 +38,10 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 5E0AE2BFBF9C8D81E583E1BE /* Pods-fakestagramTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagramTests.release.xcconfig"; path = "Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.release.xcconfig"; sourceTree = ""; }; + 66342726A6BCEEEF6289B1AA /* Pods-fakestagramTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagramTests.debug.xcconfig"; path = "Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.debug.xcconfig"; sourceTree = ""; }; + CCC6C6EA9D17CA169951A745 /* Pods-fakestagram.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagram.release.xcconfig"; path = "Target Support Files/Pods-fakestagram/Pods-fakestagram.release.xcconfig"; sourceTree = ""; }; + DB68F7FEC717545506064663 /* Pods-fakestagram.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagram.debug.xcconfig"; path = "Target Support Files/Pods-fakestagram/Pods-fakestagram.debug.xcconfig"; sourceTree = ""; }; E038FCEC233FC78600E28571 /* PostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewController.swift; sourceTree = ""; }; E084FAD6233A8734009AC50D /* fakestagram.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = fakestagram.app; sourceTree = BUILT_PRODUCTS_DIR; }; E084FAD9233A8734009AC50D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -56,6 +62,8 @@ E0E8B970234916D100DA9D1A /* RestClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestClient.swift; sourceTree = ""; }; E0E8B973234918FF00DA9D1A /* Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = ""; }; E0E8B9752349197100DA9D1A /* Post.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Post.swift; sourceTree = ""; }; + E669E31C92D68155914FC99D /* Pods_fakestagramTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_fakestagramTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + FFAA8B9133CEE464C903FDF5 /* Pods_fakestagram.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_fakestagram.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -63,6 +71,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 05D8E963168944918FFCC7FF /* Pods_fakestagram.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -70,18 +79,33 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + D3D164DC7444072103DE027D /* Pods_fakestagramTests.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 01A08896D7765C060714CF7E /* Pods */ = { + isa = PBXGroup; + children = ( + DB68F7FEC717545506064663 /* Pods-fakestagram.debug.xcconfig */, + CCC6C6EA9D17CA169951A745 /* Pods-fakestagram.release.xcconfig */, + 66342726A6BCEEEF6289B1AA /* Pods-fakestagramTests.debug.xcconfig */, + 5E0AE2BFBF9C8D81E583E1BE /* Pods-fakestagramTests.release.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; E084FACD233A8734009AC50D = { isa = PBXGroup; children = ( E084FAD8233A8734009AC50D /* fakestagram */, E084FAEF233A8735009AC50D /* fakestagramTests */, E084FAD7233A8734009AC50D /* Products */, + 01A08896D7765C060714CF7E /* Pods */, + E59E91806B162F48B9F21B96 /* Frameworks */, ); sourceTree = ""; }; @@ -150,6 +174,15 @@ path = Models; sourceTree = ""; }; + E59E91806B162F48B9F21B96 /* Frameworks */ = { + isa = PBXGroup; + children = ( + FFAA8B9133CEE464C903FDF5 /* Pods_fakestagram.framework */, + E669E31C92D68155914FC99D /* Pods_fakestagramTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -157,6 +190,7 @@ isa = PBXNativeTarget; buildConfigurationList = E084FAF5233A8735009AC50D /* Build configuration list for PBXNativeTarget "fakestagram" */; buildPhases = ( + 4AE804DBB1C330BBDB1A4587 /* [CP] Check Pods Manifest.lock */, E084FAD2233A8734009AC50D /* Sources */, E084FAD3233A8734009AC50D /* Frameworks */, E084FAD4233A8734009AC50D /* Resources */, @@ -174,9 +208,11 @@ isa = PBXNativeTarget; buildConfigurationList = E084FAF8233A8735009AC50D /* Build configuration list for PBXNativeTarget "fakestagramTests" */; buildPhases = ( + 9C7D5FC48E01207A73A3C357 /* [CP] Check Pods Manifest.lock */, E084FAE8233A8735009AC50D /* Sources */, E084FAE9233A8735009AC50D /* Frameworks */, E084FAEA233A8735009AC50D /* Resources */, + 7AA77609E4963F9B91BB29FB /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -246,6 +282,70 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 4AE804DBB1C330BBDB1A4587 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-fakestagram-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 7AA77609E4963F9B91BB29FB /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 9C7D5FC48E01207A73A3C357 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-fakestagramTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ E084FAD2233A8734009AC50D /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -420,6 +520,7 @@ }; E084FAF6233A8735009AC50D /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = DB68F7FEC717545506064663 /* Pods-fakestagram.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; @@ -438,6 +539,7 @@ }; E084FAF7233A8735009AC50D /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = CCC6C6EA9D17CA169951A745 /* Pods-fakestagram.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_STYLE = Automatic; @@ -456,6 +558,7 @@ }; E084FAF9233A8735009AC50D /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 66342726A6BCEEEF6289B1AA /* Pods-fakestagramTests.debug.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; @@ -478,6 +581,7 @@ }; E084FAFA233A8735009AC50D /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 5E0AE2BFBF9C8D81E583E1BE /* Pods-fakestagramTests.release.xcconfig */; buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; diff --git a/fakestagram.xcworkspace/contents.xcworkspacedata b/fakestagram.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..666ee12 --- /dev/null +++ b/fakestagram.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + From 98023b8a3d25199de99620637be5fc12921e3cfd Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Fri, 11 Oct 2019 19:51:45 -0500 Subject: [PATCH 06/23] Add tests for RestClient and implement endpoints --- fakestagram.xcodeproj/project.pbxproj | 23 +- .../xcschemes/xcschememanagement.plist | 2 +- .../xcshareddata/IDEWorkspaceChecks.plist | 8 + fakestagram/DataSource/RestClient.swift | 12 +- fakestagramTests/RestClientTest.swift | 49 ++ .../casettes/posts.successful.json | 444 ++++++++++++++++++ .../casettes/show_post.successful.json | 57 +++ 7 files changed, 588 insertions(+), 7 deletions(-) create mode 100644 fakestagram.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 fakestagramTests/RestClientTest.swift create mode 100644 fakestagramTests/casettes/posts.successful.json create mode 100644 fakestagramTests/casettes/show_post.successful.json diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index 9e6d3cd..88fcd16 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 51; objects = { /* Begin PBXBuildFile section */ @@ -17,6 +17,9 @@ E084FAE6233A8735009AC50D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E084FAE4233A8735009AC50D /* LaunchScreen.storyboard */; }; E084FAF1233A8735009AC50D /* RequestBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAF0233A8735009AC50D /* RequestBuilderTests.swift */; }; E084FAFC233A8888009AC50D /* PostsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAFB233A8888009AC50D /* PostsTableViewController.swift */; }; + E0C93E942351435100FD330C /* RestClientTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93E932351435100FD330C /* RestClientTest.swift */; }; + E0C93E9923514D8800FD330C /* posts.successful.json in Resources */ = {isa = PBXBuildFile; fileRef = E0C93E9823514D8800FD330C /* posts.successful.json */; }; + E0C93E9B23515A0400FD330C /* show_post.successful.json in Resources */ = {isa = PBXBuildFile; fileRef = E0C93E9A23515A0400FD330C /* show_post.successful.json */; }; E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9642348018200DA9D1A /* Credentials.swift */; }; E0E8B9682348036D00DA9D1A /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9672348036D00DA9D1A /* Client.swift */; }; E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96923481D5A00DA9D1A /* StatusCode.swift */; }; @@ -54,6 +57,9 @@ E084FAF0233A8735009AC50D /* RequestBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestBuilderTests.swift; sourceTree = ""; }; E084FAF2233A8735009AC50D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E084FAFB233A8888009AC50D /* PostsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostsTableViewController.swift; sourceTree = ""; }; + E0C93E932351435100FD330C /* RestClientTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestClientTest.swift; sourceTree = ""; }; + E0C93E9823514D8800FD330C /* posts.successful.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = posts.successful.json; sourceTree = ""; }; + E0C93E9A23515A0400FD330C /* show_post.successful.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = show_post.successful.json; sourceTree = ""; }; E0E8B9642348018200DA9D1A /* Credentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Credentials.swift; sourceTree = ""; }; E0E8B9672348036D00DA9D1A /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; E0E8B96923481D5A00DA9D1A /* StatusCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCode.swift; sourceTree = ""; }; @@ -94,7 +100,6 @@ 66342726A6BCEEEF6289B1AA /* Pods-fakestagramTests.debug.xcconfig */, 5E0AE2BFBF9C8D81E583E1BE /* Pods-fakestagramTests.release.xcconfig */, ); - name = Pods; path = Pods; sourceTree = ""; }; @@ -140,12 +145,23 @@ E084FAEF233A8735009AC50D /* fakestagramTests */ = { isa = PBXGroup; children = ( + E0C93E952351472A00FD330C /* casettes */, E084FAF0233A8735009AC50D /* RequestBuilderTests.swift */, + E0C93E932351435100FD330C /* RestClientTest.swift */, E084FAF2233A8735009AC50D /* Info.plist */, ); path = fakestagramTests; sourceTree = ""; }; + E0C93E952351472A00FD330C /* casettes */ = { + isa = PBXGroup; + children = ( + E0C93E9A23515A0400FD330C /* show_post.successful.json */, + E0C93E9823514D8800FD330C /* posts.successful.json */, + ); + path = casettes; + sourceTree = ""; + }; E0E8B9662348035800DA9D1A /* DataSource */ = { isa = PBXGroup; children = ( @@ -277,6 +293,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + E0C93E9923514D8800FD330C /* posts.successful.json in Resources */, + E0C93E9B23515A0400FD330C /* show_post.successful.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -370,6 +388,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E0C93E942351435100FD330C /* RestClientTest.swift in Sources */, E084FAF1233A8735009AC50D /* RequestBuilderTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcschemes/xcschememanagement.plist b/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcschemes/xcschememanagement.plist index 53f76f5..f8df77c 100644 --- a/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,7 +7,7 @@ fakestagram.xcscheme_^#shared#^_ orderHint - 0 + 3 diff --git a/fakestagram.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/fakestagram.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/fakestagram.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/fakestagram/DataSource/RestClient.swift b/fakestagram/DataSource/RestClient.swift index 473fba6..205a86b 100644 --- a/fakestagram/DataSource/RestClient.swift +++ b/fakestagram/DataSource/RestClient.swift @@ -48,15 +48,19 @@ class RestClient { // eg. GET /posts/ // eg. GET /posts/:id - func show(id: String, success: @escaping (T?) -> Void) { // aka read - client.get(path: "\(basePath)/\(id)") { [unowned self] data in + func show(id: String? = nil, success: @escaping (T?) -> Void) { + var path = basePath + if let uid = id { + path += "/\(uid)" + } + client.get(path: path) { [unowned self] data in guard let data = data else { - success(nil) + DispatchQueue.main.async { success(nil) } return } do { let json = try self.decoder.decode(T.self, from: data) - success(json) + DispatchQueue.main.async { success(json) } } catch let err { print("Invalid JSON format: \(err.localizedDescription)") } diff --git a/fakestagramTests/RestClientTest.swift b/fakestagramTests/RestClientTest.swift new file mode 100644 index 0000000..e718a76 --- /dev/null +++ b/fakestagramTests/RestClientTest.swift @@ -0,0 +1,49 @@ +// +// RestClientTest.swift +// fakestagramTests +// +// Created by LuisE on 10/11/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import XCTest +import DVR +@testable import fakestagram + +class RestClientTest: XCTestCase { + + func testShowPosts() { + let session = Session(cassetteName: "posts.successful") + let client = Client(session: session, baseUrl: "https://fakestagram-api.herokuapp.com") + let restClient = RestClient<[Post]>(client: client, basePath: "/api/v1/posts") + let exp = expectation(description: "Successfull index posts") + + restClient.show() { posts in + exp.fulfill() + XCTAssertNotNil(posts) + XCTAssertEqual(posts!.count, 25) + XCTAssertEqual(posts!.first!.id, 228) + XCTAssertEqual(posts!.first!.title, "Example") + } + + waitForExpectations(timeout: 2, handler: nil) + } + + func testShowPost() { + let session = Session(cassetteName: "show_post.successful") + let client = Client(session: session, baseUrl: "https://fakestagram-api.herokuapp.com") + + let restClient = RestClient(client: client, basePath: "/api/v1/posts") + let exp = expectation(description: "Successfull index posts") + + restClient.show(id: "228") { post in + exp.fulfill() + XCTAssertNotNil(post) + XCTAssertEqual(post!.id, 228) + XCTAssertEqual(post!.title, "Example") + } + + waitForExpectations(timeout: 2, handler: nil) + } + +} diff --git a/fakestagramTests/casettes/posts.successful.json b/fakestagramTests/casettes/posts.successful.json new file mode 100644 index 0000000..24d2ccf --- /dev/null +++ b/fakestagramTests/casettes/posts.successful.json @@ -0,0 +1,444 @@ +{ + "interactions" : [ + { + "request" : { + "method" : "GET", + "headers" : { + "Content-Type" : "application\/json", + "Authorization" : "Bearer f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e", + "Accept" : "application\/json" + }, + "url" : "https:\/\/fakestagram-api.herokuapp.com\/api\/v1\/posts" + }, + "recorded_at" : 1570837975.1744719, + "response" : { + "url" : "https:\/\/fakestagram-api.herokuapp.com\/api\/v1\/posts", + "headers" : { + "Etag" : "W\/\"0d7dc5010941ab1928365db038e254f9\"", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains", + "X-Request-Id" : "f9b64a0a-2902-46c5-9355-feffcda2b924", + "Vary" : "Origin", + "X-Download-Options" : "noopen", + "Via" : "1.1 vegur", + "X-Permitted-Cross-Domain-Policies" : "none", + "X-Content-Type-Options" : "nosniff", + "Content-Length" : "0", + "X-Xss-Protection" : "1; mode=block", + "Connection" : "keep-alive", + "Cache-Control" : "max-age=0, private, must-revalidate", + "Content-Type" : "application\/json; charset=utf-8", + "X-Frame-Options" : "SAMEORIGIN", + "X-Runtime" : "0.087793", + "Referrer-Policy" : "strict-origin-when-cross-origin", + "Date" : "Fri, 11 Oct 2019 23:52:54 GMT", + "Transfer-Encoding" : "Identity", + "Server" : "Cowboy" + }, + "body" : [ + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e", + "name" : "John Carney", + "avatar_url" : null + }, + "id" : 228, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZTA9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--b668068c1f6252a77beacbd9313d8f4e078a400f\/4ed83e29-b955-4dc6-b5ee-eafd994e9de8", + "title" : "Example", + "created_at" : "2019-10-04T21:15:42.650Z", + "liked" : true, + "updated_at" : "2019-10-04T21:15:42.738Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e", + "name" : "John Carney", + "avatar_url" : null + }, + "id" : 227, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZWs9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--af591b63753c7a621bbaece3f99c79c9375551b4\/9b13eeaf-3a33-45d8-9f96-09506672ddf4", + "title" : "Example", + "created_at" : "2019-10-04T05:11:50.647Z", + "liked" : true, + "updated_at" : "2019-10-04T05:11:50.701Z", + "comments_count" : 0 + }, + { + "location" : "South San Francisco BART, Bart, South San Francisco, San Mateo County, California, 94014, USA", + "likes_count" : 0, + "author" : { + "id" : "26c0b0a1-6b04-4625-9d08-f8b348b968d6", + "name" : "Gerard Hane", + "avatar_url" : null + }, + "id" : 226, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZVk9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--a89eead659aa964493322d79f9f5cca4db18ff9d\/3340cca1-dd82-4c63-ba8f-3986bddbc500", + "title" : "1566158823894", + "created_at" : "2019-08-18T20:07:04.661Z", + "liked" : false, + "updated_at" : "2019-08-18T20:07:04.686Z", + "comments_count" : 0 + }, + { + "location" : "South San Francisco BART, Bart, South San Francisco, San Mateo County, California, 94014, USA", + "likes_count" : 0, + "author" : { + "id" : "26c0b0a1-6b04-4625-9d08-f8b348b968d6", + "name" : "Gerard Hane", + "avatar_url" : null + }, + "id" : 225, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZVU9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--0e22a6bc1f9e9477762e32356036134efd54eb55\/70bb725c-e86e-4430-b925-11c25718392a", + "title" : "1566158820509", + "created_at" : "2019-08-18T20:07:01.750Z", + "liked" : false, + "updated_at" : "2019-08-18T20:07:01.854Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 2, + "author" : { + "id" : "ababf2cd-0eb9-45b6-99e5-90de794f7860", + "name" : "Katelyn Sanford", + "avatar_url" : null + }, + "id" : 224, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZVE9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--b927d8cd407bfb7f4e32dff66842cbce798e10a3\/78a88dea-8b8e-4d33-a633-5e492bc14842", + "title" : ":p", + "created_at" : "2019-08-11T20:17:49.826Z", + "liked" : false, + "updated_at" : "2019-08-11T20:17:49.895Z", + "comments_count" : 2 + }, + { + "location" : "", + "likes_count" : 1, + "author" : { + "id" : "9b590ebf-4875-4a83-8249-c6223e0d1a2a", + "name" : "Sammy Beier", + "avatar_url" : null + }, + "id" : 223, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZU09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--5726e694e2d04ec83ee589ff11293f8d4a49daf5\/3c7f898e-ae8d-410c-800d-20c590b8118e", + "title" : "1565393475188", + "created_at" : "2019-08-09T23:31:20.358Z", + "liked" : false, + "updated_at" : "2019-08-09T23:31:20.380Z", + "comments_count" : 1 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f9d53895-93f9-43c2-973e-ce47aadf6239", + "name" : "Arlinda Balistreri", + "avatar_url" : null + }, + "id" : 222, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZUk9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3d89565f024de56af1b3d510d954b64e11593812\/0314b818-2096-4387-bcee-ed62594b013e", + "title" : "1565392767381", + "created_at" : "2019-08-09T23:19:30.715Z", + "liked" : false, + "updated_at" : "2019-08-09T23:19:30.737Z", + "comments_count" : 1 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f9d53895-93f9-43c2-973e-ce47aadf6239", + "name" : "Arlinda Balistreri", + "avatar_url" : null + }, + "id" : 221, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZUU9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--26a6cfcb28d63275d7d2e38cc19cc318106bc7a1\/74ee9a0c-3fd3-413f-9a05-ed56514f9b4c", + "title" : "1565392624022", + "created_at" : "2019-08-09T23:17:06.162Z", + "liked" : false, + "updated_at" : "2019-08-09T23:17:06.191Z", + "comments_count" : 4 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f9d53895-93f9-43c2-973e-ce47aadf6239", + "name" : "Arlinda Balistreri", + "avatar_url" : null + }, + "id" : 220, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZUE9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--84f7d1d7e2c9624478e486b85ef289101adff64b\/89fe9faf-dafb-4c44-9810-55f9dc1643f7", + "title" : "1565389845416", + "created_at" : "2019-08-09T22:30:45.562Z", + "liked" : false, + "updated_at" : "2019-08-09T22:30:45.589Z", + "comments_count" : 11 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f9d53895-93f9-43c2-973e-ce47aadf6239", + "name" : "Arlinda Balistreri", + "avatar_url" : null + }, + "id" : 219, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZDg9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--aa3dbf1922f86c5ab9f874710541abd83a10aa21\/8d34e2e6-d33d-4ac1-954b-b0c3e1403301", + "title" : "1565389827272", + "created_at" : "2019-08-09T22:30:27.612Z", + "liked" : false, + "updated_at" : "2019-08-09T22:30:27.633Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f9d53895-93f9-43c2-973e-ce47aadf6239", + "name" : "Arlinda Balistreri", + "avatar_url" : null + }, + "id" : 218, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZDQ9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--9534d1e17eab3138685b2ae633f1fce2b3072fa3\/24f26bae-f215-499a-a985-ad1cca2168e3", + "title" : "1565387654424", + "created_at" : "2019-08-09T21:54:14.782Z", + "liked" : false, + "updated_at" : "2019-08-09T21:54:14.823Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 1, + "author" : { + "id" : "cb9a00b1-c23d-4dcd-84a3-0066cc930adc", + "name" : "Melvina DuBuque", + "avatar_url" : null + }, + "id" : 217, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZDA9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--ce6d7e4e61a3bad722d0b1ecc9d9c85a5d443782\/b077e3b9-7abd-4f01-a3d4-baaeaa03d035", + "title" : "1565284409539", + "created_at" : "2019-08-08T17:13:30.621Z", + "liked" : false, + "updated_at" : "2019-08-08T17:13:30.647Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "cb9a00b1-c23d-4dcd-84a3-0066cc930adc", + "name" : "Melvina DuBuque", + "avatar_url" : null + }, + "id" : 216, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZHc9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--5fd762895b481581889f8370850660961ac27ae2\/79075b3f-a2f6-4a28-8478-2b2024361b8f", + "title" : "1565284311613", + "created_at" : "2019-08-08T17:11:51.968Z", + "liked" : false, + "updated_at" : "2019-08-08T17:11:52.041Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "1a11b5ea-b450-478c-b968-6e4bf1724a27", + "name" : "Garth Hartmann", + "avatar_url" : null + }, + "id" : 215, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZHM9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--3aaf6ee04bf6e2e276af0a7542057df4bc859a9d\/b2f6db08-2257-4bd4-9371-e784c7dd3ef5", + "title" : "1565240319353", + "created_at" : "2019-08-08T04:58:39.800Z", + "liked" : false, + "updated_at" : "2019-08-08T04:58:39.871Z", + "comments_count" : 0 + }, + { + "location" : "Powell Street Station, Market Street, Union Square, San Francisco, San Francisco City and County, California, 94103-3124, USA", + "likes_count" : 0, + "author" : { + "id" : "44a51289-6d9e-4e27-8638-6d3102511ad8", + "name" : "Melanie Gaylord", + "avatar_url" : null + }, + "id" : 214, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZG89IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--475805cb649993f55820a95307fc1f7a80db3f4e\/71f1b9e0-f262-4261-ad1d-ece8046151ef", + "title" : "1565064895736", + "created_at" : "2019-08-06T04:14:56.879Z", + "liked" : false, + "updated_at" : "2019-08-06T04:14:56.920Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "90834f94-fd51-420a-b350-30851abf61d5", + "name" : "Belle Douglas", + "avatar_url" : null + }, + "id" : 213, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZGs9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--f5b051063503aadef9f0cd9a0723c12d2d627dde\/bc279b9d-2dce-49c6-9120-4e4b575f7a78", + "title" : "1565028839754", + "created_at" : "2019-08-05T18:14:00.016Z", + "liked" : false, + "updated_at" : "2019-08-05T18:14:00.078Z", + "comments_count" : 0 + }, + { + "location" : "Powell Street Station, Market Street, Union Square, San Francisco, San Francisco City and County, California, 94103-3124, USA", + "likes_count" : 0, + "author" : { + "id" : "44a51289-6d9e-4e27-8638-6d3102511ad8", + "name" : "Melanie Gaylord", + "avatar_url" : null + }, + "id" : 212, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZGc9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--ead89bde0e160956f51b9d5d7637c4ca1b8d5643\/3c16b6e2-838b-453e-87a8-c8e623efee6f", + "title" : "1564953882318", + "created_at" : "2019-08-04T21:24:43.366Z", + "liked" : false, + "updated_at" : "2019-08-04T21:24:43.424Z", + "comments_count" : 0 + }, + { + "location" : "Powell Street Station, Market Street, Union Square, San Francisco, San Francisco City and County, California, 94103-3124, USA", + "likes_count" : 1, + "author" : { + "id" : "44a51289-6d9e-4e27-8638-6d3102511ad8", + "name" : "Melanie Gaylord", + "avatar_url" : null + }, + "id" : 211, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZGM9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--aa53a5c71d2af02eb63f222e8f62666ac020626d\/70601715-1ce5-4886-8647-614a88acdc3e", + "title" : "1564938932927", + "created_at" : "2019-08-04T17:15:34.008Z", + "liked" : false, + "updated_at" : "2019-08-04T17:15:34.072Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 1, + "author" : { + "id" : "15e6a545-c5c7-4775-b3b3-f4c08622b7f8", + "name" : "Venessa Prosacco", + "avatar_url" : null + }, + "id" : 209, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZFE9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--677615c8da9ee16d4a2f2d04d71620345dad3dcb\/a37c2b48-53b0-4200-8ca4-0ab3c601c2be", + "title" : "No lo haga compa", + "created_at" : "2019-07-26T22:14:55.445Z", + "liked" : false, + "updated_at" : "2019-07-26T22:14:55.465Z", + "comments_count" : 2 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "15e6a545-c5c7-4775-b3b3-f4c08622b7f8", + "name" : "Venessa Prosacco", + "avatar_url" : null + }, + "id" : 208, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZE09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--701845e2a532406662abd63bd9903cfb3d6fa427\/f56ff4ea-21aa-416f-9644-bbcc36c0a489", + "title" : "No lo haga compa", + "created_at" : "2019-07-26T22:14:48.407Z", + "liked" : false, + "updated_at" : "2019-07-26T22:14:48.472Z", + "comments_count" : 2 + }, + { + "location" : "Calle Durango, Condesa, Mexico City, Cuauhtémoc, Mexico City, 06140, Mexico", + "likes_count" : 0, + "author" : { + "id" : "3c06d9f5-9cc0-483e-a089-8bcc4c11c14e", + "name" : "Shenita Champlin", + "avatar_url" : null + }, + "id" : 207, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZEU9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--b375a88531fce2fba8301e8f4d9cda92016317f6\/2a6c1b7a-16d8-4155-9825-e92a834f083a", + "title" : "1563810644322", + "created_at" : "2019-07-22T15:50:48.103Z", + "liked" : false, + "updated_at" : "2019-07-22T15:50:48.219Z", + "comments_count" : 1 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "10b7accf-1817-4fe5-9674-8f7703220e96", + "name" : "Shonda Hammes", + "avatar_url" : null + }, + "id" : 206, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZEE9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--6b9c9e7a5919fc296349d7e0ba3eb327fab7e28d\/8be5a13a-b703-4e9d-bfa8-640969a1d03b", + "title" : "Las svm son chidas", + "created_at" : "2019-07-11T17:43:09.553Z", + "liked" : false, + "updated_at" : "2019-07-11T17:43:09.600Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "10b7accf-1817-4fe5-9674-8f7703220e96", + "name" : "Shonda Hammes", + "avatar_url" : null + }, + "id" : 205, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBYzg9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--9bd1e3affaa38a100b254bcc0ebfbd34697367ee\/5abbd134-50c2-4529-8474-64ad58de7383", + "title" : "Mr. Bean es mi pastor!", + "created_at" : "2019-07-11T17:40:58.360Z", + "liked" : false, + "updated_at" : "2019-07-11T17:40:58.429Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "10b7accf-1817-4fe5-9674-8f7703220e96", + "name" : "Shonda Hammes", + "avatar_url" : null + }, + "id" : 204, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZEk9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--f0193550348281afd2b2998b93997529e8ca4d16\/9b188868-6f6a-424d-b577-5bd8e99fff4c", + "title" : "Todos los del diplomado en las fiestas jajaja!", + "created_at" : "2019-07-10T23:46:37.725Z", + "liked" : false, + "updated_at" : "2019-07-23T01:22:34.916Z", + "comments_count" : 0 + }, + { + "location" : "", + "likes_count" : 1, + "author" : { + "id" : "519661d9-5f38-45dc-ba4e-ec3522aa128a", + "name" : "Lesley Funk", + "avatar_url" : null + }, + "id" : 203, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBY3M9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--954b1ccc1f0dcb9d061ac38009b43f0bd727b118\/83e80764-2bd6-40e7-b6a8-01c54af1dd84", + "title" : "1562190435299", + "created_at" : "2019-07-03T21:47:15.564Z", + "liked" : false, + "updated_at" : "2019-07-03T21:47:15.623Z", + "comments_count" : 1 + } + ], + "status" : 200 + } + } + ], + "name" : "posts.successful" +} diff --git a/fakestagramTests/casettes/show_post.successful.json b/fakestagramTests/casettes/show_post.successful.json new file mode 100644 index 0000000..03e91e1 --- /dev/null +++ b/fakestagramTests/casettes/show_post.successful.json @@ -0,0 +1,57 @@ +{ + "interactions" : [ + { + "response" : { + "status" : 200, + "body" : { + "location" : "", + "likes_count" : 0, + "author" : { + "id" : "f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e", + "name" : "John Carney", + "avatar_url" : null + }, + "id" : 228, + "image_url" : "https:\/\/fakestagram-api.herokuapp.com\/rails\/active_storage\/blobs\/eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBBZTA9IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--b668068c1f6252a77beacbd9313d8f4e078a400f\/4ed83e29-b955-4dc6-b5ee-eafd994e9de8", + "title" : "Example", + "created_at" : "2019-10-04T21:15:42.650Z", + "liked" : false, + "updated_at" : "2019-10-04T21:15:42.738Z", + "comments_count" : 0 + }, + "headers" : { + "X-Permitted-Cross-Domain-Policies" : "none", + "Content-Type" : "application\/json; charset=utf-8", + "X-Request-Id" : "c6266b7f-6e74-4fc8-808c-6046b689f67f", + "Via" : "1.1 vegur", + "Cache-Control" : "max-age=0, private, must-revalidate", + "Strict-Transport-Security" : "max-age=31536000; includeSubDomains", + "Date" : "Sat, 12 Oct 2019 00:46:20 GMT", + "Transfer-Encoding" : "Identity", + "X-Xss-Protection" : "1; mode=block", + "Referrer-Policy" : "strict-origin-when-cross-origin", + "X-Download-Options" : "noopen", + "Server" : "Cowboy", + "X-Runtime" : "0.063186", + "Connection" : "keep-alive", + "Etag" : "W\/\"819b2d0fa0647c5c452d27fb77a8d11e\"", + "X-Frame-Options" : "SAMEORIGIN", + "Vary" : "Origin", + "X-Content-Type-Options" : "nosniff" + }, + "url" : "https:\/\/fakestagram-api.herokuapp.com\/api\/v1\/posts\/228" + }, + "request" : { + "headers" : { + "Accept" : "application\/json", + "Content-Type" : "application\/json", + "Authorization" : "Bearer f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e" + }, + "method" : "GET", + "url" : "https:\/\/fakestagram-api.herokuapp.com\/api\/v1\/posts\/228" + }, + "recorded_at" : 1570841180.898001 + } + ], + "name" : "show_post.successful" +} From 5335fa498cc5495b7616c163b10ca95d4e49a932 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Fri, 11 Oct 2019 20:24:58 -0500 Subject: [PATCH 07/23] Refactor by implementing serializer --- fakestagram.xcodeproj/project.pbxproj | 4 ++ .../DataSource/CodableSerializer.swift | 35 ++++++++++ fakestagram/DataSource/RestClient.swift | 65 +++---------------- fakestagramTests/RestClientTest.swift | 10 ++- 4 files changed, 53 insertions(+), 61 deletions(-) create mode 100644 fakestagram/DataSource/CodableSerializer.swift diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index 88fcd16..53113d8 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -20,6 +20,7 @@ E0C93E942351435100FD330C /* RestClientTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93E932351435100FD330C /* RestClientTest.swift */; }; E0C93E9923514D8800FD330C /* posts.successful.json in Resources */ = {isa = PBXBuildFile; fileRef = E0C93E9823514D8800FD330C /* posts.successful.json */; }; E0C93E9B23515A0400FD330C /* show_post.successful.json in Resources */ = {isa = PBXBuildFile; fileRef = E0C93E9A23515A0400FD330C /* show_post.successful.json */; }; + E0C93E9D23515CEE00FD330C /* CodableSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93E9C23515CEE00FD330C /* CodableSerializer.swift */; }; E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9642348018200DA9D1A /* Credentials.swift */; }; E0E8B9682348036D00DA9D1A /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9672348036D00DA9D1A /* Client.swift */; }; E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96923481D5A00DA9D1A /* StatusCode.swift */; }; @@ -60,6 +61,7 @@ E0C93E932351435100FD330C /* RestClientTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestClientTest.swift; sourceTree = ""; }; E0C93E9823514D8800FD330C /* posts.successful.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = posts.successful.json; sourceTree = ""; }; E0C93E9A23515A0400FD330C /* show_post.successful.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = show_post.successful.json; sourceTree = ""; }; + E0C93E9C23515CEE00FD330C /* CodableSerializer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableSerializer.swift; sourceTree = ""; }; E0E8B9642348018200DA9D1A /* Credentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Credentials.swift; sourceTree = ""; }; E0E8B9672348036D00DA9D1A /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; E0E8B96923481D5A00DA9D1A /* StatusCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCode.swift; sourceTree = ""; }; @@ -166,6 +168,7 @@ isa = PBXGroup; children = ( E0E8B970234916D100DA9D1A /* RestClient.swift */, + E0C93E9C23515CEE00FD330C /* CodableSerializer.swift */, ); path = DataSource; sourceTree = ""; @@ -372,6 +375,7 @@ E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */, E0E8B974234918FF00DA9D1A /* Account.swift in Sources */, E038FCED233FC78600E28571 /* PostViewController.swift in Sources */, + E0C93E9D23515CEE00FD330C /* CodableSerializer.swift in Sources */, E0E8B9762349197100DA9D1A /* Post.swift in Sources */, E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */, E0E8B96E2348203B00DA9D1A /* RequestBuilder.swift in Sources */, diff --git a/fakestagram/DataSource/CodableSerializer.swift b/fakestagram/DataSource/CodableSerializer.swift new file mode 100644 index 0000000..a6aedf1 --- /dev/null +++ b/fakestagram/DataSource/CodableSerializer.swift @@ -0,0 +1,35 @@ +// +// CodableSerializer.swift +// fakestagram +// +// Created by LuisE on 10/11/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +class CodableSerializer { + let data: Data? + let decoder: JSONDecoder = { + let decoder = JSONDecoder() + decoder.keyDecodingStrategy = .convertFromSnakeCase + return decoder + }() + + init(data: Data?) { + self.data = data + } + + func async(result: @escaping (T?) -> Void) { + guard let data = data else { + DispatchQueue.main.async { result(nil) } + return + } + do { + let json = try decoder.decode(T.self, from: data) + DispatchQueue.main.async { result(json) } + } catch let err { + print("Invalid JSON format: \(err.localizedDescription)") + } + } +} diff --git a/fakestagram/DataSource/RestClient.swift b/fakestagram/DataSource/RestClient.swift index 205a86b..f22198a 100644 --- a/fakestagram/DataSource/RestClient.swift +++ b/fakestagram/DataSource/RestClient.swift @@ -17,12 +17,6 @@ class RestClient { return encoder }() - let decoder: JSONDecoder = { - let decoder = JSONDecoder() - decoder.keyDecodingStrategy = .convertFromSnakeCase - return decoder - }() - init(client: Client, basePath: String) { self.client = client self.basePath = basePath @@ -31,19 +25,9 @@ class RestClient { // eg. POST /posts/ func create(_ data: T, success: @escaping (T?) -> Void) { let payload = try? encoder.encode(data) - client.post(path: basePath, body: payload) { [unowned self] data in - guard let data = data else { - success(nil) - return - } - do { - let json = try self.decoder.decode(T.self, from: data) - success(json) - } catch let err { - print("Invalid JSON format: \(err.localizedDescription)") - } - } - + client.post(path: basePath, body: payload) { data in + CodableSerializer(data: data).async(result: success) + } } // eg. GET /posts/ @@ -53,51 +37,22 @@ class RestClient { if let uid = id { path += "/\(uid)" } - client.get(path: path) { [unowned self] data in - guard let data = data else { - DispatchQueue.main.async { success(nil) } - return - } - do { - let json = try self.decoder.decode(T.self, from: data) - DispatchQueue.main.async { success(json) } - } catch let err { - print("Invalid JSON format: \(err.localizedDescription)") - } + client.get(path: path) { data in + CodableSerializer(data: data).async(result: success) } } // eg. PUT /posts/:id func update(id: String, data: T, success: @escaping (T?) -> Void) { let payload = try? encoder.encode(data) - client.put(path: "\(basePath)/\(id)", body: payload) { [unowned self] data in - guard let data = data else { - success(nil) - return - } - do { - let json = try self.decoder.decode(T.self, from: data) - success(json) - } catch let err { - print("Invalid JSON format: \(err.localizedDescription)") - } + client.put(path: "\(basePath)/\(id)", body: payload) { data in + CodableSerializer(data: data).async(result: success) } } - // eg. DELETE /posts/:id func delete(id: String, success: @escaping (T?) -> Void) { - client.delete(path: "\(basePath)/\(id)") { [unowned self] data in - guard let data = data else { - success(nil) - return - } - do { - let json = try self.decoder.decode(T.self, from: data) - success(json) - } catch let err { - print("Invalid JSON format: \(err.localizedDescription)") - } - } + client.delete(path: "\(basePath)/\(id)") { data in + CodableSerializer(data: data).async(result: success) + } } - } diff --git a/fakestagramTests/RestClientTest.swift b/fakestagramTests/RestClientTest.swift index e718a76..9ed3fc0 100644 --- a/fakestagramTests/RestClientTest.swift +++ b/fakestagramTests/RestClientTest.swift @@ -11,14 +11,13 @@ import DVR @testable import fakestagram class RestClientTest: XCTestCase { - func testShowPosts() { let session = Session(cassetteName: "posts.successful") let client = Client(session: session, baseUrl: "https://fakestagram-api.herokuapp.com") let restClient = RestClient<[Post]>(client: client, basePath: "/api/v1/posts") let exp = expectation(description: "Successfull index posts") - - restClient.show() { posts in + + restClient.show { posts in exp.fulfill() XCTAssertNotNil(posts) XCTAssertEqual(posts!.count, 25) @@ -32,10 +31,10 @@ class RestClientTest: XCTestCase { func testShowPost() { let session = Session(cassetteName: "show_post.successful") let client = Client(session: session, baseUrl: "https://fakestagram-api.herokuapp.com") - + let restClient = RestClient(client: client, basePath: "/api/v1/posts") let exp = expectation(description: "Successfull index posts") - + restClient.show(id: "228") { post in exp.fulfill() XCTAssertNotNil(post) @@ -45,5 +44,4 @@ class RestClientTest: XCTestCase { waitForExpectations(timeout: 2, handler: nil) } - } From 585b87bbc23b6ddfef51e58f7ade0711b68704c5 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Sat, 12 Oct 2019 14:03:44 -0500 Subject: [PATCH 08/23] Implement views with XIB and programatic views --- fakestagram.xcodeproj/project.pbxproj | 32 +++++ fakestagram/Base.lproj/Main.storyboard | 10 +- fakestagram/Models/Author.swift | 14 +++ fakestagram/Models/Comment.swift | 14 +++ fakestagram/Models/Like.swift | 13 ++ fakestagram/PostViewController.swift | 11 -- fakestagram/View/AuthorView.swift | 62 ++++++++++ fakestagram/View/ShowPostViewController.swift | 48 ++++++++ fakestagram/View/ShowPostViewController.xib | 111 ++++++++++++++++++ 9 files changed, 299 insertions(+), 16 deletions(-) create mode 100644 fakestagram/Models/Author.swift create mode 100644 fakestagram/Models/Comment.swift create mode 100644 fakestagram/Models/Like.swift create mode 100644 fakestagram/View/AuthorView.swift create mode 100644 fakestagram/View/ShowPostViewController.swift create mode 100644 fakestagram/View/ShowPostViewController.xib diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index 53113d8..2ec7aa6 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -21,6 +21,12 @@ E0C93E9923514D8800FD330C /* posts.successful.json in Resources */ = {isa = PBXBuildFile; fileRef = E0C93E9823514D8800FD330C /* posts.successful.json */; }; E0C93E9B23515A0400FD330C /* show_post.successful.json in Resources */ = {isa = PBXBuildFile; fileRef = E0C93E9A23515A0400FD330C /* show_post.successful.json */; }; E0C93E9D23515CEE00FD330C /* CodableSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93E9C23515CEE00FD330C /* CodableSerializer.swift */; }; + E0C93EA123523B7C00FD330C /* ShowPostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93E9F23523B7C00FD330C /* ShowPostViewController.swift */; }; + E0C93EA223523B7C00FD330C /* ShowPostViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = E0C93EA023523B7C00FD330C /* ShowPostViewController.xib */; }; + E0C93EA42352452900FD330C /* AuthorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93EA32352452900FD330C /* AuthorView.swift */; }; + E0C93EA62352454E00FD330C /* Author.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93EA52352454E00FD330C /* Author.swift */; }; + E0C93EA82352455C00FD330C /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93EA72352455C00FD330C /* Comment.swift */; }; + E0C93EAA2352457200FD330C /* Like.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93EA92352457200FD330C /* Like.swift */; }; E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9642348018200DA9D1A /* Credentials.swift */; }; E0E8B9682348036D00DA9D1A /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9672348036D00DA9D1A /* Client.swift */; }; E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96923481D5A00DA9D1A /* StatusCode.swift */; }; @@ -62,6 +68,12 @@ E0C93E9823514D8800FD330C /* posts.successful.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = posts.successful.json; sourceTree = ""; }; E0C93E9A23515A0400FD330C /* show_post.successful.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = show_post.successful.json; sourceTree = ""; }; E0C93E9C23515CEE00FD330C /* CodableSerializer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableSerializer.swift; sourceTree = ""; }; + E0C93E9F23523B7C00FD330C /* ShowPostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShowPostViewController.swift; sourceTree = ""; }; + E0C93EA023523B7C00FD330C /* ShowPostViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ShowPostViewController.xib; sourceTree = ""; }; + E0C93EA32352452900FD330C /* AuthorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthorView.swift; sourceTree = ""; }; + E0C93EA52352454E00FD330C /* Author.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Author.swift; sourceTree = ""; }; + E0C93EA72352455C00FD330C /* Comment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = ""; }; + E0C93EA92352457200FD330C /* Like.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Like.swift; sourceTree = ""; }; E0E8B9642348018200DA9D1A /* Credentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Credentials.swift; sourceTree = ""; }; E0E8B9672348036D00DA9D1A /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; E0E8B96923481D5A00DA9D1A /* StatusCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCode.swift; sourceTree = ""; }; @@ -128,6 +140,7 @@ E084FAD8233A8734009AC50D /* fakestagram */ = { isa = PBXGroup; children = ( + E0C93E9E23523B4700FD330C /* View */, E0E8B972234918ED00DA9D1A /* Models */, E0E8B96F234916AA00DA9D1A /* Network */, E0E8B9662348035800DA9D1A /* DataSource */, @@ -164,6 +177,16 @@ path = casettes; sourceTree = ""; }; + E0C93E9E23523B4700FD330C /* View */ = { + isa = PBXGroup; + children = ( + E0C93E9F23523B7C00FD330C /* ShowPostViewController.swift */, + E0C93EA023523B7C00FD330C /* ShowPostViewController.xib */, + E0C93EA32352452900FD330C /* AuthorView.swift */, + ); + path = View; + sourceTree = ""; + }; E0E8B9662348035800DA9D1A /* DataSource */ = { isa = PBXGroup; children = ( @@ -189,6 +212,9 @@ children = ( E0E8B973234918FF00DA9D1A /* Account.swift */, E0E8B9752349197100DA9D1A /* Post.swift */, + E0C93EA52352454E00FD330C /* Author.swift */, + E0C93EA72352455C00FD330C /* Comment.swift */, + E0C93EA92352457200FD330C /* Like.swift */, ); path = Models; sourceTree = ""; @@ -286,6 +312,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + E0C93EA223523B7C00FD330C /* ShowPostViewController.xib in Resources */, E084FAE6233A8735009AC50D /* LaunchScreen.storyboard in Resources */, E084FAE3233A8735009AC50D /* Assets.xcassets in Resources */, E084FAE1233A8734009AC50D /* Main.storyboard in Resources */, @@ -372,14 +399,19 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + E0C93EA42352452900FD330C /* AuthorView.swift in Sources */, E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */, E0E8B974234918FF00DA9D1A /* Account.swift in Sources */, + E0C93EA123523B7C00FD330C /* ShowPostViewController.swift in Sources */, E038FCED233FC78600E28571 /* PostViewController.swift in Sources */, + E0C93EA82352455C00FD330C /* Comment.swift in Sources */, + E0C93EAA2352457200FD330C /* Like.swift in Sources */, E0C93E9D23515CEE00FD330C /* CodableSerializer.swift in Sources */, E0E8B9762349197100DA9D1A /* Post.swift in Sources */, E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */, E0E8B96E2348203B00DA9D1A /* RequestBuilder.swift in Sources */, E0E8B9682348036D00DA9D1A /* Client.swift in Sources */, + E0C93EA62352454E00FD330C /* Author.swift in Sources */, E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */, E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */, E084FAFC233A8888009AC50D /* PostsTableViewController.swift in Sources */, diff --git a/fakestagram/Base.lproj/Main.storyboard b/fakestagram/Base.lproj/Main.storyboard index 27e1b7e..ab43aeb 100644 --- a/fakestagram/Base.lproj/Main.storyboard +++ b/fakestagram/Base.lproj/Main.storyboard @@ -1,8 +1,8 @@ - + - + @@ -20,7 +20,7 @@ - + diff --git a/fakestagram/Models/Author.swift b/fakestagram/Models/Author.swift new file mode 100644 index 0000000..9ca5efe --- /dev/null +++ b/fakestagram/Models/Author.swift @@ -0,0 +1,14 @@ +// +// Author.swift +// fakestagram +// +// Created by LuisE on 10/12/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +struct Author: Codable { + let name: String +} + diff --git a/fakestagram/Models/Comment.swift b/fakestagram/Models/Comment.swift new file mode 100644 index 0000000..12db31e --- /dev/null +++ b/fakestagram/Models/Comment.swift @@ -0,0 +1,14 @@ +// +// Comment.swift +// fakestagram +// +// Created by LuisE on 10/12/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +struct Comment: Codable { + let content: String + let author: Author? +} diff --git a/fakestagram/Models/Like.swift b/fakestagram/Models/Like.swift new file mode 100644 index 0000000..5b2ba6f --- /dev/null +++ b/fakestagram/Models/Like.swift @@ -0,0 +1,13 @@ +// +// Like.swift +// fakestagram +// +// Created by LuisE on 10/12/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +struct Like: Codable { + let author: Author +} diff --git a/fakestagram/PostViewController.swift b/fakestagram/PostViewController.swift index dc0887e..f18ad1d 100644 --- a/fakestagram/PostViewController.swift +++ b/fakestagram/PostViewController.swift @@ -8,17 +8,6 @@ import UIKit -struct Author: Codable { - let name: String -} -struct Comment: Codable { - let content: String - let author: Author? -} -struct Like: Codable { - let author: Author -} - class PostViewController: UIViewController { var post: Post? { didSet { diff --git a/fakestagram/View/AuthorView.swift b/fakestagram/View/AuthorView.swift new file mode 100644 index 0000000..15ec4be --- /dev/null +++ b/fakestagram/View/AuthorView.swift @@ -0,0 +1,62 @@ +// +// AuthorView.swift +// fakestagram +// +// Created by LuisE on 10/12/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +class AuthorView: UIView { + var author: Author? { + didSet { updateContent() } + } + + private let avatar: UIImageView = { + let iv = UIImageView() + iv.image = UIImage(systemName: "profile.circle.fill") + iv.contentMode = .scaleAspectFill + iv.translatesAutoresizingMaskIntoConstraints = false + return iv + }() + private let nameLbl: UILabel = { + let lbl = UILabel() + lbl.text = "Lorem ipsum" + return lbl + }() + + convenience init() { + self.init(frame: .zero) + } + + override init(frame: CGRect) { + super.init(frame: frame) + setupConstraints() + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupConstraints() + } + + private func setupConstraints() { + addSubview(avatar) + NSLayoutConstraint.activate([ + avatar.topAnchor.constraint(equalTo: self.topAnchor, constant: 3), + avatar.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 3), + avatar.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 3) + ]) + addSubview(nameLbl) + NSLayoutConstraint.activate([ + nameLbl.leadingAnchor.constraint(equalTo: avatar.trailingAnchor, constant: 5), + nameLbl.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 3), + nameLbl.centerYAnchor.constraint(equalTo: self.centerYAnchor) + ]) + } + + func updateContent() { + guard let uauthor = author else { return } + nameLbl.text = uauthor.name + } +} diff --git a/fakestagram/View/ShowPostViewController.swift b/fakestagram/View/ShowPostViewController.swift new file mode 100644 index 0000000..c472c43 --- /dev/null +++ b/fakestagram/View/ShowPostViewController.swift @@ -0,0 +1,48 @@ +// +// PostViewController.swift +// fakestagram +// +// Created by LuisE on 10/12/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +class ShowPostViewController: UIViewController { + @IBOutlet weak var imageView: UIImageView! + @IBOutlet weak var likeCounter: UILabel! + @IBOutlet weak var titleLabel: UILabel! + @IBOutlet weak var likeBttn: UIButton! + @IBOutlet weak var commentBttn: UIButton! + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + } + + @IBAction + func onTapLike(_ sender: Any) { + print("like") + } + + @IBAction + func onTapCreateComment(_ sender: Any) { + print("to comment") + } + + @IBAction + func onTapShowComments(_ sender: Any) { + print("to show comment") + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/fakestagram/View/ShowPostViewController.xib b/fakestagram/View/ShowPostViewController.xib new file mode 100644 index 0000000..9d91849 --- /dev/null +++ b/fakestagram/View/ShowPostViewController.xib @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From acaf37b9832bc7307d8c376cf9195a2cc1966a80 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Fri, 18 Oct 2019 17:09:54 -0500 Subject: [PATCH 09/23] Replace spagetti code with RestClient --- fakestagram/PostsTableViewController.swift | 42 +++++----------------- 1 file changed, 9 insertions(+), 33 deletions(-) diff --git a/fakestagram/PostsTableViewController.swift b/fakestagram/PostsTableViewController.swift index 7be52f3..68043c4 100644 --- a/fakestagram/PostsTableViewController.swift +++ b/fakestagram/PostsTableViewController.swift @@ -10,17 +10,16 @@ import UIKit class PostsTableViewController: UITableViewController { static let cellId = "PostCell" - var posts = [Post]() + var posts: [Post]? { + didSet { self.tableView.reloadData() } + } + let client = RestClient<[Post]>(client: Client.fakestagram, basePath: "/api/v1/posts/") override func viewDidLoad() { super.viewDidLoad() - loadPosts { data in - DispatchQueue.main.async { - self.posts = data - self.tableView.reloadData() - } + client.show { [unowned self] data in + self.posts = data } - // Uncomment the following line to preserve selection between presentations // self.clearsSelectionOnViewWillAppear = false @@ -35,11 +34,12 @@ class PostsTableViewController: UITableViewController { } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return posts.count + return posts?.count ?? 0 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: PostsTableViewController.cellId, for: indexPath) + guard let posts = self.posts else { return cell } posts[indexPath.row].load { img in cell.imageView?.contentMode = .scaleAspectFit cell.imageView?.image = img @@ -94,32 +94,8 @@ class PostsTableViewController: UITableViewController { if segue.identifier == "showPostSegue" { let dest = segue.destination as! PostViewController let idx = self.tableView.indexPathForSelectedRow?.row ?? 0 - dest.post = posts[idx] + dest.post = posts?[idx] } } - func loadPosts(successful: @escaping ([Post]) -> Void) { - let url = URL(string: "https://fakestagram-api.herokuapp.com/api/v1/posts")! - var request = URLRequest(url: url) - request.setValue("application/json", forHTTPHeaderField: "Accept") - request.setValue("application/json", forHTTPHeaderField: "Content-Type") - request.httpMethod = "get" - request.addValue("Bearer f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e", forHTTPHeaderField: "Authorization") - - let task = URLSession.shared.dataTask(with: request) { (data, _, error) in - if error != nil || data == nil { - return - } - let decoder = JSONDecoder() - decoder.keyDecodingStrategy = .convertFromSnakeCase - do { - guard let data = data else { print("Empty response"); return } - let json = try decoder.decode([Post].self, from: data) - successful(json) - } catch let err { - print("Unable to parse successfull response: \(err.localizedDescription)") - } - } - task.resume() - } } From fb29e46a578181ecd308237d44cd7330834c95a5 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Fri, 18 Oct 2019 20:41:48 -0500 Subject: [PATCH 10/23] Replace TableViewController with CollectionView through delegates --- fakestagram.xcodeproj/project.pbxproj | 26 ++- fakestagram/Base.lproj/Main.storyboard | 160 ++++++++++-------- fakestagram/Models/Author.swift | 1 - fakestagram/Models/Post.swift | 1 + fakestagram/PostsTableViewController.swift | 101 ----------- fakestagram/PostsViewController.swift | 59 +++++++ fakestagram/UIDevice+models.swift | 88 ++++++++++ fakestagram/{View => Views}/AuthorView.swift | 26 +-- .../Views/PostCollectionViewCell.swift | 42 +++++ fakestagram/Views/PostCollectionViewCell.xib | 92 ++++++++++ .../ShowPostViewController.swift | 4 +- .../ShowPostViewController.xib | 0 12 files changed, 407 insertions(+), 193 deletions(-) delete mode 100644 fakestagram/PostsTableViewController.swift create mode 100644 fakestagram/PostsViewController.swift create mode 100644 fakestagram/UIDevice+models.swift rename fakestagram/{View => Views}/AuthorView.swift (81%) create mode 100644 fakestagram/Views/PostCollectionViewCell.swift create mode 100644 fakestagram/Views/PostCollectionViewCell.xib rename fakestagram/{View => Views}/ShowPostViewController.swift (99%) rename fakestagram/{View => Views}/ShowPostViewController.xib (100%) diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index 2ec7aa6..f9a6cfc 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -16,7 +16,9 @@ E084FAE3233A8735009AC50D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E084FAE2233A8735009AC50D /* Assets.xcassets */; }; E084FAE6233A8735009AC50D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E084FAE4233A8735009AC50D /* LaunchScreen.storyboard */; }; E084FAF1233A8735009AC50D /* RequestBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAF0233A8735009AC50D /* RequestBuilderTests.swift */; }; - E084FAFC233A8888009AC50D /* PostsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAFB233A8888009AC50D /* PostsTableViewController.swift */; }; + E0A9ED51235A782F00A0527E /* PostsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0A9ED50235A782F00A0527E /* PostsViewController.swift */; }; + E0A9ED54235A7FF300A0527E /* PostCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0A9ED52235A7FF300A0527E /* PostCollectionViewCell.swift */; }; + E0A9ED55235A7FF300A0527E /* PostCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E0A9ED53235A7FF300A0527E /* PostCollectionViewCell.xib */; }; E0C93E942351435100FD330C /* RestClientTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93E932351435100FD330C /* RestClientTest.swift */; }; E0C93E9923514D8800FD330C /* posts.successful.json in Resources */ = {isa = PBXBuildFile; fileRef = E0C93E9823514D8800FD330C /* posts.successful.json */; }; E0C93E9B23515A0400FD330C /* show_post.successful.json in Resources */ = {isa = PBXBuildFile; fileRef = E0C93E9A23515A0400FD330C /* show_post.successful.json */; }; @@ -27,6 +29,7 @@ E0C93EA62352454E00FD330C /* Author.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93EA52352454E00FD330C /* Author.swift */; }; E0C93EA82352455C00FD330C /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93EA72352455C00FD330C /* Comment.swift */; }; E0C93EAA2352457200FD330C /* Like.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93EA92352457200FD330C /* Like.swift */; }; + E0E2545F235A9F3A00C55767 /* UIDevice+models.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E2545E235A9F3A00C55767 /* UIDevice+models.swift */; }; E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9642348018200DA9D1A /* Credentials.swift */; }; E0E8B9682348036D00DA9D1A /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9672348036D00DA9D1A /* Client.swift */; }; E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96923481D5A00DA9D1A /* StatusCode.swift */; }; @@ -63,7 +66,9 @@ E084FAEC233A8735009AC50D /* fakestagramTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = fakestagramTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; E084FAF0233A8735009AC50D /* RequestBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestBuilderTests.swift; sourceTree = ""; }; E084FAF2233A8735009AC50D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - E084FAFB233A8888009AC50D /* PostsTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostsTableViewController.swift; sourceTree = ""; }; + E0A9ED50235A782F00A0527E /* PostsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostsViewController.swift; sourceTree = ""; }; + E0A9ED52235A7FF300A0527E /* PostCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostCollectionViewCell.swift; sourceTree = ""; }; + E0A9ED53235A7FF300A0527E /* PostCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PostCollectionViewCell.xib; sourceTree = ""; }; E0C93E932351435100FD330C /* RestClientTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestClientTest.swift; sourceTree = ""; }; E0C93E9823514D8800FD330C /* posts.successful.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = posts.successful.json; sourceTree = ""; }; E0C93E9A23515A0400FD330C /* show_post.successful.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = show_post.successful.json; sourceTree = ""; }; @@ -74,6 +79,7 @@ E0C93EA52352454E00FD330C /* Author.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Author.swift; sourceTree = ""; }; E0C93EA72352455C00FD330C /* Comment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = ""; }; E0C93EA92352457200FD330C /* Like.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Like.swift; sourceTree = ""; }; + E0E2545E235A9F3A00C55767 /* UIDevice+models.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIDevice+models.swift"; sourceTree = ""; }; E0E8B9642348018200DA9D1A /* Credentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Credentials.swift; sourceTree = ""; }; E0E8B9672348036D00DA9D1A /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; E0E8B96923481D5A00DA9D1A /* StatusCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCode.swift; sourceTree = ""; }; @@ -140,19 +146,20 @@ E084FAD8233A8734009AC50D /* fakestagram */ = { isa = PBXGroup; children = ( - E0C93E9E23523B4700FD330C /* View */, + E0C93E9E23523B4700FD330C /* Views */, E0E8B972234918ED00DA9D1A /* Models */, E0E8B96F234916AA00DA9D1A /* Network */, E0E8B9662348035800DA9D1A /* DataSource */, E084FAD9233A8734009AC50D /* AppDelegate.swift */, E084FADB233A8734009AC50D /* SceneDelegate.swift */, - E084FAFB233A8888009AC50D /* PostsTableViewController.swift */, E084FADF233A8734009AC50D /* Main.storyboard */, E038FCEC233FC78600E28571 /* PostViewController.swift */, + E0A9ED50235A782F00A0527E /* PostsViewController.swift */, E084FAE2233A8735009AC50D /* Assets.xcassets */, E084FAE4233A8735009AC50D /* LaunchScreen.storyboard */, E084FAE7233A8735009AC50D /* Info.plist */, E0E8B9642348018200DA9D1A /* Credentials.swift */, + E0E2545E235A9F3A00C55767 /* UIDevice+models.swift */, ); path = fakestagram; sourceTree = ""; @@ -177,14 +184,16 @@ path = casettes; sourceTree = ""; }; - E0C93E9E23523B4700FD330C /* View */ = { + E0C93E9E23523B4700FD330C /* Views */ = { isa = PBXGroup; children = ( + E0A9ED52235A7FF300A0527E /* PostCollectionViewCell.swift */, + E0A9ED53235A7FF300A0527E /* PostCollectionViewCell.xib */, E0C93E9F23523B7C00FD330C /* ShowPostViewController.swift */, E0C93EA023523B7C00FD330C /* ShowPostViewController.xib */, E0C93EA32352452900FD330C /* AuthorView.swift */, ); - path = View; + path = Views; sourceTree = ""; }; E0E8B9662348035800DA9D1A /* DataSource */ = { @@ -316,6 +325,7 @@ E084FAE6233A8735009AC50D /* LaunchScreen.storyboard in Resources */, E084FAE3233A8735009AC50D /* Assets.xcassets in Resources */, E084FAE1233A8734009AC50D /* Main.storyboard in Resources */, + E0A9ED55235A7FF300A0527E /* PostCollectionViewCell.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -400,6 +410,7 @@ buildActionMask = 2147483647; files = ( E0C93EA42352452900FD330C /* AuthorView.swift in Sources */, + E0E2545F235A9F3A00C55767 /* UIDevice+models.swift in Sources */, E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */, E0E8B974234918FF00DA9D1A /* Account.swift in Sources */, E0C93EA123523B7C00FD330C /* ShowPostViewController.swift in Sources */, @@ -411,10 +422,11 @@ E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */, E0E8B96E2348203B00DA9D1A /* RequestBuilder.swift in Sources */, E0E8B9682348036D00DA9D1A /* Client.swift in Sources */, + E0A9ED51235A782F00A0527E /* PostsViewController.swift in Sources */, E0C93EA62352454E00FD330C /* Author.swift in Sources */, + E0A9ED54235A7FF300A0527E /* PostCollectionViewCell.swift in Sources */, E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */, E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */, - E084FAFC233A8888009AC50D /* PostsTableViewController.swift in Sources */, E0E8B971234916D100DA9D1A /* RestClient.swift in Sources */, E084FADC233A8734009AC50D /* SceneDelegate.swift in Sources */, ); diff --git a/fakestagram/Base.lproj/Main.storyboard b/fakestagram/Base.lproj/Main.storyboard index ab43aeb..728a195 100644 --- a/fakestagram/Base.lproj/Main.storyboard +++ b/fakestagram/Base.lproj/Main.storyboard @@ -1,98 +1,116 @@ - + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + diff --git a/fakestagram/Models/Author.swift b/fakestagram/Models/Author.swift index 9ca5efe..607dad2 100644 --- a/fakestagram/Models/Author.swift +++ b/fakestagram/Models/Author.swift @@ -11,4 +11,3 @@ import Foundation struct Author: Codable { let name: String } - diff --git a/fakestagram/Models/Post.swift b/fakestagram/Models/Post.swift index c7e6397..0db4f04 100644 --- a/fakestagram/Models/Post.swift +++ b/fakestagram/Models/Post.swift @@ -18,6 +18,7 @@ struct Post: Codable { let createdAt: String var liked: Bool let location: String + let author: Author? func likesCountText() -> String { return "\(likesCount) likes" diff --git a/fakestagram/PostsTableViewController.swift b/fakestagram/PostsTableViewController.swift deleted file mode 100644 index 68043c4..0000000 --- a/fakestagram/PostsTableViewController.swift +++ /dev/null @@ -1,101 +0,0 @@ -// -// PostsTableViewController.swift -// fakestagram -// -// Created by LuisE on 9/24/19. -// Copyright © 2019 3zcurdia. All rights reserved. -// - -import UIKit - -class PostsTableViewController: UITableViewController { - static let cellId = "PostCell" - var posts: [Post]? { - didSet { self.tableView.reloadData() } - } - let client = RestClient<[Post]>(client: Client.fakestagram, basePath: "/api/v1/posts/") - - override func viewDidLoad() { - super.viewDidLoad() - client.show { [unowned self] data in - self.posts = data - } - // Uncomment the following line to preserve selection between presentations - // self.clearsSelectionOnViewWillAppear = false - - // Uncomment the following line to display an Edit button in the navigation bar for this view controller. - // self.navigationItem.rightBarButtonItem = self.editButtonItem - } - - // MARK: - Table view data source - - override func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return posts?.count ?? 0 - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: PostsTableViewController.cellId, for: indexPath) - guard let posts = self.posts else { return cell } - posts[indexPath.row].load { img in - cell.imageView?.contentMode = .scaleAspectFit - cell.imageView?.image = img - } - cell.textLabel?.text = posts[indexPath.row].title - cell.detailTextLabel?.text = posts[indexPath.row].location - - return cell - } - - /* - // Override to support conditional editing of the table view. - override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool { - // Return false if you do not want the specified item to be editable. - return true - } - */ - - /* - // Override to support editing the table view. - override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { - if editingStyle == .delete { - // Delete the row from the data source - tableView.deleteRows(at: [indexPath], with: .fade) - } else if editingStyle == .insert { - // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view - } - } - */ - - /* - // Override to support rearranging the table view. - override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) { - - } - */ - - /* - // Override to support conditional rearranging of the table view. - override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool { - // Return false if you do not want the item to be re-orderable. - return true - } - */ - - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. - if segue.identifier == "showPostSegue" { - let dest = segue.destination as! PostViewController - let idx = self.tableView.indexPathForSelectedRow?.row ?? 0 - dest.post = posts?[idx] - } - } - -} diff --git a/fakestagram/PostsViewController.swift b/fakestagram/PostsViewController.swift new file mode 100644 index 0000000..f29f6e4 --- /dev/null +++ b/fakestagram/PostsViewController.swift @@ -0,0 +1,59 @@ +// +// PostsViewController.swift +// fakestagram +// +// Created by LuisE on 10/18/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +class PostsViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { + var posts: [Post]? { + didSet { + self.postsCollection.reloadData() + } + } + let client = RestClient<[Post]>(client: Client.fakestagram, basePath: "/api/v1/posts") + + @IBOutlet weak var postsCollection: UICollectionView! + override func viewDidLoad() { + super.viewDidLoad() + postsCollection.delegate = self + postsCollection.dataSource = self + let nib = UINib(nibName: String(describing: PostCollectionViewCell.self), bundle: nil) + postsCollection.register(nib, forCellWithReuseIdentifier: PostCollectionViewCell.identifier) + client.show { [unowned self] data in + self.posts = data + } + + // Do any additional setup after loading the view. + } + + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + + // MARK: - Collection View Delegates + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return self.posts?.count ?? 0 + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PostCollectionViewCell.identifier, for: indexPath) as! PostCollectionViewCell + guard let posts = self.posts else { return cell } + cell.post = posts[indexPath.row] + return cell + } + + // MARK: - Flow Layout Delegates + func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { + return CGSize(width: self.view.frame.width, height: 650) + } +} diff --git a/fakestagram/UIDevice+models.swift b/fakestagram/UIDevice+models.swift new file mode 100644 index 0000000..529f942 --- /dev/null +++ b/fakestagram/UIDevice+models.swift @@ -0,0 +1,88 @@ +// +// UIDevice+models.swift +// fakestagram +// +// Created by LuisE on 10/18/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +public extension UIDevice { + + static let modelName: String = { + var systemInfo = utsname() + uname(&systemInfo) + let machineMirror = Mirror(reflecting: systemInfo.machine) + let identifier = machineMirror.children.reduce("") { identifier, element in + guard let value = element.value as? Int8, value != 0 else { return identifier } + return identifier + String(UnicodeScalar(UInt8(value))) + } + + func mapToDevice(identifier: String) -> String { // swiftlint:disable:this cyclomatic_complexity + #if os(iOS) + switch identifier { + case "iPod5,1": return "iPod touch (5th generation)" + case "iPod7,1": return "iPod touch (6th generation)" + case "iPod9,1": return "iPod touch (7th generation)" + case "iPhone3,1", "iPhone3,2", "iPhone3,3": return "iPhone 4" + case "iPhone4,1": return "iPhone 4s" + case "iPhone5,1", "iPhone5,2": return "iPhone 5" + case "iPhone5,3", "iPhone5,4": return "iPhone 5c" + case "iPhone6,1", "iPhone6,2": return "iPhone 5s" + case "iPhone7,2": return "iPhone 6" + case "iPhone7,1": return "iPhone 6 Plus" + case "iPhone8,1": return "iPhone 6s" + case "iPhone8,2": return "iPhone 6s Plus" + case "iPhone9,1", "iPhone9,3": return "iPhone 7" + case "iPhone9,2", "iPhone9,4": return "iPhone 7 Plus" + case "iPhone8,4": return "iPhone SE" + case "iPhone10,1", "iPhone10,4": return "iPhone 8" + case "iPhone10,2", "iPhone10,5": return "iPhone 8 Plus" + case "iPhone10,3", "iPhone10,6": return "iPhone X" + case "iPhone11,2": return "iPhone XS" + case "iPhone11,4", "iPhone11,6": return "iPhone XS Max" + case "iPhone11,8": return "iPhone XR" + case "iPhone12,1": return "iPhone 11" + case "iPhone12,3": return "iPhone 11 Pro" + case "iPhone12,5": return "iPhone 11 Pro Max" + case "iPad2,1", "iPad2,2", "iPad2,3", "iPad2,4":return "iPad 2" + case "iPad3,1", "iPad3,2", "iPad3,3": return "iPad (3rd generation)" + case "iPad3,4", "iPad3,5", "iPad3,6": return "iPad (4th generation)" + case "iPad6,11", "iPad6,12": return "iPad (5th generation)" + case "iPad7,5", "iPad7,6": return "iPad (6th generation)" + case "iPad7,11", "iPad7,12": return "iPad (7th generation)" + case "iPad4,1", "iPad4,2", "iPad4,3": return "iPad Air" + case "iPad5,3", "iPad5,4": return "iPad Air 2" + case "iPad11,4", "iPad11,5": return "iPad Air (3rd generation)" + case "iPad2,5", "iPad2,6", "iPad2,7": return "iPad mini" + case "iPad4,4", "iPad4,5", "iPad4,6": return "iPad mini 2" + case "iPad4,7", "iPad4,8", "iPad4,9": return "iPad mini 3" + case "iPad5,1", "iPad5,2": return "iPad mini 4" + case "iPad11,1", "iPad11,2": return "iPad mini (5th generation)" + case "iPad6,3", "iPad6,4": return "iPad Pro (9.7-inch)" + case "iPad6,7", "iPad6,8": return "iPad Pro (12.9-inch)" + case "iPad7,1", "iPad7,2": return "iPad Pro (12.9-inch) (2nd generation)" + case "iPad7,3", "iPad7,4": return "iPad Pro (10.5-inch)" + case "iPad8,1", "iPad8,2", "iPad8,3", "iPad8,4":return "iPad Pro (11-inch)" + case "iPad8,5", "iPad8,6", "iPad8,7", "iPad8,8":return "iPad Pro (12.9-inch) (3rd generation)" + case "AppleTV5,3": return "Apple TV" + case "AppleTV6,2": return "Apple TV 4K" + case "AudioAccessory1,1": return "HomePod" + case "i386", "x86_64": return "Simulator \(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "iOS"))" + default: return identifier + } + #elseif os(tvOS) + switch identifier { + case "AppleTV5,3": return "Apple TV 4" + case "AppleTV6,2": return "Apple TV 4K" + case "i386", "x86_64": return "Simulator \(mapToDevice(identifier: ProcessInfo().environment["SIMULATOR_MODEL_IDENTIFIER"] ?? "tvOS"))" + default: return identifier + } + #endif + } + + return mapToDevice(identifier: identifier) + }() + +} diff --git a/fakestagram/View/AuthorView.swift b/fakestagram/Views/AuthorView.swift similarity index 81% rename from fakestagram/View/AuthorView.swift rename to fakestagram/Views/AuthorView.swift index 15ec4be..288967c 100644 --- a/fakestagram/View/AuthorView.swift +++ b/fakestagram/Views/AuthorView.swift @@ -8,14 +8,15 @@ import UIKit +@IBDesignable class AuthorView: UIView { var author: Author? { didSet { updateContent() } } - + private let avatar: UIImageView = { let iv = UIImageView() - iv.image = UIImage(systemName: "profile.circle.fill") + iv.image = UIImage(systemName: "person.circle.fill") iv.contentMode = .scaleAspectFill iv.translatesAutoresizingMaskIntoConstraints = false return iv @@ -23,38 +24,41 @@ class AuthorView: UIView { private let nameLbl: UILabel = { let lbl = UILabel() lbl.text = "Lorem ipsum" + lbl.font = UIFont.systemFont(ofSize: 18, weight: .bold) + lbl.translatesAutoresizingMaskIntoConstraints = false return lbl }() - + convenience init() { self.init(frame: .zero) } - + override init(frame: CGRect) { super.init(frame: frame) setupConstraints() } - + required init?(coder: NSCoder) { super.init(coder: coder) setupConstraints() } - + private func setupConstraints() { addSubview(avatar) NSLayoutConstraint.activate([ - avatar.topAnchor.constraint(equalTo: self.topAnchor, constant: 3), - avatar.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 3), - avatar.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 3) + avatar.topAnchor.constraint(equalTo: self.topAnchor, constant: 5), + avatar.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 5), + avatar.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -5), + avatar.widthAnchor.constraint(equalToConstant: 90) ]) addSubview(nameLbl) NSLayoutConstraint.activate([ nameLbl.leadingAnchor.constraint(equalTo: avatar.trailingAnchor, constant: 5), - nameLbl.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 3), + nameLbl.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -5), nameLbl.centerYAnchor.constraint(equalTo: self.centerYAnchor) ]) } - + func updateContent() { guard let uauthor = author else { return } nameLbl.text = uauthor.name diff --git a/fakestagram/Views/PostCollectionViewCell.swift b/fakestagram/Views/PostCollectionViewCell.swift new file mode 100644 index 0000000..1d5be7b --- /dev/null +++ b/fakestagram/Views/PostCollectionViewCell.swift @@ -0,0 +1,42 @@ +// +// PostCollectionViewCell.swift +// fakestagram +// +// Created by LuisE on 10/18/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +class PostCollectionViewCell: UICollectionViewCell { + static let identifier: String = "PostCell" + public var post: Post? { + didSet { + updateView() + } + } + @IBOutlet weak var authorView: AuthorView! + @IBOutlet weak var imageView: UIImageView! + @IBOutlet weak var likeCounter: UILabel! + @IBOutlet weak var titleLabel: UILabel! + @IBOutlet weak var likeBttn: UIButton! + @IBOutlet weak var commentBttn: UIButton! + + func reset() { + self.imageView.image = nil + self.likeCounter.text = "" + self.titleLabel.text = "" + } + + func updateView() { + reset() + guard let post = self.post else { return } + self.authorView.author = post.author + self.titleLabel.text = post.title + self.likeCounter.text = post.likesCountText() + post.load { [unowned self] img in + self.imageView.image = img + } + } + +} diff --git a/fakestagram/Views/PostCollectionViewCell.xib b/fakestagram/Views/PostCollectionViewCell.xib new file mode 100644 index 0000000..afff929 --- /dev/null +++ b/fakestagram/Views/PostCollectionViewCell.xib @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/fakestagram/View/ShowPostViewController.swift b/fakestagram/Views/ShowPostViewController.swift similarity index 99% rename from fakestagram/View/ShowPostViewController.swift rename to fakestagram/Views/ShowPostViewController.swift index c472c43..c0afe40 100644 --- a/fakestagram/View/ShowPostViewController.swift +++ b/fakestagram/Views/ShowPostViewController.swift @@ -19,7 +19,7 @@ class ShowPostViewController: UIViewController { // Do any additional setup after loading the view. } - + @IBAction func onTapLike(_ sender: Any) { print("like") @@ -29,7 +29,7 @@ class ShowPostViewController: UIViewController { func onTapCreateComment(_ sender: Any) { print("to comment") } - + @IBAction func onTapShowComments(_ sender: Any) { print("to show comment") diff --git a/fakestagram/View/ShowPostViewController.xib b/fakestagram/Views/ShowPostViewController.xib similarity index 100% rename from fakestagram/View/ShowPostViewController.xib rename to fakestagram/Views/ShowPostViewController.xib From de0cedbde1e56c2d3790382e3d5e2e8791323597 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Sat, 19 Oct 2019 11:38:48 -0500 Subject: [PATCH 11/23] Implement post creation with images using base64 --- fakestagram.xcodeproj/project.pbxproj | 8 ++++ .../spacecat.imageset/Contents.json | 21 ++++++++++ .../spacecat.imageset/spacecat.jpg | Bin 0 -> 285375 bytes fakestagram/Base.lproj/Main.storyboard | 19 ++++++++- fakestagram/CameraViewController.swift | 38 ++++++++++++++++++ fakestagram/Models/Post.swift | 5 +++ fakestagram/UIImage+Base64.swift | 17 ++++++++ 7 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 fakestagram/Assets.xcassets/spacecat.imageset/Contents.json create mode 100644 fakestagram/Assets.xcassets/spacecat.imageset/spacecat.jpg create mode 100644 fakestagram/CameraViewController.swift create mode 100644 fakestagram/UIImage+Base64.swift diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index f9a6cfc..831f0d3 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -30,6 +30,8 @@ E0C93EA82352455C00FD330C /* Comment.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93EA72352455C00FD330C /* Comment.swift */; }; E0C93EAA2352457200FD330C /* Like.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93EA92352457200FD330C /* Like.swift */; }; E0E2545F235A9F3A00C55767 /* UIDevice+models.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E2545E235A9F3A00C55767 /* UIDevice+models.swift */; }; + E0E25463235B675100C55767 /* CameraViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E25462235B675100C55767 /* CameraViewController.swift */; }; + E0E25465235B6C0500C55767 /* UIImage+Base64.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E25464235B6C0500C55767 /* UIImage+Base64.swift */; }; E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9642348018200DA9D1A /* Credentials.swift */; }; E0E8B9682348036D00DA9D1A /* Client.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B9672348036D00DA9D1A /* Client.swift */; }; E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0E8B96923481D5A00DA9D1A /* StatusCode.swift */; }; @@ -80,6 +82,8 @@ E0C93EA72352455C00FD330C /* Comment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Comment.swift; sourceTree = ""; }; E0C93EA92352457200FD330C /* Like.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Like.swift; sourceTree = ""; }; E0E2545E235A9F3A00C55767 /* UIDevice+models.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIDevice+models.swift"; sourceTree = ""; }; + E0E25462235B675100C55767 /* CameraViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraViewController.swift; sourceTree = ""; }; + E0E25464235B6C0500C55767 /* UIImage+Base64.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage+Base64.swift"; sourceTree = ""; }; E0E8B9642348018200DA9D1A /* Credentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Credentials.swift; sourceTree = ""; }; E0E8B9672348036D00DA9D1A /* Client.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Client.swift; sourceTree = ""; }; E0E8B96923481D5A00DA9D1A /* StatusCode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusCode.swift; sourceTree = ""; }; @@ -155,11 +159,13 @@ E084FADF233A8734009AC50D /* Main.storyboard */, E038FCEC233FC78600E28571 /* PostViewController.swift */, E0A9ED50235A782F00A0527E /* PostsViewController.swift */, + E0E25462235B675100C55767 /* CameraViewController.swift */, E084FAE2233A8735009AC50D /* Assets.xcassets */, E084FAE4233A8735009AC50D /* LaunchScreen.storyboard */, E084FAE7233A8735009AC50D /* Info.plist */, E0E8B9642348018200DA9D1A /* Credentials.swift */, E0E2545E235A9F3A00C55767 /* UIDevice+models.swift */, + E0E25464235B6C0500C55767 /* UIImage+Base64.swift */, ); path = fakestagram; sourceTree = ""; @@ -414,10 +420,12 @@ E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */, E0E8B974234918FF00DA9D1A /* Account.swift in Sources */, E0C93EA123523B7C00FD330C /* ShowPostViewController.swift in Sources */, + E0E25463235B675100C55767 /* CameraViewController.swift in Sources */, E038FCED233FC78600E28571 /* PostViewController.swift in Sources */, E0C93EA82352455C00FD330C /* Comment.swift in Sources */, E0C93EAA2352457200FD330C /* Like.swift in Sources */, E0C93E9D23515CEE00FD330C /* CodableSerializer.swift in Sources */, + E0E25465235B6C0500C55767 /* UIImage+Base64.swift in Sources */, E0E8B9762349197100DA9D1A /* Post.swift in Sources */, E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */, E0E8B96E2348203B00DA9D1A /* RequestBuilder.swift in Sources */, diff --git a/fakestagram/Assets.xcassets/spacecat.imageset/Contents.json b/fakestagram/Assets.xcassets/spacecat.imageset/Contents.json new file mode 100644 index 0000000..d1bb6ed --- /dev/null +++ b/fakestagram/Assets.xcassets/spacecat.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "spacecat.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/fakestagram/Assets.xcassets/spacecat.imageset/spacecat.jpg b/fakestagram/Assets.xcassets/spacecat.imageset/spacecat.jpg new file mode 100644 index 0000000000000000000000000000000000000000..32ea7fdde0e6968a48a90678fd48fa031e424b92 GIT binary patch literal 285375 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%0D2?U?D9I{Q; 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

F_9FxN%K> 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

50;TI5`^ul&>o`fE#xe9LLo(-T0A}{S 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
  • 7~ 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 literal 0 HcmV?d00001 diff --git a/fakestagram/Base.lproj/Main.storyboard b/fakestagram/Base.lproj/Main.storyboard index 728a195..be6cc42 100644 --- a/fakestagram/Base.lproj/Main.storyboard +++ b/fakestagram/Base.lproj/Main.storyboard @@ -58,11 +58,27 @@ - + + + + + + + + @@ -110,6 +126,7 @@ + diff --git a/fakestagram/CameraViewController.swift b/fakestagram/CameraViewController.swift new file mode 100644 index 0000000..f6cace4 --- /dev/null +++ b/fakestagram/CameraViewController.swift @@ -0,0 +1,38 @@ +// +// CameraViewController.swift +// fakestagram +// +// Created by LuisE on 10/19/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +class CameraViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view. + } + + let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/posts/") + @IBAction func onTapCreate(_ sender: Any) { + let img = UIImage(named: "spacecat")! + let newPost = CreatePost(title: "Spacecat🙀 - \(UUID().uuidString)", imageData: img.base64()) + client.create(newPost) { post in + print("Successful!") + print(post?.title) + } + + } + /* + // MARK: - Navigation + + // In a storyboard-based application, you will often want to do a little preparation before navigation + override func prepare(for segue: UIStoryboardSegue, sender: Any?) { + // Get the new view controller using segue.destination. + // Pass the selected object to the new view controller. + } + */ + +} diff --git a/fakestagram/Models/Post.swift b/fakestagram/Models/Post.swift index 0db4f04..47c1af0 100644 --- a/fakestagram/Models/Post.swift +++ b/fakestagram/Models/Post.swift @@ -9,6 +9,11 @@ import Foundation import UIKit +struct CreatePost: Codable { + let title: String + let imageData: String? +} + struct Post: Codable { let id: Int? let title: String diff --git a/fakestagram/UIImage+Base64.swift b/fakestagram/UIImage+Base64.swift new file mode 100644 index 0000000..85f08e9 --- /dev/null +++ b/fakestagram/UIImage+Base64.swift @@ -0,0 +1,17 @@ +// +// UIImage+Base64.swift +// fakestagram +// +// Created by LuisE on 10/19/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit + +extension UIImage { + func base64() -> String { + let data = self.jpegData(compressionQuality: 90)! + let encoded = data.base64EncodedString(options: .lineLength64Characters) + return "data:image/jpg;base64,\(encoded)" + } +} From 484cec93407bec9af846f5ebcd7aadb9dbdf9f0e Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Sat, 19 Oct 2019 12:15:52 -0500 Subject: [PATCH 12/23] Organize view controllers and utils in groups --- fakestagram.xcodeproj/project.pbxproj | 28 +++++++++++++++---- fakestagram/{ => Utils}/Credentials.swift | 0 fakestagram/{ => Utils}/UIDevice+models.swift | 0 fakestagram/{ => Utils}/UIImage+Base64.swift | 0 .../CameraViewController.swift | 0 .../PostViewController.swift | 0 .../PostsViewController.swift | 0 7 files changed, 22 insertions(+), 6 deletions(-) rename fakestagram/{ => Utils}/Credentials.swift (100%) rename fakestagram/{ => Utils}/UIDevice+models.swift (100%) rename fakestagram/{ => Utils}/UIImage+Base64.swift (100%) rename fakestagram/{ => ViewControllers}/CameraViewController.swift (100%) rename fakestagram/{ => ViewControllers}/PostViewController.swift (100%) rename fakestagram/{ => ViewControllers}/PostsViewController.swift (100%) diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index 831f0d3..79d5997 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -150,22 +150,18 @@ E084FAD8233A8734009AC50D /* fakestagram */ = { isa = PBXGroup; children = ( + E0E25466235B7BCE00C55767 /* ViewControllers */, E0C93E9E23523B4700FD330C /* Views */, E0E8B972234918ED00DA9D1A /* Models */, E0E8B96F234916AA00DA9D1A /* Network */, E0E8B9662348035800DA9D1A /* DataSource */, + E0E25467235B7BE500C55767 /* Utils */, E084FAD9233A8734009AC50D /* AppDelegate.swift */, E084FADB233A8734009AC50D /* SceneDelegate.swift */, E084FADF233A8734009AC50D /* Main.storyboard */, - E038FCEC233FC78600E28571 /* PostViewController.swift */, - E0A9ED50235A782F00A0527E /* PostsViewController.swift */, - E0E25462235B675100C55767 /* CameraViewController.swift */, E084FAE2233A8735009AC50D /* Assets.xcassets */, E084FAE4233A8735009AC50D /* LaunchScreen.storyboard */, E084FAE7233A8735009AC50D /* Info.plist */, - E0E8B9642348018200DA9D1A /* Credentials.swift */, - E0E2545E235A9F3A00C55767 /* UIDevice+models.swift */, - E0E25464235B6C0500C55767 /* UIImage+Base64.swift */, ); path = fakestagram; sourceTree = ""; @@ -202,6 +198,26 @@ path = Views; sourceTree = ""; }; + E0E25466235B7BCE00C55767 /* ViewControllers */ = { + isa = PBXGroup; + children = ( + E0A9ED50235A782F00A0527E /* PostsViewController.swift */, + E038FCEC233FC78600E28571 /* PostViewController.swift */, + E0E25462235B675100C55767 /* CameraViewController.swift */, + ); + path = ViewControllers; + sourceTree = ""; + }; + E0E25467235B7BE500C55767 /* Utils */ = { + isa = PBXGroup; + children = ( + E0E8B9642348018200DA9D1A /* Credentials.swift */, + E0E2545E235A9F3A00C55767 /* UIDevice+models.swift */, + E0E25464235B6C0500C55767 /* UIImage+Base64.swift */, + ); + path = Utils; + sourceTree = ""; + }; E0E8B9662348035800DA9D1A /* DataSource */ = { isa = PBXGroup; children = ( diff --git a/fakestagram/Credentials.swift b/fakestagram/Utils/Credentials.swift similarity index 100% rename from fakestagram/Credentials.swift rename to fakestagram/Utils/Credentials.swift diff --git a/fakestagram/UIDevice+models.swift b/fakestagram/Utils/UIDevice+models.swift similarity index 100% rename from fakestagram/UIDevice+models.swift rename to fakestagram/Utils/UIDevice+models.swift diff --git a/fakestagram/UIImage+Base64.swift b/fakestagram/Utils/UIImage+Base64.swift similarity index 100% rename from fakestagram/UIImage+Base64.swift rename to fakestagram/Utils/UIImage+Base64.swift diff --git a/fakestagram/CameraViewController.swift b/fakestagram/ViewControllers/CameraViewController.swift similarity index 100% rename from fakestagram/CameraViewController.swift rename to fakestagram/ViewControllers/CameraViewController.swift diff --git a/fakestagram/PostViewController.swift b/fakestagram/ViewControllers/PostViewController.swift similarity index 100% rename from fakestagram/PostViewController.swift rename to fakestagram/ViewControllers/PostViewController.swift diff --git a/fakestagram/PostsViewController.swift b/fakestagram/ViewControllers/PostsViewController.swift similarity index 100% rename from fakestagram/PostsViewController.swift rename to fakestagram/ViewControllers/PostsViewController.swift From 0f14a6b722d5c5fd2d9448f767fe5b24b035232a Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Sat, 19 Oct 2019 13:55:42 -0500 Subject: [PATCH 13/23] Refresh control and create account and store token --- fakestagram/AppDelegate.swift | 11 +++++++++++ fakestagram/Models/Account.swift | 4 ++-- fakestagram/Utils/Credentials.swift | 14 +++++++++++++- fakestagram/Utils/UIDevice+models.swift | 7 +++++++ .../ViewControllers/PostsViewController.swift | 13 +++++++++++++ 5 files changed, 46 insertions(+), 3 deletions(-) diff --git a/fakestagram/AppDelegate.swift b/fakestagram/AppDelegate.swift index a1d6769..ca6561f 100644 --- a/fakestagram/AppDelegate.swift +++ b/fakestagram/AppDelegate.swift @@ -13,6 +13,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. + loadOrCreateAccount() return true } @@ -30,4 +31,14 @@ class AppDelegate: UIResponder, UIApplicationDelegate { // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } + func loadOrCreateAccount() { + if Credentials.apiToken.get() != nil { return } + let account = Account(id: nil, name: "Juan Camaney", deviceNumber: UIDevice.identifier, deviceModel: UIDevice.modelName) + let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/accounts") + client.create(account) { account in + guard let account = account, let idx = account.id else { return } + _ = Credentials.apiToken.set(value: idx) + } + } + } diff --git a/fakestagram/Models/Account.swift b/fakestagram/Models/Account.swift index bb66fde..9f4c69c 100644 --- a/fakestagram/Models/Account.swift +++ b/fakestagram/Models/Account.swift @@ -11,6 +11,6 @@ import Foundation struct Account: Codable { let id: String? let name: String - let deviceNumber: String - let deviceModel: String + let deviceNumber: String? + let deviceModel: String? } diff --git a/fakestagram/Utils/Credentials.swift b/fakestagram/Utils/Credentials.swift index 2e81160..bf6a319 100644 --- a/fakestagram/Utils/Credentials.swift +++ b/fakestagram/Utils/Credentials.swift @@ -14,11 +14,23 @@ enum Credentials { func get() -> String? { switch self { case .apiToken: - return "f41af9b1-5a7e-4f0b-8c88-e44f686b1d2e" + return UserDefaults.standard.string(forKey: "apiToken") } } func set(value: String) -> Bool { + switch self { + case .apiToken: + UserDefaults.standard.set(value, forKey: "apiToken") + } + return true + } + + func destroy() -> Bool { + switch self { + case .apiToken: + UserDefaults.standard.setNilValueForKey("apiToken") + } return true } } diff --git a/fakestagram/Utils/UIDevice+models.swift b/fakestagram/Utils/UIDevice+models.swift index 529f942..4102a1e 100644 --- a/fakestagram/Utils/UIDevice+models.swift +++ b/fakestagram/Utils/UIDevice+models.swift @@ -9,6 +9,13 @@ import UIKit public extension UIDevice { + static let identifier: String = { + if let vendorId = UIDevice.current.identifierForVendor { + return "\(vendorId.hashValue):\(vendorId.uuidString)" + } else { + return ":\(UUID().uuidString)" + } + }() static let modelName: String = { var systemInfo = utsname() diff --git a/fakestagram/ViewControllers/PostsViewController.swift b/fakestagram/ViewControllers/PostsViewController.swift index f29f6e4..5835421 100644 --- a/fakestagram/ViewControllers/PostsViewController.swift +++ b/fakestagram/ViewControllers/PostsViewController.swift @@ -15,6 +15,7 @@ class PostsViewController: UIViewController, UICollectionViewDelegate, UICollect } } let client = RestClient<[Post]>(client: Client.fakestagram, basePath: "/api/v1/posts") + let refreshControl = UIRefreshControl() @IBOutlet weak var postsCollection: UICollectionView! override func viewDidLoad() { @@ -23,6 +24,10 @@ class PostsViewController: UIViewController, UICollectionViewDelegate, UICollect postsCollection.dataSource = self let nib = UINib(nibName: String(describing: PostCollectionViewCell.self), bundle: nil) postsCollection.register(nib, forCellWithReuseIdentifier: PostCollectionViewCell.identifier) + postsCollection.addSubview(refreshControl) + + refreshControl.addTarget(self, action: #selector(self.reloadData), for: UIControl.Event.valueChanged) + client.show { [unowned self] data in self.posts = data } @@ -40,6 +45,14 @@ class PostsViewController: UIViewController, UICollectionViewDelegate, UICollect } */ + @objc + func reloadData() { + client.show { [unowned self] data in + self.posts = data + self.refreshControl.endRefreshing() + } + } + // MARK: - Collection View Delegates func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return self.posts?.count ?? 0 From 13e9ae09ac17b90ec3bdc06c7d32881553d9ff13 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Fri, 8 Nov 2019 18:23:12 -0600 Subject: [PATCH 14/23] create post service --- fakestagram.xcodeproj/project.pbxproj | 12 +++++ fakestagram/AppDelegate.swift | 1 - fakestagram/Info.plist | 2 + fakestagram/Models/Post.swift | 5 -- fakestagram/Services/CreatePostService.swift | 45 +++++++++++++++++ .../CameraViewController.swift | 48 ++++++++++++++++--- 6 files changed, 100 insertions(+), 13 deletions(-) create mode 100644 fakestagram/Services/CreatePostService.swift diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index 79d5997..a6f2104 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 05D8E963168944918FFCC7FF /* Pods_fakestagram.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FFAA8B9133CEE464C903FDF5 /* Pods_fakestagram.framework */; }; D3D164DC7444072103DE027D /* Pods_fakestagramTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E669E31C92D68155914FC99D /* Pods_fakestagramTests.framework */; }; E038FCED233FC78600E28571 /* PostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E038FCEC233FC78600E28571 /* PostViewController.swift */; }; + E045844923762E10006574FA /* CreatePostService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045844823762E10006574FA /* CreatePostService.swift */; }; E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAD9233A8734009AC50D /* AppDelegate.swift */; }; E084FADC233A8734009AC50D /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FADB233A8734009AC50D /* SceneDelegate.swift */; }; E084FAE1233A8734009AC50D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E084FADF233A8734009AC50D /* Main.storyboard */; }; @@ -58,6 +59,7 @@ CCC6C6EA9D17CA169951A745 /* Pods-fakestagram.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagram.release.xcconfig"; path = "Target Support Files/Pods-fakestagram/Pods-fakestagram.release.xcconfig"; sourceTree = ""; }; DB68F7FEC717545506064663 /* Pods-fakestagram.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagram.debug.xcconfig"; path = "Target Support Files/Pods-fakestagram/Pods-fakestagram.debug.xcconfig"; sourceTree = ""; }; E038FCEC233FC78600E28571 /* PostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewController.swift; sourceTree = ""; }; + E045844823762E10006574FA /* CreatePostService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatePostService.swift; sourceTree = ""; }; E084FAD6233A8734009AC50D /* fakestagram.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = fakestagram.app; sourceTree = BUILT_PRODUCTS_DIR; }; E084FAD9233A8734009AC50D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E084FADB233A8734009AC50D /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -127,6 +129,14 @@ path = Pods; sourceTree = ""; }; + E045844723762DF8006574FA /* Services */ = { + isa = PBXGroup; + children = ( + E045844823762E10006574FA /* CreatePostService.swift */, + ); + path = Services; + sourceTree = ""; + }; E084FACD233A8734009AC50D = { isa = PBXGroup; children = ( @@ -150,6 +160,7 @@ E084FAD8233A8734009AC50D /* fakestagram */ = { isa = PBXGroup; children = ( + E045844723762DF8006574FA /* Services */, E0E25466235B7BCE00C55767 /* ViewControllers */, E0C93E9E23523B4700FD330C /* Views */, E0E8B972234918ED00DA9D1A /* Models */, @@ -447,6 +458,7 @@ E0E8B96E2348203B00DA9D1A /* RequestBuilder.swift in Sources */, E0E8B9682348036D00DA9D1A /* Client.swift in Sources */, E0A9ED51235A782F00A0527E /* PostsViewController.swift in Sources */, + E045844923762E10006574FA /* CreatePostService.swift in Sources */, E0C93EA62352454E00FD330C /* Author.swift in Sources */, E0A9ED54235A7FF300A0527E /* PostCollectionViewCell.swift in Sources */, E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */, diff --git a/fakestagram/AppDelegate.swift b/fakestagram/AppDelegate.swift index ca6561f..4fb4bbf 100644 --- a/fakestagram/AppDelegate.swift +++ b/fakestagram/AppDelegate.swift @@ -40,5 +40,4 @@ class AppDelegate: UIResponder, UIApplicationDelegate { _ = Credentials.apiToken.set(value: idx) } } - } diff --git a/fakestagram/Info.plist b/fakestagram/Info.plist index 2a3483c..75aef61 100644 --- a/fakestagram/Info.plist +++ b/fakestagram/Info.plist @@ -2,6 +2,8 @@ + NSLocationWhenInUseUsageDescription + Geololcalize your moments CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable diff --git a/fakestagram/Models/Post.swift b/fakestagram/Models/Post.swift index 47c1af0..0db4f04 100644 --- a/fakestagram/Models/Post.swift +++ b/fakestagram/Models/Post.swift @@ -9,11 +9,6 @@ import Foundation import UIKit -struct CreatePost: Codable { - let title: String - let imageData: String? -} - struct Post: Codable { let id: Int? let title: String diff --git a/fakestagram/Services/CreatePostService.swift b/fakestagram/Services/CreatePostService.swift new file mode 100644 index 0000000..b94a7ce --- /dev/null +++ b/fakestagram/Services/CreatePostService.swift @@ -0,0 +1,45 @@ +// +// CreatePostService.swift +// fakestagram +// +// Created by LuisE on 11/8/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation +import UIKit +import CoreLocation + +struct CreatePost: Codable { + let id: Int? + let title: String + let imageData: String? + let latitude: Double? + let longitude: Double? +} + +//protocol Geolocable { +// func update(coordinate: CLLocationCoordinate2D?) +//} + +class CreatePostService { + private let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/posts/") + private var currentLocation: CLLocationCoordinate2D? + + func call(image img: UIImage, title: String, success: @escaping (Int?) -> Void) { + let newPost = CreatePost( + id: nil, + title: title, + imageData: img.base64(), + latitude: currentLocation?.latitude, + longitude: currentLocation?.longitude + ) + client.create(newPost) { post in + success(post?.id) + } + } + + func update(coordinate: CLLocationCoordinate2D?) { + currentLocation = coordinate + } +} diff --git a/fakestagram/ViewControllers/CameraViewController.swift b/fakestagram/ViewControllers/CameraViewController.swift index f6cace4..6ed067d 100644 --- a/fakestagram/ViewControllers/CameraViewController.swift +++ b/fakestagram/ViewControllers/CameraViewController.swift @@ -7,24 +7,38 @@ // import UIKit +import CoreLocation -class CameraViewController: UIViewController { +class CameraViewController: UIViewController, CLLocationManagerDelegate { + let locationManager = CLLocationManager() + let service = CreatePostService() override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view. + enableBasicLocationServices() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + locationManager.startUpdatingLocation() + } + + override func viewWillDisappear(_ animated: Bool) { + locationManager.stopUpdatingLocation() + super.viewWillDisappear(animated) } - let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/posts/") @IBAction func onTapCreate(_ sender: Any) { let img = UIImage(named: "spacecat")! - let newPost = CreatePost(title: "Spacecat🙀 - \(UUID().uuidString)", imageData: img.base64()) - client.create(newPost) { post in + service.call( + image: img, + title: "Spacecat🙀 - \(UUID().uuidString)" + ) { postId in print("Successful!") - print(post?.title) + print(postId ?? -1) } - } + /* // MARK: - Navigation @@ -35,4 +49,24 @@ class CameraViewController: UIViewController { } */ + func enableBasicLocationServices() { + locationManager.delegate = self + switch CLLocationManager.authorizationStatus() { + case .notDetermined: + locationManager.requestWhenInUseAuthorization() + case .restricted, .denied: + print("Disable location features") + case .authorizedWhenInUse, .authorizedAlways: + print("Enable location features") + @unknown default: + fatalError() + } + } + + func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { + guard let location = locations.last else { return } + print(location) + service.update(coordinate: location.coordinate) + } + } From acd4af8e1ba1c722f930c99b5c6d196ea03ea1a7 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Fri, 8 Nov 2019 21:06:09 -0600 Subject: [PATCH 15/23] Implement storage layer --- fakestagram.xcodeproj/project.pbxproj | 16 +++++++ fakestagram/DataSource/CacheImage.swift | 24 ++++++++++ fakestagram/DataSource/DataContainer.swift | 52 ++++++++++++++++++++++ fakestagram/DataSource/ImageStore.swift | 42 +++++++++++++++++ fakestagram/DataSource/StorageType.swift | 47 +++++++++++++++++++ 5 files changed, 181 insertions(+) create mode 100644 fakestagram/DataSource/CacheImage.swift create mode 100644 fakestagram/DataSource/DataContainer.swift create mode 100644 fakestagram/DataSource/ImageStore.swift create mode 100644 fakestagram/DataSource/StorageType.swift diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index a6f2104..865c1ad 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -11,6 +11,10 @@ D3D164DC7444072103DE027D /* Pods_fakestagramTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E669E31C92D68155914FC99D /* Pods_fakestagramTests.framework */; }; E038FCED233FC78600E28571 /* PostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E038FCEC233FC78600E28571 /* PostViewController.swift */; }; E045844923762E10006574FA /* CreatePostService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045844823762E10006574FA /* CreatePostService.swift */; }; + E045844B237652DD006574FA /* StorageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045844A237652DD006574FA /* StorageType.swift */; }; + E045844D23765677006574FA /* DataContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045844C23765677006574FA /* DataContainer.swift */; }; + E045844F23765B0F006574FA /* ImageStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045844E23765B0F006574FA /* ImageStore.swift */; }; + E045845123766203006574FA /* CacheImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045845023766203006574FA /* CacheImage.swift */; }; E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAD9233A8734009AC50D /* AppDelegate.swift */; }; E084FADC233A8734009AC50D /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FADB233A8734009AC50D /* SceneDelegate.swift */; }; E084FAE1233A8734009AC50D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E084FADF233A8734009AC50D /* Main.storyboard */; }; @@ -60,6 +64,10 @@ DB68F7FEC717545506064663 /* Pods-fakestagram.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagram.debug.xcconfig"; path = "Target Support Files/Pods-fakestagram/Pods-fakestagram.debug.xcconfig"; sourceTree = ""; }; E038FCEC233FC78600E28571 /* PostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewController.swift; sourceTree = ""; }; E045844823762E10006574FA /* CreatePostService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatePostService.swift; sourceTree = ""; }; + E045844A237652DD006574FA /* StorageType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageType.swift; sourceTree = ""; }; + E045844C23765677006574FA /* DataContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataContainer.swift; sourceTree = ""; }; + E045844E23765B0F006574FA /* ImageStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageStore.swift; sourceTree = ""; }; + E045845023766203006574FA /* CacheImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheImage.swift; sourceTree = ""; }; E084FAD6233A8734009AC50D /* fakestagram.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = fakestagram.app; sourceTree = BUILT_PRODUCTS_DIR; }; E084FAD9233A8734009AC50D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E084FADB233A8734009AC50D /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -234,6 +242,10 @@ children = ( E0E8B970234916D100DA9D1A /* RestClient.swift */, E0C93E9C23515CEE00FD330C /* CodableSerializer.swift */, + E045845023766203006574FA /* CacheImage.swift */, + E045844E23765B0F006574FA /* ImageStore.swift */, + E045844C23765677006574FA /* DataContainer.swift */, + E045844A237652DD006574FA /* StorageType.swift */, ); path = DataSource; sourceTree = ""; @@ -445,6 +457,8 @@ E0C93EA42352452900FD330C /* AuthorView.swift in Sources */, E0E2545F235A9F3A00C55767 /* UIDevice+models.swift in Sources */, E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */, + E045845123766203006574FA /* CacheImage.swift in Sources */, + E045844B237652DD006574FA /* StorageType.swift in Sources */, E0E8B974234918FF00DA9D1A /* Account.swift in Sources */, E0C93EA123523B7C00FD330C /* ShowPostViewController.swift in Sources */, E0E25463235B675100C55767 /* CameraViewController.swift in Sources */, @@ -462,6 +476,8 @@ E0C93EA62352454E00FD330C /* Author.swift in Sources */, E0A9ED54235A7FF300A0527E /* PostCollectionViewCell.swift in Sources */, E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */, + E045844F23765B0F006574FA /* ImageStore.swift in Sources */, + E045844D23765677006574FA /* DataContainer.swift in Sources */, E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */, E0E8B971234916D100DA9D1A /* RestClient.swift in Sources */, E084FADC233A8734009AC50D /* SceneDelegate.swift in Sources */, diff --git a/fakestagram/DataSource/CacheImage.swift b/fakestagram/DataSource/CacheImage.swift new file mode 100644 index 0000000..d238ffb --- /dev/null +++ b/fakestagram/DataSource/CacheImage.swift @@ -0,0 +1,24 @@ +// +// CacheImage.swift +// fakestagram +// +// Created by LuisE on 11/8/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation +import UIKit + +class CacheImage { + static let shared = CacheImage() + private var memCache = NSCache() + + func read(key: String) -> UIImage? { + return memCache.object(forKey: key as NSString) + } + + func write(key: String, value: UIImage?) { + guard let value = value else { return } + memCache.setObject(value, forKey: key as NSString) + } +} diff --git a/fakestagram/DataSource/DataContainer.swift b/fakestagram/DataSource/DataContainer.swift new file mode 100644 index 0000000..9bd47af --- /dev/null +++ b/fakestagram/DataSource/DataContainer.swift @@ -0,0 +1,52 @@ +// +// DataContainer.swift +// fakestagram +// +// Created by LuisE on 11/8/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +// Usage +// DataContainer.cache.write("file.json",data: parsedData) +// DataContainer.cache.read("file.png") +// DataContainer.permanent.write("file.json",data: parsedData) +// DataContainer.permanent.read("file.png") +enum DataContainer { + case cache + case permanent + + var baseUrl: URL { + switch self { + case .cache: + StorageType.cache.ensureExists() + return StorageType.cache.url + case .permanent: + StorageType.permanent.ensureExists() + return StorageType.permanent.url + } + } + + func read(_ filename: String) -> Data? { + let url = urlFor(filename: filename) + return try? Data(contentsOf: url) + } + + func write(_ filename: String, data: Data) -> Bool { + do { + try data.write(to: urlFor(filename: filename)) + return true + } catch let err { + debugPrint("Error: \(err.localizedDescription)") + return false + } + } + + func urlFor(filename: String) -> URL { + var url = baseUrl + url.appendPathComponent(filename) + return url + } + +} diff --git a/fakestagram/DataSource/ImageStore.swift b/fakestagram/DataSource/ImageStore.swift new file mode 100644 index 0000000..00d5486 --- /dev/null +++ b/fakestagram/DataSource/ImageStore.swift @@ -0,0 +1,42 @@ +// +// ImageStore.swift +// fakestagram +// +// Created by LuisE on 11/8/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation +import UIKit + +// Usage +// ImagaStore.permanent.write("filename.jpg", image: img) +// ImagaStore.cache.read("filename.jpg") + +enum ImageStore { + case cache + case permanent + + var container: DataContainer { + switch self { + case .cache: + return DataContainer.cache + case .permanent: + return DataContainer.permanent + } + } + + func read(_ filename: String) -> UIImage? { + if let img = CacheImage.shared.read(key: filename) { + return img + } + guard let data = container.read(filename) else { return nil } + return UIImage(data: data) + } + + func write(_ filename: String, image: UIImage) -> Bool { + CacheImage.shared.write(key: filename, value: image) + guard let data = image.jpegData(compressionQuality: 0.9) else { return false } + return container.write(filename, data: data) + } +} diff --git a/fakestagram/DataSource/StorageType.swift b/fakestagram/DataSource/StorageType.swift new file mode 100644 index 0000000..6124523 --- /dev/null +++ b/fakestagram/DataSource/StorageType.swift @@ -0,0 +1,47 @@ +// +// StorageType.swift +// fakestagram +// +// Created by LuisE on 11/8/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +enum StorageType { + case cache + case permanent + + var searchPathDirectory: FileManager.SearchPathDirectory { + switch self { + case .cache: + return .cachesDirectory + case .permanent: + return .documentDirectory + } + } + + var url: URL { + var url = FileManager.default.urls(for: searchPathDirectory, in: .userDomainMask).first! + let applicationPath = "mx.unam.ioslab.fakestagram.storage" + url.appendPathComponent(applicationPath) + return url + } + + var path: String { + return url.path + } + + func clear() { + try? FileManager.default.removeItem(at: url) + } + + func ensureExists() { + var isDir: ObjCBool = false + if FileManager.default.fileExists(atPath: path, isDirectory: &isDir) { + if isDir.boolValue { return } + try? FileManager.default.removeItem(at: url) + } + try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: false, attributes: nil) + } +} From eaa20bad3e9c1a08e8b8b7e678998fe1da8d9189 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Sat, 9 Nov 2019 13:38:04 -0600 Subject: [PATCH 16/23] Implement cache on images through checksum and image store --- fakestagram.xcodeproj/project.pbxproj | 24 +++++++++++ ...4B2163FF-53B3-4A2D-B0E0-0AF6257FC48D.plist | 22 ++++++++++ .../Info.plist | 40 +++++++++++++++++++ fakestagram/AppDelegate.swift | 2 + fakestagram/CheckSum.h | 18 +++++++++ fakestagram/CheckSum.m | 31 ++++++++++++++ fakestagram/DataSource/DataContainer.swift | 6 +-- fakestagram/DataSource/ImageStore.swift | 14 ++++++- fakestagram/DataSource/StorageType.swift | 2 +- fakestagram/Models/Post.swift | 8 ++++ fakestagram/Services/IndexService.swift | 17 ++++++++ .../ViewControllers/PostsViewController.swift | 7 ++-- fakestagram/fakestagram-Bridging-Header.h | 5 +++ fakestagramTests/CheckSumTest.swift | 26 ++++++++++++ 14 files changed, 212 insertions(+), 10 deletions(-) create mode 100644 fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/4B2163FF-53B3-4A2D-B0E0-0AF6257FC48D.plist create mode 100644 fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/Info.plist create mode 100644 fakestagram/CheckSum.h create mode 100644 fakestagram/CheckSum.m create mode 100644 fakestagram/Services/IndexService.swift create mode 100644 fakestagram/fakestagram-Bridging-Header.h create mode 100644 fakestagramTests/CheckSumTest.swift diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index 865c1ad..211e87f 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -15,6 +15,9 @@ E045844D23765677006574FA /* DataContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045844C23765677006574FA /* DataContainer.swift */; }; E045844F23765B0F006574FA /* ImageStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045844E23765B0F006574FA /* ImageStore.swift */; }; E045845123766203006574FA /* CacheImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045845023766203006574FA /* CacheImage.swift */; }; + E0458454237721F5006574FA /* CheckSum.m in Sources */ = {isa = PBXBuildFile; fileRef = E0458453237721F5006574FA /* CheckSum.m */; }; + E0458457237725B9006574FA /* IndexService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0458456237725B9006574FA /* IndexService.swift */; }; + E0458459237727D8006574FA /* CheckSumTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0458458237727D8006574FA /* CheckSumTest.swift */; }; E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FAD9233A8734009AC50D /* AppDelegate.swift */; }; E084FADC233A8734009AC50D /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E084FADB233A8734009AC50D /* SceneDelegate.swift */; }; E084FAE1233A8734009AC50D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E084FADF233A8734009AC50D /* Main.storyboard */; }; @@ -68,6 +71,11 @@ E045844C23765677006574FA /* DataContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataContainer.swift; sourceTree = ""; }; E045844E23765B0F006574FA /* ImageStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageStore.swift; sourceTree = ""; }; E045845023766203006574FA /* CacheImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CacheImage.swift; sourceTree = ""; }; + E0458452237721F5006574FA /* fakestagram-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "fakestagram-Bridging-Header.h"; sourceTree = ""; }; + E0458453237721F5006574FA /* CheckSum.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CheckSum.m; sourceTree = ""; }; + E045845523772360006574FA /* CheckSum.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CheckSum.h; sourceTree = ""; }; + E0458456237725B9006574FA /* IndexService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndexService.swift; sourceTree = ""; }; + E0458458237727D8006574FA /* CheckSumTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckSumTest.swift; sourceTree = ""; }; E084FAD6233A8734009AC50D /* fakestagram.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = fakestagram.app; sourceTree = BUILT_PRODUCTS_DIR; }; E084FAD9233A8734009AC50D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; E084FADB233A8734009AC50D /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; @@ -141,6 +149,7 @@ isa = PBXGroup; children = ( E045844823762E10006574FA /* CreatePostService.swift */, + E0458456237725B9006574FA /* IndexService.swift */, ); path = Services; sourceTree = ""; @@ -181,6 +190,9 @@ E084FAE2233A8735009AC50D /* Assets.xcassets */, E084FAE4233A8735009AC50D /* LaunchScreen.storyboard */, E084FAE7233A8735009AC50D /* Info.plist */, + E0458453237721F5006574FA /* CheckSum.m */, + E045845523772360006574FA /* CheckSum.h */, + E0458452237721F5006574FA /* fakestagram-Bridging-Header.h */, ); path = fakestagram; sourceTree = ""; @@ -191,6 +203,7 @@ E0C93E952351472A00FD330C /* casettes */, E084FAF0233A8735009AC50D /* RequestBuilderTests.swift */, E0C93E932351435100FD330C /* RestClientTest.swift */, + E0458458237727D8006574FA /* CheckSumTest.swift */, E084FAF2233A8735009AC50D /* Info.plist */, ); path = fakestagramTests; @@ -335,6 +348,7 @@ TargetAttributes = { E084FAD5233A8734009AC50D = { CreatedOnToolsVersion = 11.0; + LastSwiftMigration = 1120; }; E084FAEB233A8735009AC50D = { CreatedOnToolsVersion = 11.0; @@ -462,10 +476,12 @@ E0E8B974234918FF00DA9D1A /* Account.swift in Sources */, E0C93EA123523B7C00FD330C /* ShowPostViewController.swift in Sources */, E0E25463235B675100C55767 /* CameraViewController.swift in Sources */, + E0458457237725B9006574FA /* IndexService.swift in Sources */, E038FCED233FC78600E28571 /* PostViewController.swift in Sources */, E0C93EA82352455C00FD330C /* Comment.swift in Sources */, E0C93EAA2352457200FD330C /* Like.swift in Sources */, E0C93E9D23515CEE00FD330C /* CodableSerializer.swift in Sources */, + E0458454237721F5006574FA /* CheckSum.m in Sources */, E0E25465235B6C0500C55767 /* UIImage+Base64.swift in Sources */, E0E8B9762349197100DA9D1A /* Post.swift in Sources */, E084FADA233A8734009AC50D /* AppDelegate.swift in Sources */, @@ -490,6 +506,7 @@ files = ( E0C93E942351435100FD330C /* RestClientTest.swift in Sources */, E084FAF1233A8735009AC50D /* RequestBuilderTests.swift in Sources */, + E0458459237727D8006574FA /* CheckSumTest.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -579,6 +596,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; @@ -632,6 +650,7 @@ MTL_FAST_MATH = YES; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OBJC_BRIDGING_HEADER = ""; SWIFT_OPTIMIZATION_LEVEL = "-O"; VALIDATE_PRODUCT = YES; }; @@ -642,6 +661,7 @@ baseConfigurationReference = DB68F7FEC717545506064663 /* Pods-fakestagram.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = D3XL2U7DQC; INFOPLIST_FILE = fakestagram/Info.plist; @@ -651,6 +671,8 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.3zcurdia.fakestagram; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "fakestagram/fakestagram-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -661,6 +683,7 @@ baseConfigurationReference = CCC6C6EA9D17CA169951A745 /* Pods-fakestagram.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = D3XL2U7DQC; INFOPLIST_FILE = fakestagram/Info.plist; @@ -670,6 +693,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = com.3zcurdia.fakestagram; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "fakestagram/fakestagram-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; diff --git a/fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/4B2163FF-53B3-4A2D-B0E0-0AF6257FC48D.plist b/fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/4B2163FF-53B3-4A2D-B0E0-0AF6257FC48D.plist new file mode 100644 index 0000000..0648835 --- /dev/null +++ b/fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/4B2163FF-53B3-4A2D-B0E0-0AF6257FC48D.plist @@ -0,0 +1,22 @@ + + + + + classNames + + CheckSumTest + + testPerformanceExample() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 6.55e-05 + baselineIntegrationDisplayName + Local Baseline + + + + + + diff --git a/fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/Info.plist b/fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/Info.plist new file mode 100644 index 0000000..fc16441 --- /dev/null +++ b/fakestagram.xcodeproj/xcshareddata/xcbaselines/E084FAEB233A8735009AC50D.xcbaseline/Info.plist @@ -0,0 +1,40 @@ + + + + + runDestinationsByUUID + + 4B2163FF-53B3-4A2D-B0E0-0AF6257FC48D + + localComputer + + busSpeedInMHz + 100 + cpuCount + 1 + cpuKind + Intel Core i7 + cpuSpeedInMHz + 2900 + logicalCPUCoresPerPackage + 8 + modelCode + MacBookPro14,3 + physicalCPUCoresPerPackage + 4 + platformIdentifier + com.apple.platform.macosx + + targetArchitecture + x86_64 + targetDevice + + modelCode + iPhone12,1 + platformIdentifier + com.apple.platform.iphonesimulator + + + + + diff --git a/fakestagram/AppDelegate.swift b/fakestagram/AppDelegate.swift index 4fb4bbf..2660552 100644 --- a/fakestagram/AppDelegate.swift +++ b/fakestagram/AppDelegate.swift @@ -13,6 +13,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. + StorageType.permanent.ensureExists() + StorageType.cache.ensureExists() loadOrCreateAccount() return true } diff --git a/fakestagram/CheckSum.h b/fakestagram/CheckSum.h new file mode 100644 index 0000000..168df88 --- /dev/null +++ b/fakestagram/CheckSum.h @@ -0,0 +1,18 @@ +// +// CheckSum.h +// fakestagram +// +// Created by LuisE on 11/9/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +#ifndef CheckSum_h +#define CheckSum_h +#import +#import + +@interface CheckSum : NSObject ++(NSString *) sha256String: (NSString *)input; +@end + +#endif /* Checksum_h */ diff --git a/fakestagram/CheckSum.m b/fakestagram/CheckSum.m new file mode 100644 index 0000000..181a11f --- /dev/null +++ b/fakestagram/CheckSum.m @@ -0,0 +1,31 @@ +// +// CheckSum.m +// fakestagram +// +// Created by LuisE on 11/9/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// +#import "CheckSum.h" + +@implementation CheckSum +- (instancetype)init { + if (self = [super init]) { + } + return self; +} + ++(NSString *) sha256String: (NSString *)input{ + const char* str = [input UTF8String]; + unsigned char result[CC_SHA256_DIGEST_LENGTH]; + CC_SHA256(str, strlen(str), result); + + NSMutableString *ret = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH*2]; + for(int i = 0; i Data? { - let url = urlFor(filename: filename) - return try? Data(contentsOf: url) + return try? Data(contentsOf: urlFor(filename: filename)) } func write(_ filename: String, data: Data) -> Bool { diff --git a/fakestagram/DataSource/ImageStore.swift b/fakestagram/DataSource/ImageStore.swift index 00d5486..b9994f5 100644 --- a/fakestagram/DataSource/ImageStore.swift +++ b/fakestagram/DataSource/ImageStore.swift @@ -28,15 +28,25 @@ enum ImageStore { func read(_ filename: String) -> UIImage? { if let img = CacheImage.shared.read(key: filename) { + print(" - Reading from memory") return img } + print(" - Reading from disk") guard let data = container.read(filename) else { return nil } - return UIImage(data: data) + let image = UIImage(data: data) + + print(" * Writting into memory") + CacheImage.shared.write(key: filename, value: image) + return image } func write(_ filename: String, image: UIImage) -> Bool { - CacheImage.shared.write(key: filename, value: image) guard let data = image.jpegData(compressionQuality: 0.9) else { return false } + + print(" - Writting into memory") + CacheImage.shared.write(key: filename, value: image) + + print(" - Writting into disk") return container.write(filename, data: data) } } diff --git a/fakestagram/DataSource/StorageType.swift b/fakestagram/DataSource/StorageType.swift index 6124523..e337d51 100644 --- a/fakestagram/DataSource/StorageType.swift +++ b/fakestagram/DataSource/StorageType.swift @@ -40,7 +40,7 @@ enum StorageType { var isDir: ObjCBool = false if FileManager.default.fileExists(atPath: path, isDirectory: &isDir) { if isDir.boolValue { return } - try? FileManager.default.removeItem(at: url) + clear() } try? FileManager.default.createDirectory(at: url, withIntermediateDirectories: false, attributes: nil) } diff --git a/fakestagram/Models/Post.swift b/fakestagram/Models/Post.swift index 0db4f04..0b4995e 100644 --- a/fakestagram/Models/Post.swift +++ b/fakestagram/Models/Post.swift @@ -30,8 +30,16 @@ struct Post: Codable { func load(_ image: @escaping (UIImage) -> Void) { guard let urlString = imageUrl, let url = URL(string: urlString) else { return } + let filename = CheckSum.sha256String(urlString)! + if let img = ImageStore.cache.read(filename) { + print("Reading cache") + image(img) + return + } DispatchQueue.global(qos: .background).async { if let data = try? Data(contentsOf: url), let img = UIImage(data: data) { + print("Loading from the internet") + _ = ImageStore.cache.write(filename, image: img) DispatchQueue.main.async { image(img) } } } diff --git a/fakestagram/Services/IndexService.swift b/fakestagram/Services/IndexService.swift new file mode 100644 index 0000000..5c6cb55 --- /dev/null +++ b/fakestagram/Services/IndexService.swift @@ -0,0 +1,17 @@ +// +// IndexService.swift +// fakestagram +// +// Created by LuisE on 11/9/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +class IndexService { + let client = RestClient<[Post]>(client: Client.fakestagram, basePath: "/api/v1/posts") + + func call(success: @escaping ([Post]?) -> Void) { + client.show(success: success) + } +} diff --git a/fakestagram/ViewControllers/PostsViewController.swift b/fakestagram/ViewControllers/PostsViewController.swift index 5835421..bf1c40c 100644 --- a/fakestagram/ViewControllers/PostsViewController.swift +++ b/fakestagram/ViewControllers/PostsViewController.swift @@ -14,7 +14,8 @@ class PostsViewController: UIViewController, UICollectionViewDelegate, UICollect self.postsCollection.reloadData() } } - let client = RestClient<[Post]>(client: Client.fakestagram, basePath: "/api/v1/posts") + + let service = IndexService() let refreshControl = UIRefreshControl() @IBOutlet weak var postsCollection: UICollectionView! @@ -28,7 +29,7 @@ class PostsViewController: UIViewController, UICollectionViewDelegate, UICollect refreshControl.addTarget(self, action: #selector(self.reloadData), for: UIControl.Event.valueChanged) - client.show { [unowned self] data in + service.call { [unowned self] data in self.posts = data } @@ -47,7 +48,7 @@ class PostsViewController: UIViewController, UICollectionViewDelegate, UICollect @objc func reloadData() { - client.show { [unowned self] data in + service.call { [unowned self] data in self.posts = data self.refreshControl.endRefreshing() } diff --git a/fakestagram/fakestagram-Bridging-Header.h b/fakestagram/fakestagram-Bridging-Header.h new file mode 100644 index 0000000..f31fb29 --- /dev/null +++ b/fakestagram/fakestagram-Bridging-Header.h @@ -0,0 +1,5 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "CheckSum.m" diff --git a/fakestagramTests/CheckSumTest.swift b/fakestagramTests/CheckSumTest.swift new file mode 100644 index 0000000..5236806 --- /dev/null +++ b/fakestagramTests/CheckSumTest.swift @@ -0,0 +1,26 @@ +// +// CheckSumTest.swift +// fakestagramTests +// +// Created by LuisE on 11/9/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import XCTest +//import CryptoKit +@testable import fakestagram + +class CheckSumTest: XCTestCase { + + func testPerformanceExample() { + let text = "lorem ipsum dolor quet sit amet consectetur" +// let data = text.data(using: .utf8)! + let expected = "df033ae7d7ff21916308e1e0f52c8f559f76bed69f5b4f8ed6237514bed8e2c4" + self.measure { + let result = CheckSum.sha256String(text) +// let result = String(SHA256.hash(data: data).description.dropFirst(15)) + XCTAssertEqual(expected, result) + } + } + +} From 655fba5d27e324f995fad15948e44cff626de215 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Sat, 9 Nov 2019 13:38:37 -0600 Subject: [PATCH 17/23] Implement Keychain wrapper --- Podfile | 1 + Podfile.lock | 6 +++++- fakestagram.xcodeproj/project.pbxproj | 18 ++++++++++++++++++ .../xcschemes/xcschememanagement.plist | 2 +- fakestagram/Utils/Credentials.swift | 7 ++++--- 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/Podfile b/Podfile index 9363ece..77cfa72 100644 --- a/Podfile +++ b/Podfile @@ -5,6 +5,7 @@ target 'fakestagram' do # Comment the next line if you don't want to use dynamic frameworks use_frameworks! # Pods for fakestagram + pod 'SAMKeychain' target 'fakestagramTests' do inherit! :search_paths diff --git a/Podfile.lock b/Podfile.lock index 918107b..12505e8 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,16 +1,20 @@ PODS: - DVR (2.0.0) + - SAMKeychain (1.5.3) DEPENDENCIES: - DVR + - SAMKeychain SPEC REPOS: trunk: - DVR + - SAMKeychain SPEC CHECKSUMS: DVR: 062c287b9dc613a84120e44640176e4ef3ecf943 + SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c -PODFILE CHECKSUM: 841e7401a398ccd6377f6b0c60295e943d9532bd +PODFILE CHECKSUM: 02c21c317ba9be4fdecdfff242f3fa20e9b269bd COCOAPODS: 1.8.3 diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index 211e87f..22ff726 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -306,6 +306,7 @@ E084FAD2233A8734009AC50D /* Sources */, E084FAD3233A8734009AC50D /* Frameworks */, E084FAD4233A8734009AC50D /* Resources */, + BA44E9C49B033049A720850E /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -461,6 +462,23 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + BA44E9C49B033049A720850E /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-fakestagram/Pods-fakestagram-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ diff --git a/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcschemes/xcschememanagement.plist b/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcschemes/xcschememanagement.plist index f8df77c..5378346 100644 --- a/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/fakestagram.xcodeproj/xcuserdata/luise.xcuserdatad/xcschemes/xcschememanagement.plist @@ -7,7 +7,7 @@ fakestagram.xcscheme_^#shared#^_ orderHint - 3 + 4 diff --git a/fakestagram/Utils/Credentials.swift b/fakestagram/Utils/Credentials.swift index bf6a319..3ce1105 100644 --- a/fakestagram/Utils/Credentials.swift +++ b/fakestagram/Utils/Credentials.swift @@ -7,6 +7,7 @@ // import Foundation +import SAMKeychain enum Credentials { case apiToken @@ -14,14 +15,14 @@ enum Credentials { func get() -> String? { switch self { case .apiToken: - return UserDefaults.standard.string(forKey: "apiToken") + return SAMKeychain.password(forService: "mx.unam.fakestagram", account: "apiToken") } } func set(value: String) -> Bool { switch self { case .apiToken: - UserDefaults.standard.set(value, forKey: "apiToken") + SAMKeychain.setPassword(value, forService: "mx.unam.fakestagram", account: "apiToken") } return true } @@ -29,7 +30,7 @@ enum Credentials { func destroy() -> Bool { switch self { case .apiToken: - UserDefaults.standard.setNilValueForKey("apiToken") + SAMKeychain.deletePassword(forService: "mx.unam.fakestagram", account: "apiToken") } return true } From 038a2ef1649ad7676511ba35ed45efa133c95adf Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Fri, 15 Nov 2019 21:08:41 -0600 Subject: [PATCH 18/23] Implement camera --- fakestagram.xcodeproj/project.pbxproj | 4 + fakestagram/Base.lproj/Main.storyboard | 45 +++++---- fakestagram/Info.plist | 8 +- fakestagram/Services/CreatePostService.swift | 4 +- fakestagram/Utils/UIImage+Base64.swift | 13 ++- .../CameraViewController.swift | 91 ++++++++++++++++--- fakestagram/Views/PreviewView.swift | 30 ++++++ 7 files changed, 157 insertions(+), 38 deletions(-) create mode 100644 fakestagram/Views/PreviewView.swift diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index 22ff726..bb8ccd2 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -27,6 +27,7 @@ E0A9ED51235A782F00A0527E /* PostsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0A9ED50235A782F00A0527E /* PostsViewController.swift */; }; E0A9ED54235A7FF300A0527E /* PostCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0A9ED52235A7FF300A0527E /* PostCollectionViewCell.swift */; }; E0A9ED55235A7FF300A0527E /* PostCollectionViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = E0A9ED53235A7FF300A0527E /* PostCollectionViewCell.xib */; }; + E0C185F0237F92C700AD9983 /* PreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C185EF237F92C700AD9983 /* PreviewView.swift */; }; E0C93E942351435100FD330C /* RestClientTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = E0C93E932351435100FD330C /* RestClientTest.swift */; }; E0C93E9923514D8800FD330C /* posts.successful.json in Resources */ = {isa = PBXBuildFile; fileRef = E0C93E9823514D8800FD330C /* posts.successful.json */; }; E0C93E9B23515A0400FD330C /* show_post.successful.json in Resources */ = {isa = PBXBuildFile; fileRef = E0C93E9A23515A0400FD330C /* show_post.successful.json */; }; @@ -89,6 +90,7 @@ E0A9ED50235A782F00A0527E /* PostsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostsViewController.swift; sourceTree = ""; }; E0A9ED52235A7FF300A0527E /* PostCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostCollectionViewCell.swift; sourceTree = ""; }; E0A9ED53235A7FF300A0527E /* PostCollectionViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PostCollectionViewCell.xib; sourceTree = ""; }; + E0C185EF237F92C700AD9983 /* PreviewView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PreviewView.swift; sourceTree = ""; }; E0C93E932351435100FD330C /* RestClientTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RestClientTest.swift; sourceTree = ""; }; E0C93E9823514D8800FD330C /* posts.successful.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = posts.successful.json; sourceTree = ""; }; E0C93E9A23515A0400FD330C /* show_post.successful.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = show_post.successful.json; sourceTree = ""; }; @@ -221,6 +223,7 @@ E0C93E9E23523B4700FD330C /* Views */ = { isa = PBXGroup; children = ( + E0C185EF237F92C700AD9983 /* PreviewView.swift */, E0A9ED52235A7FF300A0527E /* PostCollectionViewCell.swift */, E0A9ED53235A7FF300A0527E /* PostCollectionViewCell.xib */, E0C93E9F23523B7C00FD330C /* ShowPostViewController.swift */, @@ -491,6 +494,7 @@ E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */, E045845123766203006574FA /* CacheImage.swift in Sources */, E045844B237652DD006574FA /* StorageType.swift in Sources */, + E0C185F0237F92C700AD9983 /* PreviewView.swift in Sources */, E0E8B974234918FF00DA9D1A /* Account.swift in Sources */, E0C93EA123523B7C00FD330C /* ShowPostViewController.swift in Sources */, E0E25463235B675100C55767 /* CameraViewController.swift in Sources */, diff --git a/fakestagram/Base.lproj/Main.storyboard b/fakestagram/Base.lproj/Main.storyboard index be6cc42..469596b 100644 --- a/fakestagram/Base.lproj/Main.storyboard +++ b/fakestagram/Base.lproj/Main.storyboard @@ -1,8 +1,8 @@ - + - + @@ -63,29 +63,43 @@ - + + + + + + + + + + + + - - + + + + + + + - + @@ -126,7 +140,6 @@ - diff --git a/fakestagram/Info.plist b/fakestagram/Info.plist index 75aef61..d1b73e7 100644 --- a/fakestagram/Info.plist +++ b/fakestagram/Info.plist @@ -2,8 +2,6 @@ - NSLocationWhenInUseUsageDescription - Geololcalize your moments CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable @@ -22,6 +20,10 @@ 1 LSRequiresIPhoneOS + NSCameraUsageDescription + To capture your favorite moments and share with the world + NSLocationWhenInUseUsageDescription + Geololcalize your moments UIApplicationSceneManifest UIApplicationSupportsMultipleScenes @@ -52,8 +54,6 @@ UISupportedInterfaceOrientations UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad diff --git a/fakestagram/Services/CreatePostService.swift b/fakestagram/Services/CreatePostService.swift index b94a7ce..5028765 100644 --- a/fakestagram/Services/CreatePostService.swift +++ b/fakestagram/Services/CreatePostService.swift @@ -26,11 +26,11 @@ class CreatePostService { private let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/posts/") private var currentLocation: CLLocationCoordinate2D? - func call(image img: UIImage, title: String, success: @escaping (Int?) -> Void) { + func call(data: Data, title: String, success: @escaping (Int?) -> Void) { let newPost = CreatePost( id: nil, title: title, - imageData: img.base64(), + imageData: data.imageBase64(), latitude: currentLocation?.latitude, longitude: currentLocation?.longitude ) diff --git a/fakestagram/Utils/UIImage+Base64.swift b/fakestagram/Utils/UIImage+Base64.swift index 85f08e9..c46993a 100644 --- a/fakestagram/Utils/UIImage+Base64.swift +++ b/fakestagram/Utils/UIImage+Base64.swift @@ -8,10 +8,17 @@ import UIKit +extension Data { + func imageBase64(ext: String = "tiff") -> String { + let encoded = self.base64EncodedString(options: .lineLength64Characters) + return "data:image/\(ext);base64,\(encoded)" + } +} + extension UIImage { func base64() -> String { - let data = self.jpegData(compressionQuality: 90)! - let encoded = data.base64EncodedString(options: .lineLength64Characters) - return "data:image/jpg;base64,\(encoded)" + let data = self.jpegData(compressionQuality: 0.9)! + return data.imageBase64(ext: "jpg") } } + diff --git a/fakestagram/ViewControllers/CameraViewController.swift b/fakestagram/ViewControllers/CameraViewController.swift index 6ed067d..4d2c389 100644 --- a/fakestagram/ViewControllers/CameraViewController.swift +++ b/fakestagram/ViewControllers/CameraViewController.swift @@ -8,14 +8,13 @@ import UIKit import CoreLocation +import AVFoundation -class CameraViewController: UIViewController, CLLocationManagerDelegate { - let locationManager = CLLocationManager() - let service = CreatePostService() - +class CameraViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() enableBasicLocationServices() + enableCameraAccess() } override func viewWillAppear(_ animated: Bool) { @@ -28,15 +27,19 @@ class CameraViewController: UIViewController, CLLocationManagerDelegate { super.viewWillDisappear(animated) } + let service = CreatePostService() @IBAction func onTapCreate(_ sender: Any) { - let img = UIImage(named: "spacecat")! - service.call( - image: img, - title: "Spacecat🙀 - \(UUID().uuidString)" - ) { postId in - print("Successful!") - print(postId ?? -1) + print("📸") + let settings: AVCapturePhotoSettings + print(self.photoOutput.availablePhotoCodecTypes) + if self.photoOutput.availablePhotoCodecTypes.contains(.hevc) { + settings = AVCapturePhotoSettings(format: + [AVVideoCodecKey: AVVideoCodecType.hevc]) + } else { + settings = AVCapturePhotoSettings() } + settings.flashMode = .auto + photoOutput.capturePhoto(with: settings, delegate: self) } /* @@ -49,6 +52,8 @@ class CameraViewController: UIViewController, CLLocationManagerDelegate { } */ + // MARK: - CoreLocation methods + let locationManager = CLLocationManager() func enableBasicLocationServices() { locationManager.delegate = self switch CLLocationManager.authorizationStatus() { @@ -63,10 +68,70 @@ class CameraViewController: UIViewController, CLLocationManagerDelegate { } } + // MARK: - AVFoundation methods + + @IBOutlet weak var previewView: PreviewView! + func enableCameraAccess() { + switch AVCaptureDevice.authorizationStatus(for: .video) { + case .authorized: + // The user has previously granted access to the camera. + self.setupCaptureSession() + case .notDetermined: + // The user has not yet been asked for camera access. + AVCaptureDevice.requestAccess(for: .video) { granted in + if granted { + self.setupCaptureSession() + } + } + case .denied: + // The user has previously denied access. + return + case .restricted: + // The user can't grant access due to restrictions. + return + @unknown default: + fatalError() + } + } + + let session = AVCaptureSession() + let photoOutput = AVCapturePhotoOutput() + + func setupCaptureSession() { + session.beginConfiguration() + let device = AVCaptureDevice.default(.builtInDualCamera, + for: .video, position: .back)! + guard let videoDeviceInput = try? AVCaptureDeviceInput(device: device), + session.canAddInput(videoDeviceInput) else { return } + session.addInput(videoDeviceInput) + + guard session.canAddOutput(photoOutput) else { return } + session.sessionPreset = .photo + session.addOutput(photoOutput) + + session.commitConfiguration() + previewView.session = session + + session.startRunning() + } + +} + +extension CameraViewController: AVCapturePhotoCaptureDelegate { + func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { + debugPrint(photo.metadata) + + guard let data = photo.fileDataRepresentation() else { return } + service.call(data: data, title: UUID().uuidString) { postId in + print("Successful!") + print(postId ?? -1) + } + } +} + +extension CameraViewController: CLLocationManagerDelegate { func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { guard let location = locations.last else { return } - print(location) service.update(coordinate: location.coordinate) } - } diff --git a/fakestagram/Views/PreviewView.swift b/fakestagram/Views/PreviewView.swift new file mode 100644 index 0000000..8c38648 --- /dev/null +++ b/fakestagram/Views/PreviewView.swift @@ -0,0 +1,30 @@ +// +// PreviewView.swift +// HelloCamera +// +// Created by LuisE on 11/15/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import UIKit +import AVFoundation + +class PreviewView: UIView { + override class var layerClass: AnyClass { + return AVCaptureVideoPreviewLayer.self + } + + var session: AVCaptureSession? { + get { + return videoPreviewLayer.session + } + set { + videoPreviewLayer.session = newValue + } + } + + /// Convenience wrapper to get layer as its statically known type. + var videoPreviewLayer: AVCaptureVideoPreviewLayer { + return layer as! AVCaptureVideoPreviewLayer + } +} From 01d345665fbaf7c8bedc99f0aec01459262f2608 Mon Sep 17 00:00:00 2001 From: Luis Ezcurdia Razo Date: Sat, 16 Nov 2019 13:55:48 -0600 Subject: [PATCH 19/23] Upload images from camera and implement NotificationCenter --- fakestagram.xcodeproj/project.pbxproj | 4 ++++ fakestagram/Network/Client.swift | 8 ++++++++ fakestagram/Services/CreatePostService.swift | 5 +++-- fakestagram/Utils/NotificationKeys.swift | 20 +++++++++++++++++++ fakestagram/Utils/UIImage+Base64.swift | 3 +-- .../CameraViewController.swift | 4 ++-- .../ViewControllers/PostsViewController.swift | 1 + 7 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 fakestagram/Utils/NotificationKeys.swift diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index bb8ccd2..fd88dc7 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 05D8E963168944918FFCC7FF /* Pods_fakestagram.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FFAA8B9133CEE464C903FDF5 /* Pods_fakestagram.framework */; }; D3D164DC7444072103DE027D /* Pods_fakestagramTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E669E31C92D68155914FC99D /* Pods_fakestagramTests.framework */; }; + E023A5542380859200B13B7D /* NotificationKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = E023A5532380859200B13B7D /* NotificationKeys.swift */; }; E038FCED233FC78600E28571 /* PostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E038FCEC233FC78600E28571 /* PostViewController.swift */; }; E045844923762E10006574FA /* CreatePostService.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045844823762E10006574FA /* CreatePostService.swift */; }; E045844B237652DD006574FA /* StorageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E045844A237652DD006574FA /* StorageType.swift */; }; @@ -66,6 +67,7 @@ 66342726A6BCEEEF6289B1AA /* Pods-fakestagramTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagramTests.debug.xcconfig"; path = "Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.debug.xcconfig"; sourceTree = ""; }; CCC6C6EA9D17CA169951A745 /* Pods-fakestagram.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagram.release.xcconfig"; path = "Target Support Files/Pods-fakestagram/Pods-fakestagram.release.xcconfig"; sourceTree = ""; }; DB68F7FEC717545506064663 /* Pods-fakestagram.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagram.debug.xcconfig"; path = "Target Support Files/Pods-fakestagram/Pods-fakestagram.debug.xcconfig"; sourceTree = ""; }; + E023A5532380859200B13B7D /* NotificationKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationKeys.swift; sourceTree = ""; }; E038FCEC233FC78600E28571 /* PostViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostViewController.swift; sourceTree = ""; }; E045844823762E10006574FA /* CreatePostService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatePostService.swift; sourceTree = ""; }; E045844A237652DD006574FA /* StorageType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageType.swift; sourceTree = ""; }; @@ -249,6 +251,7 @@ E0E8B9642348018200DA9D1A /* Credentials.swift */, E0E2545E235A9F3A00C55767 /* UIDevice+models.swift */, E0E25464235B6C0500C55767 /* UIImage+Base64.swift */, + E023A5532380859200B13B7D /* NotificationKeys.swift */, ); path = Utils; sourceTree = ""; @@ -494,6 +497,7 @@ E0E8B96A23481D5A00DA9D1A /* StatusCode.swift in Sources */, E045845123766203006574FA /* CacheImage.swift in Sources */, E045844B237652DD006574FA /* StorageType.swift in Sources */, + E023A5542380859200B13B7D /* NotificationKeys.swift in Sources */, E0C185F0237F92C700AD9983 /* PreviewView.swift in Sources */, E0E8B974234918FF00DA9D1A /* Account.swift in Sources */, E0C93EA123523B7C00FD330C /* ShowPostViewController.swift in Sources */, diff --git a/fakestagram/Network/Client.swift b/fakestagram/Network/Client.swift index 2b9852a..187f7ca 100644 --- a/fakestagram/Network/Client.swift +++ b/fakestagram/Network/Client.swift @@ -51,6 +51,14 @@ class Client { let response = HttpResponse(response: response) if response.isSuccessful() { success(data) + } else { + #if DEBUG + debugPrint(response.status) + if let data = data { + let error = String(data: data, encoding: .utf8) + debugPrint(error) + } + #endif } }.resume() } diff --git a/fakestagram/Services/CreatePostService.swift b/fakestagram/Services/CreatePostService.swift index 5028765..6a50b85 100644 --- a/fakestagram/Services/CreatePostService.swift +++ b/fakestagram/Services/CreatePostService.swift @@ -26,15 +26,16 @@ class CreatePostService { private let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/posts/") private var currentLocation: CLLocationCoordinate2D? - func call(data: Data, title: String, success: @escaping (Int?) -> Void) { + func call(image: UIImage, title: String, success: @escaping (Int?) -> Void) { let newPost = CreatePost( id: nil, title: title, - imageData: data.imageBase64(), + imageData: image.base64(), latitude: currentLocation?.latitude, longitude: currentLocation?.longitude ) client.create(newPost) { post in + NotificationCenter.default.post(name: NotificationKeys.didFinishPostCreation.value, object: nil) success(post?.id) } } diff --git a/fakestagram/Utils/NotificationKeys.swift b/fakestagram/Utils/NotificationKeys.swift new file mode 100644 index 0000000..d0bf641 --- /dev/null +++ b/fakestagram/Utils/NotificationKeys.swift @@ -0,0 +1,20 @@ +// +// NotificationNames.swift +// fakestagram +// +// Created by LuisE on 11/16/19. +// Copyright © 2019 3zcurdia. All rights reserved. +// + +import Foundation + +enum NotificationKeys { + case didFinishPostCreation + + var value: Notification.Name { + switch self { + case .didFinishPostCreation: + return Notification.Name(rawValue: "didFinishPostCreationNotification") + } + } +} diff --git a/fakestagram/Utils/UIImage+Base64.swift b/fakestagram/Utils/UIImage+Base64.swift index c46993a..5bb19a0 100644 --- a/fakestagram/Utils/UIImage+Base64.swift +++ b/fakestagram/Utils/UIImage+Base64.swift @@ -17,8 +17,7 @@ extension Data { extension UIImage { func base64() -> String { - let data = self.jpegData(compressionQuality: 0.9)! + let data = self.jpegData(compressionQuality: 0.85)! return data.imageBase64(ext: "jpg") } } - diff --git a/fakestagram/ViewControllers/CameraViewController.swift b/fakestagram/ViewControllers/CameraViewController.swift index 4d2c389..a7996c7 100644 --- a/fakestagram/ViewControllers/CameraViewController.swift +++ b/fakestagram/ViewControllers/CameraViewController.swift @@ -121,8 +121,8 @@ extension CameraViewController: AVCapturePhotoCaptureDelegate { func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) { debugPrint(photo.metadata) - guard let data = photo.fileDataRepresentation() else { return } - service.call(data: data, title: UUID().uuidString) { postId in + guard let data = photo.fileDataRepresentation(), let img = UIImage(data: data) else { return } + service.call(image: img, title: UUID().uuidString) { postId in print("Successful!") print(postId ?? -1) } diff --git a/fakestagram/ViewControllers/PostsViewController.swift b/fakestagram/ViewControllers/PostsViewController.swift index bf1c40c..a49ab76 100644 --- a/fakestagram/ViewControllers/PostsViewController.swift +++ b/fakestagram/ViewControllers/PostsViewController.swift @@ -32,6 +32,7 @@ class PostsViewController: UIViewController, UICollectionViewDelegate, UICollect service.call { [unowned self] data in self.posts = data } + NotificationCenter.default.addObserver(self, selector: #selector(reloadData), name: NotificationKeys.didFinishPostCreation.value, object: nil) // Do any additional setup after loading the view. } From b4b15a7e80b4ed4faf53dfe2dcfce779508add0a Mon Sep 17 00:00:00 2001 From: jhovan Date: Sat, 23 Nov 2019 11:32:46 -0600 Subject: [PATCH 20/23] =?UTF-8?q?Se=20cambio=20el=20tipo=20de=20camara=20a?= =?UTF-8?q?=20uno=20m=C3=A1s=20general?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fakestagram.xcodeproj/project.pbxproj | 12 ++++++------ fakestagram/AppDelegate.swift | 2 +- .../ViewControllers/CameraViewController.swift | 5 +++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index fd88dc7..04ce79d 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -689,13 +689,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = D3XL2U7DQC; + DEVELOPMENT_TEAM = Z27ZTUPSJC; INFOPLIST_FILE = fakestagram/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.3zcurdia.fakestagram; + PRODUCT_BUNDLE_IDENTIFIER = com.jhovan.fakestagram; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "fakestagram/fakestagram-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -711,13 +711,13 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = D3XL2U7DQC; + DEVELOPMENT_TEAM = Z27ZTUPSJC; INFOPLIST_FILE = fakestagram/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); - PRODUCT_BUNDLE_IDENTIFIER = com.3zcurdia.fakestagram; + PRODUCT_BUNDLE_IDENTIFIER = com.jhovan.fakestagram; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "fakestagram/fakestagram-Bridging-Header.h"; SWIFT_VERSION = 5.0; @@ -732,7 +732,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = D3XL2U7DQC; + DEVELOPMENT_TEAM = Z27ZTUPSJC; INFOPLIST_FILE = fakestagramTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( @@ -755,7 +755,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = D3XL2U7DQC; + DEVELOPMENT_TEAM = Z27ZTUPSJC; INFOPLIST_FILE = fakestagramTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( diff --git a/fakestagram/AppDelegate.swift b/fakestagram/AppDelegate.swift index 2660552..6be5d79 100644 --- a/fakestagram/AppDelegate.swift +++ b/fakestagram/AppDelegate.swift @@ -35,7 +35,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func loadOrCreateAccount() { if Credentials.apiToken.get() != nil { return } - let account = Account(id: nil, name: "Juan Camaney", deviceNumber: UIDevice.identifier, deviceModel: UIDevice.modelName) + let account = Account(id: nil, name: "José Gallardo", deviceNumber: UIDevice.identifier, deviceModel: UIDevice.modelName) let client = RestClient(client: Client.fakestagram, basePath: "/api/v1/accounts") client.create(account) { account in guard let account = account, let idx = account.id else { return } diff --git a/fakestagram/ViewControllers/CameraViewController.swift b/fakestagram/ViewControllers/CameraViewController.swift index a7996c7..dfac05b 100644 --- a/fakestagram/ViewControllers/CameraViewController.swift +++ b/fakestagram/ViewControllers/CameraViewController.swift @@ -99,8 +99,9 @@ class CameraViewController: UIViewController { func setupCaptureSession() { session.beginConfiguration() - let device = AVCaptureDevice.default(.builtInDualCamera, - for: .video, position: .back)! + //let device = AVCaptureDevice.default(.builtInDualCamera, + let device = AVCaptureDevice.default(.builtInWideAngleCamera, + for: .video, position: .unspecified)! guard let videoDeviceInput = try? AVCaptureDeviceInput(device: device), session.canAddInput(videoDeviceInput) else { return } session.addInput(videoDeviceInput) From e3eb34e544f229cb17f0b82a4579e95015f3351a Mon Sep 17 00:00:00 2001 From: jhovan Date: Wed, 12 Feb 2020 18:32:12 -0600 Subject: [PATCH 21/23] Implement call method --- fakestagram.xcodeproj/project.pbxproj | 4 ++++ fakestagram/Services/CreateLikeService.swift | 23 ++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 fakestagram/Services/CreateLikeService.swift diff --git a/fakestagram.xcodeproj/project.pbxproj b/fakestagram.xcodeproj/project.pbxproj index 04ce79d..eb804d1 100644 --- a/fakestagram.xcodeproj/project.pbxproj +++ b/fakestagram.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 05D8E963168944918FFCC7FF /* Pods_fakestagram.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FFAA8B9133CEE464C903FDF5 /* Pods_fakestagram.framework */; }; + 0EA0E04023F4CAE300F3E463 /* CreateLikeService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EA0E03F23F4CAE300F3E463 /* CreateLikeService.swift */; }; D3D164DC7444072103DE027D /* Pods_fakestagramTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E669E31C92D68155914FC99D /* Pods_fakestagramTests.framework */; }; E023A5542380859200B13B7D /* NotificationKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = E023A5532380859200B13B7D /* NotificationKeys.swift */; }; E038FCED233FC78600E28571 /* PostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E038FCEC233FC78600E28571 /* PostViewController.swift */; }; @@ -63,6 +64,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 0EA0E03F23F4CAE300F3E463 /* CreateLikeService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateLikeService.swift; sourceTree = ""; }; 5E0AE2BFBF9C8D81E583E1BE /* Pods-fakestagramTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagramTests.release.xcconfig"; path = "Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.release.xcconfig"; sourceTree = ""; }; 66342726A6BCEEEF6289B1AA /* Pods-fakestagramTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagramTests.debug.xcconfig"; path = "Target Support Files/Pods-fakestagramTests/Pods-fakestagramTests.debug.xcconfig"; sourceTree = ""; }; CCC6C6EA9D17CA169951A745 /* Pods-fakestagram.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-fakestagram.release.xcconfig"; path = "Target Support Files/Pods-fakestagram/Pods-fakestagram.release.xcconfig"; sourceTree = ""; }; @@ -154,6 +156,7 @@ children = ( E045844823762E10006574FA /* CreatePostService.swift */, E0458456237725B9006574FA /* IndexService.swift */, + 0EA0E03F23F4CAE300F3E463 /* CreateLikeService.swift */, ); path = Services; sourceTree = ""; @@ -520,6 +523,7 @@ E0E8B96C23481E1700DA9D1A /* HttpResponse.swift in Sources */, E045844F23765B0F006574FA /* ImageStore.swift in Sources */, E045844D23765677006574FA /* DataContainer.swift in Sources */, + 0EA0E04023F4CAE300F3E463 /* CreateLikeService.swift in Sources */, E0E8B9652348018200DA9D1A /* Credentials.swift in Sources */, E0E8B971234916D100DA9D1A /* RestClient.swift in Sources */, E084FADC233A8734009AC50D /* SceneDelegate.swift in Sources */, diff --git a/fakestagram/Services/CreateLikeService.swift b/fakestagram/Services/CreateLikeService.swift new file mode 100644 index 0000000..6639e3e --- /dev/null +++ b/fakestagram/Services/CreateLikeService.swift @@ -0,0 +1,23 @@ +// +// CreateLikeService.swift +// fakestagram +// +// Created by Jhovan Gallardo on 12/02/20. +// Copyright © 2020 3zcurdia. All rights reserved. +// + +import Foundation + + +class CreateLikeService { + + let client: Client = Client.fakestagram + + func call(postId: String, success: @escaping (Int?) -> Void) { + let basePath = "/api/v1/posts/\(postId)/like" + client.post(path: basePath, body: nil) { data in + CodableSerializer(data: data).async(result: success) + } + } + +} From be6fdeacbe0b5cc0915db5cea10814cfed04ab94 Mon Sep 17 00:00:00 2001 From: jhovan Date: Wed, 12 Feb 2020 22:37:19 -0600 Subject: [PATCH 22/23] Implement like feature --- fakestagram/Models/Author.swift | 1 + fakestagram/Models/Like.swift | 2 ++ fakestagram/Services/CreateLikeService.swift | 6 ++++-- fakestagram/Views/PostCollectionViewCell.swift | 15 +++++++++++++++ fakestagram/Views/PostCollectionViewCell.xib | 7 +++++-- 5 files changed, 27 insertions(+), 4 deletions(-) diff --git a/fakestagram/Models/Author.swift b/fakestagram/Models/Author.swift index 607dad2..68ba143 100644 --- a/fakestagram/Models/Author.swift +++ b/fakestagram/Models/Author.swift @@ -10,4 +10,5 @@ import Foundation struct Author: Codable { let name: String + let id: String } diff --git a/fakestagram/Models/Like.swift b/fakestagram/Models/Like.swift index 5b2ba6f..78cf12a 100644 --- a/fakestagram/Models/Like.swift +++ b/fakestagram/Models/Like.swift @@ -9,5 +9,7 @@ import Foundation struct Like: Codable { + let createdAt: String + let updatedAt: String let author: Author } diff --git a/fakestagram/Services/CreateLikeService.swift b/fakestagram/Services/CreateLikeService.swift index 6639e3e..a829fd8 100644 --- a/fakestagram/Services/CreateLikeService.swift +++ b/fakestagram/Services/CreateLikeService.swift @@ -11,13 +11,15 @@ import Foundation class CreateLikeService { + let client: Client = Client.fakestagram - func call(postId: String, success: @escaping (Int?) -> Void) { + func call(postId: String, success: @escaping (String?) -> Void) { let basePath = "/api/v1/posts/\(postId)/like" client.post(path: basePath, body: nil) { data in - CodableSerializer(data: data).async(result: success) + CodableSerializer(data: data).async(result: {like in success(like?.createdAt)}) } } + } diff --git a/fakestagram/Views/PostCollectionViewCell.swift b/fakestagram/Views/PostCollectionViewCell.swift index 1d5be7b..a1cdcf1 100644 --- a/fakestagram/Views/PostCollectionViewCell.swift +++ b/fakestagram/Views/PostCollectionViewCell.swift @@ -9,6 +9,8 @@ import UIKit class PostCollectionViewCell: UICollectionViewCell { + let service = CreateLikeService() + static let identifier: String = "PostCell" public var post: Post? { didSet { @@ -38,5 +40,18 @@ class PostCollectionViewCell: UICollectionViewCell { self.imageView.image = img } } + + @IBAction func likeButton(_ sender: Any) { + guard var post = self.post else { return } + guard let postId = post.id else {return} + print("Se presiono like en post: \(postId)") + service.call(postId: String(postId)){ creationDate in + print("Liked Successfully! \(creationDate ?? "")") + } + post.likesCount += 1 + self.likeCounter.text = post.likesCountText() + } + + } diff --git a/fakestagram/Views/PostCollectionViewCell.xib b/fakestagram/Views/PostCollectionViewCell.xib index afff929..3b2ad23 100644 --- a/fakestagram/Views/PostCollectionViewCell.xib +++ b/fakestagram/Views/PostCollectionViewCell.xib @@ -1,8 +1,8 @@ - + - + @@ -36,6 +36,9 @@