diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dca2d25..b845e5bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +### 1.16.1 + +- **Update**: `DateFormattersReusePool` and `ISO8601DateFormattersReusePool` are now thread safe. + ### 1.16.0 - **Add**: `TIMapUtils`, `TIAppleMapUtils`, `TIGoogleMapUtils` and `TIYandexMapUtils` modules for map items clustering and interacting with them. diff --git a/LeadKit.podspec b/LeadKit.podspec index e7b810d6..6fd5d5de 100644 --- a/LeadKit.podspec +++ b/LeadKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "LeadKit" - s.version = "1.16.0" + s.version = "1.16.1" 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" diff --git a/TIAppleMapUtils/TIAppleMapUtils.podspec b/TIAppleMapUtils/TIAppleMapUtils.podspec index 0cee5f8d..e21fb50e 100644 --- a/TIAppleMapUtils/TIAppleMapUtils.podspec +++ b/TIAppleMapUtils/TIAppleMapUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIAppleMapUtils' - s.version = '1.16.0' + s.version = '1.16.1' s.summary = 'Set of helpers for map objects clustering and interacting using Apple MapKit.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TIFoundationUtils/DateFormatting/Sources/DateFormattersReusePool.swift b/TIFoundationUtils/DateFormatting/Sources/DateFormattersReusePool.swift index 7dfa34ba..fde4cf8c 100644 --- a/TIFoundationUtils/DateFormatting/Sources/DateFormattersReusePool.swift +++ b/TIFoundationUtils/DateFormatting/Sources/DateFormattersReusePool.swift @@ -28,7 +28,7 @@ import Foundation // than to create and dispose of multiple instances. // (https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW10) open class DateFormattersReusePool { - private var pool: [String: DateFormatter] = [:] + private var pool: ThreadSafeDictionary = [:] private let presetLocale: Locale? private let presetTimeZone: TimeZone? diff --git a/TIFoundationUtils/DateFormatting/Sources/ISO8601DateFormattersReusePool.swift b/TIFoundationUtils/DateFormatting/Sources/ISO8601DateFormattersReusePool.swift index ad1f2333..eb7b14a1 100644 --- a/TIFoundationUtils/DateFormatting/Sources/ISO8601DateFormattersReusePool.swift +++ b/TIFoundationUtils/DateFormatting/Sources/ISO8601DateFormattersReusePool.swift @@ -23,7 +23,7 @@ import Foundation open class ISO8601DateFormattersReusePool { - private var pool: [ISO8601DateFormatter.Options: ISO8601DateFormatter] = [:] + private var pool: ThreadSafeDictionary = [:] private let presetTimeZone: TimeZone? diff --git a/TIFoundationUtils/DateFormatting/Sources/ThreadSafeDictionary.swift b/TIFoundationUtils/DateFormatting/Sources/ThreadSafeDictionary.swift new file mode 100644 index 00000000..5239a254 --- /dev/null +++ b/TIFoundationUtils/DateFormatting/Sources/ThreadSafeDictionary.swift @@ -0,0 +1,54 @@ +import Dispatch + +public final class ThreadSafeDictionary: Collection, ExpressibleByDictionaryLiteral { + private var wrappedDict: [K: V] + private let concurrentQueue = DispatchQueue(label: "TIFoundationUtils.ThreadSafeDictionary.Queue", + attributes: .concurrent) + + // MARK: - Collection + + public var startIndex: Dictionary.Index { + concurrentQueue.sync { + self.wrappedDict.startIndex + } + } + + public var endIndex: Dictionary.Index { + concurrentQueue.sync { + self.wrappedDict.endIndex + } + } + + // MARK: - ExpressibleByDictionaryLiteral + + public init(dictionaryLiteral elements: (K, V)...) { + self.wrappedDict = Dictionary(uniqueKeysWithValues: elements) + } + + // MARK: - Collection + + public func index(after i: Dictionary.Index) -> Dictionary.Index { + concurrentQueue.sync { + self.wrappedDict.index(after: i) + } + } + + public subscript(index: Dictionary.Index) -> Dictionary.Element { + concurrentQueue.sync { + self.wrappedDict[index] + } + } + + public subscript(key: K) -> V? { + set { + concurrentQueue.async(flags: .barrier) { + self.wrappedDict[key] = newValue + } + } + get { + concurrentQueue.sync { + self.wrappedDict[key] + } + } + } +} diff --git a/TIFoundationUtils/TIFoundationUtils.podspec b/TIFoundationUtils/TIFoundationUtils.podspec index 203d5697..8076e24f 100644 --- a/TIFoundationUtils/TIFoundationUtils.podspec +++ b/TIFoundationUtils/TIFoundationUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIFoundationUtils' - s.version = '1.16.0' + s.version = '1.16.1' 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' } diff --git a/TIGoogleMapUtils/TIGoogleMapUtils.podspec b/TIGoogleMapUtils/TIGoogleMapUtils.podspec index d00ce801..41277abb 100644 --- a/TIGoogleMapUtils/TIGoogleMapUtils.podspec +++ b/TIGoogleMapUtils/TIGoogleMapUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIGoogleMapUtils' - s.version = '1.16.0' + s.version = '1.16.1' s.summary = 'Set of helpers for map objects clustering and interacting using Google Maps SDK.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TIKeychainUtils/TIKeychainUtils.podspec b/TIKeychainUtils/TIKeychainUtils.podspec index 3a1d9552..2b2d7300 100644 --- a/TIKeychainUtils/TIKeychainUtils.podspec +++ b/TIKeychainUtils/TIKeychainUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIKeychainUtils' - s.version = '1.16.0' + s.version = '1.16.1' 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' } diff --git a/TIMapUtils/TIMapUtils.podspec b/TIMapUtils/TIMapUtils.podspec index d4a63afe..dbc08c2d 100644 --- a/TIMapUtils/TIMapUtils.podspec +++ b/TIMapUtils/TIMapUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIMapUtils' - s.version = '1.16.0' + s.version = '1.16.1' s.summary = 'Set of helpers for map objects clustering and interacting.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TIMoyaNetworking/TIMoyaNetworking.podspec b/TIMoyaNetworking/TIMoyaNetworking.podspec index a25d2abc..c456ab6b 100644 --- a/TIMoyaNetworking/TIMoyaNetworking.podspec +++ b/TIMoyaNetworking/TIMoyaNetworking.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIMoyaNetworking' - s.version = '1.16.0' + s.version = '1.16.1' 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' } diff --git a/TINetworking/TINetworking.podspec b/TINetworking/TINetworking.podspec index 198294bc..fc2cbd93 100644 --- a/TINetworking/TINetworking.podspec +++ b/TINetworking/TINetworking.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TINetworking' - s.version = '1.16.0' + s.version = '1.16.1' 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' } diff --git a/TINetworkingCache/TINetworkingCache.podspec b/TINetworkingCache/TINetworkingCache.podspec index 6ec81bc0..37942f00 100644 --- a/TINetworkingCache/TINetworkingCache.podspec +++ b/TINetworkingCache/TINetworkingCache.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TINetworkingCache' - s.version = '1.16.0' + s.version = '1.16.1' 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' } diff --git a/TIPagination/TIPagination.podspec b/TIPagination/TIPagination.podspec index 93ad71e9..024625cc 100644 --- a/TIPagination/TIPagination.podspec +++ b/TIPagination/TIPagination.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIPagination' - s.version = '1.16.0' + s.version = '1.16.1' s.summary = 'Generic pagination component.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/TISwiftUtils/TISwiftUtils.podspec b/TISwiftUtils/TISwiftUtils.podspec index d9f3eb30..00514304 100644 --- a/TISwiftUtils/TISwiftUtils.podspec +++ b/TISwiftUtils/TISwiftUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TISwiftUtils' - s.version = '1.16.0' + s.version = '1.16.1' 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' } diff --git a/TITableKitUtils/TITableKitUtils.podspec b/TITableKitUtils/TITableKitUtils.podspec index 85973248..06336b61 100644 --- a/TITableKitUtils/TITableKitUtils.podspec +++ b/TITableKitUtils/TITableKitUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TITableKitUtils' - s.version = '1.16.0' + s.version = '1.16.1' 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' } diff --git a/TITransitions/TITransitions.podspec b/TITransitions/TITransitions.podspec index 3211d723..d40584ca 100644 --- a/TITransitions/TITransitions.podspec +++ b/TITransitions/TITransitions.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TITransitions' - s.version = '1.16.0' + s.version = '1.16.1' 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' } diff --git a/TIUIElements/TIUIElements.podspec b/TIUIElements/TIUIElements.podspec index 03d63acc..1c3036f7 100644 --- a/TIUIElements/TIUIElements.podspec +++ b/TIUIElements/TIUIElements.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIUIElements' - s.version = '1.16.0' + s.version = '1.16.1' 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' } diff --git a/TIUIKitCore/TIUIKitCore.podspec b/TIUIKitCore/TIUIKitCore.podspec index cd4dc918..aae3be22 100644 --- a/TIUIKitCore/TIUIKitCore.podspec +++ b/TIUIKitCore/TIUIKitCore.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIUIKitCore' - s.version = '1.16.0' + s.version = '1.16.1' 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' } diff --git a/TIYandexMapUtils/TIYandexMapUtils.podspec b/TIYandexMapUtils/TIYandexMapUtils.podspec index e1b64a7b..aa00a07d 100644 --- a/TIYandexMapUtils/TIYandexMapUtils.podspec +++ b/TIYandexMapUtils/TIYandexMapUtils.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'TIYandexMapUtils' - s.version = '1.16.0' + s.version = '1.16.1' s.summary = 'Set of helpers for map objects clustering and interacting using Yandex Maps SDK.' s.homepage = 'https://github.com/TouchInstinct/LeadKit/tree/' + s.version.to_s + '/' + s.name s.license = { :type => 'MIT', :file => 'LICENSE' }