From c1a76bd3f2644d78d0e87e4b9e84462869fbad4c Mon Sep 17 00:00:00 2001 From: Ben Lu Date: Tue, 28 Jan 2020 15:11:00 -0800 Subject: [PATCH] Use Swift Foundation Result type to represent a value and error in example --- CHANGELOG.md | 6 +++ .../project.pbxproj | 12 ++--- .../CleanseGithubBrowser/ErrorOptional.swift | 50 ------------------- .../CleanseGithubBrowser/FakeServices.swift | 8 +-- .../GithubMemberService.swift | 4 +- .../GithubRepositoriesService.swift | 4 +- .../NSURLSessionAdditions.swift | 12 ++--- 7 files changed, 24 insertions(+), 72 deletions(-) delete mode 100644 Examples/CleanseGithubBrowser/CleanseGithubBrowser/ErrorOptional.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 859bb6a..9d9f3ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,3 +17,9 @@ * Retain subcomponent graphs [Sebastian Shanus](https://github.com/sebastianv1) [#42](https://github.com/square/Cleanse/issues/42) + +#### Improvements + +* Replace demo app's ErrorOptional type with Swift Foundation Result type + [Sihao Lu](https://github.com/DJBen) + [#126](https://github.com/square/Cleanse/pull/126) \ No newline at end of file diff --git a/Examples/CleanseGithubBrowser/CleanseGithubBrowser.xcodeproj/project.pbxproj b/Examples/CleanseGithubBrowser/CleanseGithubBrowser.xcodeproj/project.pbxproj index c25c2cf..381e5a2 100644 --- a/Examples/CleanseGithubBrowser/CleanseGithubBrowser.xcodeproj/project.pbxproj +++ b/Examples/CleanseGithubBrowser/CleanseGithubBrowser.xcodeproj/project.pbxproj @@ -12,7 +12,6 @@ F69184B31D0DF28A00125872 /* GithubMemberService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F69184B21D0DF28A00125872 /* GithubMemberService.swift */; }; F69184B61D0DF2CA00125872 /* GithubRepositoriesService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F69184B51D0DF2CA00125872 /* GithubRepositoriesService.swift */; }; F69184BB1D0DF3DD00125872 /* NetworkModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = F69184BA1D0DF3DD00125872 /* NetworkModule.swift */; }; - F69184BD1D0DF5DC00125872 /* ErrorOptional.swift in Sources */ = {isa = PBXBuildFile; fileRef = F69184BC1D0DF5DC00125872 /* ErrorOptional.swift */; }; F69184BF1D0DF70F00125872 /* HTTPError.swift in Sources */ = {isa = PBXBuildFile; fileRef = F69184BE1D0DF70F00125872 /* HTTPError.swift */; }; F69184C31D0DFB4A00125872 /* GithubServicesModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = F69184C21D0DFB4A00125872 /* GithubServicesModule.swift */; }; F69184C61D0E015A00125872 /* NSURLSessionAdditions.swift in Sources */ = {isa = PBXBuildFile; fileRef = F69184C51D0E015A00125872 /* NSURLSessionAdditions.swift */; }; @@ -107,7 +106,6 @@ F69184B21D0DF28A00125872 /* GithubMemberService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GithubMemberService.swift; sourceTree = ""; }; F69184B51D0DF2CA00125872 /* GithubRepositoriesService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GithubRepositoriesService.swift; sourceTree = ""; }; F69184BA1D0DF3DD00125872 /* NetworkModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkModule.swift; sourceTree = ""; }; - F69184BC1D0DF5DC00125872 /* ErrorOptional.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ErrorOptional.swift; sourceTree = ""; }; F69184BE1D0DF70F00125872 /* HTTPError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPError.swift; sourceTree = ""; }; F69184C21D0DFB4A00125872 /* GithubServicesModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GithubServicesModule.swift; sourceTree = ""; }; F69184C51D0E015A00125872 /* NSURLSessionAdditions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSURLSessionAdditions.swift; sourceTree = ""; }; @@ -164,7 +162,6 @@ F69184B71D0DF32800125872 /* Services */ = { isa = PBXGroup; children = ( - F69184BC1D0DF5DC00125872 /* ErrorOptional.swift */, F69184CF1D0E33F600125872 /* FakeModeSettings.swift */, F69184CD1D0E31F200125872 /* FakeServices.swift */, F69184B21D0DF28A00125872 /* GithubMemberService.swift */, @@ -464,7 +461,6 @@ F6E878301D0BD911006F3FAB /* SettingsPage.swift in Sources */, 884618AF1D9324AD0001ADEB /* AppComponent.swift in Sources */, F6E878321D0D1120006F3FAB /* RepositoriesPage.swift in Sources */, - F69184BD1D0DF5DC00125872 /* ErrorOptional.swift in Sources */, F6E878381D0DD11A006F3FAB /* SplitViewController.swift in Sources */, F69184D21D0E357600125872 /* FoundationCommonModule.swift in Sources */, ); @@ -651,7 +647,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.squareup.CleanseGithubBrowserTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CleanseGithubBrowser.app/CleanseGithubBrowser"; }; name = Debug; @@ -664,7 +660,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.squareup.CleanseGithubBrowserTests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CleanseGithubBrowser.app/CleanseGithubBrowser"; }; name = Release; @@ -676,7 +672,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.squareup.CleanseGithubBrowserUITests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; TEST_TARGET_NAME = CleanseGithubBrowser; }; name = Debug; @@ -688,7 +684,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.squareup.CleanseGithubBrowserUITests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 5.0; TEST_TARGET_NAME = CleanseGithubBrowser; }; name = Release; diff --git a/Examples/CleanseGithubBrowser/CleanseGithubBrowser/ErrorOptional.swift b/Examples/CleanseGithubBrowser/CleanseGithubBrowser/ErrorOptional.swift deleted file mode 100644 index df7f781..0000000 --- a/Examples/CleanseGithubBrowser/CleanseGithubBrowser/ErrorOptional.swift +++ /dev/null @@ -1,50 +0,0 @@ -// -// ErrorOptional.swift -// CleanseGithubBrowser -// -// Created by Mike Lewis on 6/12/16. -// Copyright © 2016 Square, Inc. All rights reserved. -// - -import Foundation - - -/// Represents either an error or result type. -enum ErrorOptional { - case Result(Wrapped) - case Error(Error) - - - init(_ result: Wrapped) { - self = .Result(result) - } - - init(_ error: Error) { - self = .Error(error) - } - - func get() throws -> Wrapped { - switch self { - case let .Result(result): - return result - case let .Error(error): - throw error - } - } -} - - -extension ErrorOptional { - func map(transform: (Wrapped) throws -> NewWrapped) -> ErrorOptional { - switch self { - case let .Result(result): - do { - return try .init(transform(result)) - } catch let e { - return .init(e) - } - case let .Error(error): - return .init(error) - } - } -} diff --git a/Examples/CleanseGithubBrowser/CleanseGithubBrowser/FakeServices.swift b/Examples/CleanseGithubBrowser/CleanseGithubBrowser/FakeServices.swift index 2e008b4..86ca37c 100644 --- a/Examples/CleanseGithubBrowser/CleanseGithubBrowser/FakeServices.swift +++ b/Examples/CleanseGithubBrowser/CleanseGithubBrowser/FakeServices.swift @@ -36,9 +36,9 @@ struct FakeGithubServicesModule : GithubServicesModule { struct FakeGithubMembersService : GithubMembersService { - func list(handler: @escaping (ErrorOptional<[GithubMember]>) -> Void) { + func list(handler: @escaping (Result<[GithubMember], Error>) -> Void) { DispatchQueue.main.async() { - handler(.init([ + handler(.success([ GithubMember(login: "abrons"), GithubMember(login: "mikelikespie"), GithubMember(login: "holmes"), @@ -48,9 +48,9 @@ struct FakeGithubMembersService : GithubMembersService { } struct FakeGithubRepositoriesService : GithubRepositoriesService { - func list(_ handler: @escaping (ErrorOptional<[GithubRepository]>) -> Void) { + func list(_ handler: @escaping (Result<[GithubRepository], Error>) -> Void) { DispatchQueue.main.async() { - handler(.init([ + handler(.success([ GithubRepository(name: "okhttp", watchersCount: 11_917), GithubRepository(name: "cleanse", watchersCount: 42) ])) diff --git a/Examples/CleanseGithubBrowser/CleanseGithubBrowser/GithubMemberService.swift b/Examples/CleanseGithubBrowser/CleanseGithubBrowser/GithubMemberService.swift index dd68974..944aef9 100644 --- a/Examples/CleanseGithubBrowser/CleanseGithubBrowser/GithubMemberService.swift +++ b/Examples/CleanseGithubBrowser/CleanseGithubBrowser/GithubMemberService.swift @@ -20,7 +20,7 @@ struct GithubMember { /// Service that lists "Member" for the current organization protocol GithubMembersService { - func list(handler: @escaping (ErrorOptional<[GithubMember]>) -> Void) + func list(handler: @escaping (Result<[GithubMember], Error>) -> Void) } struct GithubMembersServiceImpl : GithubMembersService { @@ -30,7 +30,7 @@ struct GithubMembersServiceImpl : GithubMembersService { let urlSession: URLSession /// Lists members of an organization - func list(handler: @escaping (ErrorOptional<[GithubMember]>) -> Void) { + func list(handler: @escaping (Result<[GithubMember], Error>) -> Void) { urlSession.jsonListTask( baseURL: githubURL.get(), pathComponents: "orgs", githubOrganizationName.get(), "public_members") { result in diff --git a/Examples/CleanseGithubBrowser/CleanseGithubBrowser/GithubRepositoriesService.swift b/Examples/CleanseGithubBrowser/CleanseGithubBrowser/GithubRepositoriesService.swift index 4997e3c..5e35df8 100644 --- a/Examples/CleanseGithubBrowser/CleanseGithubBrowser/GithubRepositoriesService.swift +++ b/Examples/CleanseGithubBrowser/CleanseGithubBrowser/GithubRepositoriesService.swift @@ -23,7 +23,7 @@ struct GithubRepository { /// Service that lists repositories for the current user protocol GithubRepositoriesService { - func list(_ handler: @escaping (ErrorOptional<[GithubRepository]>) -> Void) + func list(_ handler: @escaping (Result<[GithubRepository], Error>) -> Void) } struct GithubRepositoriesServiceImpl : GithubRepositoriesService { @@ -32,7 +32,7 @@ struct GithubRepositoriesServiceImpl : GithubRepositoriesService { let urlSession: URLSession - func list(_ handler: @escaping (ErrorOptional<[GithubRepository]>) -> Void) { + func list(_ handler: @escaping (Result<[GithubRepository], Error>) -> Void) { urlSession.jsonListTask( baseURL: githubURL.get(), pathComponents: "users", githubOrganizationName.get(), "repos", diff --git a/Examples/CleanseGithubBrowser/CleanseGithubBrowser/NSURLSessionAdditions.swift b/Examples/CleanseGithubBrowser/CleanseGithubBrowser/NSURLSessionAdditions.swift index b6e7a95..9fcc0a6 100644 --- a/Examples/CleanseGithubBrowser/CleanseGithubBrowser/NSURLSessionAdditions.swift +++ b/Examples/CleanseGithubBrowser/CleanseGithubBrowser/NSURLSessionAdditions.swift @@ -10,22 +10,22 @@ import Foundation extension URLSession { - func jsonTask(baseURL: URL, pathComponents: String..., resultHandler: @escaping (ErrorOptional) -> Void) -> URLSessionDataTask { + func jsonTask(baseURL: URL, pathComponents: String..., resultHandler: @escaping (Result) -> Void) -> URLSessionDataTask { let url = baseURL.appendingPathComponent(pathComponents.joined(separator: "/")) return jsonTask(url: url as URL, resultHandler: resultHandler) } - private func jsonTask(url: URL, resultHandler: @escaping (ErrorOptional) -> Void) -> URLSessionDataTask { + private func jsonTask(url: URL, resultHandler: @escaping (Result) -> Void) -> URLSessionDataTask { let task = self.dataTask(with: url as URL) { (data, response, error) in if let error: Error = error ?? HTTPError(statusCode: (response as! HTTPURLResponse).statusCode) { - resultHandler(ErrorOptional(error)) + resultHandler(.failure(error)) return } do { - try resultHandler(ErrorOptional(JSONSerialization.jsonObject(with: data!, options: []))) + try resultHandler(.success(JSONSerialization.jsonObject(with: data!, options: []))) } catch let e { - resultHandler(ErrorOptional(e)) + resultHandler(.failure(e)) return } } @@ -39,7 +39,7 @@ extension URLSession { baseURL: URL, pathComponents: String..., query: String? = nil, - resultHandler: @escaping (ErrorOptional<[[String: AnyObject]]>) -> Void + resultHandler: @escaping (Result<[[String: AnyObject]], Error>) -> Void ) -> URLSessionDataTask { var url = baseURL.appendingPathComponent(pathComponents.joined(separator: "/"))