Latest 1.0.0
Homepage https://github.com/muccy/Monviso
License MIT
Platforms ios 8.0
Dependencies Ferrara
Authors

CI Status
Version
License
Platform
Xcode 8.2+
iOS 8.0+
Swift 3.0+

Monviso is a framework which gives data source structure for UITableView, UICollectionView and UIPageViewController.
You create a data source, you customize it with closures, you insert contents in provided structures and you set data source of your client object: that’s it!
What is more, this framework provides an automated system to apply content updates to UITableView and UICollectionView animating transitions.

How

Sectioned views: using with UITableView and UICollectionView

In this example I will use UITableView, but UICollectionView is very similar.

Say you have a UITableViewController subclass.

class TableViewController: UITableViewController {
}

Start creating a data source.

import Monviso

class TableViewController: UITableViewController {
    private let dataSource = TableViewDataSource()

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.dataSource = dataSource
    }
}

You need to provide content to you user.

import Monviso

struct Flower {
    let name: String
}

class TableViewController: UITableViewController {
    private let flowers = [ Flower(name: "Tulip"), Flower(name: "Rose") ]
    private let dataSource: TableViewDataSource()

    override func viewDidLoad() {
        super.viewDidLoad()

        dataSource.content.sections = [ TableViewDataSource.Section(identifier: "flowers", items: flowers, header: "Flowers") ]
        tableView.dataSource = dataSource
    }
}

You data source needs to know how to display content.

import Monviso

struct Flower {
    let name: String
}

class TableViewController: UITableViewController {
    private let flowers = [ Flower(name: "Tulip"), Flower(name: "Rose") ]
    private let dataSource: TableViewDataSource {
        let dataSource = TableViewDataSource()

        dataSource.cellFactory.creator = { item, indexPath, tableView in
            if let flower = item as? Flower {
                let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
                cell.textLabel!.text = flower.name
                return cell
            }
            else {
                throw AccessError.noUI(for: item)
            }
        }

        return dataSource
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        dataSource.content.sections = [ TableViewDataSource.Section(identifier: "flowers", items: flowers, header: "Flowers") ]
        tableView.dataSource = dataSource
    }
}

That’s all. This is the minimal setup to display static contents.
If you would like to update contents with animation, you should change a couple of things. First of all, you have to make your contents able to detect updates using embedded Ferrara.

import Monviso
import Ferrara

struct Flower: Identifiable, Matchable, Equatable {
    let identifier: String
    let name: String

    public static func ==(lhs: Flower, rhs: Flower) -> Bool {
        return lhs.identifier == rhs.identifier && lhs.name == lhs.name
    }
}

Then, you should apply changes to your client.

var flowers = [ Flower(identifier: "tulip", name: "Tulip"), Flower(identifier: "rose", name: "Rose") ]

func updateToEmojiFlowers() {
    flowers = [ Flower(identifier: "tulip", name: "🌷"), Flower(identifier: "rose", name: "🌹") ]
    let update = dataSource.content.update(sections: [ TableViewDataSource.Section(identifier: "flowers", items: flowers, header: "Flowers") ])
    tableView.apply(update: update)
}

Nothing more than this.

UIPageViewController integration

Monviso can help you when you need to display a finite number of pages inside a UIPageViewController.

Start creating a data source.

import Monviso

class PageViewController: UIPageViewController {
    let dataSource = PageViewControllerDataSource()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.dataSource = pageDataSource
    }
}

You need to provide content to you user.

import Monviso

struct Flower {
    let name: String
}

class PageViewController: UIPageViewController {
    private let flowers = [ Flower(name: "Tulip"), Flower(name: "Rose") ]
    let dataSource = PageViewControllerDataSource()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.dataSource = pageDataSource
    }
}

You data source needs to know how to display content and how to associate view controllers to content index.

import Monviso

struct Flower: Equatable {
    let name: String

    public static func ==(lhs: Flower, rhs: Flower) -> Bool {
        return lhs.name == lhs.name
    }
}

