Extension of Diffable API which allow not duplicate code and use less models. Included example for SideBar.

Overview

SPDiffable

Apple's diffable API requerid models for each object type. If you want use it in many place, you pass many time to implemenet and get over duplicates codes. This project help you do it elegant with shared models and special cell providers for one-usage models.

Navigate

Installation

Ready for use on iOS 13+.

Swift Package Manager

The Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into the swift compiler. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.

Once you have your Swift package set up, adding as a dependency is as easy as adding it to the dependencies value of your Package.swift.

dependencies: [
    .package(url: "https://github.com/ivanvorobei/SPDiffable", .upToNextMajor(from: "2.2.0"))
]

CocoaPods:

CocoaPods is a dependency manager. For usage and installation instructions, visit their website. To integrate using CocoaPods, specify it in your Podfile:

pod 'SPDiffable'

Manually

If you prefer not to use any of dependency managers, you can integrate manually. Put Sources/SPDiffable folder in your Xcode project. Make sure to enable Copy items if needed and Create groups.

Ready Use

For example you need simple table with native cells. You need create content with SPDiffableTableRow:

let section = SPDiffableSection(
    id: "example section",
    header: SPDiffableTextHeaderFooter(text: "Header"),
    footer: SPDiffableTextHeaderFooter(text: "Footer"),
    items: [
        SPDiffableTableRow(text: "First Cell", accessoryType: .disclosureIndicator, selectionStyle: .default, action: { [weak self] indexPath in
            guard let self = self else { return }
            self.tableView.deselectRow(at: indexPath, animated: true)
        }),
        SPDiffableTableRow(text: "Second Cell", accessoryType: .disclosureIndicator, selectionStyle: .default, action: { [weak self] indexPath in
            guard let self = self else { return }
            self.tableView.deselectRow(at: indexPath, animated: true)
        }),
    ]
)

You init cell model and pass action, choose selection style and other. As you see, model describe native table cell. Next, you need set cell provider, but it also already available, for get it call SPDiffableTableController.default.

setCellProviders(SPDiffableTableCellProvider.default, sections: [section])

Now project's models automatically converting to cell. No need any additional work. That all code. If you use custom table view or table controller, don't forget register cells classes. For SPDiffableTableController all cells already registered.

Available Classes

It list models which you can use now, it shoud close your task without code. Of couse you can create your models. Now in project you can find this ready-use models:

  • SPDiffableItem it basic class. All item models shoud be extend from it model. Header and footer also.
  • SPDiffableSection section class. Included footer and header properties, also items (cells).
  • SPDiffableTextHeaderFooter header or footer class with text.

For Table:

Here provided models:

  • SPDiffableTableRow it native item for table cell. Support all basic styles and action for tap event.
  • SPDiffableTableRowSubtitle it native item for table cell with subtitle. Support all as before.
  • SPDiffableTableRowButton item for table in style as button. Support table styles and action for tap.
  • SPDiffableTableRowStepper item for table cell with stepper. Has maximum value and minimum, also incuded action with passed value.
  • SPDiffableTableRowSwitch item for table with switch, included default state and action for change event.

Here provided cells:

  • SPDiffableTableViewCell basic table cell with detail text right side.
  • SPDiffableSubtitleTableViewCell basic table cell with two lines of texts.
  • SPDiffableStepper cell with stepper control. Using with SPDiffableTableRowStepper model.
  • SPDiffableSwitch cell with switch. Using with SPDiffableTableRowSwitch model.
  • SPDiffableSlider cell with slider.

For Collection:

Provided only models, becouse for most items using list registration and no need specific cell class.

  • SPDiffableSideBarItem menu item in side bar. Support accessories and actions.
  • SPDiffableSideBarButton button item in side bar. Color of title similar to tint.
  • SPDiffableSideBarHeader header model for side bar item.

Usage

Before read it, highly recomded check Example target in project. It examle show all features, like use stepper and switch, like process actions, create custom models and many other. Also you can skip full undestand logic and read Ready-use section with minimum of code for start.

For work with diffable need create model (inside project you found some ready-use models) and do cell provider, which convert data-model to UITableViewCell or UICollectionViewCell. Next example for table, but all methods and class names available for collections.

New model shoud extend from basic class SPDiffableItem:

class LocationRowModel: SPDiffableItem {

