Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/bellapplab/blresultscontroller
BLResultsController is not a drop-in replacement for the `NSFetchedResultsController` to be used with Realm. It's better.
https://github.com/bellapplab/blresultscontroller
background-realm carthage cocoapods ios macos osx realm realmswift swift tvos
Last synced: about 1 month ago
JSON representation
BLResultsController is not a drop-in replacement for the `NSFetchedResultsController` to be used with Realm. It's better.
- Host: GitHub
- URL: https://github.com/bellapplab/blresultscontroller
- Owner: BellAppLab
- License: mit
- Created: 2018-08-12T17:41:43.000Z (over 6 years ago)
- Default Branch: main
- Last Pushed: 2023-02-15T18:08:52.000Z (almost 2 years ago)
- Last Synced: 2024-03-15T09:20:50.763Z (9 months ago)
- Topics: background-realm, carthage, cocoapods, ios, macos, osx, realm, realmswift, swift, tvos
- Language: Swift
- Homepage:
- Size: 4.82 MB
- Stars: 2
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# BLResultsController [![Version](https://img.shields.io/badge/Version-3.0.0-black.svg?style=flat)](#installation) [![License](https://img.shields.io/cocoapods/l/BLResultsController.svg?style=flat)](#license)
[![Platforms](https://img.shields.io/badge/Platforms-iOS|tvOS|macOS-brightgreen.svg?style=flat)](#installation)
[![Swift support](https://img.shields.io/badge/Swift-5.0%20%7C%205.3-red.svg?style=flat)](#swift-versions-support)
[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/BLResultsController.svg?style=flat&label=CocoaPods)](https://cocoapods.org/pods/BLResultsController)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
[![SwiftPM compatible](https://img.shields.io/badge/SwiftPM-compatible-red.svg?style=flat)](https://github.com/apple/swift-package-manager)
[![Twitter](https://img.shields.io/badge/[email protected]?style=flat)](http://twitter.com/BellAppLab)![BLResultsController](./Images/BLResultsController.png)
Contrary to popular belief, BLResultsController is **not** a drop-in replacement for the `NSFetchedResultsController` to be used with Realm. Oh no. It's _better_.
A `ResultsController` takes a `Realm.Results` and divides its objects into sections based on the `sectionNameKeyPath` and the first `sortDescriptor`. It then calculates the relative positions of those objects and generates section indices and `IndexPath`s that are ready to be passed to `UITableView`s and `UICollectionView`s.
But **no expensive calculations are made on the main thread**. That's right. Everything is done in the background, so your UI will remain as smooth and responsive as always.
As with `Realm.Results`, the `ResultsController` is a live, auto-updating container that will keep notifying you of changes in the dataset for as long as you hold a strong reference to it. You register to receive those changes by calling `setChangeCallback(_:)` on your controller.
Changes to the underlying dataset are calculated on a background queue, therefore the UI thread is not impacted by the `ResultsController`'s overhead.
**Note**: As with `Realm` itself, the `ResultsController` is **not** thread-safe. You should only call most of its methods from the main thread.
## Features
- [X] Calculates everything on a **background thread**. 🏎
- [X] No objects are retained, so memory footprint is minimal. 👾
- [X] Calculates section index titles. 😲
- [X] Allows for user-initiated search. 🕵️♀️🕵️♂️
- [X] Most methods return in O(1). 😎
- [X] Well documented. 🤓
- [X] Well tested. 👩🔬👨🔬## Specs
* RealmSwift 10.0.0+
* iOS 13+
* tvOS 13+
* macOS 10.13+
* Swift 5.0+`BLResultsController` also uses the amazing [BackgroundRealm](https://github.com/BellAppLab/BackgroundRealm). Have a look!
## Example
![ResultsController](./Images/results_controller.gif)
Install the `ResultsControllerElement` protocol on your `RealmObject` subclass:
```swift
public final class Foo: Object, ResultsControllerElement
{
//If your class doesn't have a unique identifier yet, do this
public dynamic var resultsControllerId: String = UUID().uuidString
//If it does, you can do this
public var resultsControllerId: String {
return <#id#>
}
}
```Then:
```swift
import UIKit
import RealmSwift
import BLResultsControllerclass ViewController: UITableViewController {
let controller: ResultsController<<#SectionType#>>, <#ElementType#>> = {
do {
let realm = <#instantiate your realm#>
let keyPath = <#the key path to your Element's property to be used as a section#>
return try ResultsController(
realm: realm,
sectionNameKeyPath: keyPath,
sortDescriptors: [
SortDescriptor(keyPath: keyPath)
]
)
} catch {
assertionFailure("\(error)")
//do something about the error
}
}()override func viewDidLoad() {
super.viewDidLoad()controller.setChangeCallback { [weak self] change in
switch change {
case .reload(_):
self?.tableView.reloadData()
case .sectionUpdate(_, let insertedSections, let deletedSections):
self?.tableView.beginUpdates()
insertedSections.forEach { self?.tableView.insertSections($0, with: .automatic) }
deletedSections.forEach { self?.tableView.deleteSections($0, with: .automatic) }
self?.tableView.endUpdates()
case .rowUpdate(_, let insertedItems, let deletedItems, let updatedItems):
self?.tableView.beginUpdates()
self?.tableView.insertRows(at: insertedItems, with: .automatic)
self?.tableView.deleteRows(at: deletedItems, with: .automatic)
self?.tableView.reloadRows(at: updatedItems, with: .automatic)
self?.tableView.endUpdates()
}
}
controller.setFormatSectionIndexTitleCallback { (section, _) -> String in
return section
}
controller.setSortSectionIndexTitles { (sections, _) in
sections.sort(by: { $0 < $1 })
}controller.start()
}override func numberOfSections(in tableView: UITableView) -> Int {
return controller.numberOfSections()
}override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int
{
return controller.numberOfItems(in: section)
}override func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
guard let cell = tableView.dequeueReusableCell(withIdentifier: <#identifier#>) else {
fatalError("Did we configure the cell correctly on IB?")
}
<#code#>
return cell
}
override func tableView(_ tableView: UITableView,
titleForHeaderInSection section: Int) -> String?
{
return controller.section(at: section)
}
override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return controller.indexTitles()
}
override func tableView(_ tableView: UITableView,
sectionForSectionIndexTitle title: String,
at index: Int) -> Int
{
return controller.indexPath(forIndexTitle: title).section
}
}
```Boom 💥
## Installation
### Cocoapods
```ruby
pod 'BLResultsController', '~> 3.0'
```Then `import BLResultsController` where needed.
### Carthage
```swift
github "BellAppLab/BLResultsController" ~> 3.0
```Then `import BLResultsController` where needed.
### Swift Package Manager
```swift
.package(url: "https://github.com/BellAppLab/BLResultsController.git", from: "3.0")
```### Git Submodules
```shell
cd toYourProjectsFolder
git submodule add -b submodule --name BLResultsController https://github.com/BellAppLab/BLResultsController.git
```Then drag the `BLResultsController` folder into your Xcode project.
## Author
Bell App Lab, [email protected]
### Contributing
Check [this out](./CONTRIBUTING.md).
### Credits
- [Logo image](https://thenounproject.com/search/?q=controller&i=316262#) by [Andres Flores](https://thenounproject.com/aflores158) from [The Noun Project](https://thenounproject.com/)
- [Differ](https://github.com/tonyarnold/Differ) by [Tony Arnold](https://github.com/tonyarnold)## License
BLResultsController is available under the MIT license. See the LICENSE file for more info.