feat: Network services in TIMoyaNetworking now passes MoyaError in result of EnpointRequest execution.
feat: TINetworkingCache module - caching results of EndpointRequests.
This commit is contained in:
parent
19134573fa
commit
532e54fe9e
|
|
@ -1,5 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
### 1.15.0
|
||||
|
||||
- **Update**: Network services in TIMoyaNetworking now passes MoyaError in result of EnpointRequest execution.
|
||||
- **Add**: `TINetworkingCache` module - caching results of EndpointRequests.
|
||||
- **Important Note**: `TINetworkingCache` may require you to add `DISABLE_DIAMOND_PROBLEM_DIAGNOSTIC=YES` flag to build settings of project target (see [probably related problem](https://forums.swift.org/t/adding-a-package-to-two-targets-in-one-projects-results-in-an-error/35007/18))
|
||||
|
||||
### 1.14.3
|
||||
|
||||
- **Fix**: Creating headerView and footerView when initializing a section with rows in `TITableKitUtils`.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = "LeadKit"
|
||||
s.version = "1.14.3"
|
||||
s.version = "1.15.0"
|
||||
s.summary = "iOS framework with a bunch of tools for rapid development"
|
||||
s.homepage = "https://github.com/TouchInstinct/LeadKit"
|
||||
s.license = "Apache License, Version 2.0"
|
||||
|
|
|
|||
|
|
@ -10,6 +10,15 @@
|
|||
"version": "5.4.3"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "Cache",
|
||||
"repositoryURL": "https://github.com/hyperoslo/Cache.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "c7f4d633049c3bd649a353bad36f6c17e9df085f",
|
||||
"version": "6.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "Cursors",
|
||||
"repositoryURL": "https://github.com/petropavel13/Cursors",
|
||||
|
|
|
|||
|
|
@ -17,8 +17,12 @@ let package = Package(
|
|||
.library(name: "TIFoundationUtils", targets: ["TIFoundationUtils"]),
|
||||
.library(name: "TIKeychainUtils", targets: ["TIKeychainUtils"]),
|
||||
.library(name: "TITableKitUtils", targets: ["TITableKitUtils"]),
|
||||
|
||||
// MARK: - Networking
|
||||
|
||||
.library(name: "TINetworking", targets: ["TINetworking"]),
|
||||
.library(name: "TIMoyaNetworking", targets: ["TIMoyaNetworking"]),
|
||||
.library(name: "TINetworkingCache", targets: ["TINetworkingCache"]),
|
||||
|
||||
// MARK: - Elements
|
||||
.library(name: "OTPSwiftView", targets: ["OTPSwiftView"]),
|
||||
|
|
@ -31,6 +35,7 @@ let package = Package(
|
|||
.package(url: "https://github.com/petropavel13/Cursors", .upToNextMajor(from: "0.5.1")),
|
||||
.package(url: "https://github.com/Alamofire/Alamofire.git", .upToNextMajor(from: "5.4.0")),
|
||||
.package(url: "https://github.com/Moya/Moya.git", .upToNextMajor(from: "15.0.0")),
|
||||
.package(url: "https://github.com/hyperoslo/Cache.git", .upToNextMajor(from: "6.0.0"))
|
||||
],
|
||||
targets: [
|
||||
|
||||
|
|
@ -48,6 +53,7 @@ let package = Package(
|
|||
|
||||
.target(name: "TINetworking", dependencies: ["TISwiftUtils", "Alamofire"], path: "TINetworking/Sources"),
|
||||
.target(name: "TIMoyaNetworking", dependencies: ["TINetworking", "TIFoundationUtils", "Moya"], path: "TIMoyaNetworking"),
|
||||
.target(name: "TINetworkingCache", dependencies: ["TIFoundationUtils", "TINetworking", "Cache"], path: "TINetworkingCache/Sources"),
|
||||
|
||||
// MARK: - Elements
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TIFoundationUtils'
|
||||
s.version = '1.14.3'
|
||||
s.version = '1.15.0'
|
||||
s.summary = 'Set of helpers for Foundation framework classes.'
|
||||
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
|
||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TIKeychainUtils'
|
||||
s.version = '1.14.3'
|
||||
s.version = '1.15.0'
|
||||
s.summary = 'Set of helpers for Keychain classes.'
|
||||
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
|
||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
|
|
|
|||
|
|
@ -59,13 +59,17 @@ open class DefaultJsonNetworkService {
|
|||
plugins: plugins)
|
||||
}
|
||||
|
||||
open func serialize<B: Encodable, S: Decodable>(request: EndpointRequest<B, S>) throws -> SerializedRequest {
|
||||
try request.serialize(using: ApplicationJsonBodySerializer(jsonEncoder: jsonEncoder),
|
||||
defaultServer: defaultServer)
|
||||
}
|
||||
|
||||
@available(iOS 13.0.0, *)
|
||||
open func process<B: Encodable, S: Decodable, F: Decodable>(request: EndpointRequest<B, S>,
|
||||
mapMoyaError: @escaping Closure<MoyaError, F>) async -> Result<S, F> {
|
||||
open func process<B: Encodable, S, F>(request: EndpointRequest<B, S>) async -> EndpointRequestResult<S, F> {
|
||||
await process(request: request,
|
||||
mapSuccess: Result.success,
|
||||
mapFailure: Result.failure,
|
||||
mapMoyaError: { .failure(mapMoyaError($0)) })
|
||||
mapFailure: { .failure(.apiError($0)) },
|
||||
mapMoyaError: { .failure(.networkError($0)) })
|
||||
}
|
||||
|
||||
@available(iOS 13.0.0, *)
|
||||
|
|
@ -98,15 +102,14 @@ open class DefaultJsonNetworkService {
|
|||
mapMoyaError: @escaping Closure<MoyaError, R>,
|
||||
completion: @escaping ParameterClosure<R>) -> Cancellable {
|
||||
|
||||
ScopeCancellable { [jsonEncoder, serializationQueue, callbackQueue, defaultServer] scope in
|
||||
ScopeCancellable { [serializationQueue, callbackQueue] scope in
|
||||
let workItem = DispatchWorkItem {
|
||||
guard !scope.isCancelled else {
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
let serializedRequest = try request.serialize(using: ApplicationJsonBodySerializer(jsonEncoder: jsonEncoder),
|
||||
defaultServer: defaultServer)
|
||||
let serializedRequest = try self.serialize(request: request)
|
||||
|
||||
scope.add(cancellable: self.process(request: serializedRequest,
|
||||
mapSuccess: mapSuccess,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// Copyright (c) 2022 Touch Instinct
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the Software), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Moya
|
||||
import Foundation
|
||||
|
||||
public enum EndpointErrorResult<E>: Error {
|
||||
case apiError(E)
|
||||
case networkError(MoyaError)
|
||||
}
|
||||
|
||||
public extension EndpointErrorResult {
|
||||
var isNetworkConnectionProblem: Bool {
|
||||
guard case let .networkError(moyaError) = self,
|
||||
case let .underlying(error, _) = moyaError,
|
||||
case let .sessionTaskFailed(urlSessionTaskError) = error.asAFError,
|
||||
let urlError = urlSessionTaskError as? URLError else {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
return urlError.code == .notConnectedToInternet
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
//
|
||||
// Copyright (c) 2022 Touch Instinct
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the Software), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
public typealias EndpointRequestResult<S: Decodable, F: Decodable> = Result<S, EndpointErrorResult<F>>
|
||||
|
|
@ -26,45 +26,40 @@ import Moya
|
|||
|
||||
@available(iOS 13.0.0, *)
|
||||
open class DefaultRecoverableJsonNetworkService<ApiError: Decodable & Error>: DefaultJsonNetworkService {
|
||||
public typealias ErrorHandler = AnyAsyncEventHandler<ApiError>
|
||||
public typealias ErrorHandler = AnyAsyncEventHandler<EndpointErrorResult<ApiError>>
|
||||
|
||||
private(set) public var defaultErrorHandlers: [ErrorHandler] = []
|
||||
|
||||
public func process<B: Encodable, S: Decodable>(recoverableRequest: EndpointRequest<B, S>,
|
||||
prependErrorHandlers: [ErrorHandler],
|
||||
appendErrorHandlers: [ErrorHandler],
|
||||
mapMoyaError: @escaping Closure<MoyaError, ApiError>) async -> Result<S, ApiError> {
|
||||
open func process<B: Encodable, S>(recoverableRequest: EndpointRequest<B, S>,
|
||||
prependErrorHandlers: [ErrorHandler] = [],
|
||||
appendErrorHandlers: [ErrorHandler] = []) async -> EndpointRequestResult<S, ApiError> {
|
||||
|
||||
await process(recoverableRequest: recoverableRequest,
|
||||
errorHandlers: prependErrorHandlers + defaultErrorHandlers + appendErrorHandlers,
|
||||
mapMoyaError: mapMoyaError)
|
||||
errorHandlers: prependErrorHandlers + defaultErrorHandlers + appendErrorHandlers)
|
||||
}
|
||||
|
||||
public func process<B: Encodable, S: Decodable>(recoverableRequest: EndpointRequest<B, S>,
|
||||
errorHandlers: [ErrorHandler],
|
||||
mapMoyaError: @escaping Closure<MoyaError, ApiError>) async -> Result<S, ApiError> {
|
||||
open func process<B: Encodable, S>(recoverableRequest: EndpointRequest<B, S>,
|
||||
errorHandlers: [ErrorHandler]) async -> EndpointRequestResult<S, ApiError> {
|
||||
|
||||
let result = await process(request: recoverableRequest,
|
||||
mapMoyaError: mapMoyaError)
|
||||
let result: EndpointRequestResult<S, ApiError> = await process(request: recoverableRequest)
|
||||
|
||||
if case let .failure(errorResponse) = result {
|
||||
let chain = AsyncEventHandlingChain(handlers: errorHandlers)
|
||||
|
||||
if await chain.handle(errorResponse) {
|
||||
return await process(recoverableRequest: recoverableRequest,
|
||||
errorHandlers: errorHandlers,
|
||||
mapMoyaError: mapMoyaError)
|
||||
errorHandlers: errorHandlers)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
public func register<ErrorHandler: AsyncErrorHandler>(defaultErrorHandler: ErrorHandler) where ErrorHandler.EventType == ApiError {
|
||||
public func register<ErrorHandler: AsyncErrorHandler>(defaultErrorHandler: ErrorHandler) where ErrorHandler.EventType == EndpointErrorResult<ApiError> {
|
||||
defaultErrorHandlers.append(defaultErrorHandler.asAnyAsyncEventHandler())
|
||||
}
|
||||
|
||||
public func set<ErrorHandler: AsyncErrorHandler>(defaultErrorHandlers: ErrorHandler...) where ErrorHandler.EventType == ApiError {
|
||||
public func set<ErrorHandler: AsyncErrorHandler>(defaultErrorHandlers: ErrorHandler...) where ErrorHandler.EventType == EndpointErrorResult<ApiError> {
|
||||
self.defaultErrorHandlers = defaultErrorHandlers.map { $0.asAnyAsyncEventHandler() }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TIMoyaNetworking'
|
||||
s.version = '1.14.3'
|
||||
s.version = '1.15.0'
|
||||
s.summary = 'Moya + Swagger network service.'
|
||||
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
|
||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
|
|
|
|||
|
|
@ -52,3 +52,33 @@ public struct SerializedRequest {
|
|||
self.acceptableStatusCodes = acceptableStatusCodes
|
||||
}
|
||||
}
|
||||
|
||||
extension SerializedRequest: Hashable {
|
||||
private var comparableQueryParameters: [String: String] {
|
||||
queryParameters.mapValues(String.init(describing:))
|
||||
}
|
||||
|
||||
public static func == (lhs: SerializedRequest, rhs: SerializedRequest) -> Bool {
|
||||
lhs.baseURL == rhs.baseURL &&
|
||||
lhs.path == rhs.path &&
|
||||
lhs.method == rhs.method &&
|
||||
lhs.bodyData == rhs.bodyData &&
|
||||
lhs.comparableQueryParameters == rhs.comparableQueryParameters &&
|
||||
lhs.headers == rhs.headers &&
|
||||
lhs.cookies == rhs.cookies &&
|
||||
lhs.acceptableStatusCodes == rhs.acceptableStatusCodes
|
||||
}
|
||||
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
hasher.combine(baseURL)
|
||||
hasher.combine(path)
|
||||
hasher.combine(method)
|
||||
hasher.combine(bodyData)
|
||||
hasher.combine(comparableQueryParameters.keys.sorted())
|
||||
hasher.combine(comparableQueryParameters.values.sorted())
|
||||
hasher.combine(headers?.keys.sorted() ?? [])
|
||||
hasher.combine(headers?.values.sorted() ?? [])
|
||||
hasher.combine(cookies)
|
||||
hasher.combine(acceptableStatusCodes.sorted())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TINetworking'
|
||||
s.version = '1.14.3'
|
||||
s.version = '1.15.0'
|
||||
s.summary = 'Swagger-frendly networking layer helpers.'
|
||||
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
|
||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
//
|
||||
// Copyright (c) 2022 Touch Instinct
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the Software), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import TINetworking
|
||||
import TIFoundationUtils
|
||||
import Cache
|
||||
import Foundation
|
||||
|
||||
public struct EndpointCacheService<Content: Codable> {
|
||||
private let serializedRequest: SerializedRequest
|
||||
private let multiLevelStorage: Storage<SerializedRequest, Content>
|
||||
|
||||
public var cachedContent: Content? {
|
||||
get {
|
||||
guard let entry = try? multiLevelStorage.entry(forKey: serializedRequest), !entry.expiry.isExpired else {
|
||||
try? multiLevelStorage.removeObject(forKey: serializedRequest)
|
||||
return nil
|
||||
}
|
||||
|
||||
return entry.object
|
||||
}
|
||||
nonmutating set {
|
||||
if let object = newValue {
|
||||
try? multiLevelStorage.setObject(object,
|
||||
forKey: serializedRequest)
|
||||
} else {
|
||||
try? multiLevelStorage.removeObject(forKey: serializedRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public init(serializedRequest: SerializedRequest,
|
||||
cacheLifetime: TimeInterval,
|
||||
jsonCodingConfigurator: JsonCodingConfigurator) throws {
|
||||
|
||||
self.serializedRequest = serializedRequest
|
||||
|
||||
let nameWithoutLeadingSlash: String
|
||||
|
||||
if serializedRequest.path.starts(with: "/") {
|
||||
nameWithoutLeadingSlash = serializedRequest.path.drop { $0 == "/" }.string
|
||||
} else {
|
||||
nameWithoutLeadingSlash = serializedRequest.path
|
||||
}
|
||||
|
||||
let diskConfig = DiskConfig(name: nameWithoutLeadingSlash,
|
||||
expiry: .seconds(cacheLifetime))
|
||||
let memoryConfig = MemoryConfig(expiry: .seconds(cacheLifetime),
|
||||
countLimit: 0,
|
||||
totalCostLimit: 0)
|
||||
|
||||
let transformer = Transformer {
|
||||
try jsonCodingConfigurator.jsonEncoder.encode($0)
|
||||
} fromData: {
|
||||
try jsonCodingConfigurator.jsonDecoder.decode(Content.self, from: $0)
|
||||
}
|
||||
|
||||
self.multiLevelStorage = try Storage(diskConfig: diskConfig,
|
||||
memoryConfig: memoryConfig,
|
||||
transformer: transformer)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TINetworkingCache'
|
||||
s.version = '1.15.0'
|
||||
s.summary = 'Caching results of EndpointRequests.'
|
||||
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
|
||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
s.author = { 'petropavel13' => 'ivan.smolin@touchin.ru' }
|
||||
s.source = { :git => 'https://github.com/TouchInstinct/LeadKit.git', :tag => s.version.to_s }
|
||||
|
||||
s.ios.deployment_target = '11.0'
|
||||
s.swift_versions = ['5.3']
|
||||
|
||||
s.source_files = s.name + '/Sources/**/*'
|
||||
|
||||
s.dependency 'TIFoundationUtils', s.version.to_s
|
||||
s.dependency 'TINetworking', s.version.to_s
|
||||
s.dependency 'Cache', "~> 6.0.0"
|
||||
end
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TISwiftUtils'
|
||||
s.version = '1.14.3'
|
||||
s.version = '1.15.0'
|
||||
s.summary = 'Bunch of useful helpers for Swift development.'
|
||||
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
|
||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
//
|
||||
|
||||
import TableKit
|
||||
import class UIKit.UIView
|
||||
|
||||
public extension TableSection {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TITableKitUtils'
|
||||
s.version = '1.14.3'
|
||||
s.version = '1.15.0'
|
||||
s.summary = 'Set of helpers for TableKit classes.'
|
||||
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
|
||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TITransitions'
|
||||
s.version = '1.14.3'
|
||||
s.version = '1.15.0'
|
||||
s.summary = 'Set of custom transitions to present controller. '
|
||||
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
|
||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TIUIElements'
|
||||
s.version = '1.14.3'
|
||||
s.version = '1.15.0'
|
||||
s.summary = 'Bunch of useful protocols and views.'
|
||||
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
|
||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TIUIKitCore'
|
||||
s.version = '1.14.3'
|
||||
s.version = '1.15.0'
|
||||
s.summary = 'Core UI elements: protocols, views and helpers.'
|
||||
s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name
|
||||
s.license = { :type => 'MIT', :file => 'LICENSE' }
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ ORDERED_PODSPECS="../TISwiftUtils/TISwiftUtils.podspec
|
|||
../TIUIElements/TIUIElements.podspec
|
||||
../TITableKitUtils/TITableKitUtils.podspec
|
||||
../TINetworking/TINetworking.podspec
|
||||
../TINetworking/TINetworkingCache.podspec
|
||||
../TIMoyaNetworking/TIMoyaNetworking.podspec"
|
||||
|
||||
for podspec_path in ${ORDERED_PODSPECS}; do
|
||||
|
|
|
|||
Loading…
Reference in New Issue