Skip to content

Commit

Permalink
Merge pull request #86 from ishkawa/feature/session
Browse files Browse the repository at this point in the history
Rename `API` to `Session` and reorganize relationship between `Session` and `NSURLSession`
  • Loading branch information
ikesyo committed Oct 19, 2015
2 parents f2b502e + 9cdc680 commit fa085b0
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 48 deletions.
12 changes: 6 additions & 6 deletions APIKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
7F0869A11A9787AF001AD3E1 /* ResponseBodyParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7FEC5A181A96FE2600B1D3C0 /* ResponseBodyParserTests.swift */; };
7F0869A61A978BCA001AD3E1 /* URLEncodedSerialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F0869A51A978BCA001AD3E1 /* URLEncodedSerialization.swift */; };
7F0869A71A978BCA001AD3E1 /* URLEncodedSerialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F0869A51A978BCA001AD3E1 /* URLEncodedSerialization.swift */; };
7F0869A81A979088001AD3E1 /* API.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F45FD171A94D085006863BB /* API.swift */; };
7F0869A81A979088001AD3E1 /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F45FD171A94D085006863BB /* Session.swift */; };
7F1B190B1AA2CA1300C7AFCF /* APITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F1B190A1AA2CA1300C7AFCF /* APITests.swift */; };
7F1B190C1AA2CA1300C7AFCF /* APITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F1B190A1AA2CA1300C7AFCF /* APITests.swift */; };
7F30A8561A975BD600A8C136 /* RequestBodyBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F30A8551A975BD600A8C136 /* RequestBodyBuilderTests.swift */; };
7F45FD181A94D085006863BB /* API.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F45FD171A94D085006863BB /* API.swift */; };
7F45FD181A94D085006863BB /* Session.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F45FD171A94D085006863BB /* Session.swift */; };
7F5FA6B51B3C58210090B0AF /* APIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F5FA6B41B3C58210090B0AF /* APIError.swift */; };
7F68ABDA1AC4412E00688D68 /* RequestType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F68ABD91AC4412E00688D68 /* RequestType.swift */; };
7F68ABDB1AC4412E00688D68 /* RequestType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F68ABD91AC4412E00688D68 /* RequestType.swift */; };
Expand Down Expand Up @@ -94,7 +94,7 @@
7F45FCE11A94D02C006863BB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7F45FCE21A94D02C006863BB /* APIKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APIKit.h; sourceTree = "<group>"; };
7F45FCFE1A94D04D006863BB /* APIKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = APIKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7F45FD171A94D085006863BB /* API.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = API.swift; sourceTree = "<group>"; };
7F45FD171A94D085006863BB /* Session.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Session.swift; sourceTree = "<group>"; };
7F5FA6B41B3C58210090B0AF /* APIError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = APIError.swift; sourceTree = "<group>"; };
7F68ABD91AC4412E00688D68 /* RequestType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestType.swift; sourceTree = "<group>"; };
7F68ABDC1AC4414500688D68 /* HTTPMethod.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HTTPMethod.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -173,7 +173,7 @@
isa = PBXGroup;
children = (
7F45FCE21A94D02C006863BB /* APIKit.h */,
7F45FD171A94D085006863BB /* API.swift */,
7F45FD171A94D085006863BB /* Session.swift */,
7F68ABD91AC4412E00688D68 /* RequestType.swift */,
7F68ABDC1AC4414500688D68 /* HTTPMethod.swift */,
7F5FA6B41B3C58210090B0AF /* APIError.swift */,
Expand Down Expand Up @@ -402,7 +402,7 @@
buildActionMask = 2147483647;
files = (
7FCBE9DD1A9734880075AFD9 /* RequestBodyBuilder.swift in Sources */,
7F45FD181A94D085006863BB /* API.swift in Sources */,
7F45FD181A94D085006863BB /* Session.swift in Sources */,
7F68ABDD1AC4414500688D68 /* HTTPMethod.swift in Sources */,
7F68ABDA1AC4412E00688D68 /* RequestType.swift in Sources */,
7FCBE9E01A9734950075AFD9 /* ResponseBodyParser.swift in Sources */,
Expand All @@ -417,7 +417,7 @@
files = (
84B5C6BC1B42CD430032068D /* APIError.swift in Sources */,
7FCBE9DE1A9734880075AFD9 /* RequestBodyBuilder.swift in Sources */,
7F0869A81A979088001AD3E1 /* API.swift in Sources */,
7F0869A81A979088001AD3E1 /* Session.swift in Sources */,
7F68ABDE1AC4414500688D68 /* HTTPMethod.swift in Sources */,
7F68ABDB1AC4412E00688D68 /* RequestType.swift in Sources */,
7FCBE9E11A9734950075AFD9 /* ResponseBodyParser.swift in Sources */,
Expand Down
54 changes: 38 additions & 16 deletions APIKit/API.swift → APIKit/Session.swift
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
import Foundation
import Result

public class API {
public class var defaultURLSession: NSURLSession {
return internalDefaultURLSession
public class Session {
public let URLSession: NSURLSession

public init(URLSession: NSURLSession) {
self.URLSession = URLSession
}

private static let internalDefaultURLSession = NSURLSession(
configuration: NSURLSessionConfiguration.defaultSessionConfiguration(),
delegate: URLSessionDelegate(),
delegateQueue: nil
)

// send request and build response object
public static func sendRequest<T: RequestType>(request: T, URLSession: NSURLSession = defaultURLSession, handler: (Result<T.Response, APIError>) -> Void = {r in}) -> NSURLSessionDataTask? {
public func sendRequest<T: RequestType>(request: T, handler: (Result<T.Response, APIError>) -> Void = {r in}) -> NSURLSessionDataTask? {
switch request.buildURLRequest() {
case .Failure(let error):
handler(.Failure(error))
Expand Down Expand Up @@ -44,12 +40,8 @@ public class API {
return dataTask
}
}

public static func cancelRequest<T: RequestType>(requestType: T.Type, passingTest test: T -> Bool = { r in true }) {
cancelRequest(requestType, URLSession: defaultURLSession, passingTest: test)
}

public static func cancelRequest<T: RequestType>(requestType: T.Type, URLSession: NSURLSession, passingTest test: T -> Bool = { r in true }) {

public func cancelRequest<T: RequestType>(requestType: T.Type, passingTest test: T -> Bool = { r in true }) {
URLSession.getTasksWithCompletionHandler { dataTasks, uploadTasks, downloadTasks in
let allTasks = dataTasks as [NSURLSessionTask]
+ uploadTasks as [NSURLSessionTask]
Expand All @@ -76,6 +68,36 @@ public class API {
}.forEach { $0.cancel() }
}
}

// Shared session for static methods
public static let sharedSession = Session(URLSession: NSURLSession(
configuration: NSURLSessionConfiguration.defaultSessionConfiguration(),
delegate: URLSessionDelegate(),
delegateQueue: nil
))

public static func sendRequest<T: RequestType>(request: T, handler: (Result<T.Response, APIError>) -> Void = {r in}) -> NSURLSessionDataTask? {
return sharedSession.sendRequest(request, handler: handler)
}

public static func cancelRequest<T: RequestType>(requestType: T.Type, passingTest test: T -> Bool = { r in true }) {
sharedSession.cancelRequest(requestType, passingTest: test)
}
}

@available(*, unavailable, message="API is renamed as Session.")
public typealias API = Session

extension Session {
@available(*, unavailable, message="Use separated Session instance instead.")
public static func sendRequest<T: RequestType>(request: T, URLSession: NSURLSession, handler: (Result<T.Response, APIError>) -> Void = {r in}) -> NSURLSessionDataTask? {
abort()
}

@available(*, unavailable, message="Use separated Session instance instead.")
public static func cancelRequest<T: RequestType>(requestType: T.Type, URLSession: NSURLSession, passingTest test: T -> Bool = { r in true }) {
abort()
}
}

// MARK: - default implementation of URLSessionDelegate
Expand Down
38 changes: 19 additions & 19 deletions APIKitTests/APITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import APIKit
import XCTest
import OHHTTPStubs

protocol MockAPIRequestType: RequestType {
protocol MockSessionRequestType: RequestType {
}

extension MockAPIRequestType {
extension MockSessionRequestType {
var baseURL: NSURL {
return NSURL(string: "https://api.github.com")!
}
}

class MockAPI: API {
struct GetRoot: MockAPIRequestType {
class MockSession: Session {
struct GetRoot: MockSessionRequestType {
typealias Response = [String: AnyObject]

var method: HTTPMethod {
Expand All @@ -30,7 +30,7 @@ class MockAPI: API {
}
}

class AnotherMockAPI: API {
class AnotherMockSession: Session {

}

Expand All @@ -52,9 +52,9 @@ class APITests: XCTestCase {
})

let expectation = expectationWithDescription("wait for response")
let request = MockAPI.GetRoot()
let request = MockSession.GetRoot()

MockAPI.sendRequest(request) { response in
MockSession.sendRequest(request) { response in
switch response {
case .Success(let dictionary):
XCTAssertEqual(dictionary["key"] as? String, "value")
Expand All @@ -79,9 +79,9 @@ class APITests: XCTestCase {
})

let expectation = expectationWithDescription("wait for response")
let request = MockAPI.GetRoot()
let request = MockSession.GetRoot()

MockAPI.sendRequest(request) { response in
MockSession.sendRequest(request) { response in
switch response {
case .Success:
XCTFail()
Expand Down Expand Up @@ -112,9 +112,9 @@ class APITests: XCTestCase {
})

let expectation = expectationWithDescription("wait for response")
let request = MockAPI.GetRoot()
let request = MockSession.GetRoot()

MockAPI.sendRequest(request) { response in
MockSession.sendRequest(request) { response in
switch response {
case .Success:
XCTFail()
Expand Down Expand Up @@ -146,9 +146,9 @@ class APITests: XCTestCase {
})

let expectation = expectationWithDescription("wait for response")
let request = MockAPI.GetRoot()
let request = MockSession.GetRoot()

MockAPI.sendRequest(request) { response in
MockSession.sendRequest(request) { response in
switch response {
case .Success:
XCTFail()
Expand Down Expand Up @@ -182,9 +182,9 @@ class APITests: XCTestCase {
})

let expectation = expectationWithDescription("wait for response")
let request = MockAPI.GetRoot()
let request = MockSession.GetRoot()

MockAPI.sendRequest(request) { response in
MockSession.sendRequest(request) { response in
switch response {
case .Success:
XCTFail()
Expand All @@ -203,7 +203,7 @@ class APITests: XCTestCase {
expectation.fulfill()
}

MockAPI.cancelRequest(MockAPI.GetRoot.self)
MockSession.cancelRequest(MockSession.GetRoot.self)

waitForExpectationsWithTimeout(1.0, handler: nil)
}
Expand All @@ -221,9 +221,9 @@ class APITests: XCTestCase {
})

let expectation = expectationWithDescription("wait for response")
let request = MockAPI.GetRoot()
let request = MockSession.GetRoot()

MockAPI.sendRequest(request) { response in
MockSession.sendRequest(request) { response in
switch response {
case .Success:
break
Expand All @@ -235,7 +235,7 @@ class APITests: XCTestCase {
expectation.fulfill()
}

MockAPI.cancelRequest(MockAPI.GetRoot.self) { request in
MockSession.cancelRequest(MockSession.GetRoot.self) { request in
return false
}

Expand Down
6 changes: 3 additions & 3 deletions APIKitTests/RequestTypeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import OHHTTPStubs
import APIKit

class RequestTypeTests: XCTestCase {
struct SearchRequest: MockAPIRequestType {
struct SearchRequest: MockSessionRequestType {
let query: String

// MARK: RequestType
Expand Down Expand Up @@ -70,7 +70,7 @@ class RequestTypeTests: XCTestCase {
let request = SearchRequest(query: "こんにちは")
let expectation = expectationWithDescription("waiting for the response.")

API.sendRequest(request) { result in
Session.sendRequest(request) { result in
expectation.fulfill()
}

Expand All @@ -88,7 +88,7 @@ class RequestTypeTests: XCTestCase {
let request = SearchRequest(query: "!\"#$%&'()0=~|`{}*+<>?_")
let expectation = expectationWithDescription("waiting for the response.")

API.sendRequest(request) { result in
Session.sendRequest(request) { result in
expectation.fulfill()
}

Expand Down
2 changes: 1 addition & 1 deletion Demo.playground/Contents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ struct GetRateLimitRequest: GitHubRequestType {
//: Step 4: Send request
let request = GetRateLimitRequest()

API.sendRequest(request) { result in
Session.sendRequest(request) { result in
switch result {
case .Success(let rateLimit):
debugPrint("count: \(rateLimit.count)")
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ APIKit is a library for building type-safe web API client in Swift.
```swift
let request = GetSearchRepositoriesRequest(query: "APIKit", sort: .Stars)

API.sendRequest(request) { result in
Session.sendRequest(request) { result in
switch result {
case .Success(let response):
self.repositories = response // inferred as [Repository]
Expand Down Expand Up @@ -117,7 +117,7 @@ struct RateLimit {
```swift
let request = GetRateLimitRequest()

API.sendRequest(request) { result in
Session.sendRequest(request) { result in
switch result {
case .Success(let rateLimit):
print("count: \(rateLimit.count)")
Expand Down Expand Up @@ -276,7 +276,7 @@ extension GitHubRequest {
```swift
let request = GetSomePaginatedRequest(page: 1)

API.sendRequest(request) { result in
Session.sendRequest(request) { result in
switch result {
case .Success(let response):
print("results: \(response.results)")
Expand Down

0 comments on commit fa085b0

Please sign in to comment.