Hi, 大家好盯腌,我是姜友華。這兩天在適應(yīng)SwiftUI渊跋,SwiftUI較Swift UIKit在構(gòu)建APP有較大的改變腊嗡。在這里着倾,我將其中的注意點記錄下來。
通常我在學(xué)習(xí)新的界面類開發(fā)框架時燕少,回從以下幾個方面著手:頁面的構(gòu)建卡者、頁面的跳轉(zhuǎn)、狀態(tài)的改變客们、數(shù)據(jù)的傳遞及數(shù)據(jù)的持久化崇决。SwiftUI較Swift UIKit在數(shù)據(jù)的傳遞與數(shù)據(jù)的持久化沒有變化,所以這里只說說:頁面的構(gòu)建底挫、頁面的跳轉(zhuǎn)恒傻、數(shù)據(jù)的傳遞。
一盈厘、頁面的構(gòu)建。
- View:
- Text官边、
- Images
- Buttons
- Controls
- Value Selectors
- Value Indicators
...
2.Layout
- Stack
- Grids
- Containers
- Scroll Views
- List
- Tables
- Spacers and Dividers
...
二沸手、頁面的跳轉(zhuǎn)
- 判斷渲染
if isShow {
MyView()
}
- Present
struct ContentView: View {
@State private var showingSheet = false
var body: some View {
Button("Show Sheet") {
showingSheet.toggle()
}
.sheet(isPresented: $showingSheet) {
backFunc()
} content: {
MyView()
}
}
}
- Navigation
- NavigationLink、NavigationView
NavigationView {
List {
NavigationLink("Purple", destination: ColorDetail(color: .purple))
NavigationLink("Pink", destination: ColorDetail(color: .pink))
NavigationLink("Orange", destination: ColorDetail(color: .orange))
}
.navigationTitle("Colors")
Text("Select a Color") // A placeholder to show before selection.
}
struct ColorDetail: View {
var color: Color
var body: some View {
color
.frame(width: 200, height: 200)
.navigationTitle(color.description.capitalized)
}
}
- TabBar
TabView {
Text("The First Tab")
.badge(10)
.tabItem {
Image(systemName: "1.square.fill")
Text("First")
}
Text("Another Tab")
.tabItem {
Image(systemName: "2.square.fill")
Text("Second")
}
Text("The Last Tab")
.tabItem {
Image(systemName: "3.square.fill")
Text("Third")
}
}
.font(.headline)
三注簿、狀態(tài)的改變
- @State契吉、@Binding, struct诡渴;@StateObject捐晶、@Binding Object、@ObservableObject妄辩、@EnvironmentObject惑灵,class。
- @State
@State private var isVisible = true
......
if isVisible == true {
Text("Hello") // Only rendered when isVisible is true.
}
- @Binding 作用于父子視圖恩袱。
// 子視圖
struct PlayButton: View {
@Binding var isPlaying: Bool
var body: some View {
Button(action: {
self.isPlaying.toggle()
}) {
Image(systemName: isPlaying ? "pause.circle" : "play.circle")
}
}
}
// 父視圖
struct PlayerView: View {
var episode: Episode
@State private var isPlaying: Bool = false
var body: some View {
VStack {
Text(episode.title)
Text(episode.showTitle)
PlayButton(isPlaying: $isPlaying)
}
}
}
- @ObservableObject 即KVO模式泣棋。
class Contact: ObservableObject {
@Published var name: String
@Published var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
func haveBirthday() -> Int {
age += 1
return age
}
}
let john = Contact(name: "John Appleseed", age: 24)
cancellable = john.objectWillChange
.sink { _ in
print("\(john.age) will change")
}
print(john.haveBirthday())
// Prints "24 will change"
// Prints "25"
objectWillChange是ObservableObject協(xié)議的方法。
- EnvironmentObject
class User: ObservableObject {
@Publish var name: String
@Publish var age: Int
}
struct EditView: View {
@EnvironmentObject var user: User
var body: some View {
TextField("Name", text: $user.name)
}
}
struct DisplayView: View {
@EnvironmentObject var user: User
var body: some View {
Text(user.name)
}
}
struct ContentView: View {
let user = User(name: "Jiang", age)
var body: some View {
VStack {
EditView()
DisplayView()\
}.environmentObject(user)
}
}
2 @Environment畔塔、@ FocusState
- @Environment
獲取環(huán)境變量潭辈。
@Environment(\.colorScheme) var colorScheme: ColorScheme
......
if colorScheme == .dark { // Checks the wrapped value.
DarkContent()
} else {
LightContent()
}
- @FocusState
becomefirstresponder
struct LoginForm {
enum Field: Hashable {
case username
case password
}
@State private var username = ""
@State private var password = ""
@FocusState private var focusedField: Field?
var body: some View {
Form {
TextField("Username", text: $username)
.focused($focusedField, equals: .username)
SecureField("Password", text: $password)
.focused($focusedField, equals: .password)
Button("Sign In") {
if username.isEmpty {
focusedField = .username
} else if password.isEmpty {
focusedField = .password
} else {
handleLogin(username, password)
}
}
}
}
}
四、GeometryReader與Path
- GeometryReader
- 獲取屏幕信息澈吨。
GeometryReader { geometry in
HStack(spacing: 0) {
Text("Left")
.font(.largeTitle)
.foregroundColor(.black)
.frame(width: geometry.size.width * 0.33)
.background(Color.yellow)
Text("Right")
.font(.largeTitle)
.foregroundColor(.black)
.frame(width: geometry.size.width * 0.67)
.background(Color.orange)
}
}
.frame(height: 50)
- GeometryReader與Path
var body: some View {
GeometryReader{ geometry in
Path{ path in
path.moveto()
path.addLine()
}
}
}
- Shape
struct Triangle: Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to: CGPoint(x: rect.midX, y: rect.minY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.midX, y: rect.minY))
return path
}
}
五把敢、SwiftUI與UIKit組件互用。
- UIKit用SwiftUI
let swiftUIView = Text("Jiang youhua")
let viewCtrl = UIHostingController(rootView: swiftUIView)
- UIView轉(zhuǎn)SwiftUI
struct TextView: UIViewRepresentable {
@Binding var text: NSMutableAttributedString
func makeUIView(context: Context) -> UITextView {
UITextView()
}
func updateUIView(_ uiView: UITextView, context: Context) {
uiView.attributedText = text
}
}
- UIViewController轉(zhuǎn)SwiftUI
struct PageViewController<Page: View>: UIViewControllerRepresentable {
var pages: [Page]
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[context.coordinator.controllers[0]], direction: .forward, animated: true)
}
class Coordinator: NSObject, UIPageViewControllerDataSource {
var parent: PageViewController
var controllers = [UIViewController]()
init(_ pageViewController: PageViewController) {
parent = pageViewController
controllers = parent.pages.map { UIHostingController(rootView: $0) }
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController?
{
guard let index = controllers.firstIndex(of: viewController) else {
return nil
}
if index == 0 {
return controllers.last
}
return controllers[index - 1]
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController?
{
guard let index = controllers.firstIndex(of: viewController) else {
return nil
}
if index + 1 == controllers.count {
return controllers.first
}
return controllers[index + 1]
}
}
}
好谅辣,我是姜友華修赞,今天就到這里,下次見。