SwiftUI ist eine junge und noch nicht vollständig erforschte Technologie. Einerseits gibt es viel Raum für Kreativität und Erforschung, andererseits Unsicherheit, Instabilität und Probleme.
Ist es so einfach, in SwiftUI zu schreiben, wie es auf der WWDC gezeigt wird? Ich werde Ihnen von den Schwierigkeiten erzählen, auf die ich persönlich beim Schreiben meiner eigenen Bewerbung gestoßen bin. Es ist vollständig in SwiftUI geschrieben und im App Store erhältlich .
? .
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!")
}
, :
Intent ( , , . .)
Singleton
, 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?
Definitiv nicht. Es wird Probleme bei der Umsetzung von Entwürfen geben, es wird architektonische Schwierigkeiten geben. Da die Technologie frisch ist, wird es eine Menge Forschung und Probleme geben, mit denen man sich befassen muss. Andererseits ist die Geschwindigkeit der UI-Entwicklung unter SwiftUI um ein Vielfaches höher als bei UIKit, und es eröffnen sich zahlreiche Möglichkeiten, mit Animationen zu arbeiten. SwiftUI verfügt über sehr schöne Animationen und ist sehr einfach zu erstellen.
Sie können teilweise in einfache SwiftUI-Bildschirme, Bildschirme der Begrüßungskategorie oder Informationsbildschirme übersetzen. Hier funktioniert SwiftUI gut, die Probleme sind minimal und sehen mit Animationen optisch besser aus als UIKit.
Ich empfehle es auch bei Ihren persönlichen Projekten, die nicht sehr groß und komplex sind und bei denen keine strengen Designanforderungen bestehen.