Latest 1.0.0
Homepage https://github.com/BellAppLab/BLResultsController
License MIT
Platforms ios 9.0, osx 10.10, tvos 10.0
Dependencies RealmSwift, BackgroundRealm
Frameworks Foundation
Authors

BLResultsController Version License

Platforms
Swift support
CocoaPods Compatible
Carthage compatible
Twitter

BLResultsController

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 IndexPaths that are ready to be passed to UITableViews and UICollectionViews.

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 3.0.0+
  • iOS 9+
  • tvOS 10+
  • macOS 10.10+
  • Swift 4.0+

BLResultsController also uses the amazing BackgroundRealm. Have a look!

Example

ResultsController

import UIKit
import RealmSwift
import BLResultsController

class 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

pod 'BLResultsController', '~> 1.0'

Then import BLResultsController where needed.

Carthage

github "BellAppLab/BLResultsController" ~> 1.0

Then import BLResultsController where needed.

Git Submodules

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.

Credits

Logo image by Andres Flores from The Noun Project

License

BLResultsController is available under the MIT license. See the LICENSE file for more info.

Latest podspec

{
    "name": "BLResultsController",
    "version": "1.0.0",
    "summary": "BLResultsController is not a drop-in replacement for the `NSFetchedResultsController` to be used with Realm.",
    "screenshots": "https://github.com/BellAppLab/BLResultsController/raw/master/Images/BLResultsController.png",
    "description": "Contrary to popular belief, BLResultsController is **not** a drop-in replacement for the `NSFetchedResultsController` to be used with Realm. Oh no. It's _better_.nnA `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.nnBut **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.nnAs 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.nnChanges to the underlying dataset are calculated on a background queue, therefore the UI thread is not impacted by the `ResultsController`'s overhead.nn**Note**: As with `Realm` itself, the `ResultsController` is **not** thread-safe. You should only call most of its methods from the main thread.nn## Featuresnn- [X] Calculates everything on a **background thread**. ud83cudfcen- [X] No objects are retained, so memory footprint is minimal. ud83dudc7en- [X] Calculates section index titles. ud83dude32n- [X] Allows for user-initiated search. ud83dudd75ufe0fu200du2640ufe0fud83dudd75ufe0fu200du2642ufe0fn- [X] Most methods return in O(1). ud83dude0en- [X] Well documented. ud83eudd13n- [X] Well tested. ud83dudc69u200dud83dudd2cud83dudc68u200dud83dudd2c",
    "homepage": "https://github.com/BellAppLab/BLResultsController",
    "license": {
        "type": "MIT",
        "file": "LICENSE"
    },
    "authors": {
        "Bell App Lab": "[email protected]"
    },
    "social_media_url": "https://twitter.com/BellAppLab",
    "platforms": {
        "ios": "9.0",
        "osx": "10.10",
        "tvos": "10.0"
    },
    "module_name": "BLResultsController",
    "source": {
        "git": "https://github.com/BellAppLab/BLResultsController.git",
        "tag": "1.0.0"
    },
    "source_files": "BLResultsController",
    "frameworks": "Foundation",
    "ios": {
        "frameworks": "UIKit"
    },
    "osx": {
        "frameworks": "AppKit"
    },
    "tvos": {
        "frameworks": "UIKit"
    },
    "dependencies": {
        "RealmSwift": [
            "~> 3.0"
        ],
        "BackgroundRealm": [
            "~> 1.0"
        ]
    }
}

Pin It on Pinterest

Share This