# Highlighter: search-term highlighting inside iOS table cells

> Highlighter is a small Swift package for iOS that finds the text controls inside a view or table cell and highlights the part matching a search string. It is aimed at iOS developers building search screens where the matched text has to be styled inside a cell that may be recycled.

**younatics/Highlighter** — 🖍 Highlight whatever you want! 

- Repository: https://github.com/younatics/Highlighter
- Stars: 921 · Forks: 54
- Language: Swift
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/younatics-highlighter

## The problem is styling a substring, not finding a cell

Highlighter is described in one line as highlighting whatever you want, and the README explains what that means in practice. It will find UI objects such as `UILabel`, `UITextView`, `UITextField` and `UIButton` in your `UITableViewCell` or other `Class`.

The feature it provides is search term highlighting. When a user types a query and the results appear in a list, the usual expectation is that the part of each result matching the query is emphasised. In UIKit that means taking an `NSAttributedString`, locating the range of the match, and applying an attribute to that range.

The difficulty is that doing that by hand for every cell in a table is repetitive and easy to get subtly wrong, particularly in a reusable cell where the same label object is configured again and again with different text and different queries. A leftover attributed string or a stale range produces highlighting in the wrong place, and the bug only shows up as the user scrolls.

Highlighter moves that work into one call that takes the container and the search text, and applies the styling to the controls it finds. The audience is therefore iOS developers building list screens with a search field, which is a common enough pattern to be worth a package and common enough to be easy to get wrong by hand.

## It finds controls through stored properties, not subviews

The README is specific about the lookup mechanism, and the specificity matters for anyone deciding whether it fits their view hierarchy.

When you call `highlight(text:normal:highlight:type:)` on a container such as a custom `UIView` or a `UITableViewCell`, Highlighter inspects the container's stored properties and highlights directly stored supported controls. It does not recursively search `UIView.subviews`.

So the mechanism is reflection over the object's own properties rather than a traversal of the view tree. That has a clear consequence: the control you want highlighted has to be a property of the object you call the method on. If your label is declared as a stored property on the cell, the library finds it. If it is created inline in the configuration function and never stored, the library cannot see it, and the highlight silently does nothing.

The upside of the stored property approach is that it is precise. A subview traversal would find every text view in the hierarchy, including labels that are not part of the visible content, such as a badge or a caption you did not want touched. Reflection over stored properties targets exactly the controls you declared as part of the component's content.

The `type` parameter lets you narrow the target further, so you can ask for the first `UIButton` only, or only labels, rather than every supported control on the object.

## One call, two attribute dictionaries

The API surface is small enough to describe in full.

You can highlight a single control directly with `highlight(text:normal:highlight:)`, and you can highlight a container with `highlight(text:normal:highlight:type:)`.

For a single control, the call takes the text to search for, the attributes for the ordinary text and the attributes for the matched text. For a container, the same three plus an optional type constraint.

To highlight all supported controls stored as properties, the README gives:

```swift
view.highlight(text: "Foo", normal: normalAttributes, highlight: highlightedAttributes)
```

And to limit the stored properties to a single control type:

```swift
view.highlight(text: "Foo", normal: normalAttributes, highlight: highlightedAttributes, type: UIButton.self)
```

The two dictionaries are the interesting part, because they define how the rest of the string is rendered. If the `normal` attributes are nil, as in the table cell example, the control keeps its own styling for the unmatched text and only the matched range gets the highlight attributes. If you do supply `normal` attributes, you are overriding the control's appearance for the whole string, which is what you want when the cell design depends on a font or colour you set in code rather than in the storyboard.

The example shows a background colour as the highlight attribute, `.backgroundColor: UIColor.yellow`, which is the simplest possible choice and a good template for the rest of the attribute set you need.

## Installing through SPM or CocoaPods

Highlighter supports both distribution routes, and the README gives the exact instructions for each.

With Swift Package Manager, in Xcode you choose File, Add Package Dependencies and enter the repository URL:

```
https://github.com/younatics/Highlighter.git
```

Or you add it to your `Package.swift`:

```swift
dependencies: [
    .package(url: "https://github.com/younatics/Highlighter.git", from: "2.0.0")
]
```

With CocoaPods, you add one line to your Podfile:

```ruby
pod 'Highlighter', '2.0.0'
```

The requirements are stated in the README and are on the badges too. Highlighter requires Swift 6.0, with a swift-tools-version of 6.0, and iOS 13.0 or later.

The Swift 6 requirement is the notable one. It comes from the 2.0.0 release, which the release notes describe as a Swift 6 modernization. A team still on Swift 5 would have to stay on the previous major version, and the CocoaPods line pins the version explicitly while the SPM line uses a `from` range.

The repository ships the pieces for both routes, with a `Package.swift` at the root, a `Highlighter.podspec`, an `Highlighter.xcodeproj/` directory, the `Highlighter/` source directory, and a `Tests/` directory.

## The reusable cell case is the real use case