    // Add properties, which you need
    public var city: String
    public var adress: String?
}

Last step, create table controller class and extend of SPDiffableTableController. Create custom cell provider, it doing convert it data to table cell:

class DiffableTableController: SPDiffableTableController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Register cell for usage it in table view
        tableView.register(LocationTableCell.self, forCellReuseIdentifier: "LocationTableCell")
        
        // Cell provider for `LocationRowModel`
        let locationCellProvider = SPDiffableTableCellProvider() { (tableView, indexPath, model) -> UITableViewCell? in
            switch model {
            case let model as TableRowModel:
                let cell = tableView.dequeueReusableCell(withIdentifier: "LocationTableCell", for: indexPath) as! LocationTableCell
                cell.textLabel?.text = model.city
                cell.detailTextLabel?.text = model.adress
                return cell
            default:
                return nil
            }
        }
        
        // Pass cell provider and content. 
        // About content you can read in next section.
        setCellProviders([locationCellProvider], sections: content)
    }
}

Now ready model and convert it to views. Time to add content.

Set Content

Now table support models and custom cell provider. You can apply diffable content with animation (or not). Create content:

var content: [SPDiffableSection] {
    let section = SPDiffableSection(
        id: "example section",
        header: SPDiffableTextHeaderFooter(text: "Header"),
        footer: SPDiffableTextHeaderFooter(text: "Footer"),
        items: [
            LocationRowModel(city: "Minsk", adress: "Frunze Pr., bld. 47, appt. 7"),
            LocationRowModel(city: "Shanghai", adress: "Ting Wei Gong Lu 9299long 168hao"),
            LocationRowModel(city: "London", adress: "94  Whitby Road")
        ]
    )

    let content = [section]
    return content
}

You can add more items or sections. Last step - apply:

diffableDataSource?.apply(content, animating: true)

Call this when you need update content. When you call setCellProviders, it set content by default without animation. That all. You can each time create new order or count cells and it automatically show with diffable animation.

Reload Content

If you need something like old function .reloadData() in collection and table, look at this method:

// Reload fully content
diffableDataSource.reload(content)

// Reload only specific items
diffableDataSource.reload(items) // or for 1 item `reload(item)`

Changes apply without animation and like deep reload.

Get Content

You can get index path by item, item by id and many other funcs:

func item(for indexPath: IndexPath) -> SPDiffableItem? {}
func indexPath(for itemID: SPDiffableItem.Identifier) -> IndexPath? {}
func sections() -> [SPDiffableSection] {}
func section(for index: Int) -> SPDiffableSection? {}
func cell<T: UITableViewCell>(_ type: T.Type, for itemID: SPDiffableItem.Identifier) -> T? {}

Wrapper

In project you can find class SPDiffableWrapperItem. Using it, when you don't want create custom item model for you diffable struct. You can pass any your model and uwrap it later in cell provider.

let item = SPDiffableWrapperItem(id: "uniq-identifier", model: LocationRowModel(city: "Minsk"))

Sidebar

Create new controller and extend from SPDiffableSideBarController. Remember, it available only from iOS 14.

class SidebarController: SPDiffableSideBarController {}

In class available ready-use cell providers for menu item and header section. For get it shoud call:

override func viewDidLoad() {
    super.viewDidLoad()
    setCellProviders(SPDiffableCollectionCellProvider.sideBar, sections: content)
}

Content it array of SPDiffableSection. For menu model need use model SPDiffableSideBarItem or SPDiffableSideBarButton. For header and footer will create SPDiffableSideBarHeader model.

SPDiffableSection(
    id: Section.library.rawValue,
    header: SPDiffableSideBarHeader(text: "Library", accessories: [.outlineDisclosure()]),
    items: [
        SPDiffableSideBarItem(title: "Recently Added", image: UIImage(systemName: "clock"), action: { _ in }),
        SPDiffableSideBarItem(title: "Artists", image: UIImage(systemName: "music.mic"), action: { _ in }),
        SPDiffableSideBarItem(title: "Albums", image: UIImage(systemName: "rectangle.stack"), action: { _ in }),
        SPDiffableSideBarItem(title: "Songs", image: UIImage(systemName: "music.note"), action: { _ in }),
        SPDiffableSideBarButton(title: "Add New", image: UIImage(systemName: "plus.square.fill"), action: { _ in })
    ]
)

