TTGTagCollectionView for Wrapping and Scrolling iOS Tags
Useful for showing text or custom view tags in a vertical or horizontal scrollable view and support Autolayout at the same time. It is highly customizable that most features of the text tag can be configured. 标签流显示控件,同时支持文字或自定义View
At a glance
- What is it?
- TTGTagCollectionView is a Swift-first iOS component for laying out text tags or arbitrary UIView content in wrapping and horizontally scrolling collections. Its main trade-off is explicit mutation handling, since the README requires callers to invoke reload() after tag changes.
- Who is it for?
- Adopt TTGTagCollectionView when an iOS interface needs reusable text chips or arbitrary UIView tags with predictable wrapping, scrolling, alignment, and per-tag styling. Do not choose it if a simple UIStackView is sufficient or if its explicit reload requirement conflicts with an existing reactive update model.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 121 days ago.
- What is it written in?
- Mainly Swift, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 21, 2026, and from our analysis. They are not legal advice.
Editorial analysis
TTGTagCollectionView's iOS Tag Layout Problem
TTGTagCollectionView addresses a common UIKit problem: placing many compact labels or custom views in a predictable arrangement instead of manually calculating their positions. The README lists filter chips, topic labels, search facets, dense table cells, custom tag views, and horizontal tag rows as intended use cases. TextTagCollectionView handles styled text, while TagCollectionView accepts arbitrary UIView content. That distinction matters when a screen needs the same layout rules for simple strings and specialized controls.
The component is aimed at iOS developers working with Swift-first application code, although the repository also exposes Objective-C-compatible names and selectors. Its requirements are iOS 16.0 or later, Swift 5.9 or later, and Xcode 15 or later. Those versions restrict the older deployment targets and toolchains that can adopt the current package without compatibility work.
This is a layout and rendering component rather than a complete tag-selection system. Selection state can live on a TextTag, selectionLimit can restrict selected tags, and a delegate can report app-specific events, but the README does not present persistence, filtering, networking, or data modeling as part of the project. The surrounding application still owns those concerns.
TextTag Models, Styles, and Collection Containers
The documented model separates a tag into four building blocks. TextTag holds content, style, selection state, accessibility metadata, and an optional attachment. TextTagStringContent and TextTagAttributedStringContent represent displayed text and its font and color settings. TextTagStyle controls appearance, including background color, gradient colors, borders, shadows, corner radius, padding, and size constraints. TextTagCollectionView or TagCollectionView then arranges those items according to alignment, spacing, insets, line limits, and scroll direction.
For arbitrary views, TagCollectionView replaces the text-specific content model while retaining the collection and layout responsibilities described in the README. Text tags are appropriate when labels need a shared visual model and selection behavior. Custom views are appropriate when each entry needs its own controls, illustrations, or specialized presentation.
The model separation gives callers more control than a simple array of strings. An attachment can remain associated with a tag without being part of its visible text. Accessibility metadata is likewise carried by the tag model. The README does not provide a complete accessibility audit or explain every callback, so adopters still need to confirm that their labels, traits, and application actions satisfy their own requirements.
The most important mutation rule is explicit: the README says to call reload() after adding, removing, or updating tags. The examples use tagView.add(tag:) followed by tagView.reload(). This design avoids implying that every property mutation automatically refreshes layout, but it also means that incomplete integration can leave the rendered collection stale.
Pure Layout, Alignment, and Content Sizing
According to the architecture summary, TTGTagCollectionView separates a pure layout engine from its UIKit rendering flow. Its public options include vertical wrapping, horizontal scrolling, line limits, horizontal and vertical spacing, content insets, and six alignment modes. The quick-start configuration changes the view to horizontal scrolling, applies eight-point spacing in both directions, sets a two-line limit, and hides the horizontal scroll indicator. The same component can also produce wrapping tag clouds or fill-width rows.
The alignment mode changes how items are placed across available width. The README specifically demonstrates fillByExpandingWidth, but it does not enumerate all six modes. An adopter should inspect the API declarations in Sources/ before choosing among modes whose expansion or distribution behavior may differ.
AutoLayout support comes from intrinsic size updates and preferredMaxLayoutWidth. The latter is relevant when the component is placed in a stack view, form, or self-sizing table cell because wrapping decisions depend on an available maximum width. A zero, stale, or missing width can produce a different layout from the one intended. The README documents preferredMaxLayoutWidth but does not give a complete matrix for container-specific width propagation.
The repository also describes text measurement caching, pure layout caching, and precomputed content-size APIs for dense tag lists. These are documented design features, not measured performance results. No benchmark figures are provided, so the project includes cache-aware paths, while actual memory use, reload latency, and scrolling behavior require evaluation in the target application.
Installing TTGTagCollectionView with Swift Package Manager
The package supports Swift Package Manager and CocoaPods. In Xcode, the documented route is File, Add Package Dependencies, followed by this repository URL:
https://github.com/zekunyan/TTGTagCollectionView.gitFor an existing Package.swift file, the README shows a package dependency starting at version 3.3.0:
dependencies: [
.package(url: "https://github.com/zekunyan/TTGTagCollectionView.git", from: "3.3.0")
]This declaration requests the package and allows compatible versions according to SwiftPM rules. It does not by itself add TTGTags as a target dependency to an app target, and the README does not show that target configuration. The integrator must match the import and target setup to the generated package product.
CocoaPods uses this dependency declaration:
pod 'TTGTagCollectionView'The README does not state a pinned CocoaPods version. Its package declaration and pod declaration therefore express different upgrade controls. No GitHub releases are listed for the repository, so the package tag selected by SwiftPM or the pod resolution result should be recorded rather than assuming a current GitHub release exists.
Creating and Styling the First Text Tag
Start with TextTagCollectionView, add AutoLayout constraints, create a TextTag from content and style, then reload the collection. This first use follows the README's Swift example:
import TTGTags
let tagView = TextTagCollectionView()
tagView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(tagView)
NSLayoutConstraint.activate([
tagView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
tagView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
tagView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 24)
])The view is attached with explicit leading, trailing, and top constraints. The next example creates the visible tag and applies a gradient background:
let content = TextTagStringContent(text: "Swift")
content.textFont = .boldSystemFont(ofSize: 14)
content.textColor = .white
let style = TextTagStyle()
style.enableGradientBackground = true
style.gradientBackgroundStartColor = .systemBlue
style.gradientBackgroundEndColor = .systemPurple
style.cornerRadius = 12
style.extraSpace = CGSize(width: 14, height: 8)
let tag = TextTag(content: content, style: style)
tagView.add(tag: tag)
tagView.reload()The final call is required by the README's mutation rule. Without it, the data change is present in the model but the displayed layout is not necessarily updated.
Selection Limits and Horizontal Filter Rows
Selection styling is attached to the individual tag, while selection policy belongs to the collection. The README's pattern uses TextTagStyle for the selected appearance and sets selectionLimit to 3:
let selectedStyle = TextTagStyle()
selectedStyle.backgroundColor = .systemOrange
selectedStyle.cornerRadius = 12
selectedStyle.extraSpace = CGSize(width: 14, height: 8)
tag.selectedStyle = selectedStyle
tagView.selectionLimit = 3
tagView.delegate = selfThe selectedStyle is applied when that tag becomes selected. selectionLimit limits how many tags can be selected in the documented API. delegate connects the view to the host, but the README section ends as its delegate discussion begins, so it does not identify every delegate method or callback payload. The API definitions in Sources/ should be checked before implementing selection persistence.
The same collection can act as a horizontal filter row. The README applies fill-width expansion, eight-point spacing, twelve-point insets, horizontal scrolling, a two-line limit, and a hidden indicator:
tagView.alignment = .fillByExpandingWidth
tagView.horizontalSpacing = 8
tagView.verticalSpacing = 8
tagView.contentInset = UIEdgeInsets(top: 12, left: 12, bottom: 12, right: 12)
tagView.scrollDirection = .horizontal
tagView.numberOfLines = 2
tagView.showsHorizontalScrollIndicator = false
tagView.reload()This configuration makes the component resemble a filter strip rather than a wrapping cloud. Since numberOfLines is set to 2, content beyond the documented line limit will depend on the collection's horizontal behavior. The README does not state how excess rows are clipped or exposed in every alignment mode.
UIStackView Alternative and Project Maintenance Boundaries
UIStackView is the closest general alternative for simple tag rows. Its difference is architectural: a stack view arranges arranged subviews sequentially according to axis, distribution, alignment, and spacing, while TTGTagCollectionView adds tag-specific wrapping, line limits, alignment modes, selection styling, measurement caching, and model-driven text tags. UIStackView does not provide TTGTagCollectionView's TextTag, TextTagStyle, selectionLimit, attachment, or reload-based collection model. Conversely, TTGTagCollectionView adds more layout and state machinery than a plain stack needs.
For a handful of equally styled chips in a fixed row, UIStackView may be easier to reason about. For text or arbitrary UIView tags that wrap by available width, use TTGTagCollectionView's sizing and collection APIs instead of rebuilding those measurements with nested constraints.
The repository identifies the MIT License. That identifier indicates the license used for the project, but this review does not interpret the license text. The repository is not archived, and its last push was on 2026-06-24. The repository has no GitHub releases, so changelog depth, tagged upgrade notes, and long-term compatibility must be checked through Package.swift, the podspec, commits, and source tests.
The MIT license and public source do not remove adoption work. Upgrading across package versions may require checking API changes, Xcode requirements, and generated Objective-C compatibility names. Because the repository lists no releases, an upgrade should not be treated as a no-op simply because commits are recent.
Editorial conclusion
Adopt TTGTagCollectionView when an iOS interface needs reusable text chips or arbitrary UIView tags with predictable wrapping, scrolling, alignment, and per-tag styling. Do not choose it if a simple UIStackView is sufficient or if its explicit reload requirement conflicts with an existing reactive update model. Before adoption, verify the package or pod integration in the required iOS 16.0, Swift 5.9, and Xcode 15 environment, then check how preferredMaxLayoutWidth behaves in the intended stack view or self-sizing cell.
Frequently asked questions
How do I install TTGTagCollectionView in an iOS app?
The README documents installation through Swift Package Manager in Xcode or Package.swift, and it also gives the CocoaPods declaration `pod 'TTGTagCollectionView'`. It lists iOS 16.0, Swift 5.9, and Xcode 15 as requirements.
Does TTGTagCollectionView support custom views as tags?
According to the README, `TagCollectionView` accepts arbitrary `UIView` content, while `TextTagCollectionView` is intended for styled text tags.
What must I call after adding or updating a tag?
The README identifies `reload()` as the required call after adding, removing, or updating tags.
Can TTGTagCollectionView use AutoLayout?
The README states that the component supports intrinsic size updates and `preferredMaxLayoutWidth` for stack views, forms, and self-sizing cells. Its Swift example attaches the view with standard NSLayoutConstraint anchors.
What license does TTGTagCollectionView use?
The repository identifies the MIT License and includes a `LICENSE` file. The repository's license text contains the applicable terms.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/zekunyan-ttgtagcollectionview)Was this useful?