The README's example is a table view delegate method, and it shows the pattern most people will copy.

```swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  guard let cell = self.ynSearchListViewDelegate?.ynSearchListView(tableView, cellForRowAt: indexPath) as? SearchViewCell else { return UITableViewCell() }

  if let changedText = ynSearchTextFieldText {
    cell.highlight(text: changedText, normal: nil, highlight: [.backgroundColor: UIColor.yellow])
  }
  return cell
}
```

Three details carry the example. The cell is fetched through a delegate and cast to a concrete `SearchViewCell` type, so the cell type is known and its stored properties can be inspected. The search text is held in a property, `ynSearchTextFieldText`, and the call is guarded on it being present, so a nil query does not reach the highlighter. And `normal` is nil, which means the cell's own label styling survives for the unmatched text.

Because the call happens in `cellForRowAt`, every cell is configured from scratch as it comes into view. That is the point where the stale highlighting problem disappears: the highlight is recomputed from the current query each time the cell is configured, rather than being patched onto whatever state the previous cell left behind.

The example also shows the dependency on the author's other work, since the delegate and the search text come from YNSearch, a separate library for advanced search usage that the README points to, along with MotionBook.

## MIT terms and a decade between two releases

Highlighter is available under the MIT license, with the terms in the LICENSE file, and the README says so directly. MIT is the conventional choice for a small UI utility, and it means you can vendor the source into an application you ship without any obligation.

The release history is where the story is. The tags are 1.3.0 for Swift 4.2 support in February 2019, 1.4.0 for Swift 5 support in May 2019, and then 2.0.0 for the Swift 6 modernization in July 2026. The last push was on 2026-09-13.

So the project spent roughly seven years between a Swift 5 release and a Swift 6 one, and then released a major version within the last few months. The 2.0.0 label is accurate in the strict sense, since moving to Swift 6 and raising the tools version is a breaking change for consumers, but the library itself is small and its API has stayed stable: the same `highlight(text:normal:highlight:)` shape described in the introduction is what the current README documents.

What this means for adoption is that the dependency is small and unlikely to change shape, but you should check the CHANGELOG for the details of the 2.0.0 changes, since the README defers to it for update notes. If your app is still on Swift 5, the older 1.x line remains the compatible choice, and that line predates the current README examples.

The project also keeps an iOS project file, a podspec and a Tests directory alongside the SPM manifest, so it is maintained for both distribution routes rather than one.

## Conclusion

Adopt Highlighter when you have a search screen whose results live in table cells or custom views and you need the matching substring styled inside the cell's own controls, and you control the view hierarchy so the controls are stored properties. Skip it if your views build their subviews programmatically without stored references, since the container overload inspects stored properties and does not search `UIView.subviews`. Verify first that the label or text field in your cell is a stored property of the cell or view rather than a local variable, and that your app can take Swift 6.0 and iOS 13 as floors. The licence field on the repository says MIT, the last push was on 2026-09-13, and the current release is 2.0.0.

## FAQ

### What does the Highlighter iOS library do?

It finds UI objects such as `UILabel`, `UITextView`, `UITextField` and `UIButton` in your `UITableViewCell` or other class and highlights the text matching a given string, applying separate attributes for the normal and the highlighted portions.

### How does Highlighter find the controls inside a cell?

When you call the container overload, Highlighter inspects the container's stored properties and highlights directly stored supported controls. The README states explicitly that it does not recursively search `UIView.subviews`, so the control must be a stored property of the cell or view.

### How do I install Highlighter?

Through Swift Package Manager, add the repository `https://github.com/younatics/Highlighter.git` in Xcode or add `.package(url: "https://github.com/younatics/Highlighter.git", from: "2.0.0")` to your Package.swift. Through CocoaPods, add `pod 'Highlighter', '2.0.0'` to your Podfile.

### What are the requirements for Highlighter?

The README states that Highlighter requires Swift 6.0, with a swift-tools-version of 6.0, and iOS 13.0 or later. It supports both Swift Package Manager and CocoaPods.

### Can I highlight only one type of control?

Yes. The container call takes an optional type parameter, so `view.highlight(text: "Foo", normal: normalAttributes, highlight: highlightedAttributes, type: UIButton.self)` limits the stored properties it touches to buttons.

### What licence is Highlighter released under?

It is available under the MIT license, with the terms in the LICENSE file. The releases are 1.3.0 for Swift 4.2 support on 2019-02-08, 1.4.0 for Swift 5 support on 2019-05-04, and 2.0.0 for the Swift 6 modernization on 2026-07-08, with the last push on 2026-09-13.

## Sources

- [Issues](https://github.com/younatics/Highlighter/issues)
- [License: MIT](https://github.com/younatics/Highlighter/blob/master/LICENSE)
- [README](https://github.com/younatics/Highlighter/blob/master/README.md)
- [Releases](https://github.com/younatics/Highlighter/releases)
- [younatics/Highlighter on GitHub](https://github.com/younatics/Highlighter)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/younatics-highlighter
