Sunday, March 26, 2023
Learning Code
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
Learning Code
No Result
View All Result
Home Swift

How to build SwiftUI apps using VIPER?

learningcode_x1mckf by learningcode_x1mckf
September 27, 2022
in Swift
0
How to build SwiftUI apps using VIPER?
74
SHARES
1.2k
VIEWS
Share on FacebookShare on Twitter


2019/09/18

On this tutorial I will present you learn how to mix SwiftUI with the VIPER structure in an actual world iOS software instance.

VIPER

SwiftUI – the brand new child on the block

There are actually tons of of SwiftUI tutorials across the net, however I used to be solely capable of finding only one or two that focuses on real world use instances as an alternative of the smaller particulars like learn how to configure / make X in SwiftUI. Good tutorials @mecid stick with it!

I additionally had my very own “battle” with SwiftUI, as a result of my collection view framework is structured precisely the identical manner as you write SwiftUI code. After WWDC I used to be like, hell no! I am doing the identical methodology for months now, so why ought to I care? I began to consider that some Apple engineers are studying my weblog. 😂

Anyway I knew at day zero {that a} loopy quantity of latest SwiftUI tutorials will arrive and everybody might be hyped concerning the new declarative UI framework, however actually I already had my common toolkit for this goal. That is why I do not wished to put in writing about it. Truthfully I nonetheless love Mix far more than SwiftUI. I am additionally fairly dissatisfied since CollectionView is totally lacking from the framework.

Lastly, simply because what the heck lets attempt new issues and I used to be interested in how SwiftUI can match into my app constructing methodology I began to create a brand new VIPER template primarily based on these type of views. I additionally wished to make a helpful, scalable, modular actual world software instance utilizing the brand new framework, which is up-to-date. So much has modified in SwiftUI in the course of the Xcode 11 beta interval, in order that’s why I am solely publishing this tutorial now. Sufficient chatter, should not we code already? 😛



Be taught a contemporary VIPER structure

I’ve spent my final two years utilizing the VIPER structure. Some individuals say “it is manner too complicated” or “it isn’t a very good match for small groups”. I can solely inform them one phrase:

Bullshit!

I consider that I’ve created a contemporary & comparatively easy sample that can be utilized for actually something. Studying VIPER will certainly enhance your code high quality due to the clear structure and the SOLID ideas. You may have a greater understanding of how smaller items can work collectively and talk with one another.

Remoted smaller elements can velocity up growth, since you simply need to work on slightly piece directly, plus you possibly can create checks for that specific factor, which is a large win for testability & code protection (you do not have to run your app on a regular basis if you wish to take a look at one thing, you possibly can work on the module you simply want).

I am normally working with a extremely easy code generator to fireside up new modules, this manner I can save loads of time. If you need to work alone on a venture the module generator and the predefined construction may even prevent some extra time. Additionally you actually cannot mess up issues or find yourself with large information in case you are following the essential VIPER guidelines. I will train you my methodology in about 10 minutes. ⏰


What the heck is VIPER anyway?

Should you by no means heard about VIPER earlier than, the very first thing you must know is {that a} VIPER module accommodates the next elements:

  • View = UIViewController subclass or SwiftUI View
  • Interactor = Gives the required knowledge within the correct format
  • Presenter = UI impartial enterprise logic (what to do precisely)
  • Entity = Knowledge objects (generally it is lacking from the module)
  • Router = Builds up the view controller hierarchy (present, current, dismiss, and so forth)

I at all times have a module file subsequent to those ones the place I outline a module builder which builds up the entire thing from the elements above and in that file I additionally outline the module particular protocols. I normally identify these protocols as interfaces they make it doable that any of the elements might be changed utilizing dependency injection. This fashion we will take a look at something by utilizing mocked objects in our unit checks.

Some say {that a} VIPER module with a Builder known as VIPER/B. I feel the module file is a perfect place to retailer your module builder object, the module interfaces and the module delegate should you want one.


