A very simple To Do app to illustrate the principles from my A Better MVC talk

Related tags

SwiftUI App MVCTodo
Overview

MVC Todo

For more background on this repository, please consider reading these blog posts:

What this sample shows

The point of this sample code is to illustrate the power and flexibility of using UIViewController containment and composition as a way to build app UIs.

What this sample does not show

Pretty much everything outside the concept of UIViewController containment is beyond the scope of this code. There are bugs and sharp corners with the rest of the app. As an app author, I'm not entirely thrilled with how the Coordinator layer works. However, that's not the point of the sample. Feel free to inspect the rest of the code for positive or negative inspiration. Please just understand that those bits are not meant to be representative, and are there only to support the primary goals of the sample.

The interesting bits

There are a few take-aways you should have from examining this code. In no particular order, they are...

  • Observe how there's pretty much nothing inside AppDelegate.swift. That's because the object exists to be (shocker) the delegate of the UIApplication. Its purpose, then, is to interpret the events and requests the UIApplication makes, and forward them on (as necessary) to the interested parties that it knows about.

  • Observe how all view controllers are programmatically instantiated. While this is not a requirement to do view controller composition, I personally find it to be much more expressive and useful than instantiating based on identifiers in storyboards.

  • There is roughly a one-to-one correspondence between a Coordinator and a "page" or "screen" of information seen in the app. With that in mind, observe how none of the coordinators use "custom" view controllers. By this I mean that all of them have, as their "primary" view controller, a UIViewController that is a reusable view controller (ie, a view controller that has not been custom-built for that screen of content)

  • Multiple screens have the notion of "an empty state" and "a content-full state". It's pretty standard to see that implemented as hiding views or messing around with alphas or "background views" or what not. Observe in this app how this is implemented instead: A coordinator owns a "ContainerViewController" and just tells it to display different content.

  • The lists in this app use the idea of view controllers as cells. When combined with self-sizing tableview cells, this illustrates how you never again have to give a cell a delegate in order to somehow relay functionality from the cell level to the tableview's delegate. Just send it to the cell's view controller instead.

  • ContainerViewController is a UIViewController whose sole purpose is to show another view controller. When the desired "content" of the ContainerViewController is changed, it crossfades from the old content to the new content. If you'd like to see this in action, have the AppRouter go to an instance of TestViewController and play around in there.

  • ScrollingContentViewController is a UIViewController that takes its content view controller and puts it in a UIScrollView. The scrollable area of the UIScrollView is determined by the auto-layout-determined size of the content view controller. This is really handy for when you're building up a custom container view controller and then you realize you need to make it scroll.

  • MessageViewController shows a message (text) and can optionally also show an image and an action button. It's handy and I use it all over the place.

The Extensions

There are a couple of important extensions in this sample:

  • UIView.embedSubview(_:): This adds a method to add a subview to a particular UIView, but also to set up the constraints to indicate that the new subview should fill its parent and resize with it. My experience with composing view controllers has led me to have lots of "container views": placeholder views for where the content of another UIViewController will be embedded. This extension makes that process a bit more straight-forward.

  • UIViewController.embedChild(_:in:): This is the "bread and butter" method of simpler view controller composition. When you're creating view controllers programmatically, having this method means that adding a view controller as a child of another and getting it to show up in the UI is a single line of code. The second parameter is a way to indicate which subview of the new parent you want the UI to go in to. If omitted, the child vc's view is embedded inside the parent's .view. For a concrete example of this, check out TestViewController.swift in the Debug folder.

The other extensions are mostly just for convenience.

The less-interesting bits

  • The AppRouter is a bare-bones router. Please don't take it as a good example of anything. Its primary purpose is to emphasize how the concept of "I want to see this thing" is a separate idea of "I need to push/present this particular UIViewController"

  • ColorViewController is a great way to debug that your containers are behaving the way you're expecting.

  • There are some subclass of UITableViewCell for the various built-in cell types. This is so you can register those classes for cell identifiers on a UITableView and actually get the right cell type when you dequeue a cell.

  • All the model objects are structs. This does mean there's a bit of weirdness when it comes to equality. Equality of model objects is based exclusively off the value's Identifier.

Heads Up

  • UIAlertController is (ab)used for the list creation and item creation UI. Again, this was a conscious decision in order to keep the sample limited in size. There's also an insidious extension to make a textfield on the shown alert behave like a UIDatePicker, because I'm a terrible person who cuts corners in order to get the job done.

  • ListViewController does not animate changes to the content. Ideally, it should perform a diff of the new content against the old content, and use that diff to perform an animated update. However in the interest of keeping this sample from getting excessively huge, it simply does a reloadData() call. This means that swipe-to-delete actions on cells will not animate correctly.

  • ListViewController requires having all cell content loaded up-front. There are many ways to build a list of items. This is the easiest, as it doesn't require any lazy loading or whatever. However, this approach should probably not be used if you have large lists, and definitely shouldn't be used if you have infinitely long lists.

You might also like...
Droplet is a very small SwiftUI application that runs in the menubar and allows a file to be dropped onto the popover.
Droplet is a very small SwiftUI application that runs in the menubar and allows a file to be dropped onto the popover.

A Mac OS menubar application that allows drag-and-drop file uploading to an S3 bucket with a presigned URL copied to the clipboard. Work in progress.

