Artisan is an MVVM framework for Swift using the bonding features from Pharos and constraints builder from Draftsman.

Overview

Artisan

Artisan is an MVVM framework for Swift using the bonding features from Pharos, constraints builder from Draftsman and builder pattern from Builder.

codebeat badge build test SwiftPM Compatible Version License Platform

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Requirements

  • Swift 5.3 or higher (Swift 5.1 for version 3.1.1 or lower)
  • iOS 10.0 or higher
  • XCode 12.5 or higher (XCode 11 for version 3.1.1 or lower)

Installation

Cocoapods

Artisan is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'Artisan', '~> 4.0.2'
pod 'Draftsman', '~> 2.0.2'
pod 'Pharos', '~> 1.2.3'
pod 'Builder', '~> 1.0.1'

or for Swift 5.1 and XCode 11

pod 'Artisan', '~> 3.1.1'
pod 'Draftsman', '~> 1.1.1'
pod 'Pharos', '~> 1.2.2'

Swift Package Manager from XCode

  • Set rules at version, with Up to Next Major option and put 4.0.2 or 3.1.1 for Swift 5.1 and XCode 11 as its version
  • Add it using XCode menu File > Swift Package > Add Package Dependency
  • Add https://github.com/hainayanda/Artisan.git as Swift Package URL
  • Click next and wait

Swift Package Manager from Package.swift

Add as your target dependency in Package.swift

dependencies: [
    .package(url: "https://github.com/hainayanda/Artisan.git", .upToNextMajor(from: "4.0.2"))
]

or for Swift 5.1 and XCode 11

dependencies: [
    .package(url: "https://github.com/hainayanda/Draftsman.git", .upToNextMajor(from: "3.1.1"))
]

Use it in your target as Artisan

 .target(
    name: "MyModule",
    dependencies: ["Artisan"]
)

Author

Nayanda Haberty, [email protected]

License

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

Usage

Read wiki for more detailed information.

Basic Usage

Creating an MVVM Pattern using Artisan is easy. All you need to do is extend ViewMediator, TableCellMediator or CollectionCellMediator and implement bonding method. For example, If you want to create a custom UITableViewCell:

import Artisan
import UIKit
import Draftsman
import Pharos
import Builder

class MyCell: TableFragmentCell {
    lazy var title = builder(UILabel.self)
        .font(.boldSystemFont(ofSize: 16))
        .numberOfLines(1)
        .textAlignment(.left)
        .textColor(.secondary)
        .build()
    lazy var subTitle = builder(UILabel.self)
        .font(.systemFont(ofSize: 12))
        .numberOfLines(1)
        .textAlignment(.left)
        .textColor(.main)
        .build()
        
    // MARK: Dimensions
    var margin: UIEdgeInsets = .init(insets: 16)
    var spacing: CGFloat = 6
    
    @LayoutPlan
    var viewPlan: ViewPlan {
        title.plan
            .at(.fullTop, .equalTo(margin), to: .parent)
        subTitle.plan
            .at(.bottomOf(title), .equalTo(spacing))
            .at(.fullBottom, .equalTo(margin), to: .parent)
    }
}

class MyCellVM: TableCellMediator<MyCell> {
    @Observable var model: MyModel
    
    init(model: MyModel) {
        self.model = model
    }

    override func bonding(with view: MyCell) {
        $event.map { $0.title }.relayValue(to: view.title.relays.text))
        $event.map { $0.description }.relayValue(to: view.subTitle.relays.text))
    }
}

then add it to UITableView

import Artisan
import UIKit
import Draftsman
import Pharos

class MyViewController: UIViewController {
    var tableView: UITableView!
    var searchBar: UISearchBar!
  
    @Observable var searchPhrase: String?
    @Observable var models: [MyModel] = []

    override viewDidLoad() {
        super.viewDidLoad()
        $searchPhrase.bonding(with: searchBar.bondableRelays.text)
            .multipleSetDelayed(by: 1)
            .whenDidSet(invoke: self, method: MyViewController.getData(from:))
        $models.compactMap { model -> AnyTableCellMediator in
              MyCellVM(model: model) 
          }.observe(on: .main)
          .relayValue(to: tableView.relays.cells)
    }

    func getData(from changes: Changes<String?>) {
        doGetDataFromAPI(for: changes.new) { [weak self] data in
            self?.models = data
        }
    }
}

It will automatically run getData when the user type in searchBar, with a minimum interval between method calls, is 1 second and will update table cells with new data on Main Thread every time you get data from API

You can clone and check the Example folder or for more wiki, go to here

Contribute

You know how, just clone and do pull request

You might also like...
A wrapper for NavigationView and NavigationLink that makes programmatic navigation a little friendlier.

NavigatorKit A wrapper for NavigationView and NavigationLink that makes programmatic navigation a little friendlier. NavigatorKit is an opinionated wr

Create an iOS app with two views, MainViewController and DetailViewController
Create an iOS app with two views, MainViewController and DetailViewController

iOS Take Home Create an iOS app with two views, MainViewController and DetailViewController. The MainViewController contains a list of GIFs from the G

Tools for making SwiftUI navigation simpler, more ergonomic and more precise.
Tools for making SwiftUI navigation simpler, more ergonomic and more precise.

SwiftUI Navigation Tools for making SwiftUI navigation simpler, more ergonomic and more precise. Motivation Tools Navigation overloads Navigation view

A drop-in universal library helps you to manage the navigation bar styles and makes transition animations smooth between different navigation bar styles
A drop-in universal library helps you to manage the navigation bar styles and makes transition animations smooth between different navigation bar styles

