SwiftUI的注意點(diǎn)

Hi, 大家好,我是姜友華。這兩天在適應(yīng)SwiftUI,SwiftUI較Swift UIKit在構(gòu)建APP有較大的改變。在這里,我將其中的注意點(diǎn)記錄下來(lái)。

通常我在學(xué)習(xí)新的界面類開(kāi)發(fā)框架時(shí),回從以下幾個(gè)方面著手:頁(yè)面的構(gòu)建、頁(yè)面的跳轉(zhuǎn)、狀態(tài)的改變、數(shù)據(jù)的傳遞及數(shù)據(jù)的持久化。SwiftUI較Swift UIKit在數(shù)據(jù)的傳遞與數(shù)據(jù)的持久化沒(méi)有變化,所以這里只說(shuō)說(shuō):頁(yè)面的構(gòu)建、頁(yè)面的跳轉(zhuǎn)、數(shù)據(jù)的傳遞。

官網(wǎng)里有有史以來(lái)最好的教程,還有最好的說(shuō)明

一、頁(yè)面的構(gòu)建。

  1. View:
  • Text、
  • Images
  • Buttons
  • Controls
  • Value Selectors
  • Value Indicators
    ...

2.Layout

  • Stack
  • Grids
  • Containers
  • Scroll Views
  • List
  • Tables
  • Spacers and Dividers
    ...

二、頁(yè)面的跳轉(zhuǎn)

  1. 判斷渲染
if isShow {
    MyView()
}
  1. Present
struct ContentView: View {
    @State private var showingSheet = false

    var body: some View {
        Button("Show Sheet") {
            showingSheet.toggle()
        }
        .sheet(isPresented: $showingSheet) {
            backFunc()
        } content: {
            MyView()
        }
    }
}
  1. 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)
    }
}
  1. 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)的改變

  1. @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

  1. 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)
  1. GeometryReader與Path
var body: some View {
       GeometryReader{ geometry in
             Path{ path in 
                path.moveto()
                path.addLine()
            }
      }
}
  1. 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組件互用。

  1. UIKit用SwiftUI
  let swiftUIView = Text("Jiang youhua") 
  let viewCtrl = UIHostingController(rootView: swiftUIView)
  1. 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
    }

}
  1. 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]
        }
    }
}

好,我是姜友華,今天就到這里,下次見(jiàn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • SwiftUI要求 iOS13.0+ 快捷鍵 control + option + 點(diǎn)擊:出現(xiàn)屬性編輯器 comm...
    余青松閱讀 6,766評(píng)論 1 11
  • 學(xué)習(xí)文章 文集:Hacking with iOS: SwiftUI Edition[https://www.jia...
    xmb閱讀 4,696評(píng)論 3 14
  • 最近抽空終于把官方SwiftUI Tutorials擼了一遍,網(wǎng)上已經(jīng)很多翻譯或者該Tutorials說(shuō)明。 這...
    JerrySi閱讀 1,799評(píng)論 0 0
  • 原創(chuàng):有趣知識(shí)點(diǎn)摸索型文章創(chuàng)作不易,請(qǐng)珍惜,之后會(huì)持續(xù)更新,不斷完善個(gè)人比較喜歡做筆記和寫總結(jié),畢竟好記性不如爛筆...
    時(shí)光啊混蛋_97boy閱讀 4,312評(píng)論 1 11
  • SwiftUI簡(jiǎn)介 SwiftUI是wwdc2019發(fā)布的一個(gè)新的UI框架,通過(guò)聲明和修改視圖來(lái)布局UI和創(chuàng)建流暢...
    iridescentzc閱讀 2,387評(píng)論 1 1

友情鏈接更多精彩內(nèi)容