Protocol oriented VIPER structure

So the hot button is the 6 essential protocol that connects View-Interactor-Presenter-Router. These protocols be sure that not one of the VIPER elements can see greater than it is required. Should you return to my first tutorial you may see that I made a mistake there. The factor is which you can name a technique on the router via the presenter from the view, which is unhealthy. This new method fixes that situation. 🐛


View-to-Presenter
Presenter-to-View

Router-to-Presenter
Presenter-to-Router

Interactor-to-Presenter
Presenter-to-Interactor


Module

builds up pointers and returns a UIViewController


View implements View-to-Presenter

sturdy presenter as Presenter-to-View-interface


Presenter implements Presenter-to-Router, Presenter-to-Interactor, Presenter-to-View

sturdy router as Router-to-Presenter-interface
sturdy interactor as Interactor-to-Presenter-interface
weak view as View-to-Presenter-interface


Interactor implements Interactor-to-Presenter

weak presenter as Presenter-to-Interactor-interface


Router implemenents Presenter-to-Router

weak presenter as Presenter-to-Router-interface


As you possibly can see the view (which could be aUIViewController subclass) holds the presenter strongly and the presenter will retain the interactor and router lessons. The whole lot else is a weak pointer, as a result of we do not like retain cycles. It’d appears slightly bit sophisticated at first sight, however after writing your first few modules you may see how good is to separate logical elements from one another. 🐍

Please be aware that not the whole lot is a VIPER module. Do not attempt to write your API communication layer or a CoreLocation service as a module, as a result of these type of stuff are standalone as an example: providers. I will write about them within the subsequent one, however for now let’s simply concentrate on the anatomy of a VIPER module.


Generic VIPER implementation in Swift 5

Are you prepared to put in writing some Swift code? All proper, let’s create some generic VIPER interfaces that may be prolonged afterward, do not be afraid will not be that tough. 😉




public protocol RouterPresenterInterface: class 



public protocol InteractorPresenterInterface: class 



public protocol PresenterRouterInterface: class 



public protocol PresenterInteractorInterface: class 



public protocol PresenterViewInterface: class 



public protocol ViewPresenterInterface: class 





public protocol RouterInterface: RouterPresenterInterface 
    associatedtype PresenterRouter

    var presenter: PresenterRouter!  get set 


public protocol InteractorInterface: InteractorPresenterInterface 
    associatedtype PresenterInteractor

    var presenter: PresenterInteractor!  get set 


public protocol PresenterInterface: PresenterRouterInterface & PresenterInteractorInterface & PresenterViewInterface 
    associatedtype RouterPresenter
    associatedtype InteractorPresenter
    associatedtype ViewPresenter

    var router: RouterPresenter!  get set 
    var interactor: InteractorPresenter!  get set 
    var view: ViewPresenter!  get set 


public protocol ViewInterface: ViewPresenterInterface 
    associatedtype PresenterView

    var presenter: PresenterView!  get set 


public protocol EntityInterface 





public protocol ModuleInterface 

    associatedtype View the place View: ViewInterface
    associatedtype Presenter the place Presenter: PresenterInterface
    associatedtype Router the place Router: RouterInterface
    associatedtype Interactor the place Interactor: InteractorInterface

    func assemble(view: View, presenter: Presenter, router: Router, interactor: Interactor)


public extension ModuleInterface 

    func assemble(view: View, presenter: Presenter, router: Router, interactor: Interactor) 
        view.presenter = (presenter as! Self.View.PresenterView)

        presenter.view = (view as! Self.Presenter.ViewPresenter)
        presenter.interactor = (interactor as! Self.Presenter.InteractorPresenter)
        presenter.router = (router as! Self.Presenter.RouterPresenter)

        interactor.presenter = (presenter as! Self.Interactor.PresenterInteractor)

        router.presenter = (presenter as! Self.Router.PresenterRouter)
    


