Comments added
This commit is contained in:
parent
98ea69217d
commit
596f25ccc0
|
|
@ -22,10 +22,14 @@
|
|||
|
||||
import ObjectMapper
|
||||
|
||||
/// Class describes typical response from server, which designed by TouchInstinct
|
||||
public class ApiResponse: ApiResponseProtocol, ImmutableMappable {
|
||||
|
||||
/// nil in case of error, result of request otherwise
|
||||
public let result: Any?
|
||||
/// In case of error contains error code, 0 (zero) otherwise
|
||||
public let errorCode: Int
|
||||
/// nil in case of success, error description otherwise
|
||||
public let errorMessage: String?
|
||||
|
||||
public required init(map: Map) throws {
|
||||
|
|
@ -36,9 +40,12 @@ public class ApiResponse: ApiResponseProtocol, ImmutableMappable {
|
|||
|
||||
}
|
||||
|
||||
/// Describes error, which received from server designed by TouchInstinct
|
||||
public protocol ApiResponseProtocol: ImmutableMappable {
|
||||
|
||||
/// Error code
|
||||
var errorCode: Int { get }
|
||||
/// Error description
|
||||
var errorMessage: String? { get }
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
import Foundation
|
||||
import ObjectMapper
|
||||
|
||||
/// Base date formatter class, contains most frequently used formats, including RFC3339
|
||||
open class BaseDateFormatter {
|
||||
|
||||
private static let apiDateTimeFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
|
||||
|
|
@ -61,37 +62,44 @@ open class BaseDateFormatter {
|
|||
return dateFormater
|
||||
}()
|
||||
|
||||
// MARK: Public interface
|
||||
// MARK: - Public interface
|
||||
|
||||
/// DateFormatter's locale can be overriden
|
||||
open class var usedLocale: Locale {
|
||||
return .current
|
||||
}
|
||||
|
||||
/// Parse date from string with format: yyyy-MM-dd'T'HH:mm:ssZ
|
||||
public static func backendDate(fromStrDate strDate: String) -> Date? {
|
||||
apiFormatter.locale = usedLocale
|
||||
return apiFormatter.date(from: strDate)
|
||||
}
|
||||
|
||||
/// Serialize date into string with format: yyyy-MM-dd'T'HH:mm:ssZ
|
||||
public static func backendStrDate(withDate date: Date) -> String {
|
||||
apiFormatter.locale = usedLocale
|
||||
return apiFormatter.string(from: date)
|
||||
}
|
||||
|
||||
/// Serialize date into string with format: yyyy-MM-dd'T'Z
|
||||
public static func backendDateWithoutTime(withDate date: Date) -> String {
|
||||
apiDateWithoutTimeFormatter.locale = usedLocale
|
||||
return apiDateWithoutTimeFormatter.string(from: date)
|
||||
}
|
||||
|
||||
/// Serialize date into string with format: HH:mm
|
||||
public static func hourAndMinuteStrDate(withDate date: Date) -> String {
|
||||
hourAndMinuteFormatter.locale = usedLocale
|
||||
return hourAndMinuteFormatter.string(from: date)
|
||||
}
|
||||
|
||||
/// Serialize date into string with format: dd MMM
|
||||
public static func dayAndMonthStrDate(withDate date: Date) -> String {
|
||||
hourAndMinuteFormatter.locale = usedLocale
|
||||
return dayAndMonthFormatter.string(from: date)
|
||||
}
|
||||
|
||||
/// Serialize date into string with format: dd.MM.yyyy
|
||||
public static func dayMonthYearStrDate(withDate date: Date) -> String {
|
||||
hourAndMinuteFormatter.locale = usedLocale
|
||||
return dayMonthYearFormatter.string(from: date)
|
||||
|
|
@ -99,6 +107,7 @@ open class BaseDateFormatter {
|
|||
|
||||
// MARK: - Transformers
|
||||
|
||||
/// Transformer to workaround with dates in Mappable (ObjectMapper) objects
|
||||
public static var transformFromStringToDate: TransformOf<Date, String> {
|
||||
return TransformOf<Date, String>(fromJSON: { (stringValue) -> Date? in
|
||||
if let stringValue = stringValue {
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@ import UIKit
|
|||
import RxSwift
|
||||
import RxCocoa
|
||||
|
||||
/// Side to which ativity indicator applied
|
||||
public enum LoadingBarButtonSide {
|
||||
case left
|
||||
case right
|
||||
}
|
||||
|
||||
/// Workaround with navigationBarButton, that can change state (UI) into activity indicator
|
||||
public class LoadingBarButton {
|
||||
|
||||
fileprivate weak var navigationItem: UINavigationItem?
|
||||
|
|
@ -54,6 +56,13 @@ public class LoadingBarButton {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Create an instance of LoadingBarButton
|
||||
|
||||
- Parameters:
|
||||
- navigationItem: item to which apply changes
|
||||
- side: side where navigationItem would be placed
|
||||
*/
|
||||
public init(navigationItem: UINavigationItem, side: LoadingBarButtonSide) {
|
||||
self.navigationItem = navigationItem
|
||||
self.side = side
|
||||
|
|
@ -74,6 +83,14 @@ public class LoadingBarButton {
|
|||
|
||||
extension Observable {
|
||||
|
||||
/**
|
||||
Reactive extension for LoadingBarButton
|
||||
Apply transformations on subscribe and on dispose events
|
||||
|
||||
- Parameters:
|
||||
- barButton: LoadingBarButton instance to which transformations would applied
|
||||
- Returns:
|
||||
*/
|
||||
public func changeLoadingUI(using barButton: LoadingBarButton) -> Observable<Observable.E> {
|
||||
return observeOn(MainScheduler.instance)
|
||||
.do(onSubscribe: {
|
||||
|
|
|
|||
|
|
@ -20,11 +20,15 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
/// Configuration container for BasePassCodeViewController
|
||||
public struct PassCodeConfiguration {
|
||||
|
||||
/// Pass code length
|
||||
public var passCodeCharactersNumber: UInt = 4
|
||||
/// Incorrect pass code attempts count
|
||||
public var maxAttemptsLoginNumber: UInt = 5
|
||||
|
||||
/// Clear input progress when application goes to background
|
||||
public var shouldResetWhenGoBackground: Bool = true
|
||||
|
||||
private init() {}
|
||||
|
|
@ -37,6 +41,7 @@ public struct PassCodeConfiguration {
|
|||
self.passCodeCharactersNumber = passCodeCharactersNumber
|
||||
}
|
||||
|
||||
/// Returns configuration with default values
|
||||
public static var defaultConfiguration: PassCodeConfiguration {
|
||||
return PassCodeConfiguration()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
/// Describes error, which may occures during pass code entering
|
||||
public enum PassCodeError: Error {
|
||||
case codesNotMatch
|
||||
case wrongCode
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ extension PassCodeHolderProtocol {
|
|||
}
|
||||
}
|
||||
|
||||
/// Holds information about pass codes during pass code creation process
|
||||
public class PassCodeHolderCreate: PassCodeHolderProtocol {
|
||||
|
||||
public let type: PassCodeControllerType = .create
|
||||
|
|
@ -91,6 +92,7 @@ public class PassCodeHolderCreate: PassCodeHolderProtocol {
|
|||
|
||||
}
|
||||
|
||||
/// Holds information about pass code during pass code entering process
|
||||
public class PassCodeHolderEnter: PassCodeHolderProtocol {
|
||||
|
||||
public let type: PassCodeControllerType = .enter
|
||||
|
|
@ -120,6 +122,7 @@ public class PassCodeHolderEnter: PassCodeHolderProtocol {
|
|||
|
||||
}
|
||||
|
||||
/// Holds information about pass codes during pass code changing process
|
||||
public class PassCodeHolderChange: PassCodeHolderProtocol {
|
||||
|
||||
public let type: PassCodeControllerType = .change
|
||||
|
|
|
|||
|
|
@ -20,17 +20,26 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
/// Holds information about enter type (create, change, etc), step
|
||||
/// Also describes interface to manipulate with entered pass code
|
||||
public protocol PassCodeHolderProtocol {
|
||||
|
||||
/// Type of operation with pass code
|
||||
var type: PassCodeControllerType { get }
|
||||
/// Operation step
|
||||
var enterStep: PassCodeControllerState { get }
|
||||
|
||||
/// Add pass code for current step
|
||||
func add(passCode: String)
|
||||
/// Reset all progress
|
||||
func reset()
|
||||
|
||||
/// Should been pass code validated
|
||||
var shouldValidate: Bool { get }
|
||||
/// Current pass code
|
||||
var passCode: String? { get }
|
||||
|
||||
/// Returns passCode or error if pass code is invalid
|
||||
func validate() -> PassCodeValidationResult
|
||||
|
||||
}
|
||||
|
|
@ -39,6 +48,12 @@ public class PassCodeHolderBuilder {
|
|||
|
||||
private init() {}
|
||||
|
||||
/**
|
||||
Creates holder by type (create, change, etc)
|
||||
|
||||
- parameter type: type of pass code controller
|
||||
- returns: pass code information holder, specific by type
|
||||
*/
|
||||
public static func build(with type: PassCodeControllerType) -> PassCodeHolderProtocol {
|
||||
switch type {
|
||||
case .create:
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
/// Result of pass code validation
|
||||
public enum PassCodeValidationResult {
|
||||
|
||||
case valid(String)
|
||||
|
|
|
|||
|
|
@ -25,17 +25,20 @@ import RxSwift
|
|||
import RxCocoa
|
||||
import LeadKit
|
||||
|
||||
/// Describes pin image
|
||||
public enum PinImageType {
|
||||
case entered
|
||||
case clear
|
||||
}
|
||||
|
||||
/// Pass code operation type
|
||||
public enum PassCodeControllerType {
|
||||
case create
|
||||
case enter
|
||||
case change
|
||||
}
|
||||
|
||||
/// Pass code operation state
|
||||
public enum PassCodeControllerState {
|
||||
case enter
|
||||
case repeatEnter
|
||||
|
|
@ -43,6 +46,7 @@ public enum PassCodeControllerState {
|
|||
case newEnter
|
||||
}
|
||||
|
||||
/// Base view controller that operates with pass code
|
||||
open class BasePassCodeViewController: UIViewController {
|
||||
|
||||
public var viewModel: BasePassCodeViewModel!
|
||||
|
|
@ -157,41 +161,44 @@ open class BasePassCodeViewController: UIViewController {
|
|||
|
||||
// MARK: - HAVE TO OVERRIDE
|
||||
|
||||
/// Returns prompt that appears on touch id system alert
|
||||
open var touchIdHint: String {
|
||||
assertionFailure("You should override this var: touchIdHint")
|
||||
return ""
|
||||
}
|
||||
|
||||
// override to change Images
|
||||
/// Override to point certain images
|
||||
open func imageFor(type: PinImageType) -> UIImage {
|
||||
assertionFailure("You should override this method: imageFor(type: PinImageType)")
|
||||
return UIImage()
|
||||
}
|
||||
|
||||
// override to change error text
|
||||
/// Override to change error description
|
||||
open func errorDescription(for error: PassCodeError) -> String {
|
||||
assertionFailure("You should override this method: errorDescription(for error: PassCodeError)")
|
||||
return ""
|
||||
}
|
||||
|
||||
// override to change action title text
|
||||
/// Override to change action title text
|
||||
open func actionTitle(for passCodeControllerState: PassCodeControllerState) -> String {
|
||||
assertionFailure("You should override this method: actionTitle(for passCodeControllerState: PassCodeControllerState)")
|
||||
return ""
|
||||
}
|
||||
|
||||
// MARK: - Functions that can you can override to castomise your controller
|
||||
// MARK: - Functions that you can override to customize your controller
|
||||
|
||||
/// Call to show error
|
||||
open func showError(for error: PassCodeError) {
|
||||
errorLabel?.text = errorDescription(for: error)
|
||||
errorLabel?.isHidden = false
|
||||
}
|
||||
|
||||
/// Call to disappear error label
|
||||
open func hideError() {
|
||||
errorLabel?.isHidden = true
|
||||
}
|
||||
|
||||
// override to change UI for state
|
||||
/// Override to change UI for state
|
||||
open func configureUI(for passCodeControllerState: PassCodeControllerState) {
|
||||
resetDotsUI()
|
||||
titleLabel?.text = actionTitle(for: passCodeControllerState)
|
||||
|
|
@ -199,6 +206,7 @@ open class BasePassCodeViewController: UIViewController {
|
|||
|
||||
}
|
||||
|
||||
// MARK: - ConfigurableController
|
||||
// We need to implement all functions of ConfigurableController protocol to give ability to override them.
|
||||
extension BasePassCodeViewController: ConfigurableController {
|
||||
|
||||
|
|
@ -242,6 +250,7 @@ extension BasePassCodeViewController: ConfigurableController {
|
|||
|
||||
}
|
||||
|
||||
// MARK: - UITextFieldDelegate
|
||||
extension BasePassCodeViewController: UITextFieldDelegate {
|
||||
|
||||
public func textField(_ textField: UITextField,
|
||||
|
|
|
|||
|
|
@ -24,18 +24,22 @@ import LeadKit
|
|||
import RxSwift
|
||||
import RxCocoa
|
||||
|
||||
/// Describes types of authentication
|
||||
public enum PassCodeAuthType {
|
||||
case passCode(String)
|
||||
case touchId
|
||||
}
|
||||
|
||||
/// Base view model for passCodeViewController
|
||||
open class BasePassCodeViewModel: BaseViewModel {
|
||||
|
||||
public let controllerType: PassCodeControllerType
|
||||
|
||||
public let disposeBag = DisposeBag()
|
||||
|
||||
/// TouchId service, which can answer if user is authorized by finger
|
||||
public let touchIdService: TouchIDService?
|
||||
/// Contains configuration for pass code operations
|
||||
public let passCodeConfiguration: PassCodeConfiguration
|
||||
|
||||
fileprivate let validationResultHolder = Variable<PassCodeValidationResult?>(nil)
|
||||
|
|
@ -114,21 +118,25 @@ open class BasePassCodeViewModel: BaseViewModel {
|
|||
|
||||
// MARK: - HAVE TO OVERRIDE
|
||||
|
||||
/// Override to check if entered pass code is equal to stored
|
||||
open func isEnteredPassCodeValid(_ passCode: String) -> Bool {
|
||||
assertionFailure("You should override this method: isEnteredPassCodeValid(_ passCode: String)")
|
||||
return false
|
||||
}
|
||||
|
||||
/// Handler called after successful authentication
|
||||
open func authSucceed(_ type: PassCodeAuthType) {
|
||||
assertionFailure("You should override this method: authSucceed(_ type: PassCodeAuthType)")
|
||||
}
|
||||
|
||||
// MARK: - Functions that can you can override to use TouchId
|
||||
|
||||
/// Override to be able use touchId during authentication
|
||||
open var isTouchIdEnabled: Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
/// You should save user choice about authenticate by touchId
|
||||
open func activateTouchIdForUser() {
|
||||
assertionFailure("You should override this method: activateTouchIdForUser()")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,7 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Describes possible error, received from back-end
|
||||
public enum ApiError: Error {
|
||||
|
||||
case error(code: Int, message: String)
|
||||
|
|
@ -29,6 +28,7 @@ public enum ApiError: Error {
|
|||
|
||||
}
|
||||
|
||||
// MARK: - LocalizedError
|
||||
extension ApiError: LocalizedError {
|
||||
|
||||
public init(apiResponse: ApiResponseProtocol) {
|
||||
|
|
|
|||
|
|
@ -20,10 +20,12 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
/// Describes error by raw value (more likely - Int code), received from back-end
|
||||
public protocol ApiErrorProtocol: RawRepresentable {}
|
||||
|
||||
extension Error {
|
||||
|
||||
/// Method indicates that error is back-end error
|
||||
public func isApiError<T: ApiErrorProtocol>(_ apiErrorType: T) -> Bool where T.RawValue == Int {
|
||||
if let error = self as? ApiError,
|
||||
case let .error(code: code, message: _) = error,
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/// Describes "no connection to server" error
|
||||
public enum ConnectionError: LocalizedError {
|
||||
|
||||
case noConnection
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ public typealias VoidBlock = () -> Void
|
|||
|
||||
public extension Observable {
|
||||
|
||||
/// Handles connection errors during request
|
||||
public func handleConnectionErrors() -> Observable<Observable.E> {
|
||||
return observeOn(CurrentThreadScheduler.instance)
|
||||
|
||||
|
|
@ -52,6 +53,13 @@ public extension Observable {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
Allow to configure request to restart if error occured
|
||||
|
||||
- parameters:
|
||||
- errorTypes: list of error types, which triggers request restart
|
||||
- retryLimit: how many times request can restarts
|
||||
*/
|
||||
public func retryWithinErrors(_ errorTypes: [Error.Type] = [ConnectionError.self],
|
||||
retryLimit: Int = DefaultNetworkService.retryLimit)
|
||||
-> Observable<Observable.E> {
|
||||
|
|
@ -66,6 +74,13 @@ public extension Observable {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Add block that executes, when error, described by ApiErrorProtocol, occured during request
|
||||
|
||||
- parameters:
|
||||
- apiErrorType: type of errors, received frim server
|
||||
- handler: block, that executes, when error occured
|
||||
*/
|
||||
public func handleApiError<T: ApiErrorProtocol>(_ apiErrorType: T,
|
||||
handler: @escaping () -> Void) -> Observable<Observable.E>
|
||||
where T.RawValue == Int {
|
||||
|
|
@ -78,6 +93,11 @@ public extension Observable {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
Add ability to monitor request status
|
||||
|
||||
- parameter isLoading: subject, request state bind to
|
||||
*/
|
||||
public func changeLoadingBehaviour(isLoading: PublishSubject<Bool>) -> Observable<Observable.E> {
|
||||
return observeOn(CurrentThreadScheduler.instance)
|
||||
.do(onNext: { _ in
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import UIKit
|
|||
|
||||
extension UIBarButtonItem {
|
||||
|
||||
/// Creates activity indicator view and bar button item (based on activity indicator)
|
||||
public static var activityIndicator: (barButton: UIBarButtonItem, activityIndicator: UIActivityIndicatorView) {
|
||||
let indicatorView = UIActivityIndicatorView(activityIndicatorStyle: .white)
|
||||
let indicatorBar = UIBarButtonItem(customView: indicatorView)
|
||||
|
|
|
|||
|
|
@ -22,13 +22,14 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
fileprivate enum Keys {
|
||||
private enum Keys {
|
||||
static let sessionId = "sessionId"
|
||||
static let userLogin = "userLogin"
|
||||
}
|
||||
|
||||
public extension UserDefaults {
|
||||
|
||||
/// Default place to store session id
|
||||
public var sessionId: String? {
|
||||
get {
|
||||
return string(forKey: Keys.sessionId)
|
||||
|
|
@ -38,6 +39,7 @@ public extension UserDefaults {
|
|||
}
|
||||
}
|
||||
|
||||
/// Default place to store userLogin
|
||||
public var userLogin: String? {
|
||||
get {
|
||||
return string(forKey: Keys.userLogin)
|
||||
|
|
|
|||
|
|
@ -24,8 +24,10 @@ import KeychainAccess
|
|||
import CocoaLumberjack
|
||||
import IDZSwiftCommonCrypto
|
||||
|
||||
/// Represents base pass code service which encapsulates pass code storing
|
||||
open class BasePassCodeService {
|
||||
|
||||
/// Override to set specific keychain service name
|
||||
open class var keychainService: String {
|
||||
return Bundle.main.bundleIdentifier ?? ""
|
||||
}
|
||||
|
|
@ -63,10 +65,12 @@ open class BasePassCodeService {
|
|||
|
||||
extension BasePassCodeService {
|
||||
|
||||
/// Indicates is pass code already saved on this device
|
||||
public var isPassCodeSaved: Bool {
|
||||
return keychain[Keys.passCodeHash] != nil
|
||||
}
|
||||
|
||||
/// Indicates is it possible to authenticate on this device via touch id
|
||||
public var isTouchIdEnabled: Bool {
|
||||
get {
|
||||
return keychain[Keys.isTouchIdEnabled] == Values.touchIdEnabled
|
||||
|
|
@ -76,6 +80,7 @@ extension BasePassCodeService {
|
|||
}
|
||||
}
|
||||
|
||||
/// Saves new pass code
|
||||
public func save(passCode: String?) {
|
||||
if let passCode = passCode {
|
||||
keychain[Keys.passCodeHash] = sha256(passCode)
|
||||
|
|
@ -84,10 +89,12 @@ extension BasePassCodeService {
|
|||
}
|
||||
}
|
||||
|
||||
/// Check if pass code is correct
|
||||
public func check(passCode: String) -> Bool {
|
||||
return sha256(passCode) == passCodeHash
|
||||
}
|
||||
|
||||
/// Reset pass code settings
|
||||
public func reset() {
|
||||
save(passCode: nil)
|
||||
isTouchIdEnabled = false
|
||||
|
|
|
|||
|
|
@ -23,12 +23,14 @@
|
|||
import RxSwift
|
||||
import LeadKit
|
||||
|
||||
/// Represents service that store basic user information
|
||||
open class BaseUserService {
|
||||
|
||||
public init() {
|
||||
// Can be overrided
|
||||
}
|
||||
|
||||
/// Returns user login
|
||||
open var userLogin: String {
|
||||
guard let defaultsLogin = UserDefaults.standard.userLogin else {
|
||||
assertionFailure("userLogin is nil. Use isLoggedIn before read userLogin")
|
||||
|
|
@ -38,6 +40,7 @@ open class BaseUserService {
|
|||
return defaultsLogin
|
||||
}
|
||||
|
||||
/// Returns session id
|
||||
open var sessionId: String {
|
||||
guard let defaultsSessionId = UserDefaults.standard.sessionId else {
|
||||
assertionFailure("sessionId is nil. Use isLoggedIn before read sessionId")
|
||||
|
|
@ -46,10 +49,12 @@ open class BaseUserService {
|
|||
return defaultsSessionId
|
||||
}
|
||||
|
||||
/// Indicates if user is logged in
|
||||
open var isLoggedIn: Bool {
|
||||
return UserDefaults.standard.sessionId != nil
|
||||
}
|
||||
|
||||
/// Reset user information
|
||||
open class func clearData() {
|
||||
UserDefaults.standard.sessionId = nil
|
||||
UserDefaults.standard.userLogin = nil
|
||||
|
|
|
|||
|
|
@ -25,8 +25,10 @@ import Alamofire
|
|||
import ObjectMapper
|
||||
import RxSwift
|
||||
|
||||
/// Base network service implementation for back-end designed by TouchInstinct
|
||||
open class ApiNetworkService: DefaultNetworkService {
|
||||
|
||||
/// Returns observable for ImmutableMappable response model by parameters
|
||||
open func request<T: ImmutableMappable>(with parameters: ApiRequestParameters) -> Observable<T> {
|
||||
let apiResponseRequest = rxRequest(with: parameters) as Observable<(response: HTTPURLResponse, model: ApiResponse)>
|
||||
|
||||
|
|
@ -41,6 +43,7 @@ open class ApiNetworkService: DefaultNetworkService {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns observable for boolean response by parameters
|
||||
open func requestForResult(with parameters: ApiRequestParameters) -> Observable<Bool> {
|
||||
let apiResponseRequest = rxRequest(with: parameters) as Observable<(response: HTTPURLResponse, model: ApiResponse)>
|
||||
|
||||
|
|
|
|||
|
|
@ -25,16 +25,19 @@ import LeadKit
|
|||
import ObjectMapper
|
||||
import RxSwift
|
||||
|
||||
/// Default implementation of network service, which trust any server and uses default timeout interval
|
||||
open class DefaultNetworkService: NetworkService {
|
||||
|
||||
static let retryLimit = 3
|
||||
|
||||
private let disposeBag = DisposeBag()
|
||||
|
||||
/// Override to set base server url
|
||||
open class var baseUrl: String {
|
||||
fatalError("You should override this var: baseUrl")
|
||||
}
|
||||
|
||||
/// Override to change timeout interval default value
|
||||
open class var defaultTimeoutInterval: TimeInterval {
|
||||
return 20.0
|
||||
}
|
||||
|
|
@ -47,12 +50,14 @@ open class DefaultNetworkService: NetworkService {
|
|||
|
||||
// MARK: - Default Values
|
||||
|
||||
/// Override to change server trust policies
|
||||
open class var serverTrustPolicies: [String: ServerTrustPolicy] {
|
||||
return [
|
||||
baseUrl: .disableEvaluation
|
||||
]
|
||||
}
|
||||
|
||||
/// Override to change default urlSession configuration
|
||||
open class var configuration: URLSessionConfiguration {
|
||||
let configuration = URLSessionConfiguration.default
|
||||
configuration.timeoutIntervalForRequest = defaultTimeoutInterval
|
||||
|
|
@ -60,6 +65,7 @@ open class DefaultNetworkService: NetworkService {
|
|||
return configuration
|
||||
}
|
||||
|
||||
/// Override to configure alamofire session manager
|
||||
open class var sessionManager: SessionManager {
|
||||
let sessionManager = SessionManager(configuration: configuration,
|
||||
serverTrustPolicyManager: ServerTrustPolicyManager(policies: serverTrustPolicies))
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import LocalAuthentication
|
|||
|
||||
public typealias TouchIDServiceAuthHandler = (Bool) -> Void
|
||||
|
||||
/// Represents service that provides access to authentication via touch id
|
||||
public class TouchIDService {
|
||||
|
||||
private lazy var laContext: LAContext = {
|
||||
|
|
@ -32,10 +33,18 @@ public class TouchIDService {
|
|||
|
||||
public init() {}
|
||||
|
||||
/// Indicates is it possible to authenticate on this device via touch id
|
||||
public var canAuthenticateByTouchId: Bool {
|
||||
return laContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil)
|
||||
}
|
||||
|
||||
/**
|
||||
Initiates system touch id authentication process
|
||||
|
||||
- parameters:
|
||||
- description: prompt on the system alert that describes what for user should attach finger to device
|
||||
- authHandler: callback, with parameter, indicates if user authenticate successfuly
|
||||
*/
|
||||
public func authenticateByTouchId(description: String, authHandler: @escaping TouchIDServiceAuthHandler) {
|
||||
laContext.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,
|
||||
localizedReason: description) { success, _ in
|
||||
|
|
|
|||
Loading…
Reference in New Issue