In this tutorial, you’ll write your very first Core Data application with SwiftUI in Xcode

TodoApp-IOS In this tutorial, you’ll write your very first Core Data application with SwiftUI in Xcode. You’ll see how easy it is to get started with

Weather-app - Created a simple weather app on Xcode using SwiftUI, only shows one location

weather-app Created a simple weather app on Xcode using SwiftUI, only shows one

Ios-weather-app - A simple weather app with swift
Ios-weather-app - A simple weather app with swift

AHOY Assignment Weather app Main Screen Settings Architecture The Architecture u

Simple SwiftUI + CoreData app

Footnote Hello! Before you interact with this repository, please check out our Code of Conduct and Contributing Guidelines. Footnote is a SwiftUI + Co

Beers is a simple experimental app implemented using the new amazing SwiftUI.
Beers is a simple experimental app implemented using the new amazing SwiftUI.

Beers is a simple experimental app implemented using the new amazing SwiftUI. The app shows a list of beers fetched from Punk API

A simple App to Track the status of Covid-19 around the World. Using SwiftUI and GraphQL
A simple App to Track the status of Covid-19 around the World. Using SwiftUI and GraphQL

CovidUI CovidUI is a simple App to Track the status of Covid-19 around the World. This is a simple App I made to track the spread of Covid-19 for me a

Simple app to show usage of SwiftUI and Combine
Simple app to show usage of SwiftUI and Combine

Podcasts Simple app to show usage of SwiftUI and Combine. The app shows a list of podcasts fetched from listennotes and it can be played. Status: Work

A Simple ToDo app developed using SwiftUI, Combine and Coredata
A Simple ToDo app developed using SwiftUI, Combine and Coredata

SwiftUI_Tasks Tasks is simple ToDo app developed using SwiftUI and Coredata which having features like Add,Delete,Rearrange and send notification base

Comments
  • Important problem with inserting View Controllers inside Scroll View!

    Important problem with inserting View Controllers inside Scroll View!

    Your idea is beautiful. I'm amazed how easy and affordable my code is now. But recently I stumbled upon one annoying nuisance. Often it is necessary to insert Table Views and Collection Views inside the Scroll Views. And to make it all work perfectly, you need to stretch our Table Views or Collection Views to their full height, which completely kills reuse Cells. How to be in this situation?

    opened by jeudesprits 6
  • Fix adding subviews into cell content view

    Fix adding subviews into cell content view

    In some cases is not the previous view removed from cell content view and it is added another one. The result is that the cell content view contains two views of different view controllers. This issue can be replicated in these steps:

    1. Create two differently named lists.
    2. Remove first list.
    3. Select the remaining list - then both views are visible and their titles are overlapping.
    opened by tomassliz 0
Owner
Dave DeLong
Dave DeLong
Implemented MVVM-C (Coordinator) architecture pattern for the project. Which is satisfying SOLID principles altogether. Protocol oriented development has been followed.

BreakingBad BreakingBad API doc Implemented MVVM-C (Coordinator) architecture pattern for the project. Which is satisfying SOLID principples altogethe

Dhruvik Rao 2 Mar 10, 2022
QuizApp - A simple Quiz App app using MVC

Quiz App Hey folks! I'm still learning Swift and I made a simple app again. This

Damla Çim 1 Jun 29, 2022
Talk to me app built with swift

talk-to-me Интересное и оригинальное приложение для тренировки произношения на английском язые, реализованное целиком и полностью без использования ст

null 0 Oct 22, 2021
Watch WWDC and Tech Talk Videos on your Apple TV, tvOS App.

WWDCTV This project allows you to watch WWDC & Tech Talks videos on your Apple TV. It has been built for tvOS 9.0 using Xcode 7.1 You can also favouri

Aaron Stephenson 421 Nov 3, 2022
IOS-Quiz-App- - A trivia quiz app built with Swift using MVC structure

Quiz App A trivia quiz app built with Swift using MVC structure. Default Quiz

null 0 Feb 25, 2022
SwiftUI sample code for Apple's WWDC18 talk "Designing Fluid Interfaces".

Fluid Interfaces SwiftUI SwiftUI sample code for Apple's WWDC18 talk "Designing Fluid Interfaces". What is Fluid Interfaces? Fluid Interfaces is a new

 Frad LEE 32 Oct 7, 2022
UIKit (MVC), Weather App

Weather Simple weather app written on UIKit (MVC) Was used • UITableView • CoreLocation • Lottie Animations • OpenWeatherMap (API) • Author of animate

null 5 Jun 29, 2022
A very simple Rick & Morty app to demo GraphQL + SwiftUI

MortyUI A very simple Rick & Morty app to demo GraphQL + SwiftUI Characters Character detail Episode This app have a very simple SwiftUI MVVM architec

Thomas Ricouard 445 Jan 3, 2023
📱 Very simple and lightweight messenger using Firebase

?? Very simple and lightweight messenger using Firebase ??. It is a training project for the practice of MVVM architecture.

Daniel Tvorun 2 Jun 26, 2022
Headline News Widget for Better Touch Tool. You can display the articles fetched by rss.

BTTPluginHeadLineNews This is a headline news widget plugin for BTT(Better Touch Tool) You can display the articles fetched by rss. (Pock version is h

null 4 Jul 23, 2022