A drop-in universal library helps you to manage the navigation bar styles and makes transition animations smooth between different navigation bar styles while pushing or popping a view controller for all orientations. And you don't need to write any line of code for it, it all happens automatically.

Simple and integrated way to customize navigation bar experience on iOS app.

NavKit Simple and integrated way to customize navigation bar experience on iOS app. It should save our time that we usually use to make abstraction of

BulbapediaIOS - The home for Kiwix apps on iOS and macOS

Kiwix for iOS & macOS This is the home for Kiwix apps on iOS and macOS. Mobile a

NP-Open-House-Setup - Automated setup utility and instructions for Friction booth at NP Open House 2022

Friction Setup Setup Instructions Friction setup Start up the iMac Give it a cou

SwiftUINavigator: a lightweight, flexible, and super easy library which makes SwiftUI navigation a trivial task
SwiftUINavigator: a lightweight, flexible, and super easy library which makes SwiftUI navigation a trivial task

The logo is contributed with ❤️ by Mahmoud Hussein SwiftUINavigator is a lightwe

iOS UI library to show and hide an extension to your UINavigationBar
iOS UI library to show and hide an extension to your UINavigationBar

ADNavigationBarExtension is a UI library written in Swift. It allows you to show and hide an extension to your UINavigationBar Features Use Extensible

Comments
  • Binding Improvement

    Binding Improvement

    • Since some projects will have different Quick and Nimble versions, which shouldn't include in the distribution, it is now removed from dependency in the Swift Package Manager version.
    • Separate binding retaining with a regular one
    • Add bind to plan to simplified binding to applyPlan
    • Add auto binding to simplified binding
    • Removed and modified some UIControl action because its already provided by Pharos
    opened by hainayanda 0
  • Release/1.2.5

    Release/1.2.5

    • Add more builder method for cell builder
    • Add missing discardableResult on InsertablePlan extensions
    • add createViewAndApply method for BondableMediator
    • refactor ViewMediator
    opened by hainayanda 0
  • Major Refactoring

    Major Refactoring

    • StatedMediator now renamed to AnyMediator
    • CollectionCellMediator now renamed to AnyCollectionCellMediator
    • TableCellMediator now renamed to AnyTableCellMediator
    • CollectionViewCellMediator now renamed to CollectionCellMediator
    • TableViewCellMediator now renamed to TableCellMediator
    • GenericCollectionCellMediator now renamed to CollectionCellApplicator
    • GenericTableCellMediator now renamed to TableCellApplicator
    • DiffReloader now will not crash the app if the identifier is duplicated
    • TableView and CollectionView now have build cells method
    opened by hainayanda 0
Releases(5.1.0)
Owner
Nayanda Haberty
Programmer. What else?
Nayanda Haberty
sRouting - The lightweight navigation framework for SwiftUI.

sRouting The lightweight navigation framework for SwiftUI. Overview sRouting using the native navigation mechanism in SwiftUI. It's easy to handle nav

Shiro 8 Aug 15, 2022
Simple example for the coordinator design pattern and using th Xcoordinator pod

Cordinator-Pattern-Sample This an Example and base for the coordinator design pattern using the XCoordinator pod ?? XCoordinator is a navigation frame

Ali Fayed 3 Sep 13, 2022
Models UI navigation patterns using TCA

Composable Navigation The Composable Navigation is a Swift Package that builds on top of The Composable Architecture (TCA, for short). It models UI na

Michael Heinzl 41 Dec 14, 2022
An iOS view-controller navigation management. No inherit, using one line code to integrate.

KGNavigationBar Example An iOS view-controller navigation management. No inherit, using one line code to integrate. 一个 iOS 控制器导航管理库. 无需继承, 一行代码即可实现集成。

VanJay 5 Sep 6, 2021
Easily hide and show a view controller's navigation bar (and tab bar) as a user scrolls

HidingNavigationBar An easy to use library (written in Swift) that manages hiding and showing a navigation bar as a user scrolls. Features Usage Custo

Tristan Himmelman 1k Dec 21, 2022
A view that shows selectable symbols, similar to UITableView's `sectionIndexTitles` API but with support for symbols and more flexibility

?? TableOfContentsSelector Are you familiar with UITableView's sectionIndexTitles API? The little alphabet on the side of some tables for quickly jump

Christian Selig 106 Dec 19, 2022
FlowStacks allows you to hoist SwiftUI navigation and presentation state into a Coordinator

FlowStacks allow you to manage complex SwiftUI navigation and presentation flows with a single piece of state. This makes it easy to hoist that state into a high-level coordinator view. Using this pattern, you can write isolated views that have zero knowledge of their context within the navigation flow of an app.

John Patrick Morgan 471 Jan 3, 2023
An open source library for building deep-linkable SwiftUI applications with composition, testing and ergonomics in mind

Composable Navigator An open source library for building deep-linkable SwiftUI applications with composition, testing and ergonomics in mind Vanilla S

Bahn-X 539 Jan 8, 2023
Coordinators in SwiftUI. Simple, powerful and elegant.

Simple, powerful and elegant implementation of the Coordinator pattern in SwiftUI. Stinsen is written using 100% SwiftUI which makes it work seamlessl

Narek Mailian 618 Jan 7, 2023
An alternative SwiftUI NavigationView implementing classic stack-based navigation giving also some more control on animations and programmatic navigation.

swiftui-navigation-stack An alternative SwiftUI NavigationView implementing classic stack-based navigation giving also some more control on animations

Matteo 753 Jan 2, 2023