Russian Community

Я веду телеграм-канал, там публикую новости и туториалы.
С проблемой помогут в чате.

Видео-туториалы выклыдываю на YouTube:

Tutorials on YouTube

You might also like...
Swift-sidebar-menu-example - Create amazing sidebar menu with animation using swift
Swift-sidebar-menu-example - Create amazing sidebar menu with animation using swift

 SWIFT SIDEBAR MENU EXAMPLE In this project I create a awesome side bar menu fo

Duplicate Tab is a Safari Extension for iOS and iPadOS that makes duplicating tabs much easier!

Duplicate Tab Duplicate Tab is a Safari Extension for iOS and iPadOS that makes duplicating tabs much easier! Check it out on the App Store Privacy Po

A replacement for as which runs in constant time instead of O(n) when the conformance is not satisfiedA replacement for as which runs in constant time instead of O(n) when the conformance is not satisfied

ZConform A replacement for as? which runs in constant time instead of O(n) when the conformance is not satisfied. How it works ZConform does a one-tim

Advanced Catalyst Example with sidebar, list view, SwiftUI detail view, toolbar & AppKit bundle
Advanced Catalyst Example with sidebar, list view, SwiftUI detail view, toolbar & AppKit bundle

Advanced Catalyst Example This is an example of a Catalyst app using a three-column layout, with a primary toolbar. It includes topics such as: Drag &

Much a-do with compositional layouts and diffable data sources.

Film Goal Reflect upon decisions made on my last project Films (submitted in July of 2019) and make improvements on my findings. Be more pragmatic wit

This project has been developed to understand GraphQL and Diffable Data Source. Created on 20.06.2022.

SpaceX Launches First in first. You need to build all packages before building the project. Packages: Extensions API Open Extensions folder under proj

Demonstrating the use of a Sidebar, SplitView and Navigation styles in a multiplatform app.
Demonstrating the use of a Sidebar, SplitView and Navigation styles in a multiplatform app.

Demonstrate the use of a Sidebar, SplitView, TabView and Navigation styles in a multiplatform app.

Ready use service for Firebase. Included interface, recored devices and notifications.
Ready use service for Firebase. Included interface, recored devices and notifications.

SPProfiling Ready use service with using Firebase. Included interface, manage auth process, recored devices and profile data. Installation Ready for u

Not Suitable for Work (NSFW) classification using deep neural network Caffe models.

Open nsfw model This repo contains code for running Not Suitable for Work (NSFW) classification deep neural network Caffe models. Please refer our blo

Powerful autolayout framework, that can manage UIView(NSView), CALayer and not rendered views. Not Apple Autolayout wrapper. Provides placeholders. Linux support.
Powerful autolayout framework, that can manage UIView(NSView), CALayer and not rendered views. Not Apple Autolayout wrapper. Provides placeholders. Linux support.

CGLayout Powerful autolayout framework, that can manage UIView(NSView), CALayer and not rendered views. Has cross-hierarchy coordinate space. Implemen

Animate easy and with less code with Swift
Animate easy and with less code with Swift

JDAnimationKit is designed to be extremely easy to use. You can animate your UI withe less lines of code. This library use internally POP framework, a

Simple and Elegant Range(A,B) to Range(P,Q) mapper in less then five lines of code.
Simple and Elegant Range(A,B) to Range(P,Q) mapper in less then five lines of code.

