Merge pull request #270 from TouchInstinct/feature/TIKeychainUtils

feat: Add TIKeychainUtils
This commit is contained in:
Mihail 2021-04-30 19:17:08 +03:00 committed by GitHub
commit 954080891d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 150 additions and 10 deletions

View File

@ -1,5 +1,8 @@
# Changelog
### 1.2.0
- **Add**: `TIKeychainUtils` - Set of helpers for Keychain classes.
### 1.1.1
- **Fix**: `StatefullButton` propagation

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "LeadKit"
s.version = "1.1.2"
s.version = "1.2.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"

View File

@ -1,6 +1,15 @@
{
"object": {
"pins": [
{
"package": "KeychainAccess",
"repositoryURL": "https://github.com/kishikawakatsumi/KeychainAccess.git",
"state": {
"branch": null,
"revision": "84e546727d66f1adc5439debad16270d0fdd04e7",
"version": "4.2.2"
}
},
{
"package": "TableKit",
"repositoryURL": "https://github.com/maxsokolov/TableKit.git",

View File

@ -11,18 +11,21 @@ let package = Package(
.library(name: "TIUIKitCore", targets: ["TIUIKitCore"]),
.library(name: "TISwiftUtils", targets: ["TISwiftUtils"]),
.library(name: "TIFoundationUtils", targets: ["TIFoundationUtils"]),
.library(name: "TIKeychainUtils", targets: ["TIKeychainUtils"]),
.library(name: "TIUIElements", targets: ["TIUIElements"]),
.library(name: "TITableKitUtils", targets: ["TITableKitUtils"]),
.library(name: "OTPSwiftView", targets: ["OTPSwiftView"])
],
dependencies: [
.package(url: "https://github.com/maxsokolov/TableKit.git", from: "2.11.0")
.package(url: "https://github.com/maxsokolov/TableKit.git", from: "2.11.0"),
.package(url: "https://github.com/kishikawakatsumi/KeychainAccess.git", from: "4.2.2")
],
targets: [
.target(name: "TITransitions", path: "TITransitions/Sources"),
.target(name: "TIUIKitCore", path: "TIUIKitCore/Sources"),
.target(name: "TISwiftUtils", path: "TISwiftUtils/Sources"),
.target(name: "TIFoundationUtils", dependencies: ["TISwiftUtils"], path: "TIFoundationUtils/Sources"),
.target(name: "TIKeychainUtils", dependencies: ["TIFoundationUtils", "KeychainAccess"], path: "TIKeychainUtils/Sources"),
.target(name: "TIUIElements", dependencies: ["TIUIKitCore", "TISwiftUtils"], path: "TIUIElements/Sources"),
.target(name: "TITableKitUtils", dependencies: ["TIUIElements", "TableKit"], path: "TITableKitUtils/Sources"),
.target(name: "OTPSwiftView", dependencies: ["TIUIElements"], path: "OTPSwiftView/Sources")

View File

@ -10,6 +10,8 @@ This repository contains the following additional frameworks:
- [OTPSwiftView](OTPSwiftView) - a fully customizable OTP view.
- [TISwiftUtils](TISwiftUtils) - a bunch of useful helpers for development.
- [TITableKitUtils](TITableKitUtils) - Set of helpers for TableKit classes.
- [TIFoundationUtils](TIFoundationUtils) - Set of helpers for Foundation framework classes.
- [TIKeychainUtils](TIKeychainUtils) - Set of helpers for Keychain classes.
Useful docs:
- [Semantic Commit Messages](docs/semantic-commit-messages.md) - commit message codestyle.
@ -42,4 +44,4 @@ source 'https://github.com/TouchInstinct/Podspecs.git'
pod 'TISwiftUtils', 'x.y.z'
pod 'TIFoundationUtils', 'x.y.z'
# ...
```
```

View File

@ -20,7 +20,7 @@
// THE SOFTWARE.
//
enum StorageError: Error {
public enum StorageError: Error {
case valueNotFound
case unableToExtractData(underlyingError: Error)
case unableToDecode(underlyingError: Error)

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TIFoundationUtils'
s.version = '1.1.2'
s.version = '1.2.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' }

38
TIKeychainUtils/README.md Normal file
View File

@ -0,0 +1,38 @@
# TIKeychainUtils
Set of helpers for Keychain classes.
Bunch of CodableBackingStore from TIFoundationUtils and KeychainAccess.
Implement
#### @propertyWrapper example
```swift
extension StorageKey {
static var userProfileKey: StorageKey<UserProfile> {
.init(rawValue: "userProfileKey")
}
}
extension Bundle {
var bundleId: String {
Bundle.main.bundleIdentifier ?? .empty
}
}
extension Keychain {
static var defaultKeychain: Keychain {
.init(service: Bundle.main.bundleId)
}
}
final class ViewModel {
@KeychainCodableBackingStore(key: .userProfileKey, codableKeyValueStorage: .defaultKeychain)
private(set) var profile: UserProfile?
func updateProfile(newProfile: UserProfile?) {
profile = newProfile
}
}
```

View File

@ -0,0 +1,68 @@
//
// Copyright (c) 2020 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 Foundation
import KeychainAccess
import TIFoundationUtils
public typealias KeychainCodableBackingStore<T: Codable> = CodableKeyValueBackingStore<Keychain, T>
extension Keychain: CodableKeyValueStorage {
public func codableObject<Value: Decodable>(forKey key: StorageKey<Value>,
decoder: CodableKeyValueDecoder) throws -> Value {
let unwrappedStoredData: Data?
do {
unwrappedStoredData = try getData(key.rawValue)
} catch {
throw StorageError.unableToExtractData(underlyingError: error)
}
guard let storedData = unwrappedStoredData else {
throw StorageError.valueNotFound
}
return try decoder.decodeDecodable(from: storedData, for: key)
}
public func set<Value: Encodable>(encodableObject: Value,
forKey key: StorageKey<Value>,
encoder: CodableKeyValueEncoder) throws {
let objectData = try encoder.encodeEncodable(value: encodableObject, for: key)
do {
try set(objectData, key: key.rawValue)
} catch {
throw StorageError.unableToWriteData(underlyingError: error)
}
}
public func removeCodableValue<Value: Codable>(forKey key: StorageKey<Value>) throws {
do {
try remove(key.rawValue)
} catch {
throw StorageError.unableToWriteData(underlyingError: error)
}
}
}

View File

@ -0,0 +1,17 @@
Pod::Spec.new do |s|
s.name = 'TIKeychainUtils'
s.version = '1.2.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' }
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 'KeychainAccess'
end

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TISwiftUtils'
s.version = '1.1.2'
s.version = '1.2.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' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TITableKitUtils'
s.version = '1.1.2'
s.version = '1.2.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' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TITransitions'
s.version = '1.1.2'
s.version = '1.2.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' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TIUIElements'
s.version = '1.1.2'
s.version = '1.2.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' }

View File

@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'TIUIKitCore'
s.version = '1.1.2'
s.version = '1.2.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' }