Merge pull request #254 from TouchInstinct/feature/separators
Feature/separators
This commit is contained in:
commit
6b3bf25f0a
|
|
@ -1,16 +1,18 @@
|
|||
# ================
|
||||
# Swift.gitignore
|
||||
# ================
|
||||
|
||||
# Xcode
|
||||
#
|
||||
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
|
||||
|
||||
## Build generated
|
||||
build/
|
||||
DerivedData
|
||||
## User settings
|
||||
xcuserdata/
|
||||
|
||||
## Various settings
|
||||
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
|
||||
*.xcscmblueprint
|
||||
*.xccheckout
|
||||
|
||||
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
|
||||
build/
|
||||
DerivedData/
|
||||
*.moved-aside
|
||||
*.pbxuser
|
||||
!default.pbxuser
|
||||
*.mode1v3
|
||||
|
|
@ -19,17 +21,14 @@ DerivedData
|
|||
!default.mode2v3
|
||||
*.perspectivev3
|
||||
!default.perspectivev3
|
||||
xcuserdata
|
||||
|
||||
## Other
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
*.xcscmblueprint
|
||||
|
||||
## Obj-C/Swift specific
|
||||
*.hmap
|
||||
|
||||
## App packaging
|
||||
*.ipa
|
||||
*.dSYM.zip
|
||||
*.dSYM
|
||||
|
||||
## Playgrounds
|
||||
timeline.xctimeline
|
||||
|
|
@ -39,6 +38,14 @@ playground.xcworkspace
|
|||
#
|
||||
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
|
||||
# Packages/
|
||||
# Package.pins
|
||||
# Package.resolved
|
||||
# *.xcodeproj
|
||||
#
|
||||
# Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
|
||||
# hence it is not needed unless you have added a package configuration file to your project
|
||||
.swiftpm
|
||||
|
||||
.build/
|
||||
|
||||
# CocoaPods
|
||||
|
|
@ -48,33 +55,51 @@ playground.xcworkspace
|
|||
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
||||
#
|
||||
Pods/
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from the Xcode workspace
|
||||
# *.xcworkspace
|
||||
|
||||
# Carthage
|
||||
#
|
||||
# Add this line if you want to avoid checking in source code from Carthage dependencies.
|
||||
Carthage/Checkouts
|
||||
|
||||
Carthage/Build
|
||||
Carthage/Build/
|
||||
|
||||
# Accio dependency management
|
||||
Dependencies/
|
||||
.accio/
|
||||
|
||||
# fastlane
|
||||
#
|
||||
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
|
||||
# screenshots whenever they are needed.
|
||||
# It is recommended to not store the screenshots in the git repo.
|
||||
# Instead, use fastlane to re-generate the screenshots whenever they are needed.
|
||||
# For more information about the recommended setup visit:
|
||||
# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md
|
||||
# https://docs.fastlane.tools/best-practices/source-control/#source-control
|
||||
|
||||
fastlane/report.xml
|
||||
fastlane/screenshots
|
||||
fastlane/Preview.html
|
||||
fastlane/screenshots/**/*.png
|
||||
fastlane/test_output
|
||||
|
||||
# Code Injection
|
||||
#
|
||||
# After new code Injection tools there's a generated folder /iOSInjectionProject
|
||||
# https://github.com/johnno1962/injectionforxcode
|
||||
|
||||
# AppCode
|
||||
# https://intellij-support.jetbrains.com/hc/en-us/articles/206544839-How-to-manage-projects-under-Version-Control-Systems
|
||||
iOSInjectionProject/
|
||||
|
||||
.idea/workspace.xml
|
||||
.idea/tasks.xml
|
||||
# homebrew-bundle
|
||||
Brewfile.lock.json
|
||||
|
||||
cpd-output.xml
|
||||
# Node.js
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
|
||||
# Touch Instinct custom
|
||||
Downloads/
|
||||
|
||||
fastlane/README.md
|
||||
Templates/
|
||||
cpd-output.xml
|
||||
*.swp
|
||||
*IDEWorkspaceChecks.plist
|
||||
|
|
|
|||
|
|
@ -1,5 +1,13 @@
|
|||
# Changelog
|
||||
|
||||
### 0.11.0
|
||||
- **Add**: Cocoapods support for TI-family libraries.
|
||||
- **Add**: `SeparatorConfigurable` and all helper types for separator configuration.
|
||||
- **Add**: `BaseSeparatorCell` - `BaseInitializeableCell` subclass with separators support.
|
||||
- **Add**: `TITableKitUtils` - set of helpers for TableKit classes.
|
||||
- **Add**: `BaseTextAttributes` and `ViewText` implementation form LeadKit.
|
||||
- **Update**: `BaseInitializableView` and `BaseInitializableControl` are moved to `TIUIElements` from `TIUIKitCore`.
|
||||
|
||||
### 0.10.9
|
||||
- **Fix**: `change presentedOrTopViewController to open`.
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"object": {
|
||||
"pins": [
|
||||
{
|
||||
"package": "TableKit",
|
||||
"repositoryURL": "https://github.com/maxsokolov/TableKit.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "8bf4840d9d0475a92352f02f368f88b74eced447",
|
||||
"version": "2.11.0"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
|
|
@ -12,14 +12,19 @@ let package = Package(
|
|||
.library(name: "TISwiftUtils", targets: ["TISwiftUtils"]),
|
||||
.library(name: "TIFoundationUtils", targets: ["TIFoundationUtils"]),
|
||||
.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")
|
||||
],
|
||||
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: "TIUIElements", dependencies: ["TIUIKitCore"], path: "TIUIElements/Sources"),
|
||||
.target(name: "TITableKitUtils", dependencies: ["TIUIElements", "TableKit"], path: "TITableKitUtils/Sources"),
|
||||
.target(name: "OTPSwiftView", dependencies: ["TIUIKitCore", "TISwiftUtils"], path: "OTPSwiftView/Sources")
|
||||
]
|
||||
)
|
||||
|
|
|
|||
21
README.md
21
README.md
|
|
@ -8,4 +8,25 @@ This repository contains the following additional frameworks:
|
|||
- [TIUIElements](TIUIElements) - bunch of of useful protocols and views.
|
||||
- [OTPSwiftView](OTPSwiftView) - a fully customizable OTP view.
|
||||
- [TISwiftUtils](TISwiftUtils) - a bunch of useful helpers for development.
|
||||
- [TITableKitUtils](TITableKitUtils) - Set of helpers for TableKit classes.
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
### SPM
|
||||
|
||||
```swift
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/TouchInstinct/LeadKit.git", from: "x.y.z"),
|
||||
],
|
||||
```
|
||||
|
||||
### Cocoapods
|
||||
|
||||
```ruby
|
||||
source 'https://github.com/TouchInstinct/Podspecs.git'
|
||||
|
||||
pod 'TISwiftUtils', 'x.y.z'
|
||||
pod 'TIFoundationUtils', 'x.y.z'
|
||||
# ...
|
||||
```
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TIFoundationUtils'
|
||||
s.version = '0.11.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' }
|
||||
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 'TISwiftUtils', s.version.to_s
|
||||
s.framework = 'Foundation'
|
||||
end
|
||||
|
|
@ -18,7 +18,3 @@ final class ViewModel {
|
|||
var hasFinishedOnboarding: Bool
|
||||
}
|
||||
```
|
||||
|
||||
# Installation via SPM
|
||||
|
||||
You can install this framework as a target of LeadKit.
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
public extension Optional where Wrapped == String {
|
||||
var orEmpty: String {
|
||||
self ?? ""
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Substring {
|
||||
var string: String {
|
||||
String(self)
|
||||
|
|
|
|||
|
|
@ -20,8 +20,6 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/// Closure with custom arguments and return value.
|
||||
public typealias Closure<Input, Output> = (Input) -> Output
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TISwiftUtils'
|
||||
s.version = '0.11.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' }
|
||||
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 = '9.0'
|
||||
s.swift_versions = ['5.3']
|
||||
|
||||
s.source_files = s.name + '/Sources/**/*'
|
||||
end
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
# TITableKitUtils
|
||||
|
||||
Set of helpers for TableKit classes.
|
||||
|
||||
|
|
@ -0,0 +1,243 @@
|
|||
//
|
||||
// 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 TableKit
|
||||
import UIKit.UITableView
|
||||
|
||||
public extension TableDirector {
|
||||
|
||||
/**
|
||||
method replaces current table director's section at index and reloads it
|
||||
|
||||
- parameter section: new section
|
||||
- parameter index: current replaced section index
|
||||
- parameter reload: is reloaded after replace
|
||||
|
||||
- returns: self
|
||||
*/
|
||||
@discardableResult
|
||||
func replace(section: TableSection, atIndex index: Int, reload: Bool = true) -> Self {
|
||||
if index < sections.count {
|
||||
remove(sectionAt: index)
|
||||
}
|
||||
insert(section: section, atIndex: index)
|
||||
if reload {
|
||||
self.reload(sectionAtIndex: index)
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
/**
|
||||
method reloads section at index with animation
|
||||
|
||||
- parameter index: current reloaded section index
|
||||
- parameter animation: reloading animation. Default .none
|
||||
|
||||
- returns: self
|
||||
*/
|
||||
@discardableResult
|
||||
func reload(sectionAtIndex index: Int, with animation: UITableView.RowAnimation = .none) -> Self {
|
||||
let action = { [tableView] in
|
||||
guard let tableView = tableView else {
|
||||
return
|
||||
}
|
||||
|
||||
if index < tableView.numberOfSections {
|
||||
tableView.reloadSections([index], with: animation)
|
||||
} else {
|
||||
tableView.reloadData()
|
||||
}
|
||||
}
|
||||
if animation == .none {
|
||||
UIView.performWithoutAnimation(action)
|
||||
} else {
|
||||
action()
|
||||
}
|
||||
return self
|
||||
}
|
||||
|
||||
/**
|
||||
method replaces current table director's state with sections
|
||||
|
||||
- parameter sections: new sections
|
||||
|
||||
- returns: self
|
||||
*/
|
||||
@discardableResult
|
||||
func replace(withSections sections: [TableSection]) -> Self {
|
||||
clear().append(sections: sections).reload()
|
||||
return self
|
||||
}
|
||||
|
||||
/**
|
||||
method replaces current table director's state with section
|
||||
|
||||
- parameter section: new section
|
||||
|
||||
- returns: self
|
||||
*/
|
||||
@discardableResult
|
||||
func replace(withSection section: TableSection) -> Self {
|
||||
return replace(withSections: [section])
|
||||
}
|
||||
|
||||
/**
|
||||
method replaces current table director's state with rows
|
||||
|
||||
- parameter rows: new rows
|
||||
|
||||
- returns: self
|
||||
*/
|
||||
@discardableResult
|
||||
func replace(withRows rows: [Row]) -> Self {
|
||||
return replace(withSection: TableSection(rows: rows))
|
||||
}
|
||||
|
||||
/// Clear table view and reload it within empty section
|
||||
func safeClear() {
|
||||
clear().append(section: TableSection(onlyRows: [])).reload()
|
||||
}
|
||||
|
||||
/// Inserts rows into table without complete reload.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - rows: Rows to insert.
|
||||
/// - indexPath: Position of first row.
|
||||
/// - animation: The type of animation when rows are inserted
|
||||
/// - manualBeginEndUpdates: Don't call beginUpdates() & endUpdates() inside.
|
||||
func insert(rows: [Row],
|
||||
at indexPath: IndexPath,
|
||||
with animation: UITableView.RowAnimation,
|
||||
manualBeginEndUpdates: Bool = false) {
|
||||
|
||||
sections[indexPath.section].insert(rows: rows, at: indexPath.row)
|
||||
let indexPaths: [IndexPath] = rows.indices.map {
|
||||
IndexPath(row: indexPath.row + $0, section: indexPath.section)
|
||||
}
|
||||
|
||||
if manualBeginEndUpdates {
|
||||
tableView?.insertRows(at: indexPaths, with: animation)
|
||||
} else {
|
||||
tableView?.beginUpdates()
|
||||
tableView?.insertRows(at: indexPaths, with: animation)
|
||||
tableView?.endUpdates()
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes rows from table without complete reload.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - rowsCount: Number of rows to remove.
|
||||
/// - indexPath: Position of first row to remove.
|
||||
/// - animation: The type of animation when rows are deleted
|
||||
/// - manualBeginEndUpdates: Don't call beginUpdates() & endUpdates() inside.
|
||||
func remove(rowsCount: Int,
|
||||
startingAt indexPath: IndexPath,
|
||||
with animation: UITableView.RowAnimation,
|
||||
manualBeginEndUpdates: Bool = false) {
|
||||
|
||||
var indexPaths = [IndexPath]()
|
||||
for index in indexPath.row ..< indexPath.row + rowsCount {
|
||||
indexPaths.append(IndexPath(row: index, section: indexPath.section))
|
||||
}
|
||||
|
||||
indexPaths.reversed().forEach {
|
||||
sections[$0.section].remove(rowAt: $0.row)
|
||||
}
|
||||
|
||||
if manualBeginEndUpdates {
|
||||
tableView?.deleteRows(at: indexPaths, with: animation)
|
||||
} else {
|
||||
tableView?.beginUpdates()
|
||||
tableView?.deleteRows(at: indexPaths, with: animation)
|
||||
tableView?.endUpdates()
|
||||
}
|
||||
}
|
||||
|
||||
/// Method inserts section with animation.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - section: Section to insert
|
||||
/// - index: Position to insert
|
||||
/// - animation: The type of insert animation
|
||||
/// - manualBeginEndUpdates: Don't call beginUpdates() & endUpdates() inside.
|
||||
/// - Returns: self
|
||||
@discardableResult
|
||||
func insert(section: TableSection,
|
||||
at index: Int,
|
||||
with animation: UITableView.RowAnimation,
|
||||
manualBeginEndUpdates: Bool = false) -> Self {
|
||||
|
||||
insert(section: section, atIndex: index)
|
||||
if manualBeginEndUpdates {
|
||||
tableView?.insertSections([index], with: animation)
|
||||
} else {
|
||||
tableView?.beginUpdates()
|
||||
tableView?.insertSections([index], with: animation)
|
||||
tableView?.endUpdates()
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
/// Method removes section with animation.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - index: Position to remove
|
||||
/// - animation: The type of remove animation
|
||||
/// - manualBeginEndUpdates: Don't call beginUpdates() & endUpdates() inside.
|
||||
/// - Returns: self
|
||||
@discardableResult
|
||||
func remove(at index: Int,
|
||||
with animation: UITableView.RowAnimation,
|
||||
manualBeginEndUpdates: Bool = false) -> Self {
|
||||
|
||||
delete(sectionAt: index)
|
||||
if manualBeginEndUpdates {
|
||||
tableView?.deleteSections([index], with: animation)
|
||||
} else {
|
||||
tableView?.beginUpdates()
|
||||
tableView?.deleteSections([index], with: animation)
|
||||
tableView?.endUpdates()
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
/// Method replace section with animation.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - section: Section to replace
|
||||
/// - index: Position to replace
|
||||
/// - animation: The type of replace animation
|
||||
/// - manualBeginEndUpdates: Don't call beginUpdates() & endUpdates() inside.
|
||||
/// - Returns: self
|
||||
@discardableResult
|
||||
func replace(with section: TableSection,
|
||||
at index: Int,
|
||||
with animation: UITableView.RowAnimation,
|
||||
manualBeginEndUpdates: Bool = false) -> Self {
|
||||
|
||||
remove(at: index, with: animation, manualBeginEndUpdates: manualBeginEndUpdates)
|
||||
return insert(section: section, at: index, with: animation, manualBeginEndUpdates: manualBeginEndUpdates)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// 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 TableKit
|
||||
|
||||
public extension TableSection {
|
||||
|
||||
/// Initializes section with rows and zero height footer and header.
|
||||
///
|
||||
/// - Parameter rows: Rows to insert into section.
|
||||
convenience init(onlyRows rows: [Row]) {
|
||||
self.init(rows: rows)
|
||||
|
||||
self.headerView = nil
|
||||
self.footerView = nil
|
||||
|
||||
self.headerHeight = .leastNonzeroMagnitude
|
||||
self.footerHeight = .leastNonzeroMagnitude
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// 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 TableKit
|
||||
import TIUIElements
|
||||
|
||||
public extension Array where Element == SeparatorRowBox {
|
||||
|
||||
/// Create rows from SeparatorRowBox array
|
||||
var rows: [Row] {
|
||||
return map { $0.row }
|
||||
}
|
||||
|
||||
/// Configure separators from SeparatorRowBox array
|
||||
/// - parameter extreme: Configuration that will be used for extreme values, for first or last row
|
||||
/// - parameter middle: Configuration for intermediate rows
|
||||
func configureSeparators(extreme extremeSeparatorConfiguration: SeparatorConfiguration,
|
||||
middle middleSeparatorConfiguration: SeparatorConfiguration) {
|
||||
|
||||
configureSeparators(first: extremeSeparatorConfiguration,
|
||||
middle: middleSeparatorConfiguration,
|
||||
last: extremeSeparatorConfiguration)
|
||||
}
|
||||
|
||||
/// Configure separators from SeparatorRowBox array
|
||||
/// - parameter first: Configuration of the top separator of the first row
|
||||
/// - parameter middle: Configuration of the separators between the rows
|
||||
/// - parameter last: Configuration of the bottom separator of the last row
|
||||
func configureSeparators(first firstSeparatorConfiguration: SeparatorConfiguration,
|
||||
middle middleSeparatorConfiguration: SeparatorConfiguration,
|
||||
last lastSeparatorConfiguration: SeparatorConfiguration) {
|
||||
|
||||
if isEmpty {
|
||||
return
|
||||
}
|
||||
|
||||
switch count {
|
||||
case 1:
|
||||
first?.set(separatorType: .full(firstSeparatorConfiguration, lastSeparatorConfiguration))
|
||||
|
||||
default:
|
||||
dropFirst().dropLast().forEach { $0.set(separatorType: .bottom(middleSeparatorConfiguration)) }
|
||||
first?.set(separatorType: .full(firstSeparatorConfiguration, middleSeparatorConfiguration))
|
||||
last?.set(separatorType: .bottom(lastSeparatorConfiguration))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// 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 TableKit
|
||||
import TIUIElements
|
||||
|
||||
private let configureSeparatorActionId = "TableRowConfigureSeparatorActionId"
|
||||
|
||||
public extension TableRow where CellType: SeparatorConfigurable {
|
||||
|
||||
func with(separatorType: ViewSeparatorType) -> Self {
|
||||
set(separatorType: separatorType)
|
||||
return self
|
||||
}
|
||||
|
||||
func set(separatorType: ViewSeparatorType) {
|
||||
removeAction(forActionId: configureSeparatorActionId)
|
||||
|
||||
let action = TableRowAction<CellType>(.configure) {
|
||||
$0.cell?.configureSeparators(with: separatorType)
|
||||
}
|
||||
|
||||
action.id = configureSeparatorActionId
|
||||
on(action)
|
||||
}
|
||||
}
|
||||
|
||||
public extension TableRow where CellType: SeparatorConfigurable {
|
||||
|
||||
/// TableRow typed as SeparatorRowBox
|
||||
var separatorRowBox: SeparatorRowBox {
|
||||
return SeparatorRowBox(row: self)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
//
|
||||
// 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 TableKit
|
||||
import TIUIElements
|
||||
import TISwiftUtils
|
||||
|
||||
/// Class that used to configure separators when multiply cells presented in one section
|
||||
public final class SeparatorRowBox {
|
||||
private let setSeparatorHandler: ParameterClosure<ViewSeparatorType>
|
||||
|
||||
public func set(separatorType: ViewSeparatorType) {
|
||||
setSeparatorHandler(separatorType)
|
||||
}
|
||||
|
||||
public let row: Row
|
||||
|
||||
public init<T>(row: TableRow<T>) where T: SeparatorConfigurable {
|
||||
self.row = row
|
||||
setSeparatorHandler = row.set
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TITableKitUtils'
|
||||
s.version = '0.11.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' }
|
||||
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 'TIUIElements', s.version.to_s
|
||||
s.dependency 'TISwiftUtils', s.version.to_s
|
||||
s.dependency 'TableKit', '2.11.0'
|
||||
end
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
//
|
||||
// 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 UIKit
|
||||
|
||||
open class BaseSeparatorCell: BaseInitializableCell, SeparatorConfigurable {
|
||||
private lazy var topSeparatorView = createTopSeparator()
|
||||
private lazy var bottomSeparatorView = UIView()
|
||||
|
||||
private var topViewLeftConstraint: NSLayoutConstraint?
|
||||
private var topViewRightConstraint: NSLayoutConstraint?
|
||||
private var topViewTopConstraint: NSLayoutConstraint?
|
||||
private var topViewHeightConstraint: NSLayoutConstraint?
|
||||
|
||||
private var bottomViewLeftConstraint: NSLayoutConstraint?
|
||||
private var bottomViewRightConstraint: NSLayoutConstraint?
|
||||
private var bottomViewBottomConstraint: NSLayoutConstraint?
|
||||
private var bottomViewHeightConstraint: NSLayoutConstraint?
|
||||
|
||||
open func createTopSeparator() -> UIView {
|
||||
.init()
|
||||
}
|
||||
|
||||
open func createBottomSeparator() -> UIView {
|
||||
.init()
|
||||
}
|
||||
|
||||
open func add(topSeparatorView: UIView) {
|
||||
contentView.addSubview(topSeparatorView)
|
||||
}
|
||||
|
||||
open func add(bottomSeparatorView: UIView) {
|
||||
contentView.addSubview(bottomSeparatorView)
|
||||
}
|
||||
|
||||
public func configureSeparators(with separatorType: ViewSeparatorType) {
|
||||
topSeparatorView.isHidden = separatorType.topIsHidden
|
||||
bottomSeparatorView.isHidden = separatorType.bottomIsHidden
|
||||
|
||||
switch separatorType {
|
||||
case .none:
|
||||
break
|
||||
|
||||
case let .bottom(configuration):
|
||||
updateBottomSeparator(with: configuration)
|
||||
|
||||
case let .top(configuration):
|
||||
updateTopSeparator(with: configuration)
|
||||
|
||||
case let .full(topConfiguration, bottomConfiguration):
|
||||
updateTopSeparator(with: topConfiguration)
|
||||
updateBottomSeparator(with: bottomConfiguration)
|
||||
}
|
||||
}
|
||||
|
||||
open override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
configureSeparators(with: .none)
|
||||
}
|
||||
|
||||
// MARK: - InitializableView
|
||||
|
||||
open override func addViews() {
|
||||
super.addViews()
|
||||
|
||||
add(topSeparatorView: topSeparatorView)
|
||||
add(bottomSeparatorView: bottomSeparatorView)
|
||||
}
|
||||
|
||||
open override func configureLayout() {
|
||||
super.configureLayout()
|
||||
|
||||
if let separatorSuperview = topSeparatorView.superview {
|
||||
topViewTopConstraint = topSeparatorView.topAnchor.constraint(equalTo: separatorSuperview.topAnchor)
|
||||
topViewRightConstraint = separatorSuperview.rightAnchor.constraint(equalTo: topSeparatorView.rightAnchor)
|
||||
topViewLeftConstraint = topSeparatorView.leftAnchor.constraint(equalTo: separatorSuperview.leftAnchor)
|
||||
}
|
||||
|
||||
topViewHeightConstraint = topSeparatorView.heightAnchor.constraint(equalToConstant: 1)
|
||||
|
||||
if let separatorSuperview = topSeparatorView.superview {
|
||||
bottomViewRightConstraint = separatorSuperview.rightAnchor.constraint(equalTo: bottomSeparatorView.rightAnchor)
|
||||
bottomViewLeftConstraint = bottomSeparatorView.leftAnchor.constraint(equalTo: separatorSuperview.leftAnchor)
|
||||
bottomViewBottomConstraint = bottomSeparatorView.bottomAnchor.constraint(equalTo: separatorSuperview.bottomAnchor)
|
||||
}
|
||||
|
||||
bottomViewHeightConstraint = bottomSeparatorView.heightAnchor.constraint(equalToConstant: 1)
|
||||
|
||||
NSLayoutConstraint.activate([
|
||||
topViewTopConstraint,
|
||||
topViewRightConstraint,
|
||||
topViewLeftConstraint,
|
||||
topViewHeightConstraint,
|
||||
bottomViewRightConstraint,
|
||||
bottomViewLeftConstraint,
|
||||
bottomViewBottomConstraint,
|
||||
bottomViewHeightConstraint
|
||||
].compactMap { $0 })
|
||||
}
|
||||
|
||||
open override func configureAppearance() {
|
||||
super.configureAppearance()
|
||||
|
||||
[topSeparatorView, bottomSeparatorView].forEach {
|
||||
$0.isHidden = true
|
||||
$0.backgroundColor = .black
|
||||
$0.translatesAutoresizingMaskIntoConstraints = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension BaseSeparatorCell {
|
||||
func updateTopSeparator(with configuration: SeparatorConfiguration) {
|
||||
topSeparatorView.backgroundColor = configuration.color
|
||||
topViewHeightConstraint?.constant = configuration.height
|
||||
topViewTopConstraint?.constant = configuration.insets.top
|
||||
topViewLeftConstraint?.constant = configuration.insets.left
|
||||
topViewRightConstraint?.constant = -configuration.insets.right
|
||||
}
|
||||
|
||||
func updateBottomSeparator(with configuration: SeparatorConfiguration) {
|
||||
bottomSeparatorView.backgroundColor = configuration.color
|
||||
bottomViewHeightConstraint?.constant = configuration.height
|
||||
bottomViewBottomConstraint?.constant = -configuration.insets.bottom
|
||||
bottomViewLeftConstraint?.constant = configuration.insets.left
|
||||
bottomViewRightConstraint?.constant = -configuration.insets.right
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
public protocol SeparatorConfigurable {
|
||||
func configureSeparators(with separatorType: ViewSeparatorType)
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// 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 UIKit
|
||||
|
||||
public struct SeparatorConfiguration {
|
||||
|
||||
public let color: UIColor
|
||||
public let insets: UIEdgeInsets
|
||||
public let height: CGFloat
|
||||
|
||||
public init(color: UIColor, insets: UIEdgeInsets = .zero, height: CGFloat = 1) {
|
||||
self.color = color
|
||||
self.insets = insets
|
||||
self.height = height
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
public enum ViewSeparatorType {
|
||||
|
||||
/// All separators for view is hidden
|
||||
case none
|
||||
|
||||
/// Show only top separator
|
||||
case top(SeparatorConfiguration)
|
||||
|
||||
/// Show only bottom separator
|
||||
case bottom(SeparatorConfiguration)
|
||||
|
||||
/// First configuration for top, second for bottom
|
||||
case full(SeparatorConfiguration, SeparatorConfiguration)
|
||||
}
|
||||
|
||||
public extension ViewSeparatorType {
|
||||
|
||||
/// Determine if bottom separator is hidden.
|
||||
var bottomIsHidden: Bool {
|
||||
return bottomConfiguration == nil
|
||||
}
|
||||
|
||||
/// Determine if top separator is hidden.
|
||||
var topIsHidden: Bool {
|
||||
return topConfiguration == nil
|
||||
}
|
||||
|
||||
/// Returns top configuration if type is top or full.
|
||||
var topConfiguration: SeparatorConfiguration? {
|
||||
switch self {
|
||||
case let .top(configuration), let .full(configuration, _):
|
||||
return configuration
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns bottom configuration if type is bottom or full.
|
||||
var bottomConfiguration: SeparatorConfiguration? {
|
||||
switch self {
|
||||
case let .bottom(configuration), let .full(_, configuration):
|
||||
return configuration
|
||||
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import UIKit
|
||||
import TIUIKitCore
|
||||
|
||||
open class BaseInitializableControl: UIControl, InitializableView {
|
||||
open class BaseInitializableControl: UIControl, InitializableViewProtocol {
|
||||
override public init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
|
|
@ -21,8 +21,9 @@
|
|||
//
|
||||
|
||||
import UIKit
|
||||
import TIUIKitCore
|
||||
|
||||
open class BaseInitializableView: UIView, InitializableView {
|
||||
open class BaseInitializableView: UIView, InitializableViewProtocol {
|
||||
override public init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
//
|
||||
// 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 TIUIKitCore
|
||||
import UIKit
|
||||
|
||||
open class BaseInitializableCell: UITableViewCell, InitializableViewProtocol {
|
||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||
super.init(style: .default, reuseIdentifier: reuseIdentifier)
|
||||
|
||||
initializeView()
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required public init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
}
|
||||
|
||||
// MARK: - InitializableView
|
||||
|
||||
open func addViews() {
|
||||
// empty for subclasses overriding
|
||||
}
|
||||
|
||||
open func bindViews() {
|
||||
// empty for subclasses overriding
|
||||
}
|
||||
|
||||
open func configureLayout() {
|
||||
// empty for subclasses overriding
|
||||
}
|
||||
|
||||
open func configureAppearance() {
|
||||
selectionStyle = .none
|
||||
backgroundColor = .clear
|
||||
}
|
||||
|
||||
open func localize() {
|
||||
// empty for subclasses overriding
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TIUIElements'
|
||||
s.version = '0.11.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' }
|
||||
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 'TIUIKitCore', s.version.to_s
|
||||
end
|
||||
|
|
@ -12,7 +12,3 @@ Core UI elements: protocols, views and helpers.
|
|||
# Views
|
||||
|
||||
- [BaseInitializableView](BaseInitializableView/BaseInitializableView.swift) - UIView conformance to InitializableView.
|
||||
|
||||
# Installation via SPM
|
||||
|
||||
You can install this framework as a target of LeadKit.
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
public extension InitializableView {
|
||||
public extension InitializableViewProtocol {
|
||||
|
||||
func initializeView() {
|
||||
addViews()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
public protocol ConfigurableView {
|
||||
associatedtype ViewModelType
|
||||
|
||||
func configure(with _: ViewModelType)
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
//
|
||||
|
||||
/// Protocol with methods that should be called in constructor methods of view.
|
||||
public protocol InitializableView {
|
||||
public protocol InitializableViewProtocol {
|
||||
|
||||
/// Main method that should call other methods in particular order.
|
||||
func initializeView()
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// 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 UIKit.UIFont
|
||||
import UIKit.UIColor
|
||||
|
||||
/// Base set of attributes to configure appearance of text.
|
||||
open class BaseTextAttributes {
|
||||
|
||||
/// Text font.
|
||||
public let font: UIFont
|
||||
/// Text color.
|
||||
public let color: UIColor
|
||||
/// Text alignment.
|
||||
public let alignment: NSTextAlignment
|
||||
|
||||
/// Memberwise initializer.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - font: Text font.
|
||||
/// - color: Text color.
|
||||
/// - alignment: Text alignment.
|
||||
public init(font: UIFont, color: UIColor, alignment: NSTextAlignment = .natural) {
|
||||
self.font = font
|
||||
self.color = color
|
||||
self.alignment = alignment
|
||||
}
|
||||
}
|
||||
|
||||
public extension BaseTextAttributes {
|
||||
|
||||
/// Configures text appearance of given ViewTextConfigurable instance.
|
||||
///
|
||||
/// - Parameter view: ViewTextConfigurable instance to configure with BaseTextAttributes.
|
||||
func configureBaseApperance(of view: ViewTextConfigurable) {
|
||||
view.configureBaseAppearance(with: self)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
//
|
||||
// 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 UIKit
|
||||
|
||||
/// Enum that describes text with appearance options.
|
||||
///
|
||||
/// - string: Regular string with common and often-used text attributes.
|
||||
/// - attributedString: Attributed string.
|
||||
public enum ViewText {
|
||||
|
||||
case string(String, textAttributes: BaseTextAttributes)
|
||||
case attributedString(NSAttributedString)
|
||||
}
|
||||
|
||||
public extension ViewText {
|
||||
|
||||
/// Convenient initializer for .string case with default alignment parameter.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - string: Text to use.
|
||||
/// - font: Font to use.
|
||||
/// - color: Color to use.
|
||||
/// - alignment: Alignment to use. Default is natural.
|
||||
init(string: String, font: UIFont, color: UIColor, alignment: NSTextAlignment = .natural) {
|
||||
self = .string(string, textAttributes: BaseTextAttributes(font: font,
|
||||
color: color,
|
||||
alignment: alignment))
|
||||
}
|
||||
|
||||
/// Attributed string created using text attributes.
|
||||
var attributedString: NSAttributedString {
|
||||
switch self {
|
||||
case let .string(title, textAttributes):
|
||||
|
||||
let paragraphStyle = NSMutableParagraphStyle()
|
||||
paragraphStyle.alignment = textAttributes.alignment
|
||||
|
||||
let attributes: [NSAttributedString.Key: Any] = [
|
||||
.font: textAttributes.font,
|
||||
.foregroundColor: textAttributes.color,
|
||||
.paragraphStyle: paragraphStyle
|
||||
]
|
||||
|
||||
return NSAttributedString(string: title, attributes: attributes)
|
||||
|
||||
case .attributedString(let attributedTitle):
|
||||
return attributedTitle
|
||||
}
|
||||
}
|
||||
|
||||
/// Method that calculates size of view text using given max width and height arguments.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - maxWidth: The width constraint to apply when computing the string’s bounding rectangle.
|
||||
/// - maxHeight: The width constraint to apply when computing the string’s bounding rectangle.
|
||||
/// - Returns: Returns the size required to draw the text.
|
||||
func size(maxWidth: CGFloat = CGFloat.greatestFiniteMagnitude,
|
||||
maxHeight: CGFloat = CGFloat.greatestFiniteMagnitude) -> CGSize {
|
||||
|
||||
return attributedString.boundingRect(with: CGSize(width: maxWidth, height: maxHeight),
|
||||
options: [.usesLineFragmentOrigin, .usesFontLeading],
|
||||
context: nil).size
|
||||
}
|
||||
|
||||
/// Configures given ViewTextConfigurable instance.
|
||||
///
|
||||
/// - Parameter view: ViewTextConfigurable instance to configure with ViewText.
|
||||
func configure(view: ViewTextConfigurable) {
|
||||
view.configure(with: self)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
//
|
||||
// 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 UIKit.UIButton
|
||||
|
||||
extension UIButton: ViewTextConfigurable {
|
||||
|
||||
public var textFont: UIFont? {
|
||||
get {
|
||||
return titleLabel?.font
|
||||
}
|
||||
set {
|
||||
titleLabel?.font = newValue
|
||||
}
|
||||
}
|
||||
|
||||
public var titleColor: UIColor? {
|
||||
get {
|
||||
return currentTitleColor
|
||||
}
|
||||
set {
|
||||
setTitleColor(newValue, for: [])
|
||||
}
|
||||
}
|
||||
|
||||
public var textAlignment: NSTextAlignment {
|
||||
get {
|
||||
return contentHorizontalAlignment.textAlignment
|
||||
}
|
||||
set {
|
||||
contentHorizontalAlignment = .init(textAlignment: newValue)
|
||||
}
|
||||
}
|
||||
|
||||
public var text: String? {
|
||||
get {
|
||||
return currentTitle
|
||||
}
|
||||
set {
|
||||
setTitle(newValue, for: [])
|
||||
}
|
||||
}
|
||||
|
||||
public var attributedText: NSAttributedString? {
|
||||
get {
|
||||
return currentAttributedTitle
|
||||
}
|
||||
set {
|
||||
setAttributedTitle(newValue, for: [])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension UIControl.ContentHorizontalAlignment {
|
||||
|
||||
init(textAlignment: NSTextAlignment) {
|
||||
switch textAlignment {
|
||||
case .left:
|
||||
self = .leading
|
||||
|
||||
case .right:
|
||||
self = .trailing
|
||||
|
||||
case .center:
|
||||
self = .center
|
||||
|
||||
case .justified:
|
||||
self = .fill
|
||||
|
||||
case .natural:
|
||||
self = .leading
|
||||
|
||||
@unknown default:
|
||||
self = .leading
|
||||
}
|
||||
}
|
||||
|
||||
var textAlignment: NSTextAlignment {
|
||||
switch self {
|
||||
case .left:
|
||||
return .left
|
||||
|
||||
case .right:
|
||||
return .right
|
||||
|
||||
case .center:
|
||||
return .center
|
||||
|
||||
case .fill:
|
||||
return .justified
|
||||
|
||||
case .leading:
|
||||
return .natural
|
||||
|
||||
case .trailing:
|
||||
return .right
|
||||
|
||||
@unknown default:
|
||||
return .natural
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// 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 UIKit.UILabel
|
||||
|
||||
extension UILabel: ViewTextConfigurable {
|
||||
|
||||
public var textFont: UIFont? {
|
||||
get {
|
||||
return font
|
||||
}
|
||||
set {
|
||||
font = newValue
|
||||
}
|
||||
}
|
||||
|
||||
public var titleColor: UIColor? {
|
||||
get {
|
||||
return textColor
|
||||
}
|
||||
set {
|
||||
textColor = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
//
|
||||
// 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 UIKit.UITextField
|
||||
|
||||
extension UITextField: ViewTextConfigurable {
|
||||
|
||||
public var textFont: UIFont? {
|
||||
get {
|
||||
return font
|
||||
}
|
||||
set {
|
||||
font = newValue
|
||||
}
|
||||
}
|
||||
|
||||
public var titleColor: UIColor? {
|
||||
get {
|
||||
return textColor
|
||||
}
|
||||
set {
|
||||
textColor = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
//
|
||||
// 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 UIKit.UIFont
|
||||
import UIKit.UIColor
|
||||
|
||||
/// Protocol that represents text object with appearance attributes.
|
||||
public protocol ViewTextConfigurable: AnyObject {
|
||||
|
||||
/// Font of text object.
|
||||
var textFont: UIFont? { get set }
|
||||
|
||||
/// Text color of text object.
|
||||
var titleColor: UIColor? { get set }
|
||||
|
||||
/// Text alignment of text object.
|
||||
var textAlignment: NSTextAlignment { get set }
|
||||
|
||||
/// Text itself of text object.
|
||||
var text: String? { get set }
|
||||
|
||||
/// Attributed text of text object.
|
||||
var attributedText: NSAttributedString? { get set }
|
||||
}
|
||||
|
||||
public extension ViewTextConfigurable {
|
||||
|
||||
/// Configures text and text appearance of view using ViewText object.
|
||||
///
|
||||
/// - Parameter viewText: ViewText object with text and text appearance.
|
||||
func configure(with viewText: ViewText) {
|
||||
switch viewText {
|
||||
case let .string(text, textAttributes):
|
||||
self.text = text
|
||||
self.configureBaseAppearance(with: textAttributes)
|
||||
|
||||
case .attributedString(let attributedString):
|
||||
self.attributedText = attributedString
|
||||
}
|
||||
}
|
||||
|
||||
/// Configures text appearance of view.
|
||||
///
|
||||
/// - Parameter baseTextAttributes: Set of attributes to configure appearance of text.
|
||||
func configureBaseAppearance(with baseTextAttributes: BaseTextAttributes) {
|
||||
textFont = baseTextAttributes.font
|
||||
titleColor = baseTextAttributes.color
|
||||
textAlignment = baseTextAttributes.alignment
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = 'TIUIKitCore'
|
||||
s.version = '0.11.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' }
|
||||
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.framework = 'UIKit'
|
||||
end
|
||||
Loading…
Reference in New Issue