IGListKit/Examples/Examples-macOS/IGListKitExamples/ViewControllers/UsersViewController.swift
Guilherme Rambo 47fbb72fa6 macOS example app
Summary:
Related issue: #333

I've made a very simple macOS example app. It's just a list of names which can be searched, shuffled or deleted.

I think this is a good starting point for anyone who wants to use this on macOS projects :)

![iglistkitmac](https://cloud.githubusercontent.com/assets/67184/21238494/7245f242-c2ea-11e6-98ea-218a6150d14c.gif)
Closes https://github.com/Instagram/IGListKit/pull/337

Reviewed By: rnystrom

Differential Revision: D4345236

Pulled By: jessesquires

fbshipit-source-id: ce75372263d3f451e34f2c816c14ab6bc82116a7
2016-12-19 10:59:03 -08:00

149 lines
4.5 KiB
Swift

/**
Copyright (c) 2016-present, Facebook, Inc. All rights reserved.
The examples provided by Facebook are for non-commercial testing and evaluation
purposes only. Facebook reserves all rights not expressly granted.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import Cocoa
import IGListKit
final class UsersViewController: NSViewController {
@IBOutlet weak var tableView: NSTableView!
//MARK: Data
var users = [User]() {
didSet {
computeFilteredUsers()
}
}
var searchTerm = "" {
didSet {
computeFilteredUsers()
}
}
private func computeFilteredUsers() {
guard searchTerm.characters.count > 1 else {
filteredUsers = users
return
}
filteredUsers = users.filter({ $0.name.localizedCaseInsensitiveContains(self.searchTerm) })
}
fileprivate func delete(user: User) {
guard let index = self.users.index(where: { $0.pk == user.pk }) else { return }
self.users.remove(at: index)
}
//MARK: -
//MARK: Diffing
var filteredUsers = [User]() {
didSet {
// get the difference between the old array of Users and the new array of Users
let diff = IGListDiff(oldValue, filteredUsers, .equality)
// this difference is used here to update the table view, but it can be used
// to update collection views and other similar interface elements
// this code can also be added to an extension of NSTableView ;)
tableView.beginUpdates()
tableView.insertRows(at: diff.inserts, withAnimation: .slideDown)
tableView.removeRows(at: diff.deletes, withAnimation: .slideUp)
tableView.reloadData(forRowIndexes: diff.updates, columnIndexes: .zero)
diff.moves.forEach { move in
self.tableView.moveRow(at: move.from, to: move.to)
}
tableView.endUpdates()
}
}
//MARK: -
private func loadSampleUsers() {
guard let file = Bundle.main.url(forResource: "users", withExtension: "json") else { return }
do {
self.users = try UsersProvider(with: file).users
} catch {
NSAlert(error: error).runModal()
}
}
// MARK: Interface
override func viewDidLoad() {
super.viewDidLoad()
loadSampleUsers()
}
override func viewDidAppear() {
super.viewDidAppear()
view.window?.titleVisibility = .hidden
}
@IBAction func shuffle(_ sender: Any?) {
users = users.shuffled
}
@IBAction func search(_ sender: NSSearchField) {
searchTerm = sender.stringValue
}
@IBAction func delete(_ sender: Any?) {
guard tableView.selectedRowIndexes.count > 0 else { return }
tableView.selectedRowIndexes.forEach({ self.delete(user: self.filteredUsers[$0]) })
}
}
extension UsersViewController: NSTableViewDataSource {
func numberOfRows(in tableView: NSTableView) -> Int {
return filteredUsers.count
}
}
extension UsersViewController: NSTableViewDelegate {
private struct Storyboard {
static let cellIdentifier = "cell"
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
guard let cell = tableView.make(withIdentifier: Storyboard.cellIdentifier, owner: tableView) as? NSTableCellView else {
return nil
}
cell.textField?.stringValue = filteredUsers[row].name
return cell
}
func tableView(_ tableView: NSTableView, rowActionsForRow row: Int, edge: NSTableRowActionEdge) -> [NSTableViewRowAction] {
let delete = NSTableViewRowAction(style: .destructive, title: "Delete") { action, row in
guard row < self.filteredUsers.count else { return }
self.delete(user: self.filteredUsers[row])
}
return [delete]
}
}