From a14b3137a1a315680e4b80bd6b8f67557bdfd4cb Mon Sep 17 00:00:00 2001 From: "seongho.hong" Date: Sun, 11 Aug 2019 00:50:21 +0900 Subject: [PATCH] Modify completion as `Result` type --- Cartfile.private | 2 +- Cartfile.resolved | 2 +- OpenGraph.xcodeproj/project.pbxproj | 8 ++-- OpenGraph/OpenGraph.swift | 61 +++++++++++------------------ README.md | 34 +++++++++------- Tests/OpenGraphTests.swift | 40 ++++++++++++------- 6 files changed, 73 insertions(+), 74 deletions(-) diff --git a/Cartfile.private b/Cartfile.private index 16f179d..2c8c545 100644 --- a/Cartfile.private +++ b/Cartfile.private @@ -1 +1 @@ -github "AliSoftware/OHHTTPStubs" "6.0.0" \ No newline at end of file +github "AliSoftware/OHHTTPStubs" "8.0.0" \ No newline at end of file diff --git a/Cartfile.resolved b/Cartfile.resolved index bf0e19e..4d37985 100644 --- a/Cartfile.resolved +++ b/Cartfile.resolved @@ -1 +1 @@ -github "AliSoftware/OHHTTPStubs" "6.0.0" +github "AliSoftware/OHHTTPStubs" "8.0.0" diff --git a/OpenGraph.xcodeproj/project.pbxproj b/OpenGraph.xcodeproj/project.pbxproj index fce6f51..885efcb 100644 --- a/OpenGraph.xcodeproj/project.pbxproj +++ b/OpenGraph.xcodeproj/project.pbxproj @@ -405,7 +405,7 @@ SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TVOS_DEPLOYMENT_TARGET = 9.0; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; @@ -435,7 +435,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; TVOS_DEPLOYMENT_TARGET = 9.0; WATCHOS_DEPLOYMENT_TARGET = 2.0; }; @@ -456,7 +456,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "net.cloud-dj.OpenGraphTests"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -474,7 +474,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "net.cloud-dj.OpenGraphTests"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/OpenGraph/OpenGraph.swift b/OpenGraph/OpenGraph.swift index f3ac6c0..61196d5 100644 --- a/OpenGraph/OpenGraph.swift +++ b/OpenGraph/OpenGraph.swift @@ -1,54 +1,39 @@ import Foundation public struct OpenGraph { - public let source: [OpenGraphMetadata: String] - public static func fetch(url: URL, completion: @escaping (OpenGraph?, Error?) -> Void) { - let configuration = URLSessionConfiguration.default - let session = URLSession(configuration: configuration) - let task = session.dataTask(with: url, completionHandler: { (data, response, error) in - handleFetchResult(data: data, response: response, error: error, callback: completion) - }) - task.resume() - } + public let source: [OpenGraphMetadata: String] - public static func fetch(url: URL, headers: [String:String], completion: @escaping (OpenGraph?, Error?) -> Void) { + public static func fetch(url: URL, headers: [String: String]? = nil, completion: @escaping (Result) -> Void) { var mutableURLRequest = URLRequest(url: url) - for hkey in headers.keys { - let value:String! = headers[hkey] - if value != nil { - mutableURLRequest.setValue(value, forHTTPHeaderField: hkey) - } + headers?.compactMapValues { $0 }.forEach { + mutableURLRequest.setValue($1, forHTTPHeaderField: $0) } - let configuration = URLSessionConfiguration.default let session = URLSession(configuration: configuration) - let task = session.dataTask(with: mutableURLRequest, completionHandler: { (data, response, error) in - handleFetchResult(data: data, response: response, error: error, callback: completion) - }) + let task = session.dataTask(with: mutableURLRequest, completionHandler: { data, response, error in + if let error = error { + completion(.failure(error)) + } else { + handleFetchResult(data: data, response: response, completion: completion) + } + }) task.resume() } - private static func handleFetchResult(data: Data?, response: URLResponse?, error: Error?, callback: @escaping (OpenGraph?, Error?) -> Void){ - switch (data, response, error) { - case (_, _, let error?): - callback(nil, error) - break - case (let data?, let response as HTTPURLResponse, _): - if !(200..<300).contains(response.statusCode) { - callback(nil, OpenGraphResponseError.unexpectedStatusCode(response.statusCode)) - } else { - guard let htmlString = String(data: data, encoding: String.Encoding.utf8) else { - callback(nil, OpenGraphParseError.encodingError) - return - } - - let og = OpenGraph(htmlString: htmlString) - callback(og, error) + private static func handleFetchResult(data: Data?, response: URLResponse?, completion: @escaping (Result) -> Void) { + guard let data = data, let response = response as? HTTPURLResponse else { + return + } + if !(200..<300).contains(response.statusCode) { + completion(.failure(OpenGraphResponseError.unexpectedStatusCode(response.statusCode))) + } else { + guard let htmlString = String(data: data, encoding: String.Encoding.utf8) else { + completion(.failure(OpenGraphParseError.encodingError)) + return } - break - default: - break + let og = OpenGraph(htmlString: htmlString) + completion(.success(og)) } } diff --git a/README.md b/README.md index 13a8e44..be6b4a1 100644 --- a/README.md +++ b/README.md @@ -3,35 +3,39 @@ OpenGraph is a Swift wrapper for the OGP ([Open Graph protocol](http://ogp.me/)). You can fetch OpenGraph,then you can access the attributes with subscript and the key provided by enum type. ```swift -OpenGraph.fetch(url) { og, error in - print(og?[.title]) // => og:title of the web site - print(og?[.type]) // => og:type of the web site - print(og?[.image]) // => og:image of the web site - print(og?[.url]) // => og:url of the web site +OpenGraph.fetch(url: url) { result in + switch result { + case .success(let og): + print(og[.title]) // => og:title of the web site + print(og[.type]) // => og:type of the web site + print(og[.image]) // => og:image of the web site + print(og[.url]) // => og:url of the web site + case .failure(let error): + print(error) + } } ``` If you want to use Rx interface, use an extension below. ```swift -extension OpenGraph { - static func rx_fetch(url: URL?) -> Observable { +extension Reactive where Base: OpenGraph { + static func fetch(url: URL?) -> Observable { return Observable.create { observer in guard let url = url else { observer.onCompleted() return Disposables.create() } - - OpenGraph.fetch(url: url) { og, err in - if let og = og { + + OpenGraph.fetch(url: url) { result in + switch result { + case .success(let og): observer.onNext(og) + case .failure(let error): + observer.onError(error) } - if let err = err { - observer.onError(err) - } - observer.onCompleted() } - + return Disposables.create() } } diff --git a/Tests/OpenGraphTests.swift b/Tests/OpenGraphTests.swift index 94b0e25..edc06b4 100644 --- a/Tests/OpenGraphTests.swift +++ b/Tests/OpenGraphTests.swift @@ -33,9 +33,11 @@ class OpenGraphTests: XCTestCase { var og: OpenGraph! var error: Error? let headers = ["User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"] - OpenGraph.fetch(url: url, headers: headers) { (_og, _error) in - og = _og - error = _error + OpenGraph.fetch(url: url, headers: headers) { result in + switch result { + case .success(let _og): og = _og + case .failure(let _error): error = _error + } responseArrived.fulfill() } @@ -57,9 +59,11 @@ class OpenGraphTests: XCTestCase { let url = URL(string: "https://www.example.com")! var og: OpenGraph! var error: Error? - OpenGraph.fetch(url: url) { _og, _error in - og = _og - error = _error + OpenGraph.fetch(url: url) { result in + switch result { + case .success(let _og): og = _og + case .failure(let _error): error = _error + } responseArrived.fulfill() } @@ -82,9 +86,11 @@ class OpenGraphTests: XCTestCase { let url = URL(string: "https://www.example.com")! var og: OpenGraph! var error: Error? - OpenGraph.fetch(url: url) { _og, _error in - og = _og - error = _error + OpenGraph.fetch(url: url) { result in + switch result { + case .success(let _og): og = _og + case .failure(let _error): error = _error + } responseArrived.fulfill() } @@ -110,9 +116,11 @@ class OpenGraphTests: XCTestCase { let url = URL(string: "https://www.example.com")! var og: OpenGraph? var error: Error? - OpenGraph.fetch(url: url) { _og, _error in - og = _og - error = _error + OpenGraph.fetch(url: url) { result in + switch result { + case .success(let _og): og = _og + case .failure(let _error): error = _error + } responseArrived.fulfill() } @@ -144,9 +152,11 @@ class OpenGraphTests: XCTestCase { let url = URL(string: "https://www.example.com")! var og: OpenGraph? var error: Error? - OpenGraph.fetch(url: url) { _og, _error in - og = _og - error = _error + OpenGraph.fetch(url: url) { result in + switch result { + case .success(let _og): og = _og + case .failure(let _error): error = _error + } responseArrived.fulfill() }