feat: Change access modifiers in `DefaultJsonNetworkService` from `public` to `open`, added additional Moya plugins processing
add `DisplayDecodingErrorPlugin` for showing developer-frendly decoding error messages add Gemfile for cocoapods versioning
This commit is contained in:
parent
e67136013c
commit
10ec9408ad
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
BUNDLE_PATH: ".gem"
|
||||
|
|
@ -104,4 +104,7 @@ cpd-output.xml
|
|||
*.swp
|
||||
*IDEWorkspaceChecks.plist
|
||||
|
||||
# Gem
|
||||
.gem/
|
||||
|
||||
.DS_Store
|
||||
|
|
@ -1,5 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
### 1.13.0
|
||||
|
||||
- **Update**: Change access modifiers in `DefaultJsonNetworkService` from `public` to `open`, added additional Moya plugins processing
|
||||
- **Add**: `DisplayDecodingErrorPlugin` for showing developer-frendly decoding error messages
|
||||
- **Add**: Gemfile for cocoapods versioning
|
||||
|
||||
### 1.12.3
|
||||
|
||||
- **Fix**: Try parse date in ISO8601 format appending `.withFractionalSeconds` if `.withInternetDateTime` fails
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "cocoapods", "~> 1.11"
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.5)
|
||||
rexml
|
||||
activesupport (6.1.5)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
tzinfo (~> 2.0)
|
||||
zeitwerk (~> 2.3)
|
||||
addressable (2.8.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
algoliasearch (1.27.5)
|
||||
httpclient (~> 2.8, >= 2.8.3)
|
||||
json (>= 1.5.1)
|
||||
atomos (0.1.3)
|
||||
claide (1.1.0)
|
||||
cocoapods (1.11.3)
|
||||
addressable (~> 2.8)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
cocoapods-core (= 1.11.3)
|
||||
cocoapods-deintegrate (>= 1.0.3, < 2.0)
|
||||
cocoapods-downloader (>= 1.4.0, < 2.0)
|
||||
cocoapods-plugins (>= 1.0.0, < 2.0)
|
||||
cocoapods-search (>= 1.0.0, < 2.0)
|
||||
cocoapods-trunk (>= 1.4.0, < 2.0)
|
||||
cocoapods-try (>= 1.1.0, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
escape (~> 0.0.4)
|
||||
fourflusher (>= 2.3.0, < 3.0)
|
||||
gh_inspector (~> 1.0)
|
||||
molinillo (~> 0.8.0)
|
||||
nap (~> 1.0)
|
||||
ruby-macho (>= 1.0, < 3.0)
|
||||
xcodeproj (>= 1.21.0, < 2.0)
|
||||
cocoapods-core (1.11.3)
|
||||
activesupport (>= 5.0, < 7)
|
||||
addressable (~> 2.8)
|
||||
algoliasearch (~> 1.0)
|
||||
concurrent-ruby (~> 1.1)
|
||||
fuzzy_match (~> 2.0.4)
|
||||
nap (~> 1.0)
|
||||
netrc (~> 0.11)
|
||||
public_suffix (~> 4.0)
|
||||
typhoeus (~> 1.0)
|
||||
cocoapods-deintegrate (1.0.5)
|
||||
cocoapods-downloader (1.6.2)
|
||||
cocoapods-plugins (1.0.0)
|
||||
nap
|
||||
cocoapods-search (1.0.1)
|
||||
cocoapods-trunk (1.6.0)
|
||||
nap (>= 0.8, < 2.0)
|
||||
netrc (~> 0.11)
|
||||
cocoapods-try (1.2.0)
|
||||
colored2 (3.1.2)
|
||||
concurrent-ruby (1.1.10)
|
||||
escape (0.0.4)
|
||||
ethon (0.15.0)
|
||||
ffi (>= 1.15.0)
|
||||
ffi (1.15.5)
|
||||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.10.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
json (2.6.1)
|
||||
minitest (5.15.0)
|
||||
molinillo (0.8.0)
|
||||
nanaimo (0.3.0)
|
||||
nap (1.1.0)
|
||||
netrc (0.11.0)
|
||||
public_suffix (4.0.6)
|
||||
rexml (3.2.5)
|
||||
ruby-macho (2.5.1)
|
||||
typhoeus (1.4.0)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (2.0.4)
|
||||
concurrent-ruby (~> 1.0)
|
||||
xcodeproj (1.21.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.3.0)
|
||||
rexml (~> 3.2.4)
|
||||
zeitwerk (2.5.4)
|
||||
|
||||
PLATFORMS
|
||||
x86_64-darwin-20
|
||||
|
||||
DEPENDENCIES
|
||||
cocoapods (~> 1.11)
|
||||
|
||||
BUNDLED WITH
|
||||
2.3.10
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = "LeadKit"
|
||||
s.version = "1.12.3"
|
||||
s.version = "1.13.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"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TIFoundationUtils'
|
||||
s.version = '1.12.3'
|
||||
s.version = '1.13.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.12.3'
|
||||
s.version = '1.13.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' }
|
||||
|
|
|
|||
|
|
@ -60,8 +60,8 @@ open class DefaultJsonNetworkService {
|
|||
}
|
||||
|
||||
@available(iOS 13.0.0, *)
|
||||
public 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: Decodable, F: Decodable>(request: EndpointRequest<B, S>,
|
||||
mapMoyaError: @escaping Closure<MoyaError, F>) async -> Result<S, F> {
|
||||
await process(request: request,
|
||||
mapSuccess: Result.success,
|
||||
mapFailure: Result.failure,
|
||||
|
|
@ -69,10 +69,10 @@ open class DefaultJsonNetworkService {
|
|||
}
|
||||
|
||||
@available(iOS 13.0.0, *)
|
||||
public func process<B: Encodable, S: Decodable, F: Decodable, R>(request: EndpointRequest<B, S>,
|
||||
mapSuccess: @escaping Closure<S, R>,
|
||||
mapFailure: @escaping Closure<F, R>,
|
||||
mapMoyaError: @escaping Closure<MoyaError, R>) async -> R {
|
||||
open func process<B: Encodable, S: Decodable, F: Decodable, R>(request: EndpointRequest<B, S>,
|
||||
mapSuccess: @escaping Closure<S, R>,
|
||||
mapFailure: @escaping Closure<F, R>,
|
||||
mapMoyaError: @escaping Closure<MoyaError, R>) async -> R {
|
||||
|
||||
let cancellableBag = CancellableBag()
|
||||
|
||||
|
|
@ -87,16 +87,16 @@ open class DefaultJsonNetworkService {
|
|||
|
||||
continuation.resume(returning: $0)
|
||||
}
|
||||
.add(to: cancellableBag)
|
||||
.add(to: cancellableBag)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public func process<B: Encodable, S: Decodable, F: Decodable, R>(request: EndpointRequest<B, S>,
|
||||
mapSuccess: @escaping Closure<S, R>,
|
||||
mapFailure: @escaping Closure<F, R>,
|
||||
mapMoyaError: @escaping Closure<MoyaError, R>,
|
||||
completion: @escaping ParameterClosure<R>) -> Cancellable {
|
||||
open func process<B: Encodable, S: Decodable, F: Decodable, R>(request: EndpointRequest<B, S>,
|
||||
mapSuccess: @escaping Closure<S, R>,
|
||||
mapFailure: @escaping Closure<F, R>,
|
||||
mapMoyaError: @escaping Closure<MoyaError, R>,
|
||||
completion: @escaping ParameterClosure<R>) -> Cancellable {
|
||||
|
||||
ScopeCancellable { [jsonEncoder, serializationQueue, callbackQueue, defaultServer] scope in
|
||||
let workItem = DispatchWorkItem {
|
||||
|
|
@ -126,13 +126,17 @@ open class DefaultJsonNetworkService {
|
|||
}
|
||||
}
|
||||
|
||||
public func process<S: Decodable, F: Decodable, R>(request: SerializedRequest,
|
||||
mapSuccess: @escaping Closure<S, R>,
|
||||
mapFailure: @escaping Closure<F, R>,
|
||||
mapMoyaError: @escaping Closure<MoyaError, R>,
|
||||
completion: @escaping ParameterClosure<R>) -> Cancellable {
|
||||
open func process<S: Decodable, F: Decodable, R>(request: SerializedRequest,
|
||||
mapSuccess: @escaping Closure<S, R>,
|
||||
mapFailure: @escaping Closure<F, R>,
|
||||
mapMoyaError: @escaping Closure<MoyaError, R>,
|
||||
completion: @escaping ParameterClosure<R>) -> Cancellable {
|
||||
|
||||
createProvider().request(request) { [jsonDecoder, callbackQueue, decodableSuccessStatusCodes, decodableFailureStatusCodes] in
|
||||
createProvider().request(request) { [jsonDecoder,
|
||||
callbackQueue,
|
||||
decodableSuccessStatusCodes,
|
||||
decodableFailureStatusCodes,
|
||||
plugins] in
|
||||
let result: R
|
||||
|
||||
switch $0 {
|
||||
|
|
@ -163,11 +167,19 @@ open class DefaultJsonNetworkService {
|
|||
((failureStatusCodes, CommonMediaTypes.applicationJson.rawValue), jsonDecoder.decoding(to: mapFailure)),
|
||||
])
|
||||
|
||||
let pluginResult: Result<Response, MoyaError>
|
||||
|
||||
switch decodeResult {
|
||||
case let .success(model):
|
||||
result = model
|
||||
pluginResult = .success(rawResponse)
|
||||
case let .failure(moyaError):
|
||||
result = mapMoyaError(moyaError)
|
||||
pluginResult = .failure(moyaError)
|
||||
}
|
||||
|
||||
plugins.forEach {
|
||||
$0.didReceive(pluginResult, target: request)
|
||||
}
|
||||
case let .failure(moyaError):
|
||||
result = mapMoyaError(moyaError)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
//
|
||||
// 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 struct DecodingErrorSummary: CustomStringConvertible {
|
||||
public let url: String
|
||||
public let requestMethod: String
|
||||
public let statusCode: Int
|
||||
public let codingPath: String
|
||||
public let jsonValue: String
|
||||
public let errorDescription: String
|
||||
|
||||
public let formatter: DecodingErrorSummaryFormatter
|
||||
|
||||
public var description: String {
|
||||
formatter.format(summary: self)
|
||||
}
|
||||
|
||||
public init(decodingError: DecodingError,
|
||||
response: Response,
|
||||
formatter: DecodingErrorSummaryFormatter) {
|
||||
|
||||
switch decodingError {
|
||||
case let .typeMismatch(_, context):
|
||||
self.init(context: context, response: response, formatter: formatter)
|
||||
case let .dataCorrupted(context):
|
||||
self.init(context: context, response: response, formatter: formatter)
|
||||
case let .keyNotFound(_, context):
|
||||
self.init(context: context, response: response, formatter: formatter)
|
||||
case let .valueNotFound(_, context):
|
||||
self.init(context: context, response: response, formatter: formatter)
|
||||
@unknown default:
|
||||
self.init(context: .init(codingPath: [],
|
||||
debugDescription: ">>UNHANDLED DECODING ERROR CASE<<",
|
||||
underlyingError: nil),
|
||||
response: response,
|
||||
formatter: formatter)
|
||||
}
|
||||
}
|
||||
|
||||
public init(context: DecodingError.Context,
|
||||
response: Response,
|
||||
formatter: DecodingErrorSummaryFormatter) {
|
||||
|
||||
self.url = response.request?.url?.relativePath ?? formatter.missingDataPlaceholder
|
||||
self.statusCode = response.statusCode
|
||||
self.requestMethod = response.request?.httpMethod ?? formatter.missingDataPlaceholder
|
||||
self.codingPath = formatter.format(codingPath: context.codingPath)
|
||||
self.errorDescription = context.debugDescription
|
||||
self.jsonValue = formatter.format(jsonValue: context.extractJsonValue(from: response))
|
||||
|
||||
self.formatter = formatter
|
||||
}
|
||||
}
|
||||
|
||||
private extension DecodingError.Context {
|
||||
func extractJsonValue(from response: Response) -> Any? {
|
||||
do {
|
||||
let jsonObject = try JSONSerialization.jsonObject(with: response.data, options: .fragmentsAllowed)
|
||||
|
||||
return value(forCodingPath: codingPath, in: jsonObject)
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func value<C: Collection>(forCodingPath path: C, in obj: Any?) -> Any? where C.Element == CodingKey {
|
||||
guard let part = path.first else {
|
||||
return obj
|
||||
}
|
||||
|
||||
switch obj {
|
||||
case let dict as [AnyHashable: Any]:
|
||||
return value(forCodingPath: path.dropFirst(), in: dict[part.stringValue])
|
||||
case let array as [Any]:
|
||||
guard let arrayIndex = part.intValue else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return value(forCodingPath: path.dropFirst(), in: array[arrayIndex])
|
||||
case let anyObj as AnyObject:
|
||||
return value(forCodingPath: path.dropFirst(), in: anyObj.value(forKey: part.stringValue))
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
open class DecodingErrorSummaryFormatter {
|
||||
public var codingPathSeparator = "."
|
||||
public var missingDataPlaceholder = "N/A"
|
||||
|
||||
public init() {}
|
||||
|
||||
open func format(summary: DecodingErrorSummary) -> String {
|
||||
"""
|
||||
\(summary.errorDescription)
|
||||
|
||||
json_value: \(summary.jsonValue)
|
||||
|
||||
json_path: \(summary.codingPath)
|
||||
|
||||
\(summary.requestMethod) \(summary.statusCode) \(summary.url)
|
||||
"""
|
||||
}
|
||||
|
||||
open func format(codingPath: [CodingKey]) -> String {
|
||||
let formattedPath = codingPath.reduce(into: "") {
|
||||
if let intValue = $1.intValue {
|
||||
$0.append("[\(intValue)]")
|
||||
} else {
|
||||
$0.append(codingPathSeparator)
|
||||
$0.append($1.stringValue)
|
||||
}
|
||||
}
|
||||
|
||||
guard formattedPath.range(of: codingPathSeparator)?.lowerBound != formattedPath.startIndex else {
|
||||
return String(formattedPath.dropFirst())
|
||||
}
|
||||
|
||||
return formattedPath
|
||||
}
|
||||
|
||||
open func format(jsonValue: Any?) -> String {
|
||||
String(reflecting: jsonValue ?? missingDataPlaceholder)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
open class DisplayDecodingErrorPlugin: PluginType {
|
||||
public var formatter: DecodingErrorSummaryFormatter
|
||||
|
||||
public init(formatter: DecodingErrorSummaryFormatter = .init()) {
|
||||
self.formatter = formatter
|
||||
}
|
||||
|
||||
open func didReceive(_ result: Result<Response, MoyaError>, target: TargetType) {
|
||||
guard case let .failure(moyaError) = result else {
|
||||
return
|
||||
}
|
||||
|
||||
guard case let .objectMapping(error as DecodingError, response) = moyaError else {
|
||||
return
|
||||
}
|
||||
|
||||
display(summary: .init(decodingError: error, response: response, formatter: formatter))
|
||||
}
|
||||
|
||||
open func display(summary: DecodingErrorSummary) {
|
||||
debugPrint(summary.description)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TIMoyaNetworking'
|
||||
s.version = '1.12.3'
|
||||
s.version = '1.13.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' }
|
||||
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 = '10.0'
|
||||
s.ios.deployment_target = '11.0'
|
||||
s.swift_versions = ['5.3']
|
||||
|
||||
s.source_files = s.name + '/**/Sources/**/*'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TINetworking'
|
||||
s.version = '1.12.3'
|
||||
s.version = '1.13.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' }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TISwiftUtils'
|
||||
s.version = '1.12.3'
|
||||
s.version = '1.13.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' }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TITableKitUtils'
|
||||
s.version = '1.12.3'
|
||||
s.version = '1.13.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.12.3'
|
||||
s.version = '1.13.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.12.3'
|
||||
s.version = '1.13.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.12.3'
|
||||
s.version = '1.13.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' }
|
||||
|
|
|
|||
Loading…
Reference in New Issue