├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── .swiftpm
└── xcode
│ └── package.xcworkspace
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── CODE_OF_CONDUCT.md
├── Center.jpg
├── LICENSE
├── Left.jpg
├── Package.swift
├── README.md
├── Replay_Insert_Remove.gif
├── Right.jpg
├── Sources
└── TagsFlowLayout
│ └── TagsFlowLayout.swift
├── TagsFlowLayout.podspec
├── TagsFlowLayout
├── .gitignore
├── .travis.yml
└── 1.0
│ └── TagsFlowLayout.podspec
└── Tests
└── TagsFlowLayoutTests
└── TagsFlowLayoutTests.swift
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /.build
3 | /Packages
4 | /*.xcodeproj
5 | xcuserdata/
6 | DerivedData/
7 | .swiftpm/config/registries.json
8 | .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
9 | .netrc
10 |
--------------------------------------------------------------------------------
/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, religion, or sexual identity
10 | and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the
26 | overall community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or
31 | advances of any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email
35 | address, without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at
63 | rastaman.alex007@gmail.com.
64 | All complaints will be reviewed and investigated promptly and fairly.
65 |
66 | All community leaders are obligated to respect the privacy and security of the
67 | reporter of any incident.
68 |
69 | ## Enforcement Guidelines
70 |
71 | Community leaders will follow these Community Impact Guidelines in determining
72 | the consequences for any action they deem in violation of this Code of Conduct:
73 |
74 | ### 1. Correction
75 |
76 | **Community Impact**: Use of inappropriate language or other behavior deemed
77 | unprofessional or unwelcome in the community.
78 |
79 | **Consequence**: A private, written warning from community leaders, providing
80 | clarity around the nature of the violation and an explanation of why the
81 | behavior was inappropriate. A public apology may be requested.
82 |
83 | ### 2. Warning
84 |
85 | **Community Impact**: A violation through a single incident or series
86 | of actions.
87 |
88 | **Consequence**: A warning with consequences for continued behavior. No
89 | interaction with the people involved, including unsolicited interaction with
90 | those enforcing the Code of Conduct, for a specified period of time. This
91 | includes avoiding interactions in community spaces as well as external channels
92 | like social media. Violating these terms may lead to a temporary or
93 | permanent ban.
94 |
95 | ### 3. Temporary Ban
96 |
97 | **Community Impact**: A serious violation of community standards, including
98 | sustained inappropriate behavior.
99 |
100 | **Consequence**: A temporary ban from any sort of interaction or public
101 | communication with the community for a specified period of time. No public or
102 | private interaction with the people involved, including unsolicited interaction
103 | with those enforcing the Code of Conduct, is allowed during this period.
104 | Violating these terms may lead to a permanent ban.
105 |
106 | ### 4. Permanent Ban
107 |
108 | **Community Impact**: Demonstrating a pattern of violation of community
109 | standards, including sustained inappropriate behavior, harassment of an
110 | individual, or aggression toward or disparagement of classes of individuals.
111 |
112 | **Consequence**: A permanent ban from any sort of public interaction within
113 | the community.
114 |
115 | ## Attribution
116 |
117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
118 | version 2.0, available at
119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
120 |
121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
122 | enforcement ladder](https://github.com/mozilla/diversity).
123 |
124 | [homepage]: https://www.contributor-covenant.org
125 |
126 | For answers to common questions about this code of conduct, see the FAQ at
127 | https://www.contributor-covenant.org/faq. Translations are available at
128 | https://www.contributor-covenant.org/translations.
129 |
--------------------------------------------------------------------------------
/Center.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rastaman111/TagsFlowLayout/d6e407d166c981e546659177555745e118a59796/Center.jpg
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | MIT License
3 |
4 | Copyright © 2022 Alexandr Sibirtsev
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/Left.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rastaman111/TagsFlowLayout/d6e407d166c981e546659177555745e118a59796/Left.jpg
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.6
2 |
3 | import PackageDescription
4 |
5 | let package = Package(
6 | name: "TagsFlowLayout",
7 | platforms: [
8 | .iOS(.v11)
9 | ],
10 | products: [
11 | .library(
12 | name: "TagsFlowLayout", targets: ["TagsFlowLayout"]),
13 | ],
14 | dependencies: [],
15 | targets: [
16 | .target(
17 | name: "TagsFlowLayout",
18 | dependencies: [],
19 | path: "Sources")
20 | ]
21 | )
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # TagsFlowLayout
2 |
3 | This implementation is built using a `UICollectionView` and a custom flowLayout.
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | ### Horizontal Alignment:
25 |
26 | * `horizontalAlignment = .left`
27 |
28 |
29 |
30 | * `horizontalAlignment = .right`
31 |
32 |
33 |
34 | * `horizontalAlignment = .center`
35 |
36 |
37 |
38 | ### Inserting and Deleting tags
39 |
40 |
41 |
42 | # Table of contents
43 |
44 | * [Requirements](#requirements)
45 | * [Installation](#installation)
46 | - [CocoaPods](#cocoapods)
47 | - [Swift Package Manager](#swift-package-manager)
48 | - [Carthage](#carthage)
49 | - [Manually](#manually)
50 | * [Usage](#usage)
51 | * [License](#license)
52 | * [Donation](#donation)
53 |
54 | ## Requirements
55 | * iOS 11.0+
56 | * Swift 5
57 |
58 | ## Installation
59 |
60 | ### CocoaPods
61 | Add Instructions to your Podfile:
62 |
63 | ```ruby
64 | pod 'TagsFlowLayout'
65 | ```
66 |
67 | Then, run the following command:
68 |
69 | ```bash
70 | $ pod install
71 | ```
72 |
73 | ### Swift Package Manager
74 | In Xcode, use File > Swift Packages > Add Package Dependency and use `https://github.com/rastaman111/TagsFlowLayout`.
75 |
76 | ### Carthage
77 | To install with [Carthage](https://github.com/Carthage/Carthage), simply add the following line to your Podfile:
78 | ```ruby
79 | github "rastaman111/TagsFlowLayout"
80 | ```
81 |
82 | ### Manually
83 | If you prefer not to use any of dependency managers, you can integrate manually. Put `Sources/TagsFlowLayout` folder in your Xcode project. Make sure to enable `Copy items if needed` and `Create groups`.
84 |
85 | ## Usage
86 | To use `TagsFlowLayout` inside your `UIViewController`:
87 |
88 | ```swift
89 | import TagsFlowLayout
90 |
91 | class ViewController: UICollectionViewController {
92 |
93 | override func viewDidLoad() {
94 | super.viewDidLoad()
95 |
96 | let tagsFlowLayout = TagsFlowLayout(alignment: .left ,minimumInteritemSpacing: 10, minimumLineSpacing: 10, sectionInset: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10))
97 | collectionView.collectionViewLayout = tagsFlowLayout
98 |
99 | // register cell
100 | collectionView.register(nib: UINib(nibName: "ExampleCell", bundle: nil), forCellWithReuseIdentifier: "ExampleCell")
101 | }
102 |
103 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
104 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ExampleCell", for: indexPath) as! ExampleCell
105 |
106 | cell.maxWidth = collectionView.bounds.width - 30
107 |
108 | return cell
109 | }
110 | }
111 | ```
112 | ```swift
113 | class TagCollectionViewCell: UICollectionViewCell {
114 |
115 | @IBOutlet weak var tagLabel: UILabel!
116 |
117 | @IBOutlet private var maxWidthConstraint: NSLayoutConstraint! {
118 | didSet {
119 | maxWidthConstraint.isActive = false
120 | }
121 | }
122 |
123 | var maxWidth: CGFloat? = nil {
124 | didSet {
125 | guard let maxWidth = maxWidth else {
126 | return
127 | }
128 | maxWidthConstraint.isActive = true
129 | maxWidthConstraint.constant = maxWidth
130 | }
131 | }
132 | }
133 | ```
134 | ## License
135 | TagsFlowLayout is available under the MIT license. See the LICENSE file for more info.
136 |
137 | ## Donation
138 |
139 |
--------------------------------------------------------------------------------
/Replay_Insert_Remove.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rastaman111/TagsFlowLayout/d6e407d166c981e546659177555745e118a59796/Replay_Insert_Remove.gif
--------------------------------------------------------------------------------
/Right.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rastaman111/TagsFlowLayout/d6e407d166c981e546659177555745e118a59796/Right.jpg
--------------------------------------------------------------------------------
/Sources/TagsFlowLayout/TagsFlowLayout.swift:
--------------------------------------------------------------------------------
1 | // MIT License
2 | //
3 | // Copyright (c) 2022 Alexandr Sibirtsev
4 | //
5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
6 | // of this software and associated documentation files (the "Software"), to deal
7 | // in the Software without restriction, including without limitation the rights
8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | // copies of the Software, and to permit persons to whom the Software is
10 | // furnished to do so, subject to the following conditions:
11 | //
12 | // The above copyright notice and this permission notice shall be included in all
13 | // copies or substantial portions of the Software.
14 | //
15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | // SOFTWARE.
22 |
23 | import UIKit
24 |
25 | public extension TagsFlowLayout {
26 |
27 | enum LayoutAlignment: Int {
28 | case left
29 | case center
30 | case right
31 | }
32 | }
33 |
34 | public class TagsFlowLayout: UICollectionViewFlowLayout {
35 |
36 | let alignment: LayoutAlignment
37 |
38 | //MARK: - Init Methods
39 |
40 | required init(alignment: LayoutAlignment = .left, minimumInteritemSpacing: CGFloat = 0, minimumLineSpacing: CGFloat = 0, sectionInset: UIEdgeInsets = .zero) {
41 | self.alignment = alignment
42 | super.init()
43 |
44 | self.minimumInteritemSpacing = minimumInteritemSpacing
45 | self.minimumLineSpacing = minimumLineSpacing
46 | self.sectionInset = sectionInset
47 |
48 | self.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
49 | self.sectionInsetReference = SectionInsetReference.fromLayoutMargins
50 | }
51 |
52 | required init?(coder aDecoder: NSCoder) {
53 | fatalError("init(coder:) has not been implemented")
54 | }
55 |
56 | public override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
57 | guard let superArray = super.layoutAttributesForElements(in: rect) else { return nil }
58 | guard let attributes = NSArray(array: superArray, copyItems: true) as? [UICollectionViewLayoutAttributes] else { return nil }
59 | // Constants
60 | let leftPadding: CGFloat = 8
61 | let interItemSpacing = minimumInteritemSpacing
62 | // Tracking values
63 | var leftMargin: CGFloat = leftPadding // Modified to determine origin.x for each item
64 | var maxY: CGFloat = -1.0 // Modified to determine origin.y for each item
65 | var rowSizes: [[CGFloat]] = [] // Tracks the starting and ending x-values for the first and last item in the row
66 | var currentRow: Int = 0 // Tracks the current row
67 | attributes.forEach { layoutAttribute in
68 | guard layoutAttribute.representedElementCategory == .cell else {
69 | return
70 | }
71 | // Each layoutAttribute represents its own item
72 | if layoutAttribute.frame.origin.y >= maxY {
73 | // This layoutAttribute represents the left-most item in the row
74 | leftMargin = leftPadding
75 | // Register its origin.x in rowSizes for use later
76 | if rowSizes.count == 0 {
77 | // Add to first row
78 | rowSizes = [[leftMargin, 0]]
79 | } else {
80 | // Append a new row
81 | rowSizes.append([leftMargin, 0])
82 | currentRow += 1
83 | }
84 | }
85 | layoutAttribute.frame.origin.x = leftMargin
86 | leftMargin += layoutAttribute.frame.width + interItemSpacing
87 | maxY = max(layoutAttribute.frame.maxY, maxY)
88 | // Add right-most x value for last item in the row
89 | rowSizes[currentRow][1] = leftMargin - interItemSpacing
90 | }
91 |
92 | guard alignment != .left && alignment != .right else {
93 | return attributes
94 | }
95 |
96 | // At this point, all cells are left aligned
97 | // Reset tracking values and add extra left padding to center align entire row
98 | leftMargin = leftPadding
99 | maxY = -1.0
100 | currentRow = 0
101 | attributes.forEach { layoutAttribute in
102 | // Each layoutAttribute is its own item
103 | if layoutAttribute.frame.origin.y >= maxY {
104 | // This layoutAttribute represents the left-most item in the row
105 | leftMargin = leftPadding
106 | // Need to bump it up by an appended margin
107 | let rowWidth = rowSizes[currentRow][1] - rowSizes[currentRow][0] // last.x - first.x
108 | let appendedMargin = (collectionView!.frame.width - leftPadding - rowWidth - leftPadding) / 2
109 | leftMargin += appendedMargin
110 | currentRow += 1
111 | }
112 | layoutAttribute.frame.origin.x = leftMargin
113 | leftMargin += layoutAttribute.frame.width + interItemSpacing
114 | maxY = max(layoutAttribute.frame.maxY, maxY)
115 | }
116 |
117 | return attributes
118 | }
119 |
120 | public override var flipsHorizontallyInOppositeLayoutDirection: Bool {
121 | return true
122 | }
123 |
124 | public override var developmentLayoutDirection: UIUserInterfaceLayoutDirection {
125 | if alignment == .right {
126 | return UIUserInterfaceLayoutDirection.rightToLeft
127 | } else {
128 | return UIUserInterfaceLayoutDirection.leftToRight
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/TagsFlowLayout.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 |
3 | s.name = "TagsFlowLayout"
4 | s.version = "1.0"
5 | s.summary = "This implementation is built using a UICollectionView and a custom flowLayout in Swift."
6 | s.homepage = "https://github.com/rastaman111/TagsFlowLayout"
7 | s.source = { :git => "https://github.com/rastaman111/TagsFlowLayout.git", :tag => s.version }
8 | s.license = { :type => "MIT", :file => "LICENSE" }
9 | s.author = { 'Alexander' => "rastaman.alex007@gmail.com" }
10 |
11 | s.swift_version = '5.0'
12 | s.ios.deployment_target = '11.0'
13 |
14 | s.source_files = 'Sources/TagsFlowLayout/**/*.swift'
15 |
16 | end
17 |
--------------------------------------------------------------------------------
/TagsFlowLayout/.gitignore:
--------------------------------------------------------------------------------
1 | # macOS
2 | .DS_Store
3 |
4 | # Xcode
5 | build/
6 | *.pbxuser
7 | !default.pbxuser
8 | *.mode1v3
9 | !default.mode1v3
10 | *.mode2v3
11 | !default.mode2v3
12 | *.perspectivev3
13 | !default.perspectivev3
14 | xcuserdata/
15 | *.xccheckout
16 | profile
17 | *.moved-aside
18 | DerivedData
19 | *.hmap
20 | *.ipa
21 |
22 | # Bundler
23 | .bundle
24 |
25 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
26 | # Carthage/Checkouts
27 |
28 | Carthage/Build
29 |
30 | # We recommend against adding the Pods directory to your .gitignore. However
31 | # you should judge for yourself, the pros and cons are mentioned at:
32 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
33 | #
34 | # Note: if you ignore the Pods directory, make sure to uncomment
35 | # `pod install` in .travis.yml
36 | #
37 | # Pods/
38 |
--------------------------------------------------------------------------------
/TagsFlowLayout/.travis.yml:
--------------------------------------------------------------------------------
1 | # references:
2 | # * https://www.objc.io/issues/6-build-tools/travis-ci/
3 | # * https://github.com/supermarin/xcpretty#usage
4 |
5 | osx_image: xcode7.3
6 | language: objective-c
7 | # cache: cocoapods
8 | # podfile: Example/Podfile
9 | # before_install:
10 | # - gem install cocoapods # Since Travis is not always on latest version
11 | # - pod install --project-directory=Example
12 | script:
13 | - set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/TagsFlowLayout.xcworkspace -scheme TagsFlowLayout-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty
14 | - pod lib lint
15 |
--------------------------------------------------------------------------------
/TagsFlowLayout/1.0/TagsFlowLayout.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 |
3 | s.name = "TagsFlowLayout"
4 | s.version = "1.0"
5 | s.summary = "This implementation is built using a UICollectionView and a custom flowLayout in Swift."
6 | s.homepage = "https://github.com/rastaman111/TagsFlowLayout"
7 | s.source = { :git => "https://github.com/rastaman111/TagsFlowLayout.git", :tag => s.version }
8 | s.license = { :type => "MIT", :file => "LICENSE" }
9 | s.author = { 'Alexander' => "rastaman.alex007@gmail.com" }
10 |
11 | s.swift_version = '5.0'
12 | s.ios.deployment_target = '11.0'
13 |
14 | s.source_files = 'Sources/TagsFlowLayout/**/*.swift'
15 |
16 | end
17 |
--------------------------------------------------------------------------------
/Tests/TagsFlowLayoutTests/TagsFlowLayoutTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import TagsFlowLayout
3 |
4 | final class TagsFlowLayoutTests: XCTestCase {
5 | func testExample() throws {
6 | // This is an example of a functional test case.
7 | // Use XCTAssert and related functions to verify your tests produce the correct
8 | // results.
9 | }
10 | }
11 |
--------------------------------------------------------------------------------