Skip to content

Commit

Permalink
Moved delegates to data source object. Updated providers models and n…
Browse files Browse the repository at this point in the history
…aming.
  • Loading branch information
ivanvorobei committed Jan 3, 2022
1 parent 15827b7 commit 5135a00
Show file tree
Hide file tree
Showing 18 changed files with 317 additions and 204 deletions.
196 changes: 73 additions & 123 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,15 @@ Apple's diffable API requerid models for each object type. If you want use it in
- [Swift Package Manager](#swift-package-manager)
- [CocoaPods](#cocoapods)
- [Manually](#manually)
- [Ready Use](#ready-use)
- [Example](#ready-use)
- [Available Classes](#available-classes)
- [Usage](#usage)
- [How it work](#usage)
- [Set Content](#set-content)
- [Get Content](#get-content)
- [Mediator](#mediator)
- [Diffable Delegate](#diffable-delegate)
- [Sidebar](#sidebar)
- [Ready Use](#ready-use)
- [Example](#ready-use)
- [List classes](#ready-use-classes)
- [Wrapper](#wrapper)
- [Sidebar](#sidebar)
- [Russian Community](#russian-community)

## Installation
Expand Down Expand Up @@ -55,6 +53,72 @@ pod 'SPDiffable'

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`:

```swift
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`.

```swift
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](https://github.com/ivanvorobei/SPDiffable#ready-use) with minimum of code for start.
Expand Down Expand Up @@ -148,7 +212,6 @@ diffableDataSource.reload(content)

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

```

Changes apply without animation and like deep reload.
Expand All @@ -165,51 +228,12 @@ func section(for index: Int) -> SPDiffableSection? {}
func cell<T: UITableViewCell>(_ type: T.Type, for itemID: SPDiffableItem.Identifier) -> T? {}
```

### Mediator

Some methods in diffable data source can't ovveride without custom data source. It solved with mediator delegate. It simple. Next example for table. Set delegate `SPTableDiffableMediator`, all method optional:

```swift
class DiffableTableController: SPDiffableTableController, SPTableDiffableMediator {

override func viewDidLoad() {
super.viewDidLoad()
setCellProviders([cellProvider], sections: content)
diffableDataSource?.mediator = self
}
}
```

Now you can implemented requerid methods, for example title of header:
### Wrapper

```swift
func diffableTableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Overridden in of diffable mediator"
}
```

In protocol you can find more methods, like `canEdit` and other.

### Diffable Delegate

For handle some useful extensions, you can use delegates `SPDiffableTableDelegate`, `SPDiffableCollectionDelegate`. For example, when you need get which model did select, use this:
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.

```swift
class DiffableTableController: SPDiffableTableController, SPDiffableTableDelegate {

override func viewDidLoad() {
super.viewDidLoad()

// Hidded code for cell providers and content

setCellProviders([cellProvider], sections: content)
diffableDelegate = self
}

func diffableTableView(_ tableView: UITableView, didSelectItem item: SPDiffableItem) {
// Here you get model, which did select.
}
}
let item = SPDiffableWrapperItem(id: "uniq-identifier", model: LocationRowModel(city: "Minsk"))
```

### Sidebar
Expand Down Expand Up @@ -245,80 +269,6 @@ SPDiffableSection(
)
```

## Ready Use

You can save time and count lines of code using ready-use classes. In project available models and views. For example you need simple table with native cells. You need create content with `SPDiffableTableRow`:

```swift
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.defaultCellProvider`.

```swift
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.

## Ready-use 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.

## 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.

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

## Russian Community

Я веду [телеграм-канал](https://sparrowcode.by/telegram), там публикую новости и туториалы.<br>
Expand Down
2 changes: 1 addition & 1 deletion SPDiffable.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = 'SPDiffable'
s.version = '2.2.0'
s.version = '3.0.0'
s.summary = 'Extension of Diffable API which allow not duplicate code and use less models. Included example for SideBar.'
s.homepage = 'https://github.com/ivanvorobei/SPDiffable'
s.source = { :git => 'https://github.com/ivanvorobei/SPDiffable.git', :tag => s.version }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ extension SPDiffableCollectionDataSource {

/**
SPDiffable: Update layout.

- parameter animating: Shoud update layout with animation or not.
- parameter completion: A closure to execute when the updating complete.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// The MIT License (MIT)
// Copyright © 2020 Ivan Vorobei ([email protected])
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// 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 THE
// AUTHORS OR COPYRIGHT HOLDERS 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 UIKit

@available(iOS 13.0, *)
extension SPDiffableCollectionDataSource: UICollectionViewDelegate {

// Process actions after tap.
open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let item = item(for: indexPath) else { return }
diffableDelegate?.diffableCollectionView?(collectionView, didSelectItem: item, indexPath: indexPath)
switch item {
case let model as SPDiffableActionableItem:
model.action?(model, indexPath)
default:
break
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,22 @@ open class SPDiffableCollectionDataSource: UICollectionViewDiffableDataSource<SP
*/
public let headerAsFirstCell: Bool

/**
SPDiffable: Mirror of `UICollectionViewDelegate`.
*/
open weak var diffableDelegate: SPDiffableCollectionDelegate?

// Using for get cells or update its.
internal weak var collectionView: UICollectionView?

// MARK: - Init

public init(collectionView: UICollectionView, cellProviders: [SPDiffableCollectionCellProvider], supplementaryViewProviders: [SupplementaryViewProvider] = [], headerAsFirstCell: Bool = true) {

public init(
collectionView: UICollectionView,
cellProviders: [SPDiffableCollectionCellProvider],
headerFooterProviders: [SPDiffableCollectionHeaderFooterProvider] = [],
headerAsFirstCell: Bool = true
) {
self.headerAsFirstCell = headerAsFirstCell
self.collectionView = collectionView

Expand All @@ -55,22 +64,18 @@ open class SPDiffableCollectionDataSource: UICollectionViewDiffableDataSource<SP
}
return nil
}
if !supplementaryViewProviders.isEmpty {

if !headerFooterProviders.isEmpty {
supplementaryViewProvider = { (collectionView, kind, indexPath) -> UICollectionReusableView? in
for provider in supplementaryViewProviders {
if let view = provider(collectionView, kind, indexPath) {
for provider in headerFooterProviders {
if let view = provider.clouser(collectionView, kind, indexPath) {
return view
}
}
return nil
}
}

collectionView.delegate = self
}
}

/**
SPDiffable: Wrapper of collection supplementary view provider.
*/
@available(iOS 13.0, *)
public typealias SPDiffableCollectionSupplementaryViewProvider = SPDiffableCollectionDataSource.SupplementaryViewProvider
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import UIKit

/**
SPDiffable: Protocol with collection events.
SPDiffable: Protocol for mirrir `UICollectionViewDelegate`.
*/
@available(iOS 13.0, *)
@objc public protocol SPDiffableCollectionDelegate: AnyObject {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,8 @@

import UIKit

import UIKit

/**
SPDiffable: Wrapper of collection cell provider.
SPDiffable: Cell Provider.
*/
@available(iOS 13.0, *)
open class SPDiffableCollectionCellProvider {
Expand Down
Loading

0 comments on commit 5135a00

Please sign in to comment.