class PageViewController: UIPageViewController {
    private let flowers = [ Flower(name: "Tulip"), Flower(name: "Rose") ]
    private let dataSource: PageViewControllerDataSource {
        let dataSource = PageViewControllerDataSource()

        dataSource.viewControllerFactory.creator = { item, index, _ in
            return FlowerViewController(flower: Flower)
        }

        dataSource.indexer = { viewController, content in
            if let viewController = viewController as? FlowerViewController,
                let index = (content as! [Flower]).index(of: viewController.flower)
            {
                return index
            }
            else {
                throw AccessError.invalidOutput(nil)
            }
        }

        return dataSource
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.dataSource = pageDataSource
    }
}

Now you need to inform you page view controller to display first page.

import Monviso

struct Flower: Equatable {
    let name: String

    public static func ==(lhs: Flower, rhs: Flower) -> Bool {
        return lhs.name == lhs.name
    }
}

class PageViewController: UIPageViewController {
    private let flowers = [ Flower(name: "Tulip"), Flower(name: "Rose") ]
    private let dataSource: PageViewControllerDataSource {
        let dataSource = PageViewControllerDataSource()

        dataSource.viewControllerFactory.creator = { item, index, _ in
            return FlowerViewController(flower: Flower)
        }

        dataSource.indexer = { viewController, content in
            if let viewController = viewController as? FlowerViewController,
                let index = (content as! [Flower]).index(of: viewController.flower)
            {
                return index
            }
            else {
                throw AccessError.invalidOutput(nil)
            }
        }

        return dataSource
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.dataSource = pageDataSource

        let update = try! pageDataSource.update(content: flowers, toShowPages: 0...0, in: self)
        apply(update: update, animated: false)
    }
}

That’s all.

Now, implementing page swap methods is trivial.

func goToNextPage(animated: Bool = true) throws {
    let indexes = try pageDataSource.indexesOfContent(displayedIn: self)
    let index = indexes.first! + 1
    let update = try! pageDataSource.update(toShowPages: index...index, in: self)
    apply(update: update, animated: animated)
}

func canGoToNextPage() -> Bool {
    if let indexes = try? pageDataSource.indexesOfContent(displayedIn: self), let lastIndex = indexes.last
    {
        return lastIndex < pageDataSource.content.count - 1
    }
    else {
        return false
    }
}

Requirements

  • iOS 8.2 SDK.
  • Minimum deployment target: iOS 8.

Installation

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

pod "Monviso"

Author

Marco Muccinelli, [email protected]

License

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

About the name

Monviso

Monte Viso or Monviso, is the highest mountain of the Cottian Alps. It is located in Italy close to the French border.On a very clear day it can be seen from the spires of the Milan Cathedral. On the northern slopes of Monte Viso are the headwaters of the Po, the longest Italian river. Po river source, data source… that’s why ;)

Latest podspec

{
    "name": "Monviso",
    "version": "1.0.0",
    "summary": "Data sources in protocol-oriented, type-safe, modular, swifty sauce",
    "description": "A framework which gives data source structure for UITableView, UICollectionView and UIPageViewController.nYou create a data source, you customize it with closures, you insert contents in provided structures and you set data source of your client object: that's it!nWhat is more, this framework provides an automated system to apply content updates to UITableView and UICollectionView animating transitions.",
    "homepage": "https://github.com/muccy/Monviso",
    "license": "MIT",
    "authors": {
        "Marco Muccinelli": "[email protected]"
    },
    "platforms": {
        "ios": "8.0"
    },
    "source": {
        "git": "https://github.com/muccy/Monviso.git",
        "tag": "1.0.0"
    },
    "source_files": [
        "Source",
        "Source/**/*.{swift,h,m}"
    ],
    "dependencies": {
        "Ferrara": [
            "~> 1.1"
        ]
    },
    "pushed_with_swift_version": "3.0"
}

Pin It on Pinterest

Share This