[Swift4]Update templates for swift 4 (#6921)

* update versions of dependencies on swift4 and swift3

* change syntax for swift4

* run petstore script

* change enum case from UpperCamel to lowerCamel

* remove unneeded break statements

* avoid wrapping conditionals in parentheses

* avoid force casting

* run pod update on petstore/swift4/rxswift

* update project for swift 4

* run swift4-petstore-all.sh

* fix compile error

* avoid use iso8601 date strategy for encoder / decoder

* resolve file references
This commit is contained in:
Daiki Matsudate
2017-11-21 12:33:52 +09:00
committed by William Cheng
parent b06ccec11e
commit a5e4abe5ec
379 changed files with 5282 additions and 8237 deletions

View File

@@ -1 +1 @@
2.3.0-SNAPSHOT
unset

View File

@@ -1,2 +1,2 @@
github "Alamofire/Alamofire" >= 3.1.0
github "ReactiveX/RxSwift" ~> 2.0
github "Alamofire/Alamofire" ~> 4.5.0
github "ReactiveX/RxSwift" ~> 4.0

View File

@@ -9,6 +9,6 @@ Pod::Spec.new do |s|
s.homepage = 'https://github.com/swagger-api/swagger-codegen'
s.summary = 'PetstoreClient'
s.source_files = 'PetstoreClient/Classes/**/*.swift'
s.dependency 'RxSwift', '~> 3.4.1'
s.dependency 'RxSwift', '~> 4.0'
s.dependency 'Alamofire', '~> 4.5.0'
end

View File

@@ -1,5 +1,5 @@
//
// AnotherfakeAPI.swift
// AnotherFakeAPI.swift
//
// Generated by swagger-codegen
// https://github.com/swagger-api/swagger-codegen
@@ -11,7 +11,7 @@ import RxSwift
open class AnotherfakeAPI {
open class AnotherFakeAPI {
/**
To test special tags
@@ -34,7 +34,7 @@ open class AnotherfakeAPI {
return Observable.create { observer -> Disposable in
testSpecialTags(body: body) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}

View File

@@ -32,7 +32,7 @@ open class FakeAPI {
return Observable.create { observer -> Disposable in
fakeOuterBooleanSerialize(body: body) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}
@@ -84,7 +84,7 @@ open class FakeAPI {
return Observable.create { observer -> Disposable in
fakeOuterCompositeSerialize(body: body) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}
@@ -140,7 +140,7 @@ open class FakeAPI {
return Observable.create { observer -> Disposable in
fakeOuterNumberSerialize(body: body) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}
@@ -192,7 +192,7 @@ open class FakeAPI {
return Observable.create { observer -> Disposable in
fakeOuterStringSerialize(body: body) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}
@@ -246,7 +246,7 @@ open class FakeAPI {
return Observable.create { observer -> Disposable in
testClientModel(body: body) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}
@@ -329,9 +329,9 @@ open class FakeAPI {
return Observable.create { observer -> Disposable in
testEndpointParameters(number: number, double: double, patternWithoutDelimiter: patternWithoutDelimiter, byte: byte, integer: integer, int32: int32, int64: int64, float: float, string: string, binary: binary, date: date, dateTime: dateTime, password: password, callback: callback) { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}
@@ -498,9 +498,9 @@ open class FakeAPI {
return Observable.create { observer -> Disposable in
testEnumParameters(enumFormStringArray: enumFormStringArray, enumFormString: enumFormString, enumHeaderStringArray: enumHeaderStringArray, enumHeaderString: enumHeaderString, enumQueryStringArray: enumQueryStringArray, enumQueryString: enumQueryString, enumQueryInteger: enumQueryInteger, enumQueryDouble: enumQueryDouble) { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}
@@ -554,6 +554,60 @@ open class FakeAPI {
return requestBuilder.init(method: "GET", URLString: (url?.string ?? URLString), parameters: parameters, isBody: false, headers: headerParameters)
}
/**
test inline additionalProperties
- parameter param: (body) request body
- parameter completion: completion handler to receive the data and the error objects
*/
open class func testInlineAdditionalProperties(param: Any, completion: @escaping ((_ error: Error?) -> Void)) {
testInlineAdditionalPropertiesWithRequestBuilder(param: param).execute { (response, error) -> Void in
completion(error);
}
}
/**
test inline additionalProperties
- parameter param: (body) request body
- returns: Observable<Void>
*/
open class func testInlineAdditionalProperties(param: Any) -> Observable<Void> {
return Observable.create { observer -> Disposable in
testInlineAdditionalProperties(param: param) { error in
if let error = error {
observer.on(.error(error))
} else {
observer.on(.next(()))
}
observer.on(.completed)
}
return Disposables.create()
}
}
/**
test inline additionalProperties
- POST /fake/inline-additionalProperties
-
- parameter param: (body) request body
- returns: RequestBuilder<Void>
*/
open class func testInlineAdditionalPropertiesWithRequestBuilder(param: Any) -> RequestBuilder<Void> {
let path = "/fake/inline-additionalProperties"
let URLString = PetstoreClientAPI.basePath + path
let parameters = JSONEncodingHelper.encodingParameters(forEncodableObject: param)
let url = NSURLComponents(string: URLString)
let requestBuilder: RequestBuilder<Void>.Type = PetstoreClientAPI.requestBuilderFactory.getNonDecodableBuilder()
return requestBuilder.init(method: "POST", URLString: (url?.string ?? URLString), parameters: parameters, isBody: true)
}
/**
test json serialization of form data
@@ -578,9 +632,9 @@ open class FakeAPI {
return Observable.create { observer -> Disposable in
testJsonFormData(param: param, param2: param2) { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}

View File

@@ -1,5 +1,5 @@
//
// Fake_classname_tags123API.swift
// FakeClassnameTags123API.swift
//
// Generated by swagger-codegen
// https://github.com/swagger-api/swagger-codegen
@@ -11,7 +11,7 @@ import RxSwift
open class Fake_classname_tags123API {
open class FakeClassnameTags123API {
/**
To test class name in snake case
@@ -34,7 +34,7 @@ open class Fake_classname_tags123API {
return Observable.create { observer -> Disposable in
testClassname(body: body) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}

View File

@@ -34,9 +34,9 @@ open class PetAPI {
return Observable.create { observer -> Disposable in
addPet(body: body) { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}
@@ -93,9 +93,9 @@ open class PetAPI {
return Observable.create { observer -> Disposable in
deletePet(petId: petId, apiKey: apiKey) { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}
@@ -165,7 +165,7 @@ open class PetAPI {
return Observable.create { observer -> Disposable in
findPetsByStatus(status: status) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}
@@ -309,7 +309,7 @@ open class PetAPI {
return Observable.create { observer -> Disposable in
findPetsByTags(tags: tags) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}
@@ -453,7 +453,7 @@ open class PetAPI {
return Observable.create { observer -> Disposable in
getPetById(petId: petId) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}
@@ -563,9 +563,9 @@ open class PetAPI {
return Observable.create { observer -> Disposable in
updatePet(body: body) { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}
@@ -624,9 +624,9 @@ open class PetAPI {
return Observable.create { observer -> Disposable in
updatePetWithForm(petId: petId, name: name, status: status) { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}
@@ -694,7 +694,7 @@ open class PetAPI {
return Observable.create { observer -> Disposable in
uploadFile(petId: petId, additionalMetadata: additionalMetadata, file: file) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}

View File

@@ -34,9 +34,9 @@ open class StoreAPI {
return Observable.create { observer -> Disposable in
deleteOrder(orderId: orderId) { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}
@@ -87,7 +87,7 @@ open class StoreAPI {
return Observable.create { observer -> Disposable in
getInventory() { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}
@@ -145,7 +145,7 @@ open class StoreAPI {
return Observable.create { observer -> Disposable in
getOrderById(orderId: orderId) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}
@@ -230,7 +230,7 @@ open class StoreAPI {
return Observable.create { observer -> Disposable in
placeOrder(body: body) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}

View File

@@ -34,9 +34,9 @@ open class UserAPI {
return Observable.create { observer -> Disposable in
createUser(body: body) { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}
@@ -88,9 +88,9 @@ open class UserAPI {
return Observable.create { observer -> Disposable in
createUsersWithArrayInput(body: body) { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}
@@ -142,9 +142,9 @@ open class UserAPI {
return Observable.create { observer -> Disposable in
createUsersWithListInput(body: body) { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}
@@ -196,9 +196,9 @@ open class UserAPI {
return Observable.create { observer -> Disposable in
deleteUser(username: username) { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}
@@ -251,7 +251,7 @@ open class UserAPI {
return Observable.create { observer -> Disposable in
getUserByName(username: username) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}
@@ -346,7 +346,7 @@ open class UserAPI {
return Observable.create { observer -> Disposable in
loginUser(username: username, password: password) { data, error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next(data!))
}
@@ -407,9 +407,9 @@ open class UserAPI {
return Observable.create { observer -> Disposable in
logoutUser() { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}
@@ -461,9 +461,9 @@ open class UserAPI {
return Observable.create { observer -> Disposable in
updateUser(username: username, body: body) { error in
if let error = error {
observer.on(.error(error as Error))
observer.on(.error(error))
} else {
observer.on(.next())
observer.on(.next(()))
}
observer.on(.completed)
}

View File

@@ -77,16 +77,12 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
else {
mpForm.append(fileURL, withName: k)
}
break
case let string as String:
mpForm.append(string.data(using: String.Encoding.utf8)!, withName: k)
break
case let number as NSNumber:
mpForm.append(number.stringValue.data(using: String.Encoding.utf8)!, withName: k)
break
default:
fatalError("Unprocessable value \(v) with key \(k)")
break
}
}
}, to: URLString, method: xMethod!, headers: nil, encodingCompletion: { encodingResult in
@@ -97,7 +93,7 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
}
self.processRequest(request: upload, managerId, completion)
case .failure(let encodingError):
completion(nil, ErrorResponse.Error(415, nil, encodingError))
completion(nil, ErrorResponse.error(415, nil, encodingError))
}
})
} else {
@@ -129,7 +125,7 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
if stringResponse.result.isFailure {
completion(
nil,
ErrorResponse.Error(stringResponse.response?.statusCode ?? 500, stringResponse.data, stringResponse.result.error as Error!)
ErrorResponse.error(stringResponse.response?.statusCode ?? 500, stringResponse.data, stringResponse.result.error as Error!)
)
return
}
@@ -186,9 +182,9 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
)
} catch let requestParserError as DownloadException {
completion(nil, ErrorResponse.Error(400, dataResponse.data, requestParserError))
completion(nil, ErrorResponse.error(400, dataResponse.data, requestParserError))
} catch let error {
completion(nil, ErrorResponse.Error(400, dataResponse.data, error))
completion(nil, ErrorResponse.error(400, dataResponse.data, error))
}
return
})
@@ -199,7 +195,7 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
if voidResponse.result.isFailure {
completion(
nil,
ErrorResponse.Error(voidResponse.response?.statusCode ?? 500, voidResponse.data, voidResponse.result.error!)
ErrorResponse.error(voidResponse.response?.statusCode ?? 500, voidResponse.data, voidResponse.result.error!)
)
return
}
@@ -215,10 +211,10 @@ open class AlamofireRequestBuilder<T>: RequestBuilder<T> {
validatedRequest.responseData(completionHandler: { (dataResponse) in
cleanupRequest()
if (dataResponse.result.isFailure) {
if dataResponse.result.isFailure {
completion(
nil,
ErrorResponse.Error(dataResponse.response?.statusCode ?? 500, dataResponse.data, dataResponse.result.error!)
ErrorResponse.error(dataResponse.response?.statusCode ?? 500, dataResponse.data, dataResponse.result.error!)
)
return
}
@@ -331,7 +327,7 @@ open class AlamofireDecodableRequestBuilder<T:Decodable>: AlamofireRequestBuilde
if stringResponse.result.isFailure {
completion(
nil,
ErrorResponse.Error(stringResponse.response?.statusCode ?? 500, stringResponse.data, stringResponse.result.error as Error!)
ErrorResponse.error(stringResponse.response?.statusCode ?? 500, stringResponse.data, stringResponse.result.error as Error!)
)
return
}
@@ -351,7 +347,7 @@ open class AlamofireDecodableRequestBuilder<T:Decodable>: AlamofireRequestBuilde
if voidResponse.result.isFailure {
completion(
nil,
ErrorResponse.Error(voidResponse.response?.statusCode ?? 500, voidResponse.data, voidResponse.result.error!)
ErrorResponse.error(voidResponse.response?.statusCode ?? 500, voidResponse.data, voidResponse.result.error!)
)
return
}
@@ -367,10 +363,10 @@ open class AlamofireDecodableRequestBuilder<T:Decodable>: AlamofireRequestBuilde
validatedRequest.responseData(completionHandler: { (dataResponse) in
cleanupRequest()
if (dataResponse.result.isFailure) {
if dataResponse.result.isFailure {
completion(
nil,
ErrorResponse.Error(dataResponse.response?.statusCode ?? 500, dataResponse.data, dataResponse.result.error!)
ErrorResponse.error(dataResponse.response?.statusCode ?? 500, dataResponse.data, dataResponse.result.error!)
)
return
}
@@ -388,17 +384,17 @@ open class AlamofireDecodableRequestBuilder<T:Decodable>: AlamofireRequestBuilde
cleanupRequest()
guard dataResponse.result.isSuccess else {
completion(nil, ErrorResponse.Error(dataResponse.response?.statusCode ?? 500, dataResponse.data, dataResponse.result.error!))
completion(nil, ErrorResponse.error(dataResponse.response?.statusCode ?? 500, dataResponse.data, dataResponse.result.error!))
return
}
guard let data = dataResponse.data, !data.isEmpty else {
completion(nil, ErrorResponse.Error(-1, nil, AlamofireDecodableRequestBuilderError.emptyDataResponse))
completion(nil, ErrorResponse.error(-1, nil, AlamofireDecodableRequestBuilderError.emptyDataResponse))
return
}
guard let httpResponse = dataResponse.response else {
completion(nil, ErrorResponse.Error(-2, nil, AlamofireDecodableRequestBuilderError.nilHTTPResponse))
completion(nil, ErrorResponse.error(-2, nil, AlamofireDecodableRequestBuilderError.nilHTTPResponse))
return
}

View File

@@ -22,9 +22,12 @@ open class CodableHelper {
decoder.dateDecodingStrategy = .formatted(df)
} else {
decoder.dataDecodingStrategy = .base64
if #available(iOS 10.0, *) {
decoder.dateDecodingStrategy = .iso8601
}
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
decoder.dateDecodingStrategy = .formatted(formatter)
}
do {
@@ -45,9 +48,12 @@ open class CodableHelper {
encoder.outputFormatting = .prettyPrinted
}
encoder.dataEncodingStrategy = .base64
if #available(iOS 10.0, *) {
encoder.dateEncodingStrategy = .iso8601
}
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
encoder.dateEncodingStrategy = .formatted(formatter)
do {
returnedData = try encoder.encode(value)

View File

@@ -53,7 +53,7 @@ extension Dictionary: JSONEncodable {
func encodeToJSON() -> Any {
var dictionary = [AnyHashable: Any]()
for (key, value) in self {
dictionary[key as! NSObject] = encodeIfPossible(value)
dictionary[key] = encodeIfPossible(value)
}
return dictionary as Any
}

View File

@@ -11,7 +11,7 @@ protocol JSONEncodable {
}
public enum ErrorResponse : Error {
case Error(Int, Data?, Error)
case error(Int, Data?, Error)
}
open class Response<T> {
@@ -28,8 +28,8 @@ open class Response<T> {
public convenience init(response: HTTPURLResponse, body: T?) {
let rawHeader = response.allHeaderFields
var header = [String:String]()
for (key, value) in rawHeader {
header[key as! String] = value as? String
for case let (key, value) as (String, String) in rawHeader {
header[key] = value
}
self.init(statusCode: response.statusCode, header: header, body: body)
}

View File

@@ -15,10 +15,12 @@ open class AdditionalPropertiesClass: Codable {
public var mapOfMapProperty: [String:[String:String]]?
public init(mapProperty: [String:String]?, mapOfMapProperty: [String:[String:String]]?) {
self.mapProperty = mapProperty
self.mapOfMapProperty = mapOfMapProperty
}
// Encodable protocol methods

View File

@@ -15,10 +15,12 @@ open class Animal: Codable {
public var color: String?
public init(className: String, color: String?) {
self.className = className
self.color = color
}
// Encodable protocol methods

View File

@@ -16,11 +16,13 @@ open class ApiResponse: Codable {
public var message: String?
public init(code: Int?, type: String?, message: String?) {
self.code = code
self.type = type
self.message = message
}
// Encodable protocol methods

View File

@@ -14,9 +14,11 @@ open class ArrayOfArrayOfNumberOnly: Codable {
public var arrayArrayNumber: [[Double]]?
public init(arrayArrayNumber: [[Double]]?) {
self.arrayArrayNumber = arrayArrayNumber
}
// Encodable protocol methods
@@ -24,7 +26,7 @@ open class ArrayOfArrayOfNumberOnly: Codable {
var container = encoder.container(keyedBy: String.self)
try container.encodeArrayIfPresent(arrayArrayNumber, forKey: "ArrayArrayNumber")
try container.encodeIfPresent(arrayArrayNumber, forKey: "ArrayArrayNumber")
}
// Decodable protocol methods
@@ -32,7 +34,7 @@ open class ArrayOfArrayOfNumberOnly: Codable {
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: String.self)
arrayArrayNumber = try container.decodeArrayIfPresent([Double].self, forKey: "ArrayArrayNumber")
arrayArrayNumber = try container.decodeIfPresent([[Double]].self, forKey: "ArrayArrayNumber")
}
}

View File

@@ -14,9 +14,11 @@ open class ArrayOfNumberOnly: Codable {
public var arrayNumber: [Double]?
public init(arrayNumber: [Double]?) {
self.arrayNumber = arrayNumber
}
// Encodable protocol methods
@@ -24,7 +26,7 @@ open class ArrayOfNumberOnly: Codable {
var container = encoder.container(keyedBy: String.self)
try container.encodeArrayIfPresent(arrayNumber, forKey: "ArrayNumber")
try container.encodeIfPresent(arrayNumber, forKey: "ArrayNumber")
}
// Decodable protocol methods
@@ -32,7 +34,7 @@ open class ArrayOfNumberOnly: Codable {
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: String.self)
arrayNumber = try container.decodeArrayIfPresent(Double.self, forKey: "ArrayNumber")
arrayNumber = try container.decodeIfPresent([Double].self, forKey: "ArrayNumber")
}
}

View File

@@ -16,11 +16,13 @@ open class ArrayTest: Codable {
public var arrayArrayOfModel: [[ReadOnlyFirst]]?
public init(arrayOfString: [String]?, arrayArrayOfInteger: [[Int64]]?, arrayArrayOfModel: [[ReadOnlyFirst]]?) {
self.arrayOfString = arrayOfString
self.arrayArrayOfInteger = arrayArrayOfInteger
self.arrayArrayOfModel = arrayArrayOfModel
}
// Encodable protocol methods
@@ -28,9 +30,9 @@ open class ArrayTest: Codable {
var container = encoder.container(keyedBy: String.self)
try container.encodeArrayIfPresent(arrayOfString, forKey: "array_of_string")
try container.encodeArrayIfPresent(arrayArrayOfInteger, forKey: "array_array_of_integer")
try container.encodeArrayIfPresent(arrayArrayOfModel, forKey: "array_array_of_model")
try container.encodeIfPresent(arrayOfString, forKey: "array_of_string")
try container.encodeIfPresent(arrayArrayOfInteger, forKey: "array_array_of_integer")
try container.encodeIfPresent(arrayArrayOfModel, forKey: "array_array_of_model")
}
// Decodable protocol methods
@@ -38,9 +40,9 @@ open class ArrayTest: Codable {
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: String.self)
arrayOfString = try container.decodeArrayIfPresent(String.self, forKey: "array_of_string")
arrayArrayOfInteger = try container.decodeArrayIfPresent([Int64].self, forKey: "array_array_of_integer")
arrayArrayOfModel = try container.decodeArrayIfPresent([ReadOnlyFirst].self, forKey: "array_array_of_model")
arrayOfString = try container.decodeIfPresent([String].self, forKey: "array_of_string")
arrayArrayOfInteger = try container.decodeIfPresent([[Int64]].self, forKey: "array_array_of_integer")
arrayArrayOfModel = try container.decodeIfPresent([[ReadOnlyFirst]].self, forKey: "array_array_of_model")
}
}

View File

@@ -20,6 +20,7 @@ open class Capitalization: Codable {
public var ATT_NAME: String?
public init(smallCamel: String?, capitalCamel: String?, smallSnake: String?, capitalSnake: String?, sCAETHFlowPoints: String?, ATT_NAME: String?) {
self.smallCamel = smallCamel
self.capitalCamel = capitalCamel
@@ -28,6 +29,7 @@ open class Capitalization: Codable {
self.sCAETHFlowPoints = sCAETHFlowPoints
self.ATT_NAME = ATT_NAME
}
// Encodable protocol methods

View File

@@ -14,9 +14,7 @@ open class Cat: Animal {
public var declawed: Bool?
public init(declawed: Bool?) {
self.declawed = declawed
}
// Encodable protocol methods
@@ -29,10 +27,11 @@ open class Cat: Animal {
// Decodable protocol methods
public override required init(from decoder: Decoder) throws {
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: String.self)
declawed = try container.decodeIfPresent(Bool.self, forKey: "declawed")
try super.init(from: decoder)
}
}

View File

@@ -15,10 +15,12 @@ open class Category: Codable {
public var name: String?
public init(id: Int64?, name: String?) {
self.id = id
self.name = name
}
// Encodable protocol methods

View File

@@ -15,9 +15,11 @@ open class ClassModel: Codable {
public var _class: String?
public init(_class: String?) {
self._class = _class
}
// Encodable protocol methods

View File

@@ -14,9 +14,11 @@ open class Client: Codable {
public var client: String?
public init(client: String?) {
self.client = client
}
// Encodable protocol methods

View File

@@ -14,9 +14,7 @@ open class Dog: Animal {
public var breed: String?
public init(breed: String?) {
self.breed = breed
}
// Encodable protocol methods
@@ -29,10 +27,11 @@ open class Dog: Animal {
// Decodable protocol methods
public override required init(from decoder: Decoder) throws {
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: String.self)
breed = try container.decodeIfPresent(String.self, forKey: "breed")
try super.init(from: decoder)
}
}

View File

@@ -23,10 +23,12 @@ open class EnumArrays: Codable {
public var arrayEnum: [ArrayEnum]?
public init(justSymbol: JustSymbol?, arrayEnum: [ArrayEnum]?) {
self.justSymbol = justSymbol
self.arrayEnum = arrayEnum
}
// Encodable protocol methods
@@ -35,7 +37,7 @@ open class EnumArrays: Codable {
var container = encoder.container(keyedBy: String.self)
try container.encodeIfPresent(justSymbol, forKey: "just_symbol")
try container.encodeArrayIfPresent(arrayEnum, forKey: "array_enum")
try container.encodeIfPresent(arrayEnum, forKey: "array_enum")
}
// Decodable protocol methods
@@ -43,8 +45,8 @@ open class EnumArrays: Codable {
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: String.self)
justSymbol = try container.decodeIfPresent(String.self, forKey: "just_symbol")
arrayEnum = try container.decodeArrayIfPresent(String.self, forKey: "array_enum")
justSymbol = try container.decodeIfPresent(JustSymbol.self, forKey: "just_symbol")
arrayEnum = try container.decodeIfPresent([ArrayEnum].self, forKey: "array_enum")
}
}

View File

@@ -30,12 +30,14 @@ open class EnumTest: Codable {
public var outerEnum: OuterEnum?
public init(enumString: EnumString?, enumInteger: EnumInteger?, enumNumber: EnumNumber?, outerEnum: OuterEnum?) {
self.enumString = enumString
self.enumInteger = enumInteger
self.enumNumber = enumNumber
self.outerEnum = outerEnum
}
// Encodable protocol methods
@@ -54,9 +56,9 @@ open class EnumTest: Codable {
public required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: String.self)
enumString = try container.decodeIfPresent(String.self, forKey: "enum_string")
enumInteger = try container.decodeIfPresent(Int.self, forKey: "enum_integer")
enumNumber = try container.decodeIfPresent(Double.self, forKey: "enum_number")
enumString = try container.decodeIfPresent(EnumString.self, forKey: "enum_string")
enumInteger = try container.decodeIfPresent(EnumInteger.self, forKey: "enum_integer")
enumNumber = try container.decodeIfPresent(EnumNumber.self, forKey: "enum_number")
outerEnum = try container.decodeIfPresent(OuterEnum.self, forKey: "outerEnum")
}
}

View File

@@ -26,6 +26,7 @@ open class FormatTest: Codable {
public var password: String
public init(integer: Int?, int32: Int?, int64: Int64?, number: Double, float: Float?, double: Double?, string: String?, byte: Data, binary: Data?, date: Date, dateTime: Date?, uuid: UUID?, password: String) {
self.integer = integer
self.int32 = int32
@@ -41,6 +42,7 @@ open class FormatTest: Codable {
self.uuid = uuid
self.password = password
}
// Encodable protocol methods

View File

@@ -15,10 +15,12 @@ open class HasOnlyReadOnly: Codable {
public var foo: String?
public init(bar: String?, foo: String?) {
self.bar = bar
self.foo = foo
}
// Encodable protocol methods

View File

@@ -14,9 +14,11 @@ open class List: Codable {
public var _123List: String?
public init(_123List: String?) {
self._123List = _123List
}
// Encodable protocol methods

View File

@@ -19,10 +19,12 @@ open class MapTest: Codable {
public var mapOfEnumString: [String:String]?
public init(mapMapOfString: [String:[String:String]]?, mapOfEnumString: [String:String]?) {
self.mapMapOfString = mapMapOfString
self.mapOfEnumString = mapOfEnumString
}
// Encodable protocol methods

View File

@@ -16,11 +16,13 @@ open class MixedPropertiesAndAdditionalPropertiesClass: Codable {
public var map: [String:Animal]?
public init(uuid: UUID?, dateTime: Date?, map: [String:Animal]?) {
self.uuid = uuid
self.dateTime = dateTime
self.map = map
}
// Encodable protocol methods

View File

@@ -16,10 +16,12 @@ open class Model200Response: Codable {
public var _class: String?
public init(name: Int?, _class: String?) {
self.name = name
self._class = _class
}
// Encodable protocol methods

View File

@@ -18,12 +18,14 @@ open class Name: Codable {
public var _123Number: Int?
public init(name: Int, snakeCase: Int?, property: String?, _123Number: Int?) {
self.name = name
self.snakeCase = snakeCase
self.property = property
self._123Number = _123Number
}
// Encodable protocol methods

View File

@@ -14,9 +14,11 @@ open class NumberOnly: Codable {
public var justNumber: Double?
public init(justNumber: Double?) {
self.justNumber = justNumber
}
// Encodable protocol methods

View File

@@ -25,6 +25,7 @@ open class Order: Codable {
public var complete: Bool?
public init(id: Int64?, petId: Int64?, quantity: Int?, shipDate: Date?, status: Status?, complete: Bool?) {
self.id = id
self.petId = petId
@@ -33,6 +34,7 @@ open class Order: Codable {
self.status = status
self.complete = complete
}
// Encodable protocol methods
@@ -57,7 +59,7 @@ open class Order: Codable {
petId = try container.decodeIfPresent(Int64.self, forKey: "petId")
quantity = try container.decodeIfPresent(Int.self, forKey: "quantity")
shipDate = try container.decodeIfPresent(Date.self, forKey: "shipDate")
status = try container.decodeIfPresent(String.self, forKey: "status")
status = try container.decodeIfPresent(Status.self, forKey: "status")
complete = try container.decodeIfPresent(Bool.self, forKey: "complete")
}
}

View File

@@ -13,6 +13,7 @@ open class OuterBoolean: Codable {
// Encodable protocol methods

View File

@@ -16,11 +16,13 @@ open class OuterComposite: Codable {
public var myBoolean: OuterBoolean?
public init(myNumber: OuterNumber?, myString: OuterString?, myBoolean: OuterBoolean?) {
self.myNumber = myNumber
self.myString = myString
self.myBoolean = myBoolean
}
// Encodable protocol methods

View File

@@ -13,6 +13,7 @@ open class OuterNumber: Codable {
// Encodable protocol methods

View File

@@ -13,6 +13,7 @@ open class OuterString: Codable {
// Encodable protocol methods

View File

@@ -25,6 +25,7 @@ open class Pet: Codable {
public var status: Status?
public init(id: Int64?, category: Category?, name: String, photoUrls: [String], tags: [Tag]?, status: Status?) {
self.id = id
self.category = category
@@ -33,6 +34,7 @@ open class Pet: Codable {
self.tags = tags
self.status = status
}
// Encodable protocol methods
@@ -43,8 +45,8 @@ open class Pet: Codable {
try container.encodeIfPresent(id, forKey: "id")
try container.encodeIfPresent(category, forKey: "category")
try container.encode(name, forKey: "name")
try container.encodeArray(photoUrls, forKey: "photoUrls")
try container.encodeArrayIfPresent(tags, forKey: "tags")
try container.encode(photoUrls, forKey: "photoUrls")
try container.encodeIfPresent(tags, forKey: "tags")
try container.encodeIfPresent(status, forKey: "status")
}
@@ -56,9 +58,9 @@ open class Pet: Codable {
id = try container.decodeIfPresent(Int64.self, forKey: "id")
category = try container.decodeIfPresent(Category.self, forKey: "category")
name = try container.decode(String.self, forKey: "name")
photoUrls = try container.decodeArray(String.self, forKey: "photoUrls")
tags = try container.decodeArrayIfPresent(Tag.self, forKey: "tags")
status = try container.decodeIfPresent(String.self, forKey: "status")
photoUrls = try container.decode([String].self, forKey: "photoUrls")
tags = try container.decodeIfPresent([Tag].self, forKey: "tags")
status = try container.decodeIfPresent(Status.self, forKey: "status")
}
}

View File

@@ -15,10 +15,12 @@ open class ReadOnlyFirst: Codable {
public var baz: String?
public init(bar: String?, baz: String?) {
self.bar = bar
self.baz = baz
}
// Encodable protocol methods

View File

@@ -15,9 +15,11 @@ open class Return: Codable {
public var _return: Int?
public init(_return: Int?) {
self._return = _return
}
// Encodable protocol methods

View File

@@ -14,9 +14,11 @@ open class SpecialModelName: Codable {
public var specialPropertyName: Int64?
public init(specialPropertyName: Int64?) {
self.specialPropertyName = specialPropertyName
}
// Encodable protocol methods

View File

@@ -15,10 +15,12 @@ open class Tag: Codable {
public var name: String?
public init(id: Int64?, name: String?) {
self.id = id
self.name = name
}
// Encodable protocol methods

View File

@@ -22,6 +22,7 @@ open class User: Codable {
public var userStatus: Int?
public init(id: Int64?, username: String?, firstName: String?, lastName: String?, email: String?, password: String?, phone: String?, userStatus: Int?) {
self.id = id
self.username = username
@@ -32,6 +33,7 @@ open class User: Codable {
self.phone = phone
self.userStatus = userStatus
}
// Encodable protocol methods

View File

@@ -8,11 +8,3 @@ target 'SwaggerClient' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |configuration|
configuration.build_settings['SWIFT_VERSION'] = "3.0"
end
end
end

View File

@@ -1,9 +1,9 @@
PODS:
- Alamofire (4.5.0)
- Alamofire (4.5.1)
- PetstoreClient (0.0.1):
- Alamofire (~> 4.5)
- RxSwift (~> 3.4.1)
- RxSwift (3.4.1)
- Alamofire (~> 4.5.0)
- RxSwift (~> 4.0)
- RxSwift (4.0.0)
DEPENDENCIES:
- PetstoreClient (from `../`)
@@ -13,10 +13,10 @@ EXTERNAL SOURCES:
:path: ../
SPEC CHECKSUMS:
Alamofire: f28cdffd29de33a7bfa022cbd63ae95a27fae140
PetstoreClient: 23a1f7941fd65b9ebc1806a1646b3ff415371e34
RxSwift: 656f8fbeca5bc372121a72d9ebdd3cd3bc0ffade
Alamofire: 2d95912bf4c34f164fdfc335872e8c312acaea4a
PetstoreClient: 321849311dc2fb14d6801d393b57c016953b6319
RxSwift: fd680d75283beb5e2559486f3c0ff852f0d35334
PODFILE CHECKSUM: 417049e9ed0e4680602b34d838294778389bd418
PODFILE CHECKSUM: cedb3058b02f4776d7c31f6d92ae2f674fdf424d
COCOAPODS: 1.1.1
COCOAPODS: 1.3.1

View File

@@ -1,4 +1,4 @@
Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,9 +1,9 @@
![Alamofire: Elegant Networking in Swift](https://raw.githubusercontent.com/Alamofire/Alamofire/assets/alamofire.png)
![Alamofire: Elegant Networking in Swift](https://raw.githubusercontent.com/Alamofire/Alamofire/master/alamofire.png)
[![Build Status](https://travis-ci.org/Alamofire/Alamofire.svg?branch=master)](https://travis-ci.org/Alamofire/Alamofire)
[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Alamofire.svg)](https://img.shields.io/cocoapods/v/Alamofire.svg)
[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![Platform](https://img.shields.io/cocoapods/p/Alamofire.svg?style=flat)](http://cocoadocs.org/docsets/Alamofire)
[![Platform](https://img.shields.io/cocoapods/p/Alamofire.svg?style=flat)](https://alamofire.github.io/Alamofire)
[![Twitter](https://img.shields.io/badge/twitter-@AlamofireSF-blue.svg?style=flat)](http://twitter.com/AlamofireSF)
[![Gitter](https://badges.gitter.im/Alamofire/Alamofire.svg)](https://gitter.im/Alamofire/Alamofire?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
@@ -45,7 +45,7 @@ Alamofire is an HTTP networking library written in Swift.
- [x] TLS Certificate and Public Key Pinning
- [x] Network Reachability
- [x] Comprehensive Unit and Integration Test Coverage
- [x] [Complete Documentation](http://cocoadocs.org/docsets/Alamofire)
- [x] [Complete Documentation](https://alamofire.github.io/Alamofire)
## Component Libraries
@@ -57,8 +57,8 @@ In order to keep Alamofire focused specifically on core networking implementatio
## Requirements
- iOS 8.0+ / macOS 10.10+ / tvOS 9.0+ / watchOS 2.0+
- Xcode 8.1, 8.2, 8.3, and 9.0
- Swift 3.0, 3.1, 3.2, and 4.0
- Xcode 8.3+
- Swift 3.1+
## Migration Guides
@@ -84,7 +84,7 @@ In order to keep Alamofire focused specifically on core networking implementatio
$ gem install cocoapods
```
> CocoaPods 1.1.0+ is required to build Alamofire 4.0.0+.
> CocoaPods 1.1+ is required to build Alamofire 4.0+.
To integrate Alamofire into your Xcode project using CocoaPods, specify it in your `Podfile`:
@@ -94,7 +94,7 @@ platform :ios, '10.0'
use_frameworks!
target '<Your Target Name>' do
pod 'Alamofire', '~> 4.4'
pod 'Alamofire', '~> 4.5'
end
```
@@ -118,7 +118,7 @@ $ brew install carthage
To integrate Alamofire into your Xcode project using Carthage, specify it in your `Cartfile`:
```ogdl
github "Alamofire/Alamofire" ~> 4.4
github "Alamofire/Alamofire" ~> 4.5
```
Run `carthage update` to build the framework and drag the built `Alamofire.framework` into your Xcode project.
@@ -736,7 +736,7 @@ When sending relatively small amounts of data to a server using JSON or URL enco
#### Uploading Data
```swift
let imageData = UIPNGRepresentation(image)!
let imageData = UIImagePNGRepresentation(image)!
Alamofire.upload(imageData, to: "https://httpbin.org/post").responseJSON { response in
debugPrint(response)
@@ -1812,10 +1812,15 @@ There are some important things to remember when using network reachability to d
The following radars have some effect on the current implementation of Alamofire.
- [`rdar://21349340`](http://www.openradar.me/radar?id=5517037090635776) - Compiler throwing warning due to toll-free bridging issue in test case
- [`rdar://26761490`](http://www.openradar.me/radar?id=5010235949318144) - Swift string interpolation causing memory leak with common usage
- `rdar://26870455` - Background URL Session Configurations do not work in the simulator
- `rdar://26849668` - Some URLProtocol APIs do not properly handle `URLRequest`
## Resolved Radars
The following radars have been resolved over time after being filed against the Alamofire project.
- [`rdar://26761490`](http://www.openradar.me/radar?id=5010235949318144) - Swift string interpolation causing memory leak with common usage (Resolved on 9/1/17 in Xcode 9 beta 6).
## FAQ
### What's the origin of the name Alamofire?

View File

@@ -1,7 +1,7 @@
//
// AFError.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
//
// Alamofire.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
//
// DispatchQueue+Alamofire.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
//
// MultipartFormData.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
//
// NetworkReachabilityManager.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
//
// Notifications.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
//
// ParameterEncoding.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -223,9 +223,9 @@ public struct URLEncoding: ParameterEncoding {
let endIndex = string.index(index, offsetBy: batchSize, limitedBy: string.endIndex) ?? string.endIndex
let range = startIndex..<endIndex
let substring = string.substring(with: range)
let substring = string[range]
escaped += substring.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? substring
escaped += substring.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? String(substring)
index = endIndex
}
@@ -241,11 +241,7 @@ public struct URLEncoding: ParameterEncoding {
let value = parameters[key]!
components += queryComponents(fromKey: key, value: value)
}
#if swift(>=4.0)
return components.map { "\($0.0)=\($0.1)" }.joined(separator: "&")
#else
return components.map { "\($0)=\($1)" }.joined(separator: "&")
#endif
}
private func encodesParametersInURL(with method: HTTPMethod) -> Bool {

View File

@@ -1,7 +1,7 @@
//
// Request.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -293,11 +293,12 @@ extension Request: CustomDebugStringConvertible {
if let credentials = credentialStorage.credentials(for: protectionSpace)?.values {
for credential in credentials {
components.append("-u \(credential.user!):\(credential.password!)")
guard let user = credential.user, let password = credential.password else { continue }
components.append("-u \(user):\(password)")
}
} else {
if let credential = delegate.credential {
components.append("-u \(credential.user!):\(credential.password!)")
if let credential = delegate.credential, let user = credential.user, let password = credential.password {
components.append("-u \(user):\(password)")
}
}
}
@@ -308,7 +309,12 @@ extension Request: CustomDebugStringConvertible {
let cookies = cookieStorage.cookies(for: url), !cookies.isEmpty
{
let string = cookies.reduce("") { $0 + "\($1.name)=\($1.value);" }
#if swift(>=3.2)
components.append("-b \"\(string[..<string.index(before: string.endIndex)])\"")
#else
components.append("-b \"\(string.substring(to: string.characters.index(before: string.endIndex)))\"")
#endif
}
}

View File

@@ -1,7 +1,7 @@
//
// Response.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
//
// ResponseSerialization.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
//
// Result.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
//
// ServerTrustPolicy.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
//
// SessionDelegate.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
//
// SessionManager.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -58,18 +58,10 @@ open class SessionManager {
let acceptEncoding: String = "gzip;q=1.0, compress;q=0.5"
// Accept-Language HTTP Header; see https://tools.ietf.org/html/rfc7231#section-5.3.5
#if swift(>=4.0)
let acceptLanguage = Locale.preferredLanguages.prefix(6).enumerated().map { enumeratedLanguage in
let (index, languageCode) = enumeratedLanguage
let quality = 1.0 - (Double(index) * 0.1)
return "\(languageCode);q=\(quality)"
}.joined(separator: ", ")
#else
let acceptLanguage = Locale.preferredLanguages.prefix(6).enumerated().map { index, languageCode in
let quality = 1.0 - (Double(index) * 0.1)
return "\(languageCode);q=\(quality)"
}.joined(separator: ", ")
#endif
// User-Agent Header; see https://tools.ietf.org/html/rfc7231#section-5.5.3
// Example: `iOS Example/1.0 (org.alamofire.iOS-Example; build:1; iOS 10.0.0) Alamofire/4.0.0`

View File

@@ -1,7 +1,7 @@
//
// TaskDelegate.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -40,17 +40,30 @@ open class TaskDelegate: NSObject {
public var error: Error?
var task: URLSessionTask? {
didSet { reset() }
set {
taskLock.lock(); defer { taskLock.unlock() }
_task = newValue
}
get {
taskLock.lock(); defer { taskLock.unlock() }
return _task
}
}
var initialResponseTime: CFAbsoluteTime?
var credential: URLCredential?
var metrics: AnyObject? // URLSessionTaskMetrics
private var _task: URLSessionTask? {
didSet { reset() }
}
private let taskLock = NSLock()
// MARK: Lifecycle
init(task: URLSessionTask?) {
self.task = task
_task = task
self.queue = {
let operationQueue = OperationQueue()

View File

@@ -1,7 +1,7 @@
//
// Timeline.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,7 +1,7 @@
//
// Validation.swift
//
// Copyright (c) 2014-2016 Alamofire Software Foundation (http://alamofire.org/)
// Copyright (c) 2014-2017 Alamofire Software Foundation (http://alamofire.org/)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
@@ -48,7 +48,13 @@ extension Request {
init?(_ string: String) {
let components: [String] = {
let stripped = string.trimmingCharacters(in: .whitespacesAndNewlines)
#if swift(>=3.2)
let split = stripped[..<(stripped.range(of: ";")?.lowerBound ?? stripped.endIndex)]
#else
let split = stripped.substring(to: stripped.range(of: ";")?.lowerBound ?? stripped.endIndex)
#endif
return split.components(separatedBy: "/")
}()

View File

@@ -13,13 +13,13 @@
"license": "Proprietary",
"homepage": "https://github.com/swagger-api/swagger-codegen",
"summary": "PetstoreClient",
"source_files": "PetstoreClient/Classes/Swaggers/**/*.swift",
"source_files": "PetstoreClient/Classes/**/*.swift",
"dependencies": {
"RxSwift": [
"~> 3.4.1"
"~> 4.0"
],
"Alamofire": [
"~> 4.5"
"~> 4.5.0"
]
}
}

View File

@@ -1,9 +1,9 @@
PODS:
- Alamofire (4.5.0)
- Alamofire (4.5.1)
- PetstoreClient (0.0.1):
- Alamofire (~> 4.5)
- RxSwift (~> 3.4.1)
- RxSwift (3.4.1)
- Alamofire (~> 4.5.0)
- RxSwift (~> 4.0)
- RxSwift (4.0.0)
DEPENDENCIES:
- PetstoreClient (from `../`)
@@ -13,10 +13,10 @@ EXTERNAL SOURCES:
:path: ../
SPEC CHECKSUMS:
Alamofire: f28cdffd29de33a7bfa022cbd63ae95a27fae140
PetstoreClient: 23a1f7941fd65b9ebc1806a1646b3ff415371e34
RxSwift: 656f8fbeca5bc372121a72d9ebdd3cd3bc0ffade
Alamofire: 2d95912bf4c34f164fdfc335872e8c312acaea4a
PetstoreClient: 321849311dc2fb14d6801d393b57c016953b6319
RxSwift: fd680d75283beb5e2559486f3c0ff852f0d35334
PODFILE CHECKSUM: 417049e9ed0e4680602b34d838294778389bd418
PODFILE CHECKSUM: cedb3058b02f4776d7c31f6d92ae2f674fdf424d
COCOAPODS: 1.1.1
COCOAPODS: 1.3.1

View File

@@ -80,7 +80,7 @@ struct Bag<T> : CustomDebugStringConvertible {
}
if _pairs.count < arrayDictionaryMaxSize {
_pairs.append(key: key, value: element)
_pairs.append((key: key, value: element))
return key
}

View File

@@ -52,7 +52,11 @@ struct PriorityQueue<Element> {
private mutating func removeAt(_ index: Int) {
let removingLast = index == _elements.count - 1
if !removingLast {
#if swift(>=3.2)
_elements.swapAt(index, _elements.count - 1)
#else
swap(&_elements[index], &_elements[_elements.count - 1])
#endif
}
_ = _elements.popLast()
@@ -72,8 +76,11 @@ struct PriorityQueue<Element> {
while unbalancedIndex > 0 {
let parentIndex = (unbalancedIndex - 1) / 2
guard _hasHigherPriority(_elements[unbalancedIndex], _elements[parentIndex]) else { break }
#if swift(>=3.2)
_elements.swapAt(unbalancedIndex, parentIndex)
#else
swap(&_elements[unbalancedIndex], &_elements[parentIndex])
#endif
unbalancedIndex = parentIndex
}
}
@@ -99,7 +106,11 @@ struct PriorityQueue<Element> {
guard highestPriorityIndex != unbalancedIndex else { break }
#if swift(>=3.2)
_elements.swapAt(highestPriorityIndex, unbalancedIndex)
#else
swap(&_elements[highestPriorityIndex], &_elements[unbalancedIndex])
#endif
unbalancedIndex = highestPriorityIndex
}
}

View File

@@ -3,11 +3,8 @@
[![Travis CI](https://travis-ci.org/ReactiveX/RxSwift.svg?branch=master)](https://travis-ci.org/ReactiveX/RxSwift) ![platforms](https://img.shields.io/badge/platforms-iOS%20%7C%20macOS%20%7C%20tvOS%20%7C%20watchOS%20%7C%20Linux-333333.svg) ![pod](https://img.shields.io/cocoapods/v/RxSwift.svg) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Swift Package Manager compatible](https://img.shields.io/badge/Swift%20Package%20Manager-compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager)
## About Rx
**:warning: This readme describes RxSwift 3.0 version that requires Swift 3.0.**
**:warning: If you are looking for Swift 2.3 compatible version, please take a look at RxSwift ~> 2.0 versions and [swift-2.3](https://github.com/ReactiveX/RxSwift/tree/rxswift-2.0) branch.**
* RxSwift 4.x / Swift 4.x can be found in [**rxswift4.0-swift4.0** branch](https://github.com/ReactiveX/RxSwift/tree/rxswift4.0-swift4.0).
* RxSwift 3.x / Swift 3.x can be found in [**master** branch](https://github.com/ReactiveX/RxSwift/tree/master).
Rx is a [generic abstraction of computation](https://youtu.be/looJcaeboBY) expressed through `Observable<Element>` interface.
@@ -110,6 +107,7 @@ searchResults
* Xcode 8.0
* Swift 3.0
* Swift 2.3 ([use `rxswift-2.0` branch](https://github.com/ReactiveX/RxSwift/tree/rxswift-2.0) instead)
## Installation
@@ -183,6 +181,12 @@ let package = Package(
$ swift build
```
To build or test a module with RxTest dependency, set `TEST=1`. ([RxSwift >= 3.4.2](https://github.com/ReactiveX/RxSwift/releases/tag/3.4.2))
```bash
$ TEST=1 swift test
```
### Manually using git submodules
* Add RxSwift as a submodule
@@ -199,6 +203,8 @@ $ git submodule add git@github.com:ReactiveX/RxSwift.git
* [http://reactivex.io/](http://reactivex.io/)
* [Reactive Extensions GitHub (GitHub)](https://github.com/Reactive-Extensions)
* [RxSwift RayWenderlich.com Book](https://store.raywenderlich.com/products/rxswift)
* [Boxue.io RxSwift Online Course](https://boxueio.com/series/rxswift-101) (Chinese 🇨🇳)
* [Erik Meijer (Wikipedia)](http://en.wikipedia.org/wiki/Erik_Meijer_%28computer_scientist%29)
* [Expert to Expert: Brian Beckman and Erik Meijer - Inside the .NET Reactive Framework (Rx) (video)](https://youtu.be/looJcaeboBY)
* [Reactive Programming Overview (Jafar Husain from Netflix)](https://www.youtube.com/watch?v=dwP1TNXE6fc)

View File

@@ -1,18 +0,0 @@
//
// SynchronizedSubscribeType.swift
// RxSwift
//
// Created by Krunoslav Zaher on 10/25/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
protocol SynchronizedSubscribeType : class, ObservableType, Lock {
func _synchronized_subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E
}
extension SynchronizedSubscribeType {
func synchronizedSubscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E {
lock(); defer { unlock() }
return _synchronized_subscribe(observer)
}
}

View File

@@ -35,15 +35,179 @@ extension Observable {
}
}
extension ObservableType {
/**
Projects each element of an observable sequence into a new form by incorporating the element's index.
- seealso: [map operator on reactivex.io](http://reactivex.io/documentation/operators/map.html)
- parameter selector: A transform function to apply to each source element; the second parameter of the function represents the index of the source element.
- returns: An observable sequence whose elements are the result of invoking the transform function on each element of source.
*/
@available(*, deprecated, message: "Please use enumerated().map()")
public func mapWithIndex<R>(_ selector: @escaping (E, Int) throws -> R)
-> Observable<R> {
return enumerated().map { try selector($0.element, $0.index) }
}
/**
Projects each element of an observable sequence to an observable sequence by incorporating the element's index and merges the resulting observable sequences into one observable sequence.
- seealso: [flatMap operator on reactivex.io](http://reactivex.io/documentation/operators/flatmap.html)
- parameter selector: A transform function to apply to each element; the second parameter of the function represents the index of the source element.
- returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence.
*/
@available(*, deprecated, message: "Please use enumerated().flatMap()")
public func flatMapWithIndex<O: ObservableConvertibleType>(_ selector: @escaping (E, Int) throws -> O)
-> Observable<O.E> {
return enumerated().flatMap { try selector($0.element, $0.index) }
}
/**
Bypasses elements in an observable sequence as long as a specified condition is true and then returns the remaining elements.
The element's index is used in the logic of the predicate function.
- seealso: [skipWhile operator on reactivex.io](http://reactivex.io/documentation/operators/skipwhile.html)
- parameter predicate: A function to test each element for a condition; the second parameter of the function represents the index of the source element.
- returns: An observable sequence that contains the elements from the input sequence starting at the first element in the linear series that does not pass the test specified by predicate.
*/
@available(*, deprecated, message: "Please use enumerated().skipWhile().map()")
public func skipWhileWithIndex(_ predicate: @escaping (E, Int) throws -> Bool) -> Observable<E> {
return enumerated().skipWhile { try predicate($0.element, $0.index) }.map { $0.element }
}
/**
Returns elements from an observable sequence as long as a specified condition is true.
The element's index is used in the logic of the predicate function.
- seealso: [takeWhile operator on reactivex.io](http://reactivex.io/documentation/operators/takewhile.html)
- parameter predicate: A function to test each element for a condition; the second parameter of the function represents the index of the source element.
- returns: An observable sequence that contains the elements from the input sequence that occur before the element at which the test no longer passes.
*/
@available(*, deprecated, message: "Please use enumerated().takeWhile().map()")
public func takeWhileWithIndex(_ predicate: @escaping (E, Int) throws -> Bool) -> Observable<E> {
return enumerated().takeWhile { try predicate($0.element, $0.index) }.map { $0.element }
}
}
extension Disposable {
/// Deprecated in favor of `disposed(by:)`
///
/// **@available(\*, deprecated, message="use disposed(by:) instead")**
///
/// Adds `self` to `bag`.
///
/// - parameter bag: `DisposeBag` to add `self` to.
@available(*, deprecated, message: "use disposed(by:) instead", renamed: "disposed(by:)")
public func addDisposableTo(_ bag: DisposeBag) {
disposed(by: bag)
}
}
extension ObservableType {
/**
Returns an observable sequence that shares a single subscription to the underlying sequence, and immediately upon subscription replays latest element in buffer.
This operator is a specialization of replay which creates a subscription when the number of observers goes from zero to one, then shares that subscription with all subsequent observers until the number of observers returns to zero, at which point the subscription is disposed.
- seealso: [shareReplay operator on reactivex.io](http://reactivex.io/documentation/operators/replay.html)
- returns: An observable sequence that contains the elements of a sequence produced by multicasting the source sequence.
*/
@available(*, deprecated, message: "use share(replay: 1) instead", renamed: "share(replay:)")
public func shareReplayLatestWhileConnected()
-> Observable<E> {
return share(replay: 1, scope: .whileConnected)
}
}
extension ObservableType {
/**
Returns an observable sequence that shares a single subscription to the underlying sequence, and immediately upon subscription replays maximum number of elements in buffer.
This operator is a specialization of replay which creates a subscription when the number of observers goes from zero to one, then shares that subscription with all subsequent observers until the number of observers returns to zero, at which point the subscription is disposed.
- seealso: [shareReplay operator on reactivex.io](http://reactivex.io/documentation/operators/replay.html)
- parameter bufferSize: Maximum element count of the replay buffer.
- returns: An observable sequence that contains the elements of a sequence produced by multicasting the source sequence.
*/
@available(*, deprecated, message: "Suggested replacement is `share(replay: 1)`. In case old 3.x behavior of `shareReplay` is required please use `share(replay: 1, scope: .forever)` instead.", renamed: "share(replay:)")
public func shareReplay(_ bufferSize: Int)
-> Observable<E> {
return self.share(replay: bufferSize, scope: .forever)
}
}
/// Variable is a wrapper for `BehaviorSubject`.
///
/// Unlike `BehaviorSubject` it can't terminate with error, and when variable is deallocated
/// it will complete its observable sequence (`asObservable`).
public final class Variable<Element> {
public typealias E = Element
private let _subject: BehaviorSubject<Element>
private var _lock = SpinLock()
// state
private var _value: E
#if DEBUG
fileprivate let _synchronizationTracker = SynchronizationTracker()
#endif
/// Gets or sets current value of variable.
///
/// Whenever a new value is set, all the observers are notified of the change.
///
/// Even if the newly set value is same as the old value, observers are still notified for change.
public var value: E {
get {
_lock.lock(); defer { _lock.unlock() }
return _value
}
set(newValue) {
#if DEBUG
_synchronizationTracker.register(synchronizationErrorMessage: .variable)
defer { _synchronizationTracker.unregister() }
#endif
_lock.lock()
_value = newValue
_lock.unlock()
_subject.on(.next(newValue))
}
}
/// Initializes variable with initial value.
///
/// - parameter value: Initial variable value.
public init(_ value: Element) {
_value = value
_subject = BehaviorSubject(value: value)
}
/// - returns: Canonical interface for push style sequence
public func asObservable() -> Observable<E> {
return _subject
}
deinit {
_subject.on(.completed)
}
}

View File

@@ -13,7 +13,7 @@ let RxCompositeFailures = "RxCompositeFailures"
public enum RxError
: Swift.Error
, CustomDebugStringConvertible {
/// Unknown error occured.
/// Unknown error occurred.
case unknown
/// Performing an action on disposed object.
case disposed(object: AnyObject)
@@ -34,11 +34,11 @@ extension RxError {
public var debugDescription: String {
switch self {
case .unknown:
return "Unknown error occured."
return "Unknown error occurred."
case .disposed(let object):
return "Object `\(object)` was already disposed."
case .overflow:
return "Arithmetic overflow occured."
return "Arithmetic overflow occurred."
case .argumentOutOfRange:
return "Argument out of range."
case .noElements:

View File

@@ -9,7 +9,7 @@
/// Represents an object that immediately schedules units of work.
public protocol ImmediateSchedulerType {
/**
Schedules an action to be executed immediatelly.
Schedules an action to be executed immediately.
- parameter state: State passed to the action to be executed.
- parameter action: Action to be executed.

View File

@@ -6,7 +6,7 @@
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
/// Type that can be converted to observable sequence (`Observer<E>`).
/// Type that can be converted to observable sequence (`Observable<E>`).
public protocol ObservableConvertibleType {
/// Type of elements in sequence.
associatedtype E

View File

@@ -6,112 +6,136 @@
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
#if DEBUG
import Foundation
#endif
extension ObservableType {
/**
Subscribes an event handler to an observable sequence.
- parameter on: Action to invoke for each event in the observable sequence.
- returns: Subscription object used to unsubscribe from the observable sequence.
*/
Subscribes an event handler to an observable sequence.
- parameter on: Action to invoke for each event in the observable sequence.
- returns: Subscription object used to unsubscribe from the observable sequence.
*/
public func subscribe(_ on: @escaping (Event<E>) -> Void)
-> Disposable {
let observer = AnonymousObserver { e in
on(e)
}
return self.subscribeSafe(observer)
}
#if DEBUG
/**
Subscribes an element handler, an error handler, a completion handler and disposed handler to an observable sequence.
- parameter onNext: Action to invoke for each element in the observable sequence.
- parameter onError: Action to invoke upon errored termination of the observable sequence.
- parameter onCompleted: Action to invoke upon graceful termination of the observable sequence.
- parameter onDisposed: Action to invoke upon any type of termination of sequence (if the sequence has
gracefully completed, errored, or if the generation is cancelled by disposing subscription).
- returns: Subscription object used to unsubscribe from the observable sequence.
*/
public func subscribe(file: String = #file, line: UInt = #line, function: String = #function, onNext: ((E) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil)
-> Disposable {
let disposable: Disposable
if let disposed = onDisposed {
disposable = Disposables.create(with: disposed)
}
else {
disposable = Disposables.create()
}
let observer = AnonymousObserver<E> { e in
switch e {
case .next(let value):
onNext?(value)
case .error(let e):
if let onError = onError {
onError(e)
}
else {
print("Received unhandled error: \(file):\(line):\(function) -> \(e)")
}
disposable.dispose()
case .completed:
onCompleted?()
disposable.dispose()
let observer = AnonymousObserver { e in
on(e)
}
}
return Disposables.create(
self.subscribeSafe(observer),
disposable
)
return self.asObservable().subscribe(observer)
}
#else
/**
Subscribes an element handler, an error handler, a completion handler and disposed handler to an observable sequence.
- parameter onNext: Action to invoke for each element in the observable sequence.
- parameter onError: Action to invoke upon errored termination of the observable sequence.
- parameter onCompleted: Action to invoke upon graceful termination of the observable sequence.
- parameter onDisposed: Action to invoke upon any type of termination of sequence (if the sequence has
gracefully completed, errored, or if the generation is cancelled by disposing subscription).
- returns: Subscription object used to unsubscribe from the observable sequence.
*/
Subscribes an element handler, an error handler, a completion handler and disposed handler to an observable sequence.
- parameter onNext: Action to invoke for each element in the observable sequence.
- parameter onError: Action to invoke upon errored termination of the observable sequence.
- parameter onCompleted: Action to invoke upon graceful termination of the observable sequence.
- parameter onDisposed: Action to invoke upon any type of termination of sequence (if the sequence has
gracefully completed, errored, or if the generation is canceled by disposing subscription).
- returns: Subscription object used to unsubscribe from the observable sequence.
*/
public func subscribe(onNext: ((E) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil)
-> Disposable {
#if DEBUG
let disposable: Disposable
if let disposed = onDisposed {
disposable = Disposables.create(with: disposed)
}
else {
disposable = Disposables.create()
}
let synchronizationTracker = SynchronizationTracker()
let disposable: Disposable
let callStack = Thread.callStackSymbols
if let disposed = onDisposed {
disposable = Disposables.create(with: disposed)
}
else {
disposable = Disposables.create()
}
let observer = AnonymousObserver<E> { e in
switch e {
case .next(let value):
onNext?(value)
case .error(let e):
onError?(e)
disposable.dispose()
case .completed:
onCompleted?()
disposable.dispose()
}
}
return Disposables.create(
self.subscribeSafe(observer),
disposable
)
}
#endif
}
extension ObservableType {
/// All internal subscribe calls go through this method.
fileprivate func subscribeSafe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E {
return self.asObservable().subscribe(observer)
let observer = AnonymousObserver<E> { event in
synchronizationTracker.register(synchronizationErrorMessage: .default)
defer { synchronizationTracker.unregister() }
switch event {
case .next(let value):
onNext?(value)
case .error(let error):
if let onError = onError {
onError(error)
}
else {
Hooks.defaultErrorHandler(callStack, error)
}
disposable.dispose()
case .completed:
onCompleted?()
disposable.dispose()
}
}
return Disposables.create(
self.asObservable().subscribe(observer),
disposable
)
#else
let disposable: Disposable
if let disposed = onDisposed {
disposable = Disposables.create(with: disposed)
}
else {
disposable = Disposables.create()
}
let observer = AnonymousObserver<E> { event in
switch event {
case .next(let value):
onNext?(value)
case .error(let error):
if let onError = onError {
onError(error)
}
else {
Hooks.defaultErrorHandler([], error)
}
disposable.dispose()
case .completed:
onCompleted?()
disposable.dispose()
}
}
return Disposables.create(
self.asObservable().subscribe(observer),
disposable
)
#endif
}
}
import class Foundation.NSRecursiveLock
extension Hooks {
public typealias DefaultErrorHandler = (_ subscriptionCallStack: [String], _ error: Error) -> ()
fileprivate static let _lock = RecursiveLock()
fileprivate static var _defaultErrorHandler: DefaultErrorHandler = { subscriptionCallStack, error in
#if DEBUG
let serializedCallStack = subscriptionCallStack.joined(separator: "\n")
print("Unhandled error happened: \(error)\n subscription called from:\n\(serializedCallStack)")
#endif
}
/// Error handler called in case onError handler wasn't provided.
public static var defaultErrorHandler: DefaultErrorHandler {
get {
_lock.lock(); defer { _lock.unlock() }
return _defaultErrorHandler
}
set {
_lock.lock(); defer { _lock.unlock() }
_defaultErrorHandler = newValue
}
}
}

View File

@@ -8,9 +8,6 @@
/// Represents a push style sequence.
public protocol ObservableType : ObservableConvertibleType {
/// Type of elements in sequence.
associatedtype E
/**
Subscribes `observer` to receive events for this sequence.
@@ -29,7 +26,7 @@ public protocol ObservableType : ObservableConvertibleType {
When sequence sends `Complete` or `Error` event all internal resources that compute sequence elements
will be freed.
To cancel production of sequence elements and free resources immediatelly, call `dispose` on returned
To cancel production of sequence elements and free resources immediately, call `dispose` on returned
subscription.
- returns: Subscription for `observer` that can be used to cancel production of sequence elements and free resources.

View File

@@ -6,7 +6,7 @@
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
extension Observable {
extension ObservableType {
/**
Propagates the observable sequence that reacts first.
@@ -14,8 +14,8 @@ extension Observable {
- returns: An observable sequence that surfaces any of the given sequences, whichever reacted first.
*/
public static func amb<S: Sequence>(_ sequence: S) -> Observable<Element>
where S.Iterator.Element == Observable<Element> {
public static func amb<S: Sequence>(_ sequence: S) -> Observable<E>
where S.Iterator.Element == Observable<E> {
return sequence.reduce(Observable<S.Iterator.Element.E>.never()) { a, o in
return a.amb(o.asObservable())
}

View File

@@ -36,7 +36,7 @@ extension ObservableType {
}
extension Observable {
extension ObservableType {
/**
Continues an observable sequence that is terminated by an error with the next observable sequence.
@@ -44,8 +44,8 @@ extension Observable {
- returns: An observable sequence containing elements from consecutive source sequences until a source sequence terminates successfully.
*/
public static func catchError<S: Sequence>(_ sequence: S) -> Observable<Element>
where S.Iterator.Element == Observable<Element> {
public static func catchError<S: Sequence>(_ sequence: S) -> Observable<E>
where S.Iterator.Element == Observable<E> {
return CatchSequence(sources: sequence)
}
}
@@ -77,7 +77,7 @@ extension ObservableType {
*/
public func retry(_ maxAttemptCount: Int)
-> Observable<E> {
return CatchSequence(sources: repeatElement(self.asObservable(), count: maxAttemptCount))
return CatchSequence(sources: Swift.repeatElement(self.asObservable(), count: maxAttemptCount))
}
}

View File

@@ -6,7 +6,7 @@
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
extension Observable {
extension ObservableType {
/**
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
@@ -15,7 +15,7 @@ extension Observable {
- parameter resultSelector: Function to invoke whenever any of the sources produces an element.
- returns: An observable sequence containing the result of combining elements of the sources using the specified result selector function.
*/
public static func combineLatest<C: Collection>(_ collection: C, _ resultSelector: @escaping ([C.Iterator.Element.E]) throws -> Element) -> Observable<Element>
public static func combineLatest<C: Collection>(_ collection: C, _ resultSelector: @escaping ([C.Iterator.Element.E]) throws -> E) -> Observable<E>
where C.Iterator.Element: ObservableType {
return CombineLatestCollectionType(sources: collection, resultSelector: resultSelector)
}
@@ -27,8 +27,8 @@ extension Observable {
- returns: An observable sequence containing the result of combining elements of the sources.
*/
public static func combineLatest<C: Collection>(_ collection: C) -> Observable<[Element]>
where C.Iterator.Element: ObservableType, C.Iterator.Element.E == Element {
public static func combineLatest<C: Collection>(_ collection: C) -> Observable<[E]>
where C.Iterator.Element: ObservableType, C.Iterator.Element.E == E {
return CombineLatestCollectionType(sources: collection, resultSelector: { $0 })
}
}
@@ -146,7 +146,7 @@ final fileprivate class CombineLatestCollectionType<C: Collection, R> : Producer
init(sources: C, resultSelector: @escaping ResultSelector) {
_sources = sources
_resultSelector = resultSelector
_count = Int(self._sources.count.toIntMax())
_count = Int(Int64(self._sources.count))
}
override func run<O : ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == R {

View File

@@ -11,7 +11,7 @@
// 2
extension Observable {
extension ObservableType {
/**
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
@@ -109,7 +109,7 @@ final class CombineLatest2<E1, E2, R> : Producer<R> {
// 3
extension Observable {
extension ObservableType {
/**
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
@@ -214,7 +214,7 @@ final class CombineLatest3<E1, E2, E3, R> : Producer<R> {
// 4
extension Observable {
extension ObservableType {
/**
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
@@ -326,7 +326,7 @@ final class CombineLatest4<E1, E2, E3, E4, R> : Producer<R> {
// 5
extension Observable {
extension ObservableType {
/**
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
@@ -445,7 +445,7 @@ final class CombineLatest5<E1, E2, E3, E4, E5, R> : Producer<R> {
// 6
extension Observable {
extension ObservableType {
/**
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
@@ -571,7 +571,7 @@ final class CombineLatest6<E1, E2, E3, E4, E5, E6, R> : Producer<R> {
// 7
extension Observable {
extension ObservableType {
/**
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.
@@ -704,7 +704,7 @@ final class CombineLatest7<E1, E2, E3, E4, E5, E6, E7, R> : Producer<R> {
// 8
extension Observable {
extension ObservableType {
/**
Merges the specified observable sequences into one observable sequence by using the selector function whenever any of the observable sequences produces an element.

View File

@@ -21,7 +21,7 @@ extension ObservableType {
}
}
extension Observable {
extension ObservableType {
/**
Concatenates all observable sequences in the given sequence, as long as the previous observable sequence terminated successfully.
@@ -35,8 +35,8 @@ extension Observable {
- returns: An observable sequence that contains the elements of each given sequence, in sequential order.
*/
public static func concat<S: Sequence >(_ sequence: S) -> Observable<Element>
where S.Iterator.Element == Observable<Element> {
public static func concat<S: Sequence >(_ sequence: S) -> Observable<E>
where S.Iterator.Element == Observable<E> {
return Concat(sources: sequence, count: nil)
}
@@ -53,9 +53,9 @@ extension Observable {
- returns: An observable sequence that contains the elements of each given sequence, in sequential order.
*/
public static func concat<S: Collection >(_ collection: S) -> Observable<Element>
where S.Iterator.Element == Observable<Element> {
return Concat(sources: collection, count: collection.count.toIntMax())
public static func concat<S: Collection >(_ collection: S) -> Observable<E>
where S.Iterator.Element == Observable<E> {
return Concat(sources: collection, count: Int64(collection.count))
}
/**
@@ -71,8 +71,8 @@ extension Observable {
- returns: An observable sequence that contains the elements of each given sequence, in sequential order.
*/
public static func concat(_ sources: Observable<Element> ...) -> Observable<Element> {
return Concat(sources: sources, count: sources.count.toIntMax())
public static func concat(_ sources: Observable<E> ...) -> Observable<E> {
return Concat(sources: sources, count: Int64(sources.count))
}
}
@@ -128,3 +128,4 @@ final fileprivate class Concat<S: Sequence> : Producer<S.Iterator.Element.E> whe
return (sink: sink, subscription: subscription)
}
}

View File

@@ -1,129 +0,0 @@
//
// ConnectableObservable.swift
// RxSwift
//
// Created by Krunoslav Zaher on 3/1/15.
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
extension ObservableType {
/**
Multicasts the source sequence notifications through the specified subject to the resulting connectable observable.
Upon connection of the connectable observable, the subject is subscribed to the source exactly one, and messages are forwarded to the observers registered with the connectable observable.
For specializations with fixed subject types, see `publish` and `replay`.
- seealso: [multicast operator on reactivex.io](http://reactivex.io/documentation/operators/publish.html)
- parameter subject: Subject to push source elements into.
- returns: A connectable observable sequence that upon connection causes the source sequence to push results into the specified subject.
*/
public func multicast<S: SubjectType>(_ subject: S)
-> ConnectableObservable<S.E> where S.SubjectObserverType.E == E {
return ConnectableObservableAdapter(source: self.asObservable(), subject: subject)
}
}
/**
Represents an observable wrapper that can be connected and disconnected from its underlying observable sequence.
*/
public class ConnectableObservable<Element>
: Observable<Element>
, ConnectableObservableType {
/**
Connects the observable wrapper to its source. All subscribed observers will receive values from the underlying observable sequence as long as the connection is established.
- returns: Disposable used to disconnect the observable wrapper from its source, causing subscribed observer to stop receiving values from the underlying observable sequence.
*/
public func connect() -> Disposable {
rxAbstractMethod()
}
}
final class Connection<S: SubjectType> : ObserverType, Disposable {
typealias E = S.SubjectObserverType.E
private var _lock: RecursiveLock
// state
private var _parent: ConnectableObservableAdapter<S>?
private var _subscription : Disposable?
private var _subjectObserver: S.SubjectObserverType
private var _disposed: Bool = false
init(parent: ConnectableObservableAdapter<S>, subjectObserver: S.SubjectObserverType, lock: RecursiveLock, subscription: Disposable) {
_parent = parent
_subscription = subscription
_lock = lock
_subjectObserver = subjectObserver
}
func on(_ event: Event<S.SubjectObserverType.E>) {
if _disposed {
return
}
_subjectObserver.on(event)
if event.isStopEvent {
self.dispose()
}
}
func dispose() {
_lock.lock(); defer { _lock.unlock() } // {
_disposed = true
guard let parent = _parent else {
return
}
if parent._connection === self {
parent._connection = nil
}
_parent = nil
_subscription?.dispose()
_subscription = nil
// }
}
}
final class ConnectableObservableAdapter<S: SubjectType>
: ConnectableObservable<S.E> {
typealias ConnectionType = Connection<S>
fileprivate let _subject: S
fileprivate let _source: Observable<S.SubjectObserverType.E>
fileprivate let _lock = RecursiveLock()
// state
fileprivate var _connection: ConnectionType?
init(source: Observable<S.SubjectObserverType.E>, subject: S) {
_source = source
_subject = subject
_connection = nil
}
override func connect() -> Disposable {
return _lock.calculateLocked {
if let connection = _connection {
return connection
}
let singleAssignmentDisposable = SingleAssignmentDisposable()
let connection = Connection(parent: self, subjectObserver: _subject.asObserver(), lock: _lock, subscription: singleAssignmentDisposable)
_connection = connection
let subscription = _source.subscribe(connection)
singleAssignmentDisposable.setDisposable(subscription)
return connection
}
}
override func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == S.E {
return _subject.subscribe(observer)
}
}

View File

@@ -6,7 +6,7 @@
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
extension Observable {
extension ObservableType {
// MARK: create
/**
@@ -30,7 +30,7 @@ final fileprivate class AnonymousObservableSink<O: ObserverType> : Sink<O>, Obse
private var _isStopped: AtomicInt = 0
#if DEBUG
fileprivate var _numberOfConcurrentCalls: AtomicInt = 0
fileprivate let _synchronizationTracker = SynchronizationTracker()
#endif
override init(observer: O, cancel: Cancelable) {
@@ -39,13 +39,8 @@ final fileprivate class AnonymousObservableSink<O: ObserverType> : Sink<O>, Obse
func on(_ event: Event<E>) {
#if DEBUG
if AtomicIncrement(&_numberOfConcurrentCalls) > 1 {
rxFatalError("Warning: Recursive call or synchronization error!")
}
defer {
_ = AtomicDecrement(&_numberOfConcurrentCalls)
}
_synchronizationTracker.register(synchronizationErrorMessage: .default)
defer { _synchronizationTracker.unregister() }
#endif
switch event {
case .next:

View File

@@ -52,8 +52,8 @@ final fileprivate class DebugSink<Source: ObservableType, O: ObserverType> : Sin
let maxEventTextLength = 40
let eventText = "\(event)"
let eventNormalized = (eventText.characters.count > maxEventTextLength) && _parent._trimOutput
? String(eventText.characters.prefix(maxEventTextLength / 2)) + "..." + String(eventText.characters.suffix(maxEventTextLength / 2))
let eventNormalized = (eventText.count > maxEventTextLength) && _parent._trimOutput
? String(eventText.prefix(maxEventTextLength / 2)) + "..." + String(eventText.suffix(maxEventTextLength / 2))
: eventText
logEvent(_parent._identifier, dateFormat: _timestampFormatter, content: "Event \(eventNormalized)")
@@ -85,7 +85,7 @@ final fileprivate class Debug<Source: ObservableType> : Producer<Source.E> {
else {
let trimmedFile: String
if let lastIndex = file.lastIndexOf("/") {
trimmedFile = file[file.index(after: lastIndex) ..< file.endIndex]
trimmedFile = String(file[file.index(after: lastIndex) ..< file.endIndex])
}
else {
trimmedFile = file

View File

@@ -6,7 +6,7 @@
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
extension Observable {
extension ObservableType {
/**
Returns an observable sequence that invokes the specified factory function whenever a new observer subscribes.

View File

@@ -57,7 +57,7 @@ final fileprivate class DelaySink<O: ObserverType>
}
// All of these complications in this method are caused by the fact that
// error should be propagated immediatelly. Error can bepotentially received on different
// error should be propagated immediately. Error can be potentially received on different
// scheduler so this process needs to be synchronized somehow.
//
// Another complication is that scheduler is potentially concurrent so internal queue is used.

View File

@@ -37,18 +37,18 @@ extension ObservableType {
final fileprivate class DoSink<O: ObserverType> : Sink<O>, ObserverType {
typealias Element = O.E
typealias Parent = Do<Element>
typealias EventHandler = (Event<Element>) throws -> Void
private let _parent: Parent
private let _eventHandler: EventHandler
init(parent: Parent, observer: O, cancel: Cancelable) {
_parent = parent
init(eventHandler: @escaping EventHandler, observer: O, cancel: Cancelable) {
_eventHandler = eventHandler
super.init(observer: observer, cancel: cancel)
}
func on(_ event: Event<Element>) {
do {
try _parent._eventHandler(event)
try _eventHandler(event)
forwardOn(event)
if event.isStopEvent {
dispose()
@@ -80,7 +80,7 @@ final fileprivate class Do<Element> : Producer<Element> {
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element {
_onSubscribe?()
let sink = DoSink(parent: self, observer: observer, cancel: cancel)
let sink = DoSink(eventHandler: _eventHandler, observer: observer, cancel: cancel)
let subscription = _source.subscribe(sink)
_onSubscribed?()
let onDispose = _onDispose

View File

@@ -6,7 +6,7 @@
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
extension Observable {
extension ObservableType {
/**
Returns an empty observable sequence, using the specified scheduler to send out the single `Completed` message.

View File

@@ -0,0 +1,62 @@
//
// Enumerated.swift
// RxSwift
//
// Created by Krunoslav Zaher on 8/6/17.
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
//
extension ObservableType {
/**
Enumerates the elements of an observable sequence.
- seealso: [map operator on reactivex.io](http://reactivex.io/documentation/operators/map.html)
- returns: An observable sequence that contains tuples of source sequence elements and their indexes.
*/
public func enumerated()
-> Observable<(index: Int, element: E)> {
return Enumerated(source: self.asObservable())
}
}
final fileprivate class EnumeratedSink<Element, O : ObserverType>: Sink<O>, ObserverType where O.E == (index: Int, element: Element) {
typealias E = Element
var index = 0
func on(_ event: Event<Element>) {
switch event {
case .next(let value):
do {
let nextIndex = try incrementChecked(&index)
let next = (index: nextIndex, element: value)
forwardOn(.next(next))
}
catch let e {
forwardOn(.error(e))
dispose()
}
case .completed:
forwardOn(.completed)
dispose()
case .error(let error):
forwardOn(.error(error))
dispose()
}
}
}
final fileprivate class Enumerated<Element> : Producer<(index: Int, element: Element)> {
private let _source: Observable<Element>
init(source: Observable<Element>) {
_source = source
}
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == (index: Int, element: Element) {
let sink = EnumeratedSink<Element, O>(observer: observer, cancel: cancel)
let subscription = _source.subscribe(sink)
return (sink: sink, subscription: subscription)
}
}

View File

@@ -6,7 +6,7 @@
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
extension Observable {
extension ObservableType {
/**
Returns an observable sequence that terminates with an `error`.

View File

@@ -32,10 +32,11 @@ extension ObservableType {
- returns: An observable sequence that skips all elements of the source sequence.
*/
public func ignoreElements()
-> Observable<E> {
return filter { _ -> Bool in
return false
-> Completable {
return flatMap { _ in
return Observable<Never>.empty()
}
.asCompletable()
}
}

View File

@@ -0,0 +1,42 @@
//
// First.swift
// RxSwift
//
// Created by Krunoslav Zaher on 7/31/17.
// Copyright © 2017 Krunoslav Zaher. All rights reserved.
//
fileprivate final class FirstSink<Element, O: ObserverType> : Sink<O>, ObserverType where O.E == Element? {
typealias E = Element
typealias Parent = First<E>
func on(_ event: Event<E>) {
switch event {
case .next(let value):
forwardOn(.next(value))
forwardOn(.completed)
dispose()
case .error(let error):
forwardOn(.error(error))
dispose()
case .completed:
forwardOn(.next(nil))
forwardOn(.completed)
dispose()
}
}
}
final class First<Element>: Producer<Element?> {
fileprivate let _source: Observable<Element>
init(source: Observable<Element>) {
_source = source
}
override func run<O : ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element? {
let sink = FirstSink(observer: observer, cancel: cancel)
let subscription = _source.subscribe(sink)
return (sink: sink, subscription: subscription)
}
}

View File

@@ -6,7 +6,7 @@
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
extension Observable {
extension ObservableType {
/**
Generates an observable sequence by running a state-driven loop producing the sequence's elements, using the specified scheduler
to run the loop send out observer messages.

View File

@@ -6,7 +6,7 @@
// Copyright © 2015 Krunoslav Zaher. All rights reserved.
//
extension Observable {
extension ObservableType {
/**
Returns an observable sequence that contains a single element.

View File

@@ -21,19 +21,6 @@ extension ObservableType {
-> Observable<R> {
return self.asObservable().composeMap(transform)
}
/**
Projects each element of an observable sequence into a new form by incorporating the element's index.
- seealso: [map operator on reactivex.io](http://reactivex.io/documentation/operators/map.html)
- parameter selector: A transform function to apply to each source element; the second parameter of the function represents the index of the source element.
- returns: An observable sequence whose elements are the result of invoking the transform function on each element of source.
*/
public func mapWithIndex<R>(_ selector: @escaping (E, Int) throws -> R)
-> Observable<R> {
return MapWithIndex(source: asObservable(), selector: selector)
}
}
final fileprivate class MapSink<SourceType, O : ObserverType> : Sink<O>, ObserverType {
@@ -70,62 +57,6 @@ final fileprivate class MapSink<SourceType, O : ObserverType> : Sink<O>, Observe
}
}
final fileprivate class MapWithIndexSink<SourceType, O : ObserverType> : Sink<O>, ObserverType {
typealias Selector = (SourceType, Int) throws -> ResultType
typealias ResultType = O.E
typealias Element = SourceType
typealias Parent = MapWithIndex<SourceType, ResultType>
private let _selector: Selector
private var _index = 0
init(selector: @escaping Selector, observer: O, cancel: Cancelable) {
_selector = selector
super.init(observer: observer, cancel: cancel)
}
func on(_ event: Event<SourceType>) {
switch event {
case .next(let element):
do {
let mappedElement = try _selector(element, try incrementChecked(&_index))
forwardOn(.next(mappedElement))
}
catch let e {
forwardOn(.error(e))
dispose()
}
case .error(let error):
forwardOn(.error(error))
dispose()
case .completed:
forwardOn(.completed)
dispose()
}
}
}
final fileprivate class MapWithIndex<SourceType, ResultType> : Producer<ResultType> {
typealias Selector = (SourceType, Int) throws -> ResultType
private let _source: Observable<SourceType>
private let _selector: Selector
init(source: Observable<SourceType>, selector: @escaping Selector) {
_source = source
_selector = selector
}
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == ResultType {
let sink = MapWithIndexSink(selector: _selector, observer: observer, cancel: cancel)
let subscription = _source.subscribe(sink)
return (sink: sink, subscription: subscription)
}
}
#if TRACE_RESOURCES
fileprivate var _numberOfMapOperators: AtomicInt = 0
extension Resources {

View File

@@ -21,18 +21,6 @@ extension ObservableType {
return FlatMap(source: asObservable(), selector: selector)
}
/**
Projects each element of an observable sequence to an observable sequence by incorporating the element's index and merges the resulting observable sequences into one observable sequence.
- seealso: [flatMap operator on reactivex.io](http://reactivex.io/documentation/operators/flatmap.html)
- parameter selector: A transform function to apply to each element; the second parameter of the function represents the index of the source element.
- returns: An observable sequence whose elements are the result of invoking the one-to-many transform function on each element of the input sequence.
*/
public func flatMapWithIndex<O: ObservableConvertibleType>(_ selector: @escaping (E, Int) throws -> O)
-> Observable<O.E> {
return FlatMapWithIndex(source: asObservable(), selector: selector)
}
}
extension ObservableType {
@@ -93,7 +81,7 @@ extension ObservableType where E : ObservableConvertibleType {
}
}
extension Observable {
extension ObservableType {
/**
Merges elements from all observable sequences from collection into a single observable sequence.
@@ -131,13 +119,30 @@ extension Observable {
}
}
fileprivate final class MergeLimitedSinkIter<S: ObservableConvertibleType, O: ObserverType>
// MARK: concatMap
extension ObservableType {
/**
Projects each element of an observable sequence to an observable sequence and concatenates the resulting observable sequences into one observable sequence.
- seealso: [concat operator on reactivex.io](http://reactivex.io/documentation/operators/concat.html)
- returns: An observable sequence that contains the elements of each observed inner sequence, in sequential order.
*/
public func concatMap<O: ObservableConvertibleType>(_ selector: @escaping (E) throws -> O)
-> Observable<O.E> {
return ConcatMap(source: asObservable(), selector: selector)
}
}
fileprivate final class MergeLimitedSinkIter<SourceElement, SourceSequence: ObservableConvertibleType, Observer: ObserverType>
: ObserverType
, LockOwnerType
, SynchronizedOnType where S.E == O.E {
typealias E = O.E
, SynchronizedOnType where SourceSequence.E == Observer.E {
typealias E = Observer.E
typealias DisposeKey = CompositeDisposable.DisposeKey
typealias Parent = MergeLimitedSink<S, O>
typealias Parent = MergeLimitedSink<SourceElement, SourceSequence, Observer>
private let _parent: Parent
private let _disposeKey: DisposeKey
@@ -179,13 +184,32 @@ fileprivate final class MergeLimitedSinkIter<S: ObservableConvertibleType, O: Ob
}
}
fileprivate final class MergeLimitedSink<S: ObservableConvertibleType, O: ObserverType>
: Sink<O>
, ObserverType
, LockOwnerType
, SynchronizedOnType where S.E == O.E {
typealias E = S
typealias QueueType = Queue<S>
fileprivate final class ConcatMapSink<SourceElement, SourceSequence: ObservableConvertibleType, Observer: ObserverType>: MergeLimitedSink<SourceElement, SourceSequence, Observer> where Observer.E == SourceSequence.E {
typealias Selector = (SourceElement) throws -> SourceSequence
private let _selector: Selector
init(selector: @escaping Selector, observer: Observer, cancel: Cancelable) {
_selector = selector
super.init(maxConcurrent: 1, observer: observer, cancel: cancel)
}
override func performMap(_ element: SourceElement) throws -> SourceSequence {
return try _selector(element)
}
}
fileprivate final class MergeLimitedBasicSink<SourceSequence: ObservableConvertibleType, Observer: ObserverType>: MergeLimitedSink<SourceSequence, SourceSequence, Observer> where Observer.E == SourceSequence.E {
override func performMap(_ element: SourceSequence) throws -> SourceSequence {
return element
}
}
fileprivate class MergeLimitedSink<SourceElement, SourceSequence: ObservableConvertibleType, Observer: ObserverType>
: Sink<Observer>
, ObserverType where Observer.E == SourceSequence.E {
typealias QueueType = Queue<SourceSequence>
let _maxConcurrent: Int
@@ -199,14 +223,14 @@ fileprivate final class MergeLimitedSink<S: ObservableConvertibleType, O: Observ
let _sourceSubscription = SingleAssignmentDisposable()
let _group = CompositeDisposable()
init(maxConcurrent: Int, observer: O, cancel: Cancelable) {
init(maxConcurrent: Int, observer: Observer, cancel: Cancelable) {
_maxConcurrent = maxConcurrent
let _ = _group.insert(_sourceSubscription)
super.init(observer: observer, cancel: cancel)
}
func run(_ source: Observable<S>) -> Disposable {
func run(_ source: Observable<SourceElement>) -> Disposable {
let _ = _group.insert(_sourceSubscription)
let disposable = source.subscribe(self)
@@ -214,7 +238,7 @@ fileprivate final class MergeLimitedSink<S: ObservableConvertibleType, O: Observ
return _group
}
func subscribe(_ innerSource: E, group: CompositeDisposable) {
func subscribe(_ innerSource: SourceSequence, group: CompositeDisposable) {
let subscription = SingleAssignmentDisposable()
let key = group.insert(subscription)
@@ -227,30 +251,56 @@ fileprivate final class MergeLimitedSink<S: ObservableConvertibleType, O: Observ
}
}
func on(_ event: Event<E>) {
synchronizedOn(event)
func performMap(_ element: SourceElement) throws -> SourceSequence {
rxAbstractMethod()
}
func _synchronized_on(_ event: Event<E>) {
switch event {
case .next(let value):
@inline(__always)
final private func nextElementArrived(element: SourceElement) -> SourceSequence? {
_lock.lock(); defer { _lock.unlock() } // {
let subscribe: Bool
if _activeCount < _maxConcurrent {
_activeCount += 1
subscribe = true
}
else {
_queue.enqueue(value)
do {
let value = try performMap(element)
_queue.enqueue(value)
} catch {
forwardOn(.error(error))
dispose()
}
subscribe = false
}
if subscribe {
self.subscribe(value, group: _group)
do {
return try performMap(element)
} catch {
forwardOn(.error(error))
dispose()
}
}
return nil
// }
}
func on(_ event: Event<SourceElement>) {
switch event {
case .next(let element):
if let sequence = self.nextElementArrived(element: element) {
self.subscribe(sequence, group: _group)
}
case .error(let error):
_lock.lock(); defer { _lock.unlock() }
forwardOn(.error(error))
dispose()
case .completed:
_lock.lock(); defer { _lock.unlock() }
if _activeCount == 0 {
forwardOn(.completed)
dispose()
@@ -264,17 +314,17 @@ fileprivate final class MergeLimitedSink<S: ObservableConvertibleType, O: Observ
}
}
final fileprivate class MergeLimited<S: ObservableConvertibleType> : Producer<S.E> {
private let _source: Observable<S>
final fileprivate class MergeLimited<SourceSequence: ObservableConvertibleType> : Producer<SourceSequence.E> {
private let _source: Observable<SourceSequence>
private let _maxConcurrent: Int
init(source: Observable<S>, maxConcurrent: Int) {
init(source: Observable<SourceSequence>, maxConcurrent: Int) {
_source = source
_maxConcurrent = maxConcurrent
}
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == S.E {
let sink = MergeLimitedSink<S, O>(maxConcurrent: _maxConcurrent, observer: observer, cancel: cancel)
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == SourceSequence.E {
let sink = MergeLimitedBasicSink<SourceSequence, O>(maxConcurrent: _maxConcurrent, observer: observer, cancel: cancel)
let subscription = sink.run(_source)
return (sink: sink, subscription: subscription)
}
@@ -283,10 +333,6 @@ final fileprivate class MergeLimited<S: ObservableConvertibleType> : Producer<S.
// MARK: Merge
fileprivate final class MergeBasicSink<S: ObservableConvertibleType, O: ObserverType> : MergeSink<S, S, O> where O.E == S.E {
override init(observer: O, cancel: Cancelable) {
super.init(observer: observer, cancel: cancel)
}
override func performMap(_ element: S) throws -> S {
return element
}
@@ -294,41 +340,25 @@ fileprivate final class MergeBasicSink<S: ObservableConvertibleType, O: Observer
// MARK: flatMap
fileprivate final class FlatMapSink<SourceType, S: ObservableConvertibleType, O: ObserverType> : MergeSink<SourceType, S, O> where O.E == S.E {
typealias Selector = (SourceType) throws -> S
fileprivate final class FlatMapSink<SourceElement, SourceSequence: ObservableConvertibleType, Observer: ObserverType> : MergeSink<SourceElement, SourceSequence, Observer> where Observer.E == SourceSequence.E {
typealias Selector = (SourceElement) throws -> SourceSequence
private let _selector: Selector
init(selector: @escaping Selector, observer: O, cancel: Cancelable) {
init(selector: @escaping Selector, observer: Observer, cancel: Cancelable) {
_selector = selector
super.init(observer: observer, cancel: cancel)
}
override func performMap(_ element: SourceType) throws -> S {
override func performMap(_ element: SourceElement) throws -> SourceSequence {
return try _selector(element)
}
}
fileprivate final class FlatMapWithIndexSink<SourceType, S: ObservableConvertibleType, O: ObserverType> : MergeSink<SourceType, S, O> where O.E == S.E {
typealias Selector = (SourceType, Int) throws -> S
private var _index = 0
private let _selector: Selector
init(selector: @escaping Selector, observer: O, cancel: Cancelable) {
_selector = selector
super.init(observer: observer, cancel: cancel)
}
override func performMap(_ element: SourceType) throws -> S {
return try _selector(element, try incrementChecked(&_index))
}
}
// MARK: FlatMapFirst
fileprivate final class FlatMapFirstSink<SourceType, S: ObservableConvertibleType, O: ObserverType> : MergeSink<SourceType, S, O> where O.E == S.E {
typealias Selector = (SourceType) throws -> S
fileprivate final class FlatMapFirstSink<SourceElement, SourceSequence: ObservableConvertibleType, Observer: ObserverType> : MergeSink<SourceElement, SourceSequence, Observer> where Observer.E == SourceSequence.E {
typealias Selector = (SourceElement) throws -> SourceSequence
private let _selector: Selector
@@ -336,20 +366,20 @@ fileprivate final class FlatMapFirstSink<SourceType, S: ObservableConvertibleTyp
return _activeCount == 0
}
init(selector: @escaping Selector, observer: O, cancel: Cancelable) {
init(selector: @escaping Selector, observer: Observer, cancel: Cancelable) {
_selector = selector
super.init(observer: observer, cancel: cancel)
}
override func performMap(_ element: SourceType) throws -> S {
override func performMap(_ element: SourceElement) throws -> SourceSequence {
return try _selector(element)
}
}
fileprivate final class MergeSinkIter<SourceType, S: ObservableConvertibleType, O: ObserverType> : ObserverType where O.E == S.E {
typealias Parent = MergeSink<SourceType, S, O>
fileprivate final class MergeSinkIter<SourceElement, SourceSequence: ObservableConvertibleType, Observer: ObserverType> : ObserverType where Observer.E == SourceSequence.E {
typealias Parent = MergeSink<SourceElement, SourceSequence, Observer>
typealias DisposeKey = CompositeDisposable.DisposeKey
typealias E = O.E
typealias E = Observer.E
private let _parent: Parent
private let _disposeKey: DisposeKey
@@ -377,11 +407,11 @@ fileprivate final class MergeSinkIter<SourceType, S: ObservableConvertibleType,
}
fileprivate class MergeSink<SourceType, S: ObservableConvertibleType, O: ObserverType>
: Sink<O>
, ObserverType where O.E == S.E {
typealias ResultType = O.E
typealias Element = SourceType
fileprivate class MergeSink<SourceElement, SourceSequence: ObservableConvertibleType, Observer: ObserverType>
: Sink<Observer>
, ObserverType where Observer.E == SourceSequence.E {
typealias ResultType = Observer.E
typealias Element = SourceElement
let _lock = RecursiveLock()
@@ -396,55 +426,66 @@ fileprivate class MergeSink<SourceType, S: ObservableConvertibleType, O: Observe
var _activeCount = 0
var _stopped = false
override init(observer: O, cancel: Cancelable) {
override init(observer: Observer, cancel: Cancelable) {
super.init(observer: observer, cancel: cancel)
}
func performMap(_ element: SourceType) throws -> S {
func performMap(_ element: SourceElement) throws -> SourceSequence {
rxAbstractMethod()
}
func on(_ event: Event<SourceType>) {
_lock.lock(); defer { _lock.unlock() } // lock {
switch event {
case .next(let element):
if !subscribeNext {
return
}
do {
let value = try performMap(element)
subscribeInner(value.asObservable())
}
catch let e {
forwardOn(.error(e))
dispose()
}
case .error(let error):
forwardOn(.error(error))
dispose()
case .completed:
_stopped = true
_sourceSubscription.dispose()
checkCompleted()
@inline(__always)
final private func nextElementArrived(element: SourceElement) -> SourceSequence? {
_lock.lock(); defer { _lock.unlock() } // {
if !subscribeNext {
return nil
}
//}
do {
let value = try performMap(element)
_activeCount += 1
return value
}
catch let e {
forwardOn(.error(e))
dispose()
return nil
}
// }
}
func on(_ event: Event<SourceElement>) {
switch event {
case .next(let element):
if let value = nextElementArrived(element: element) {
subscribeInner(value.asObservable())
}
case .error(let error):
_lock.lock(); defer { _lock.unlock() }
forwardOn(.error(error))
dispose()
case .completed:
_lock.lock(); defer { _lock.unlock() }
_stopped = true
_sourceSubscription.dispose()
checkCompleted()
}
}
func subscribeInner(_ source: Observable<O.E>) {
func subscribeInner(_ source: Observable<Observer.E>) {
let iterDisposable = SingleAssignmentDisposable()
if let disposeKey = _group.insert(iterDisposable) {
_activeCount += 1
let iter = MergeSinkIter(parent: self, disposeKey: disposeKey)
let subscription = source.subscribe(iter)
iterDisposable.setDisposable(subscription)
}
}
func run(_ sources: [SourceType]) -> Disposable {
let _ = _group.insert(_sourceSubscription)
func run(_ sources: [Observable<Observer.E>]) -> Disposable {
_activeCount += sources.count
for source in sources {
self.on(.next(source))
subscribeInner(source)
}
_stopped = true
@@ -462,7 +503,7 @@ fileprivate class MergeSink<SourceType, S: ObservableConvertibleType, O: Observe
}
}
func run(_ source: Observable<SourceType>) -> Disposable {
func run(_ source: Observable<SourceElement>) -> Disposable {
let _ = _group.insert(_sourceSubscription)
let subscription = source.subscribe(self)
@@ -474,82 +515,80 @@ fileprivate class MergeSink<SourceType, S: ObservableConvertibleType, O: Observe
// MARK: Producers
final fileprivate class FlatMap<SourceType, S: ObservableConvertibleType>: Producer<S.E> {
typealias Selector = (SourceType) throws -> S
final fileprivate class FlatMap<SourceElement, SourceSequence: ObservableConvertibleType>: Producer<SourceSequence.E> {
typealias Selector = (SourceElement) throws -> SourceSequence
private let _source: Observable<SourceType>
private let _source: Observable<SourceElement>
private let _selector: Selector
init(source: Observable<SourceType>, selector: @escaping Selector) {
init(source: Observable<SourceElement>, selector: @escaping Selector) {
_source = source
_selector = selector
}
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == S.E {
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == SourceSequence.E {
let sink = FlatMapSink(selector: _selector, observer: observer, cancel: cancel)
let subscription = sink.run(_source)
return (sink: sink, subscription: subscription)
}
}
final fileprivate class FlatMapWithIndex<SourceType, S: ObservableConvertibleType>: Producer<S.E> {
typealias Selector = (SourceType, Int) throws -> S
final fileprivate class FlatMapFirst<SourceElement, SourceSequence: ObservableConvertibleType>: Producer<SourceSequence.E> {
typealias Selector = (SourceElement) throws -> SourceSequence
private let _source: Observable<SourceType>
private let _selector: Selector
init(source: Observable<SourceType>, selector: @escaping Selector) {
_source = source
_selector = selector
}
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == S.E {
let sink = FlatMapWithIndexSink<SourceType, S, O>(selector: _selector, observer: observer, cancel: cancel)
let subscription = sink.run(_source)
return (sink: sink, subscription: subscription)
}
}
final fileprivate class FlatMapFirst<SourceType, S: ObservableConvertibleType>: Producer<S.E> {
typealias Selector = (SourceType) throws -> S
private let _source: Observable<SourceType>
private let _source: Observable<SourceElement>
private let _selector: Selector
init(source: Observable<SourceType>, selector: @escaping Selector) {
init(source: Observable<SourceElement>, selector: @escaping Selector) {
_source = source
_selector = selector
}
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == S.E {
let sink = FlatMapFirstSink<SourceType, S, O>(selector: _selector, observer: observer, cancel: cancel)
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == SourceSequence.E {
let sink = FlatMapFirstSink<SourceElement, SourceSequence, O>(selector: _selector, observer: observer, cancel: cancel)
let subscription = sink.run(_source)
return (sink: sink, subscription: subscription)
}
}
final fileprivate class Merge<S: ObservableConvertibleType> : Producer<S.E> {
private let _source: Observable<S>
final class ConcatMap<SourceElement, SourceSequence: ObservableConvertibleType>: Producer<SourceSequence.E> {
typealias Selector = (SourceElement) throws -> SourceSequence
private let _source: Observable<SourceElement>
private let _selector: Selector
init(source: Observable<SourceElement>, selector: @escaping Selector) {
_source = source
_selector = selector
}
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == SourceSequence.E {
let sink = ConcatMapSink<SourceElement, SourceSequence, O>(selector: _selector, observer: observer, cancel: cancel)
let subscription = sink.run(_source)
return (sink: sink, subscription: subscription)
}
}
init(source: Observable<S>) {
final class Merge<SourceSequence: ObservableConvertibleType> : Producer<SourceSequence.E> {
private let _source: Observable<SourceSequence>
init(source: Observable<SourceSequence>) {
_source = source
}
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == S.E {
let sink = MergeBasicSink<S, O>(observer: observer, cancel: cancel)
override func run<O: ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == SourceSequence.E {
let sink = MergeBasicSink<SourceSequence, O>(observer: observer, cancel: cancel)
let subscription = sink.run(_source)
return (sink: sink, subscription: subscription)
}
}
final fileprivate class MergeArray<E> : Producer<E> {
private let _sources: [Observable<E>]
final fileprivate class MergeArray<Element> : Producer<Element> {
private let _sources: [Observable<Element>]
init(sources: [Observable<E>]) {
init(sources: [Observable<Element>]) {
_sources = sources
}

Some files were not shown because too many files have changed in this diff Show More