This project adheres to MVVM architecture. MVVM is a design pattern which organizes objects by model, view model, and view.
Arrows designate subscriptions in their pointed direction, i.e PlayViewModel subscribes to PredictionLayer.
View files define the look-and-feel of the app. This starter project defines a PlayView superview which imports all other view objects. Please consult the README in the /Views folder for more information.
PlayViewModel is the view model which publishes data to the PlayView view. View models act as important intermediaries between the view and model by de-coupling business logic from views and by subscribing to changes from the model.
PlayViewModel publishes changes to the view by subscribing to the following events:
- New images (either from video capture or image preview) will trigger a prediction request.
- Responses to prediction requests update the UI to display the prediction result.
- Switching to
ImagePreviewmode (which uses prediction on a chosen image from the device's library) will tear-down the video capture session manager.
The model layer handles all data processing in the app, publishing results to any subscribers. In this case, PlayViewModel is the only subscriber to model objects, which are:
CaptureSessionManager: publishes select frames from the video capture feed.PredictionLayer: uses the imported Core ML model to publish the results from prediction requests.Project: a struct for managing Core ML models.
CaptureSessionViewController is an exception to the MVVM rule. Although we leverage the SwiftUI library whenever possible, we still need the older UIKit library for select purposes relating to video capture handling.
Thankfully, we can integrate UIKit easily into SwiftUI with UIViewControllerRepresentable, a struct that manages view controllers directly in a SwiftUI view. In our app, CameraView is a UIViewControllerRepresentable which creates CaptureSessionViewController. This view controller is responsible for:
- Setting the view frame to the video feed.
- Handling device orientation changes, ensuring the video feed is correctly oriented.
- Managing tap gestures. UIKit handles conflicts between multiple tap gesture handlers better than SwiftUI, at the time of this writing. Click here to read more about tap-gestures in iOS-bootstrap.
For further reading and guidance for Swift best practices:
- Ray Wenderlich has a great tutorial showcasing MVVM with the Combine library, which is used to define publishers and subscribers between MVVM layers. We use Combine a lot in the view model and model layers.
- Design+Code has in-depth material for creating a Swift app in iOS 14.
