Application SwiftUI dans l'AppStore - difficultés de développement

SwiftUI est une technologie jeune et pas encore complètement explorée. D'une part, il y a beaucoup d'espace pour la créativité et l'exploration, et d'autre part, l'incertitude, l'instabilité et les problèmes.





Est-il aussi simple d'écrire en SwiftUI que sur la WWDC? Je vais vous parler des difficultés que j'ai personnellement rencontrées lors de la rédaction de ma propre candidature. Il est entièrement écrit en SwiftUI et est disponible dans l' 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?





Définitivement pas. Il y aura des problèmes avec la mise en œuvre des conceptions, il y aura des difficultés architecturales. Comme la technologie est récente, il y aura beaucoup de recherches et de problèmes à résoudre. D'autre part, la vitesse de développement de l'interface utilisateur sur SwiftUI est plusieurs fois supérieure à celle d'UIKit, et il existe de nombreuses possibilités de travailler avec des animations - SwiftUI a de très belles animations et il est très facile de les faire. 





Vous pouvez traduire partiellement en écrans simples SwiftUI, écrans de la catégorie Bienvenue ou écrans d'information. Ici, SwiftUI fonctionne bien, les problèmes sont minimes et sont visuellement plus beaux avec des animations qu'avec UIKit.





Je recommande également de l'essayer sur vos projets personnels, pas très grands et complexes, où il n'y a pas d'exigences de conception strictes. 








All Articles