HSRange Description HSRangeConvertor Simple and Elegant Range[A,B] to Range[P,Q] mapper in less then three lines of code. E.g. Suppose we have Range[1

Async GIF image decoder and Image viewer supporting play GIF images. It just use very less memory.
Async GIF image decoder and Image viewer supporting play GIF images. It just use very less memory.

YLGIFImage Asynchronized GIF image class and Image viewer supporting play/stop GIF images. It just use very less memory. Following GIF usually will co

Write less UI code
Write less UI code

Layoutless Layoutless enables you to spend less time writing UI code. It provides a way to declaratively style and layout views. Here is an example of

Simple side/slide menu control for iOS, no code necessary! Lots of customization. Add it to your project in 5 minutes or less.
Simple side/slide menu control for iOS, no code necessary! Lots of customization. Add it to your project in 5 minutes or less.

▤ SideMenu If you like SideMenu, give it a ★ at the top right of this page. SideMenu needs your help! If you're a skilled iOS developer and want to he

This project explores the capabilities of the new iOS 16+ Passkeys API to support password-less authentications.

iOS 16+ Passkeys Swift Sample This project explores the capabilities of the new iOS 16+ Passkeys API to support password-less authentications. ⚠️ This

Demonstrates hosting SwiftUI in a UISplitViewController to gain the sidebar style in Mac Catalyst
Demonstrates hosting SwiftUI in a UISplitViewController to gain the sidebar style in Mac Catalyst

Really trivial example showing how to wrap SwiftUI in a UISplitViewController, so that you can use the correct sidebar background style when building for macOS.

Alchemy, an elegant, batteries included backend framework for Swift.
Alchemy, an elegant, batteries included backend framework for Swift.

Elegant, batteries included web framework for Swift.

A subclass of UITabBarController that translates UITabBarItems 1:1 into a Sidebar on iPadOS.
A subclass of UITabBarController that translates UITabBarItems 1:1 into a Sidebar on iPadOS.

FredKitTabBarSplitView A subclass of UITabBarController that translates UITabBarItems 1:1 into a Sidebar on iPadOS. Simply use FredKitTabBarSplitView

Comments
  • Support iOS 11 and iOS 12

    Support iOS 11 and iOS 12

    Support iOS 11 and iOS 12 Improved library to support older versions, we agree with you that the icons are from iOS 13 but we can provide our icons to us the main thing is your ViewController and your cells

    enhancement 
    opened by devzhr 3
  • Question: Does it also work with Core Data?

    Question: Does it also work with Core Data?

    Hi, thank you very much for this library, very useful. Does DiffableKit also works with Core Data and the NSFetchedResultsController? How can i use it with DiffableKit? Could you provide a simple example, so i can understand better how can i implement it?

    Thanks

    question 
    opened by niklasgrewe 0
Releases(4.2.0)
Owner
Ivan Vorobei
iOS Developer
Ivan Vorobei
Examples of commonly used data structures and algorithms in Swift.

Swift Structures This project provides a framework for commonly used data structures and algorithms written in a new iOS development language called S

Wayne Bishop 2.1k Dec 28, 2022
:droplet: A generic view model for both basic and complex scenarios

Brick Description Brick is a generic view model for both basic and complex scenarios. Mapping a basic table view cells is as easy as pie, if you have

HyperRedink 59 Jul 31, 2021
Swift μ-framework for efficient array diffs and datasource adapters.

Buffer Swift μ-framework for efficient array diffs, collection observation and data source implementation. C++11 port here Installation cd {PROJECT_RO

Alex Usbergo 348 Aug 2, 2022
Algorithms and data structures in Swift, with explanations!

Welcome to the Swift Algorithm Club! Here you'll find implementations of popular algorithms and data structures in everyone's favorite new language Sw

raywenderlich 27.3k Jan 8, 2023
Swift library to generate differences and patches between collections.

Differ Differ generates the differences between Collection instances (this includes Strings!). It uses a fast algorithm (O((N+M)*D)) to do this. Featu

Tony Arnold 628 Dec 29, 2022
A Swift probability and statistics library

Probably Probably is a set of Swift structures for computing the probability and cumulative distributions of different probablistic functions. Right n

Harlan Haskins 270 Dec 2, 2022
KeyPathKit is a library that provides the standard functions to manipulate data along with a call-syntax that relies on typed keypaths to make the call sites as short and clean as possible.

KeyPathKit Context Swift 4 has introduced a new type called KeyPath, with allows to access the properties of an object with a very nice syntax. For in

Vincent Pradeilles 406 Dec 25, 2022
Differific - a fast and convenient diffing framework.

Differific Description Differific is a diffing tool that helps you compare Hashable objects using the Paul Heckel's diffing algorithm. Creating a chan

Christoffer Winterkvist 127 Jun 3, 2022
💻 A fast and flexible O(n) difference algorithm framework for Swift collection.

A fast and flexible O(n) difference algorithm framework for Swift collection. The algorithm is optimized based on the Paul Heckel's algorithm. Made wi

Ryo Aoyama 3.3k Jan 4, 2023
Swivl - A set of BLAS-accelerated linerar algebra structures and functions

Swivl - Swift Vector Library A set of BLAS-accelerated linerar algebra structure

null 0 Jan 19, 2022