SwiftUIは若く、まだ十分に検討されていないテクノロジーです。一方では、創造性と探求のための大きなスペースがあり、他方では、不確実性、不安定性、および問題があります。
WWDCに示されているようにSwiftUIで書くのは簡単ですか?自分のアプリケーションを書いているときに私が個人的に遭遇した困難についてお話します。それはSwiftUIに書かれたとで利用可能です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!")
}
, :
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?
絶対にありません。デザインの実装に問題があり、アーキテクチャ上の問題が発生します。技術は新鮮なので、対処すべき研究や問題がたくさんあります。一方、SwiftUIでのUI開発の速度はUIKitの数倍であり、アニメーションを操作するための幅広い可能性が開かれます。SwiftUIは非常に美しいアニメーションを備えており、非常に簡単に作成できます。
SwiftUIの単純な画面、ようこそカテゴリの画面、または情報画面に部分的に変換できます。ここでは、SwiftUIのパフォーマンスが高く、問題は最小限であり、UIKitよりもアニメーションの方が視覚的に見栄えがします。
また、厳密な設計要件がない、それほど大きく複雑ではない個人的なプロジェクトで試してみることをお勧めします。