TestsTested | ✗ |
LangLanguage | SwiftSwift |
License | Apache 2 |
ReleasedLast Release | Oct 2017 |
SwiftSwift Version | 4.0 |
SPMSupports SPM | ✗ |
Maintained by Andrea Antonioni.
MenuListKit provides a fast way to create lists and menus with declarative programming in Swift. It's a thin abstraction layer over the powerful IGListKit.
Features | |
---|---|
Declaratively define lists and menu | |
🙏🏻 | The code reflects the UI |
Less code and less files to manage | |
No performance impact | |
Efficient cell updates thanks to ListDiffable by IGListKit
|
The idea of MenuListKit is to provide a declarative way to create menus in iOS without writing boilerplate code. With MenuListKit you will spend less time thinking about how to load different cells, update them without a performance impact. Now you can focus on the artchitecture and business logic of your app 👍🏻.
In the example below there's a classic and simple ToDo List app; as you can see the array of models reflects the cells in the UICollectionView
. This will make you code more explicit and readable.
MenuItem
The first thing to do is to create a UICollectionViewCell
with a custom UI. You can both create a cell programmatically or load it from a xib.
class ToDoCell: UICollectionViewCell {
@IBOutlet private weak var statusLabel: UILabel!
@IBOutlet private weak var textLabel: UILabel!
var text: String? {
get { return textLabel.text }
set { textLabel.text = newValue }
}
var isCompleted: Bool = false {
didSet {
statusLabel.text = isCompleted ? "✅" : "⏺"
}
}
override func awakeFromNib() {
super.awakeFromNib()
isCompleted = false
}
}
In MenuListKit every cell is represented by a MenuItem
object. The MenuItem
class is a "model representation" of your cell. It contains all the information to configure the UICollectionViewCell
view.
Create your item class that inheritance from MenuItem
and implement ListDiffable
(from IGListKit).
Remember to write
import IGListKit
at the top
import MenuListKit
import IGListKit
class ToDoItem: MenuItem<ToDoCell>, ListDiffable {
let uuid = UUID().uuidString
var text: String
var isCompleted: Bool
init(text: String, isCompleted: Bool) {
self.text = text
self.isCompleted = isCompleted
super.init(bundle: Bundle.main,
height: 55,
actionDelegate: nil)
}
override func bind(to cell: ToDoCell) {
cell.text = text
cell.isCompleted = isCompleted
}
// MARK: - ListDiffable
func diffIdentifier() -> NSObjectProtocol {
return uuid as NSObjectProtocol
}
func isEqual(toDiffableObject object: ListDiffable?) -> Bool {
if let object = object as? ToDoItem {
return object.text == text && object.isCompleted == isCompleted
}
return false
}
}
MenuAdapterItem
and data sourceTo load the array of model into a UICollectionView
, we've reused the idea of IGListKit and we've created the MenuListAdapter
.
To all get the work done, implement the data source protocol MenuListAdapterDataSource
to provide the array of models to the collectionView. The adapter will manage all insertions, deletions and updates base on the array.
You can also provide a UIView
to present when there's no data to show.
import MenuListKit
import IGListKit
class ToDoViewController: UIViewController {
let collectionView = UICollectionView(frame: .zero,
collectionViewLayout: UICollectionViewFlowLayout())
lazy var adapter: MenuListAdapter = {
return MenuListAdapter(viewController: self)
}()
let todos = [
ToDoItem(text: "Clean up my room", isCompleted: false),
ToDoItem(text: "Buy 3 apples", isCompleted: true),
ToDoItem(text: "Plan my next trip", isCompleted: true),
ToDoItem(text: "Book a hotel room in Rome", isCompleted: false)
]
override func viewDidLoad() {
super.viewDidLoad()
collectionView.backgroundColor = .white
view.addSubview(collectionView)
adapter.collectionView = collectionView
adapter.dataSource = self
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionView.frame = view.bounds
}
}
// MARK: - MenuListAdapterDataSource
extension ToDoViewController: MenuListAdapterDataSource {
func objects(for menuListAdapter: MenuListAdapter) -> [ListDiffable & BaseMenuItem] {
return todos
}
func emptyView(for menuListAdapter: MenuListAdapter) -> UIView? {
return nil
}
}
We're 3 friends who love to work on open source projects
Get in touch with us saying hi 👋🏻 at [email protected]. We're also on Medium
Feel free to collaborate with ideas, issues and/or pull requests.
P.S. If you use MenuListKit in your app we would love to hear about it!
MenuListKit is available under the Apache 2.0 license. See the LICENSE file for more info.