This repository has been archived by the owner on May 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
Home
Lukas Romsicki edited this page Jun 19, 2020
·
4 revisions
Welcome to the wiki! Since there isn't much content yet, the core information is contained in this "Home" page.
Views are constructed using a "container" pattern. That is, presentational views are wrapped in Container
views that handle the business logic. Why is this important?
- This app pulls a lot of data from its environment using
@EnvironmentObject
. - If we weren't using the container pattern, the app would experience massive repainting of views throughout the app, since there is no mechanism to tell the view if it should change or not.
- Unfortunately, we can't simply conform views that use
@EnvironmentObject
toEquatable
. This is well explained in this article.
- References to the environment should be kept as deep in the view hierarchy as possible. This will prevent from massive subtrees of views from being re-rendered if they don't need to be.
- Always conform any view to
Equatable
, and be explicit about which properties must change for the view to re-render.
If you're a React developer, the folder structure will be familiar to you. Here's a breakdown of what the Xcode project looks like:
-
Application
- Anything that pertains to the core application and its environment.- This folder is also home to
AppDelegate
andSceneDelegate
. -
Binders
- Binders are
ViewModifier
s that are used to bindObservableObject
s together. - For example, you may want to trigger a weather data refresh when the location changes.
- Binders are
Controllers
-
Environment
- Classes that are used to configure the "environment" that the app is running in. -
Services
- Services are usually
ObservableObject
s that facilitate some sort of interaction with external data. - For example,
WeatherService
is used to communicate with the Nimbus API to fetch the weather.
- Services are usually
-
States
-ObservableObjects
that store the current state of various parts of the user interface.
- This folder is also home to
-
Concepts
- Implementation-less classes used to distinguish views based on purpose. -
Constants
- Classes that store global constants. -
Extensions
- Self-explanatory. -
GraphQL
- Stores the models and schemas of the GraphQL APIs. -
Sections
- Implementations of each of the main sections of the app, such as
Now
,Week
,Radar
are stored here. - Views that are specific to their sections are stored in the appropriate folders.
- The router that handles which section to display is stored at the root and is called
CurrentSection
.
- Implementations of each of the main sections of the app, such as
-
Views
- SwiftUI views that can be reused across the app, or are always visible no matter the current section.-
AppLayout
is the main view that renders the frame of the app. -
Master
is the view responsible for rendering the contents of the main coloured sliding panel.
-
A single view follows the following structure. Let's say a view is called ImportantButton
:
-
ImportantButton
- The core folder.-
Components
- A folder that contains all the subviews, formatted using a similar structure. -
ImportantButton.swift
- The presentational logic. -
ImportantButtonContainer.swift
- The containing view that handles business logic (if required).
-
This structured can be repeated indefinitely. That is, it can be nested within itself. When in doubt, copy the pattern used in an existing component.
SwiftUI isn't perfect, and there are still a number of issues that have workarounds:
- The "pull-to-dismiss" feature for the
LocationPicker
uses introspection viaDismissableScrollViewModifier
to dig into the view hierarchy to find theUIScrollView
that implements theScrollView
in order to register the appropriate gestures. - The
DayPicker
uses a preference key to size the parent scroll view, since scroll views implemented inUIViewRepresentable
currently have a bug in which they don't auto resize when their content changes.