Related sorts are simply placeholders for particular sorts, by utilizing a generic interface design I can assemble my modules with a generic module interface extension and if some protocol is lacking the app will crash simply as I attempt to initialize the unhealthy module.

I really like this method, as a result of it saves me from loads of boilerplate module builder code. Additionally this manner the whole lot may have a base protocol, so I can lengthen something in a extremely neat protocol oriented manner. Anyway should you do not perceive generics that is not an enormous deal, within the precise module implementation you’ll barely meet them.

So how does an precise module appears like?




protocol TodoRouterPresenterInterface: RouterPresenterInterface 





protocol TodoPresenterRouterInterface: PresenterRouterInterface 



protocol TodoPresenterInteractorInterface: PresenterInteractorInterface 



protocol TodoPresenterViewInterface: PresenterViewInterface 





protocol TodoInteractorPresenterInterface: InteractorPresenterInterface 





protocol TodoViewPresenterInterface: ViewPresenterInterface 






last class TodoModule: ModuleInterface 

    typealias View = TodoView
    typealias Presenter = TodoPresenter
    typealias Router = TodoRouter
    typealias Interactor = TodoInteractor

    func construct() -> UIViewController 
        let view = View()
        let interactor = Interactor()
        let presenter = Presenter()
        let router = Router()

        self.assemble(view: view, presenter: presenter, router: router, interactor: interactor)

        router.viewController = view

        return view
    





last class TodoPresenter: PresenterInterface 
    var router: TodoRouterPresenterInterface!
    var interactor: TodoInteractorPresenterInterface!
    weak var view: TodoViewPresenterInterface!


extension TodoPresenter: TodoPresenterRouterInterface 



extension TodoPresenter: TodoPresenterInteractorInterface 



extension TodoPresenter: TodoPresenterViewInterface 





last class TodoInteractor: InteractorInterface 
    weak var presenter: TodoPresenterInteractorInterface!


extension TodoInteractor: TodoInteractorPresenterInterface 





last class TodoRouter: RouterInterface 
    weak var presenter: TodoPresenterRouterInterface!
    weak var viewController: UIViewController?


extension TodoRouter: TodoRouterPresenterInterface 





last class TodoView: UIViewController, ViewInterface 
    var presenter: TodoPresenterViewInterface!


extension TodoView: TodoViewPresenterInterface 



A VIPER module is constituted of 5 information, which is a large enchancment in comparison with my outdated methodology (I used 9 information for a single module, which remains to be higher than a 2000 traces of code large view controller, however yeah it was fairly many information… 😂 ).

You need to use my VIPER protocol library in order for you or just copy & paste these interfaces to your venture. I even have a VIPER module generator written totally in Swift that may generate a module primarily based on this template (or you can also make your individual).


construct VIPER interfaces?

Let me clarify a pattern movement actual fast, take into account the next instance:


protocol TodoRouterPresenterInterface: RouterPresenterInterface 
    func dismiss()




protocol TodoPresenterRouterInterface: PresenterRouterInterface 



protocol TodoPresenterInteractorInterface: PresenterInteractorInterface 
    func didLoadWelcomeText(_ textual content: String)


protocol TodoPresenterViewInterface: PresenterViewInterface 
    func prepared()
    func shut()




protocol TodoInteractorPresenterInterface: InteractorPresenterInterface 
    func startLoadingWelcomeText()




protocol TodoViewPresenterInterface: ViewPresenterInterface 
    func setLoadingIndicator(seen: Bool)
    func setWelcomeText(_ textual content: String)


The view calls prepared() on the presenter in some unspecified time in the future in time viewDidLoad(), so the presenter can kick off. First it tells the view to indicate the loading indicator by calling setLoadingIndicator(seen: true), subsequent asks the interactor to load the welcome textual content asynchronously startLoadingWelcomeText(). After the info arrives again to the interactor it could possibly notify the presenter by utilizing the didLoadWelcomeText("") methodology. The presenter can now inform the view to cover the loading indicator utilizing the identical methodology setLoadingIndicator(seen: false) this time with a false parameter and to show the welcome textual content by utilizing setWelcomeText("").

