Merge pull request #36 from TouchInstinct/feature/concurrent_mapping
implement concurrent mapping
This commit is contained in:
commit
dd26a70db0
|
|
@ -11,6 +11,8 @@
|
|||
78011AB31D48B53600EA16A2 /* ApiRequestParameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78011AB21D48B53600EA16A2 /* ApiRequestParameters.swift */; };
|
||||
780D23431DA412470084620D /* CGImage+Alpha.swift in Sources */ = {isa = PBXBuildFile; fileRef = 780D23421DA412470084620D /* CGImage+Alpha.swift */; };
|
||||
780D23461DA416F80084620D /* CGContext+Initializers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 780D23451DA416F80084620D /* CGContext+Initializers.swift */; };
|
||||
780F56CA1E0D76B8004530B6 /* Sequence+ConcurrentMap.swift in Sources */ = {isa = PBXBuildFile; fileRef = 780F56C91E0D76B8004530B6 /* Sequence+ConcurrentMap.swift */; };
|
||||
780F56CC1E0D7ACA004530B6 /* ObservableMappable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 780F56CB1E0D7ACA004530B6 /* ObservableMappable.swift */; };
|
||||
7827C9341DE4ADB2009DA4E6 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7827C92E1DE4ADB2009DA4E6 /* Alamofire.framework */; };
|
||||
7827C9351DE4ADB2009DA4E6 /* CocoaLumberjack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7827C92F1DE4ADB2009DA4E6 /* CocoaLumberjack.framework */; };
|
||||
7827C9361DE4ADB2009DA4E6 /* ObjectMapper.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7827C9301DE4ADB2009DA4E6 /* ObjectMapper.framework */; };
|
||||
|
|
@ -22,13 +24,17 @@
|
|||
7845A15A1E0BCD9A00B527BB /* KeyboardNotificationValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7845A1591E0BCD9A00B527BB /* KeyboardNotificationValues.swift */; };
|
||||
786D78E81D53C378006B2CEA /* AlamofireRequest+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 786D78E71D53C378006B2CEA /* AlamofireRequest+Extensions.swift */; };
|
||||
786D78EC1D53C46E006B2CEA /* AlamofireManager+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 786D78EB1D53C46E006B2CEA /* AlamofireManager+Extensions.swift */; };
|
||||
7873D14F1E1127BC001816EB /* LeadKitError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7873D14E1E1127BC001816EB /* LeadKitError.swift */; };
|
||||
7873D1511E112B0D001816EB /* Any+Cast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7873D1501E112B0D001816EB /* Any+Cast.swift */; };
|
||||
78753E241DE58A5D006BC0FB /* CursorError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78753E231DE58A5D006BC0FB /* CursorError.swift */; };
|
||||
78753E2C1DE58BF9006BC0FB /* StaticCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78753E2B1DE58BF9006BC0FB /* StaticCursor.swift */; };
|
||||
78753E2E1DE58DBA006BC0FB /* FixedPageCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78753E2D1DE58DBA006BC0FB /* FixedPageCursor.swift */; };
|
||||
78753E301DE594B4006BC0FB /* MapCursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 78753E2F1DE594B4006BC0FB /* MapCursor.swift */; };
|
||||
787609221E1403830093CE36 /* Observable+DeferredJust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787609211E1403830093CE36 /* Observable+DeferredJust.swift */; };
|
||||
787682FA1CAD40C300532AB3 /* StaticEstimatedViewHeightProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787682F91CAD40C200532AB3 /* StaticEstimatedViewHeightProtocol.swift */; };
|
||||
787783631CA03CA0001CDC9B /* IndexPath+ImmutableIndexPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787783621CA03CA0001CDC9B /* IndexPath+ImmutableIndexPath.swift */; };
|
||||
787783671CA04D4A001CDC9B /* String+SizeCalculation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787783661CA04D4A001CDC9B /* String+SizeCalculation.swift */; };
|
||||
787D874A1E10E1A400D6015C /* ImmutableMappable+ObservableMappable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 787D87491E10E1A400D6015C /* ImmutableMappable+ObservableMappable.swift */; };
|
||||
7884DB9C1DC1439200E52A63 /* UserDefaults+MappableDataTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884DB9B1DC1439200E52A63 /* UserDefaults+MappableDataTypes.swift */; };
|
||||
788EC15A1CF64528009CFB6B /* UIStoryboard+InstantiateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 788EC1591CF64528009CFB6B /* UIStoryboard+InstantiateViewController.swift */; };
|
||||
789CC6081DE5835600F789D3 /* CursorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789CC6071DE5835600F789D3 /* CursorType.swift */; };
|
||||
|
|
@ -87,6 +93,8 @@
|
|||
78011AB21D48B53600EA16A2 /* ApiRequestParameters.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApiRequestParameters.swift; sourceTree = "<group>"; };
|
||||
780D23421DA412470084620D /* CGImage+Alpha.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGImage+Alpha.swift"; sourceTree = "<group>"; };
|
||||
780D23451DA416F80084620D /* CGContext+Initializers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGContext+Initializers.swift"; sourceTree = "<group>"; };
|
||||
780F56C91E0D76B8004530B6 /* Sequence+ConcurrentMap.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Sequence+ConcurrentMap.swift"; sourceTree = "<group>"; };
|
||||
780F56CB1E0D7ACA004530B6 /* ObservableMappable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObservableMappable.swift; sourceTree = "<group>"; };
|
||||
7827C92E1DE4ADB2009DA4E6 /* Alamofire.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Alamofire.framework; path = ../../../Carthage/Build/iOS/Alamofire.framework; sourceTree = "<group>"; };
|
||||
7827C92F1DE4ADB2009DA4E6 /* CocoaLumberjack.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CocoaLumberjack.framework; path = ../../../Carthage/Build/iOS/CocoaLumberjack.framework; sourceTree = "<group>"; };
|
||||
7827C9301DE4ADB2009DA4E6 /* ObjectMapper.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjectMapper.framework; path = ../../../Carthage/Build/iOS/ObjectMapper.framework; sourceTree = "<group>"; };
|
||||
|
|
@ -98,13 +106,17 @@
|
|||
7845A1591E0BCD9A00B527BB /* KeyboardNotificationValues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardNotificationValues.swift; sourceTree = "<group>"; };
|
||||
786D78E71D53C378006B2CEA /* AlamofireRequest+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AlamofireRequest+Extensions.swift"; sourceTree = "<group>"; };
|
||||
786D78EB1D53C46E006B2CEA /* AlamofireManager+Extensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AlamofireManager+Extensions.swift"; sourceTree = "<group>"; };
|
||||
7873D14E1E1127BC001816EB /* LeadKitError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LeadKitError.swift; sourceTree = "<group>"; };
|
||||
7873D1501E112B0D001816EB /* Any+Cast.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Any+Cast.swift"; sourceTree = "<group>"; };
|
||||
78753E231DE58A5D006BC0FB /* CursorError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CursorError.swift; sourceTree = "<group>"; };
|
||||
78753E2B1DE58BF9006BC0FB /* StaticCursor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StaticCursor.swift; sourceTree = "<group>"; };
|
||||
78753E2D1DE58DBA006BC0FB /* FixedPageCursor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FixedPageCursor.swift; sourceTree = "<group>"; };
|
||||
78753E2F1DE594B4006BC0FB /* MapCursor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapCursor.swift; sourceTree = "<group>"; };
|
||||
787609211E1403830093CE36 /* Observable+DeferredJust.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Observable+DeferredJust.swift"; sourceTree = "<group>"; };
|
||||
787682F91CAD40C200532AB3 /* StaticEstimatedViewHeightProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StaticEstimatedViewHeightProtocol.swift; sourceTree = "<group>"; };
|
||||
787783621CA03CA0001CDC9B /* IndexPath+ImmutableIndexPath.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "IndexPath+ImmutableIndexPath.swift"; sourceTree = "<group>"; };
|
||||
787783661CA04D4A001CDC9B /* String+SizeCalculation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+SizeCalculation.swift"; sourceTree = "<group>"; };
|
||||
787D87491E10E1A400D6015C /* ImmutableMappable+ObservableMappable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "ImmutableMappable+ObservableMappable.swift"; sourceTree = "<group>"; };
|
||||
7884DB9B1DC1439200E52A63 /* UserDefaults+MappableDataTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UserDefaults+MappableDataTypes.swift"; sourceTree = "<group>"; };
|
||||
788EC1591CF64528009CFB6B /* UIStoryboard+InstantiateViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIStoryboard+InstantiateViewController.swift"; sourceTree = "<group>"; };
|
||||
789CC6071DE5835600F789D3 /* CursorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CursorType.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -195,6 +207,7 @@
|
|||
78753E231DE58A5D006BC0FB /* CursorError.swift */,
|
||||
789F5A131DFECD54004A3694 /* KeyboardNotificationValuesError.swift */,
|
||||
789F5A1F1DFECF9F004A3694 /* KeyboardNotification.swift */,
|
||||
7873D14E1E1127BC001816EB /* LeadKitError.swift */,
|
||||
);
|
||||
path = Enums;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -237,6 +250,14 @@
|
|||
path = CGContext;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
780F56C81E0D76A5004530B6 /* Sequence */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
780F56C91E0D76B8004530B6 /* Sequence+ConcurrentMap.swift */,
|
||||
);
|
||||
path = Sequence;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
786D78E61D53C355006B2CEA /* Alamofire */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -256,6 +277,14 @@
|
|||
path = Cursors;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
787609201E1403460093CE36 /* Observable */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
787609211E1403830093CE36 /* Observable+DeferredJust.swift */,
|
||||
);
|
||||
path = Observable;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
787783611CA03C84001CDC9B /* IndexPath */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -273,6 +302,14 @@
|
|||
path = String;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
787D87481E10E19000D6015C /* ObjectMapper */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
787D87491E10E1A400D6015C /* ImmutableMappable+ObservableMappable.swift */,
|
||||
);
|
||||
path = ObjectMapper;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
7884DB9A1DC1432B00E52A63 /* UserDefaults */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -423,6 +460,9 @@
|
|||
789CC6091DE584C000F789D3 /* CursorType */,
|
||||
789F5A0A1DFECB52004A3694 /* UIViewAnimationCurve */,
|
||||
789F5A1C1DFECF44004A3694 /* NotificationCenter */,
|
||||
780F56C81E0D76A5004530B6 /* Sequence */,
|
||||
787D87481E10E19000D6015C /* ObjectMapper */,
|
||||
787609201E1403460093CE36 /* Observable */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -441,6 +481,7 @@
|
|||
7837F60E1CBCF5C0000D74C1 /* EstimatedViewHeightProtocol.swift */,
|
||||
783423691DB8D0E100A79643 /* StoryboardProtocol.swift */,
|
||||
789CC6071DE5835600F789D3 /* CursorType.swift */,
|
||||
780F56CB1E0D7ACA004530B6 /* ObservableMappable.swift */,
|
||||
);
|
||||
path = Protocols;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -457,6 +498,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
78D4B5491DA64EAB005B0764 /* Any+TypeName.swift */,
|
||||
7873D1501E112B0D001816EB /* Any+Cast.swift */,
|
||||
);
|
||||
path = Functions;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -668,6 +710,8 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
787D874A1E10E1A400D6015C /* ImmutableMappable+ObservableMappable.swift in Sources */,
|
||||
780F56CA1E0D76B8004530B6 /* Sequence+ConcurrentMap.swift in Sources */,
|
||||
7837F60F1CBCF5C0000D74C1 /* EstimatedViewHeightProtocol.swift in Sources */,
|
||||
78CFEE541C5C45E500F50370 /* UIView+LoadFromNib.swift in Sources */,
|
||||
78D4B5461DA64D49005B0764 /* UIViewController+DefaultStoryboardIdentifier.swift in Sources */,
|
||||
|
|
@ -683,6 +727,7 @@
|
|||
78CFEE571C5C45E500F50370 /* StaticNibNameProtocol.swift in Sources */,
|
||||
788EC15A1CF64528009CFB6B /* UIStoryboard+InstantiateViewController.swift in Sources */,
|
||||
787783671CA04D4A001CDC9B /* String+SizeCalculation.swift in Sources */,
|
||||
7873D1511E112B0D001816EB /* Any+Cast.swift in Sources */,
|
||||
78B036431DA4FEC90021D5CC /* CGImage+Transform.swift in Sources */,
|
||||
78011A641D47ABC500EA16A2 /* UIView+DefaultReuseIdentifier.swift in Sources */,
|
||||
786D78EC1D53C46E006B2CEA /* AlamofireManager+Extensions.swift in Sources */,
|
||||
|
|
@ -690,11 +735,13 @@
|
|||
7845A15A1E0BCD9A00B527BB /* KeyboardNotificationValues.swift in Sources */,
|
||||
78B036491DA562C30021D5CC /* CGImage+Template.swift in Sources */,
|
||||
789F5A1E1DFECF5F004A3694 /* NotificationCenter+RxKeyboardExtensions.swift in Sources */,
|
||||
7873D14F1E1127BC001816EB /* LeadKitError.swift in Sources */,
|
||||
78753E301DE594B4006BC0FB /* MapCursor.swift in Sources */,
|
||||
780D23461DA416F80084620D /* CGContext+Initializers.swift in Sources */,
|
||||
95B39A861D9D51250057BD54 /* String+Localization.swift in Sources */,
|
||||
78C36F7E1D801E3E00E7EBEA /* Double+Rounding.swift in Sources */,
|
||||
78CFEE551C5C45E500F50370 /* NibNameProtocol.swift in Sources */,
|
||||
787609221E1403830093CE36 /* Observable+DeferredJust.swift in Sources */,
|
||||
78CFEE561C5C45E500F50370 /* ReuseIdentifierProtocol.swift in Sources */,
|
||||
78A0FCC81DC366A10070B5E1 /* StoryboardProtocol+Extensions.swift in Sources */,
|
||||
78B036411DA4D7060021D5CC /* UIImage+Extensions.swift in Sources */,
|
||||
|
|
@ -705,6 +752,7 @@
|
|||
78CFEE5B1C5C45E500F50370 /* ViewModelProtocol.swift in Sources */,
|
||||
789F5A121DFECD11004A3694 /* KeyboardDidNotificationValues.swift in Sources */,
|
||||
EF5FB5691E0141610030E4BE /* UIView+Rotation.swift in Sources */,
|
||||
780F56CC1E0D7ACA004530B6 /* ObservableMappable.swift in Sources */,
|
||||
780D23431DA412470084620D /* CGImage+Alpha.swift in Sources */,
|
||||
78CFEE5A1C5C45E500F50370 /* ViewHeightProtocol.swift in Sources */,
|
||||
787682FA1CAD40C300532AB3 /* StaticEstimatedViewHeightProtocol.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// LeadKitError.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Ivan Smolin on 26/12/16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Enum which represents common errors in LeadKit framework
|
||||
///
|
||||
/// - failedToCastValue: attempt to cast was failed
|
||||
public enum LeadKitError: Error {
|
||||
|
||||
case failedToCastValue(expectedType: Any.Type, givenType: Any.Type)
|
||||
|
||||
}
|
||||
|
|
@ -11,15 +11,12 @@ import RxSwift
|
|||
import RxAlamofire
|
||||
import ObjectMapper
|
||||
|
||||
public extension Alamofire.SessionManager {
|
||||
public extension Reactive where Base: Alamofire.SessionManager {
|
||||
|
||||
/**
|
||||
method which executes request with given api parameters
|
||||
|
||||
- parameter requestParameters: api parameters to pass Alamofire
|
||||
|
||||
- returns: Observable with request
|
||||
*/
|
||||
/// Method which executes request with given api parameters
|
||||
///
|
||||
/// - Parameter requestParameters: api parameters to pass Alamofire
|
||||
/// - Returns: Observable with request
|
||||
func apiRequest(requestParameters: ApiRequestParameters) -> Observable<DataRequest> {
|
||||
return RxAlamofire.request(requestParameters.method,
|
||||
requestParameters.url,
|
||||
|
|
@ -28,15 +25,26 @@ public extension Alamofire.SessionManager {
|
|||
headers: requestParameters.headers)
|
||||
}
|
||||
|
||||
/**
|
||||
method which executes request and serialize response into target object
|
||||
|
||||
- parameter requestParameters: api parameters to pass Alamofire
|
||||
|
||||
- returns: Observable with HTTP URL Response and target object
|
||||
*/
|
||||
/// Method which executes request and serializes response into target object
|
||||
///
|
||||
/// - Parameter requestParameters: api parameters to pass Alamofire
|
||||
/// - Returns: Observable with HTTP URL Response and target object
|
||||
func responseModel<T: ImmutableMappable>(requestParameters: ApiRequestParameters) -> Observable<(HTTPURLResponse, T)> {
|
||||
return apiRequest(requestParameters: requestParameters).flatMap { $0.rx.apiResponse() }
|
||||
return apiRequest(requestParameters: requestParameters)
|
||||
.observeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
|
||||
.flatMap { $0.rx.apiResponse() }
|
||||
}
|
||||
|
||||
/// Method which executes request and serializes response into target object
|
||||
///
|
||||
/// - Parameter requestParameters: api parameters to pass Alamofire
|
||||
/// - Returns: Observable with HTTP URL Response and target object
|
||||
func responseObservableModel<T: ObservableMappable>(requestParameters: ApiRequestParameters) ->
|
||||
Observable<(HTTPURLResponse, T)> where T.ModelType == T {
|
||||
|
||||
return apiRequest(requestParameters: requestParameters)
|
||||
.observeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
|
||||
.flatMap { $0.rx.apiResponse() }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,28 +11,28 @@ import RxSwift
|
|||
import ObjectMapper
|
||||
import RxAlamofire
|
||||
|
||||
public enum ApiResponseMappingError: Error {
|
||||
|
||||
case incorrectValueType(message: String)
|
||||
|
||||
}
|
||||
|
||||
public extension Reactive where Base: DataRequest {
|
||||
|
||||
/**
|
||||
method which serialize response into target object
|
||||
|
||||
- returns: Observable with HTTP URL Response and target object
|
||||
*/
|
||||
/// Method which serializes response into target object
|
||||
///
|
||||
/// - Returns: Observable with HTTP URL Response and target object
|
||||
func apiResponse<T: ImmutableMappable>() -> Observable<(HTTPURLResponse, T)> {
|
||||
return responseJSON().map { resp, value in
|
||||
if let json = value as? [String: Any] {
|
||||
return (resp, try T(JSON: json))
|
||||
} else {
|
||||
let failureReason = "Value has incorrect type: \(type(of: value)), expected: [String: Any]"
|
||||
let json = try cast(value) as [String: Any]
|
||||
|
||||
throw ApiResponseMappingError.incorrectValueType(message: failureReason)
|
||||
}
|
||||
return (resp, try T(JSON: json))
|
||||
}
|
||||
}
|
||||
|
||||
/// Method which serializes response into target object
|
||||
///
|
||||
/// - Returns: Observable with HTTP URL Response and target object
|
||||
func apiResponse<T: ObservableMappable>() -> Observable<(HTTPURLResponse, T)> where T.ModelType == T {
|
||||
return responseJSON().flatMap { resp, value -> Observable<(HTTPURLResponse, T)> in
|
||||
let json = try cast(value) as [String: Any]
|
||||
|
||||
return T.createFrom(map: Map(mappingType: .fromJSON, JSON: json))
|
||||
.map { (resp, $0) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// ImmutableMappable+ObservableMappable.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Ivan Smolin on 26/12/16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import ObjectMapper
|
||||
import RxSwift
|
||||
|
||||
public extension ObservableMappable where Self: ImmutableMappable, ModelType == Self {
|
||||
|
||||
/// Default implementation of ObservableMappable protocol for ImmutableMappable protocol
|
||||
///
|
||||
/// - Parameter map: ObjectMapper.Map object
|
||||
/// - Returns: Observable with value of ModelType(map: ObjectMapper.Map)
|
||||
/// - Throws: error of ModelType(map: ObjectMapper.Map)
|
||||
static func createFrom(map: Map) -> Observable<Self> {
|
||||
return Observable.deferredJust { try ModelType(map: map) }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// Observable+DeferredJust.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Ivan Smolin on 28/12/16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import RxSwift
|
||||
|
||||
public extension Observable {
|
||||
|
||||
/// Returns an observable sequence that invokes the specified factory function whenever a new observer subscribes.
|
||||
///
|
||||
/// - Parameter elementFactory: Element factory function to invoke for each observer
|
||||
/// that subscribes to the resulting sequence.
|
||||
/// - Returns: An observable sequence whose observers trigger an invocation of the given element factory function.
|
||||
static func deferredJust(_ elementFactory: @escaping () throws -> Element) -> Observable<Element> {
|
||||
return create { (observer) -> Disposable in
|
||||
do {
|
||||
observer.onNext(try elementFactory())
|
||||
observer.onCompleted()
|
||||
} catch {
|
||||
observer.onError(error)
|
||||
}
|
||||
|
||||
return Disposables.create()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// Sequence+ConcurrentMap.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Ivan Smolin on 23/12/16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import RxSwift
|
||||
|
||||
public extension Sequence {
|
||||
|
||||
/// Method which asynchronous transforms sequence using given transform closure
|
||||
/// and given number of concurrent operations
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - concurrentOperationCount: Number of concurrent operations
|
||||
/// - qos: Target global dispatch queue, by quality of service class.
|
||||
/// - transform: Transform closure
|
||||
/// - Returns: Observable of array which contains transform return type
|
||||
func concurrentRxMap<R>(concurrentOperationCount: Int = ProcessInfo.processInfo.activeProcessorCount,
|
||||
qos: DispatchQoS = .default,
|
||||
transform: @escaping ((Iterator.Element) throws -> R)) -> Observable<[R]> {
|
||||
|
||||
let operationsCount = Swift.max(1, concurrentOperationCount)
|
||||
|
||||
let array = Array(self)
|
||||
|
||||
let step = Int(ceil(Double(array.count) / Double(operationsCount)))
|
||||
let numberOfSlices = Int(ceil(Double(array.count) / Double(step)))
|
||||
|
||||
let indexedRanges: [(idx: Int, range: CountableRange<Int>)] = (0..<numberOfSlices).map {
|
||||
let start = $0 * step
|
||||
let end = Swift.min(start + step, array.count)
|
||||
|
||||
return ($0, start..<end)
|
||||
}
|
||||
|
||||
let scheduler = ConcurrentDispatchQueueScheduler(qos: qos)
|
||||
|
||||
return Observable.from(indexedRanges)
|
||||
.flatMap { indexedRange -> Observable<(idx: Int, results: [R])> in
|
||||
return Observable.just(indexedRange)
|
||||
.observeOn(scheduler)
|
||||
.map { (idx: $0.idx, results: try array[$0.range].map(transform)) }
|
||||
}
|
||||
.toArray()
|
||||
.map { $0.sorted { $0.0.idx < $0.1.idx }.flatMap { $0.results } }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,12 +14,10 @@ import RxSwift
|
|||
/// model or array of specified type from UserDefaults.
|
||||
///
|
||||
/// - noSuchValue: there is no such value for given key
|
||||
/// - wrongStoredValueType: the stored value type is unsuitable for performing mapping with it
|
||||
/// - unableToMap: the value cannot be mapped to given type for some reason
|
||||
public enum UserDefaultsError: Error {
|
||||
|
||||
case noSuchValue(key: String)
|
||||
case wrongStoredValueType(expected: Any.Type, received: Any.Type)
|
||||
case unableToMap(mappingError: Error)
|
||||
|
||||
}
|
||||
|
|
@ -33,11 +31,7 @@ public extension UserDefaults {
|
|||
throw UserDefaultsError.noSuchValue(key: key)
|
||||
}
|
||||
|
||||
guard let storedValue = objectForKey as? ST else {
|
||||
throw UserDefaultsError.wrongStoredValueType(expected: ST.self, received: type(of: objectForKey))
|
||||
}
|
||||
|
||||
return storedValue
|
||||
return try cast(objectForKey) as ST
|
||||
}
|
||||
|
||||
/// Returns the object with specified type associated with the first occurrence of the specified default.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
// Any+Cast.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Ivan Smolin on 26/12/16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Function which attempts to cast given value to specific type
|
||||
///
|
||||
/// - Parameter value: value to cast
|
||||
/// - Returns: value casted to specific type
|
||||
/// - Throws: LeadKitError.failedToCastValue cast fails
|
||||
public func cast<T>(_ value: Any?) throws -> T {
|
||||
guard let val = value as? T else {
|
||||
throw LeadKitError.failedToCastValue(expectedType: T.self, givenType: type(of: value))
|
||||
}
|
||||
|
||||
return val
|
||||
}
|
||||
|
|
@ -8,6 +8,10 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/// Function which returns string representation of type without ".Type" suffix
|
||||
///
|
||||
/// - Parameter type: a type
|
||||
/// - Returns: string representation of type without ".Type" suffix
|
||||
public func className<T>(of type: T) -> String {
|
||||
let clsName = String(describing: type(of: type))
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
//
|
||||
// ObservableMappable.swift
|
||||
// LeadKit
|
||||
//
|
||||
// Created by Ivan Smolin on 23/12/16.
|
||||
// Copyright © 2016 Touch Instinct. All rights reserved.
|
||||
//
|
||||
|
||||
import ObjectMapper
|
||||
import RxSwift
|
||||
|
||||
/// Protocol for concurrent model mapping
|
||||
public protocol ObservableMappable {
|
||||
|
||||
associatedtype ModelType
|
||||
|
||||
static func createFrom(map: Map) -> Observable<ModelType>
|
||||
|
||||
}
|
||||
|
|
@ -17,5 +17,5 @@ public protocol StaticViewHeightProtocol {
|
|||
|
||||
- returns: view height
|
||||
*/
|
||||
static func viewHeight() -> CGFloat
|
||||
static var viewHeight: CGFloat { get }
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue