Aplicativo SwiftUI na AppStore - dificuldades de desenvolvimento

SwiftUI é uma tecnologia jovem e ainda não totalmente explorada. Por um lado, existe um grande espaço de criatividade e exploração e, por outro, incertezas, instabilidades e problemas.





É tão fácil escrever em SwiftUI como mostrado na WWDC? Contarei a você as dificuldades que encontrei pessoalmente ao escrever meu próprio requerimento. Ele foi escrito inteiramente em SwiftUI e está disponível na App Store .





? .





View

, . MVI, . MVI MVI SwiftUI –





:





@ObservedObject @StateObject

MVI , , Intent. View Intent .





struct ContentView: View {

    @ObservedObject var intent: ContentIntent

    var body: some View {
        Text("Hello, world!")
    }
}
      
      



@ObservableObject , , View, , , , UI .





.





View SwiftUI — View, , init . , View , View, , .





, View .





// MARK: - Screen ContentView
struct ContentView: View {

    @State var isNextScreenVisible = false
    @State var seconds = "0"

    var body: some View {
        NavigationView {
            VStack(spacing: 16) {
                Text("Seconds: \(seconds)")
                NavigationLink("Next screen", destination: NextView(), isActive: $isNextScreenVisible)
            }
        }.onAppear {
            Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
                self.seconds = String(Int(Date().timeIntervalSince1970) % 60)
            }
        }
    }
}

// MARK: - Scren NextView
struct NextView: View {

    @ObservedObject var intent: NextIntent

    init() {
        intent = ContentIntent()

        print("init NextView")
    }

    var body: some View {
        Text("Hello Weold!")
    }

      
      



NextView, . :





init NextView
init NextView
init NextView
init NextView
init NextView
init NextView
init NextView
init NextView
init NextView
      
      







init, View , ( Intent), , . , . . .





, @ObservedObject @StateObject Intent View. 









View , ( MVI Intent Model, MVVM ViewModel).





, Intent , @StateObject; Intent, Intent . @StateObject Singleton, .





, Intent , @StateObject, init Intent .









@StateObject iOS 14.





@ObservedObject, Singleton?

, .





struct ContentView: View {

    @ObservedObject var intent: ContentInten

    init() {
        self.intent = ContentInten.shared
        let model = ContentModel()
        self.intent.update(model: model)
    }
    
    var body: some View {
        Text("Hello, world!")
    }

      
      



, :





  1. Intent ( , , . .)





  2. Singleton  





  3. , Singleton . 





SwiftUI iOS 14 , , iOS 14 SwiftUI.





@StateObject init View

. Intent View. , , , .





struct ContentView: View {

    @StateObject var intent: ContentInten

    var body: some View {
        Text("Hello, world!")
    }

    static func build() -> some View {
        let model = ContentModel()
        let intent = ContentInten(model: model)
        return ContentView(intent: intent)
    }

      
      







, iOS 13.





onAppear onDisappear

, View , , View . , onAppear onDisappear , . . . 









struct ContentView: View {

    @State var isVisibleHomeScreen = false

    var body: some View {
        NavigationView {
            VStack {
                Text("Hello, world!")

                NavigationLink(destination: Text("Screen Home"),
                               isActive: $isVisibleHomeScreen,
                               label: { Text("Open screen") })
            }.onAppear {
                print("onAppear was called")
            }.onDisappear {
                print("onDisappear was called")
            }
        }
    }

      
      



NavigationView . :





onDisappear was called
onAppear was called
      
      







, NavigationView , , . onAppear onDisappear . - .





SwiftUI? , , UIKit . , SwiftUI. , , , . , , WWDC. , "some View". 





, , MVI. , , , , .





Router
//  ContentRouter.swift
//
//  Copyright © 2020 Vyacheslav Ansimov. All rights reserved.
//
import SwiftUI
import Combine

// MARK: - Realization
struct ContentRouter: View {

    enum ScreenType {
        case sheetScreen(value: String)
        case navigationScreen(value: String)
        case exit
    }

    private class ScreenTypeHolder: ObservableObject {
        @Published var type: ScreenType?
    }

    // API
    let screen: PassthroughSubject<ScreenType, Never>

    // private
    @Environment(\.presentationMode) private var presentationMode
    @StateObject private var screenType = ScreenTypeHolder()

    // Life cycle
    var body: some View {
        displayView().onReceive(screen) { self.screenType.type = $0 }
    }

    private func displayView() -> some View {
        let isVisible = Binding<Bool>(get: { screenType.type != nil },
                                      set: { if !$0 { screenType.type = nil } })
        // Screens
        switch screenType.type {
        case .sheetScreen(let value):
            return AnyView(
                Spacer().sheet(isPresented: isVisible) {
                    Text(value)
                }
            )

        case .navigationScreen(let value):
            return AnyView (
                NavigationLink("", destination: Text(value), isActive: isVisible)
            )

        case .exit:
            presentationMode.wrappedValue.dismiss()
            return AnyView(EmptyView())

        case .none:
            return AnyView(EmptyView())
        }
    }
}

// MARK: - Example
struct ContentRouter_Previews: PreviewProvider {
    static let routeSubject = PassthroughSubject<ContentRouter.ScreenType, Never>()

    static var previews: some View {
        NavigationView {
            VStack {
                Button(action: {
                    self.routeSubject.send(.sheetScreen(value: "Hello World!"))
                }, label: { Text("Display Sheet Screen") })

                Button(action: {
                    self.routeSubject.send(.navigationScreen(value: "Hello World!"))
                }, label: { Text("Display NavigationLink Screen") })
            }
            .overlay(ContentRouter(screen: routeSubject))
        }
    }
}
      
      







Property wrapper (State, Binding, ObservedObject .) SwiftUI UI.





. , ObservableObject View





// MARK: Model
class ContentModel: ObservableObject {
    @Publised var title = "Hello World!"
}

// MARK: View
struct ContentView: View {

    @ObservedObject var model:  ContentModel

    var body: some View {
        Text(model.title)
    }
}
      
      



, ? .





Intent. , View.





// MARK: View
struct ContentView: View {

  @StateObject var intent:  ContentIntent

  var body: some View {
      Text(intent.model .title).onAppear {
          self.intent.onAppear()
      }
  }
}

// MARK: Intent
class ContentIntent {

  let model:  ContentModel

  ... 

  func onAppear() {
    model.title = "Hello World!"
  }
}

// MARK: Model
class ContentModel: ObservableObject {
  @Published var title = "Loaded"
}
      
      



, UI Text "Loaded", .





let model: ContentModel
      
      



 





@Published var model: ContentModel
      
      



. ObservableObject Model Intent , - , View. 





, View Model - , Intent . , Intent ObservableObject. 





import Combine

class ContentIntent: ObservableObject {

    let model: ContentModel
    private var cancellable: Set<AnyCancellable> = []

    init(model: ContentModel) {
        self.model = model
        cancellable.insert(model.objectWillChange.sink { [weak self] in
           self?.objectWillChange.send()
        })
    }

    ...
}
      
      



Model - , objectWillChange, Intent , Model . Intent objectWillChange.send(), View .





ObservableObject Intent , objectWillChange.





. UI  View, .





UI

, UIKit, SwiftUI. SwiftUI . . , , .





UI :





  • UISearchBar SwiftUI , , .





  • UIPageControll. SwiftUI - TabBar, , UIPageControll.





  • PikerView: , . , PikerView. , , .





  • TextEditor: background, . 









! . . , , . , Apple . 





SwiftUI?





Definitivamente não. Haverá problemas com a implementação de projetos, haverá dificuldades arquitetônicas. Como a tecnologia é nova, haverá muitas pesquisas e muitos problemas para resolver. Por outro lado, a velocidade de desenvolvimento da IU no SwiftUI é várias vezes maior do que no UIKit, e amplas possibilidades para trabalhar com animações se abrem - o SwiftUI tem animações muito bonitas e é muito fácil de fazer. 





Você pode traduzir parcialmente em telas simples do SwiftUI, telas da categoria Bem-vindo ou telas de informações. Aqui, o SwiftUI tem um bom desempenho, os problemas são mínimos e, visualmente, com animações parece melhor do que o UIKit.





Também recomendo experimentá-lo em seus projetos pessoais, não muito grandes e complexos, onde não haja requisitos de design rígidos. 








All Articles