One other use case is that somebody faucets a button on the view so as to shut the controller. The view calls shut() on the presenter, and the presenter can merely name dismiss() on the router. The presenter can even do another stuff (like cleansing up some sources) earlier than it asks the router to dismiss the view controller.

I hope that you simply get the instance, really feel charge to implement the whole lot by your individual, it is fairly a pleasant activity to apply. In fact you possibly can make the most of blocks, guarantees or the model new Mix framework to make your dwell simpler. You possibly can for instance auto-notify the presenter if some async knowledge loading have completed. 😉

So now that you’ve got a primary understanding a couple of fashionable VIPER structure lets discuss learn how to change the standard ViewController subclass with SwiftUI.



design a VIPER primarily based SwiftUI software?

SwiftUI is kind of a singular beast. View are structs so our generic VIPER protocol wants some alterations so as to make the whole lot work.

The very first thing you need to do is to eliminate the ViewPresenterInterface protocol. Subsequent you possibly can take away the view property from the PresenterInterface since we’ll use an observable view-model sample to auto-update the view with knowledge. The final modification is that you need to take away the view parameter from the default implementation of the assemble operate contained in the ModuleInterface extension.

So I discussed a view-model, let’s make one. For the sake of simplicity I’ll use an error Bool to point if one thing went mistaken, however you might use one other view, or a standalone VIPER module that presents an alert message.


import Mix
import SwiftUI

last class TodoViewModel: ObservableObject 

    let objectWillChange = ObservableObjectPublisher()

    @Printed var error: Bool = false 
        willSet 
            self.objectWillChange.ship()
        
    

    @Printed var todos: [TodoEntity] = [] 
       willSet 
            self.objectWillChange.ship()
        
    


This class conforms to the ObservableObject which makes SwiftUI doable to examine for updates & re-render the view hierarchy if one thing modified. You simply want a property with the ObservableObjectPublisher kind and actually ship() a message if one thing will change this set off the auto-update in your views. 🔥

The TodoEntity is only a primary struct that conforms to a bunch of protocols like the brand new Identifiable from SwiftUI, as a result of we might prefer to show entities in a listing.


import Basis
import SwiftUI

struct TodoEntity: EntityInterface, Codable, Identifiable 
    let id: Int
    let title: String
    let accomplished: Bool


A primary SwiftUI view will nonetheless implement the ViewInterface and it will have a reference to the presenter. Our view-model property can be going for use right here marked with an @ObservedObject property wrapper. That is the way it appears like in code up to now:


import SwiftUI

struct TodoView: ViewInterface, View 

    var presenter: TodoPresenterViewInterface!

    @ObservedObject var viewModel: TodoViewModel

    var physique: some View 
        Textual content("SwiftUI ❤️ VIPER")
    


The presenter may also have a weak var viewModel: TodoViewModel! reference to have the ability to replace the the view-model. Looks like we’ve got a two-way communication movement between the view and the presenter by utilizing a view-model. Appears good to me. 👍

We are able to additionally make the most of the model new @EnvironmentObject if we need to move round some knowledge within the view hierarchy. You simply need to implement the identical remark protocol in your surroundings object that we did for the view-model. For instance:


import Basis
import Mix

last class TodoEnvironment: ObservableObject 

    let objectWillChange = ObservableObjectPublisher()

    @Printed var title: String = "Todo listing" 
       willSet 
            self.objectWillChange.ship()
        
    


Lastly let me present you learn how to implement the module builder, as a result of that is fairly tough. You need to use the brand new generic UIHostingController, which is fortunately an UIViewController subclass so you possibly can return it after you end module constructing.


last class TodoModule: ModuleInterface 
    typealias View = TodoView
    typealias Presenter = TodoPresenter
    typealias Router = TodoRouter
    typealias Interactor = TodoInteractor

    func construct() -> UIViewController 
        let presenter = Presenter()
        let interactor = Interactor()
        let router = Router()

        let viewModel = TodoViewModel()
        let view = View(presenter: presenter, viewModel: viewModel)
            .environmentObject(TodoEnvironment())
        presenter.viewModel = viewModel

        self.assemble(presenter: presenter, router: router, interactor: interactor)

        let viewController = UIHostingController(rootView: view)
        router.viewController = viewController
        return viewController
    


Placing collectively the items from now’s only a piece of cake. If you would like, you possibly can problem your self to construct one thing with out downloading the final project. 🍰

Nicely, should you’re not into challenges that is nice too, be at liberty to seize the instance code from The.Swift.Dev tutorials on GitHub. It accommodates a pleasant interactor with some cool networking stuff utilizing URLSession and the Combine framework. The ultimate SwiftUI code is only a tough implementation, as a result of as I instructed you to start with there actually good tutorials about SwiftUI with examples.

I hope you loved this tutorial, please subscribe & tell me what you suppose. 🤔






Source link

You might also like

Introducing – AI Utils for macOS

Encoding and decoding data using the Hummingbird framework

Hummingbird routing and requests – The.Swift.Dev.

Share30Tweet19
learningcode_x1mckf

learningcode_x1mckf

Recommended For You

Introducing – AI Utils for macOS

by learningcode_x1mckf
March 24, 2023
0
Introducing – AI Utils for macOS

⚠️ REQUIRES a FREE OpenAI API key. You will get one utilizing this hyperlink. ⚠️ Improve your productiveness with our AI powered utility application. - accessible...

Read more

Encoding and decoding data using the Hummingbird framework

by learningcode_x1mckf
March 22, 2023
0
Encoding and decoding data using the Hummingbird framework

HTTP is all about sending and receiving information over the community. Initially it was solely utilized to switch HTML paperwork, however these days we use HTTP to switch...

Read more

Hummingbird routing and requests – The.Swift.Dev.

by learningcode_x1mckf
March 17, 2023
0
Hummingbird routing and requests – The.Swift.Dev.

Routing on the server facet means the server goes to ship a response primarily based on the URL path that the consumer referred to as when firing up...

Read more

Building a Scrollable Custom Tab Bar in SwiftUI

by learningcode_x1mckf
March 10, 2023
0
Building a Scrollable Custom Tab Bar in SwiftUI

Whether or not you’re making a social media app or a productiveness device, the tab bar interface can improve the consumer expertise by making it extra intuitive and...

Read more

Beginner’s guide to server-side Swift using the Hummingbird framework

by learningcode_x1mckf
March 8, 2023
0
Beginner’s guide to server-side Swift using the Hummingbird framework

Swift on the Server in 2023 Three years in the past I began to focus on Vapor, the preferred web-framework written in Swift, which served me very...

Read more
Next Post
Understanding Constructors in JavaScript

Understanding Constructors in JavaScript

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Related News

Google expands open source bounties, will soon support Javascript fuzzing too – ZDNet

Java News Roundup: JDK 20 in Rampdown Phase 2, New JEP … – InfoQ.com

February 4, 2023
Google expands open source bounties, will soon support Javascript fuzzing too – ZDNet

A quick glance at the history of C programming languages – TechTarget

March 12, 2023
Google expands open source bounties, will soon support Javascript fuzzing too – ZDNet

C++ 23 Language Standard Declared Feature-Complete – Slashdot

March 6, 2023

Browse by Category

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

RECENT POSTS

  • 2023 Java roadmap for developers – TheServerSide.com
  • YS Jagan launches Ragi Java in Jagananna Gorumudda, says focused on intellectual development of students – The Hans India
  • Disadvantages of Java – TheServerSide.com

CATEGORIES

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

© 2022 Copyright Learning Code

No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#

© 2022 Copyright Learning Code

Are you sure want to unlock this post?
Unlock left : 0
Are you sure want to cancel subscription?