美文网首页Swift 专栏
SwiftUI的注意点

SwiftUI的注意点

作者: Jiangyouhua | 来源:发表于2021-12-01 15:03 被阅读0次

    Hi, 大家好,我是姜友华。这两天在适应SwiftUI,SwiftUI较Swift UIKit在构建APP有较大的改变。在这里,我将其中的注意点记录下来。

    通常我在学习新的界面类开发框架时,回从以下几个方面着手:页面的构建、页面的跳转、状态的改变、数据的传递及数据的持久化。SwiftUI较Swift UIKit在数据的传递与数据的持久化没有变化,所以这里只说说:页面的构建、页面的跳转、数据的传递。

    官网里有有史以来最好的教程,还有最好的说明

    一、页面的构建。

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

    2.Layout

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

    二、页面的跳转

    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)
    

    三、状态的改变

    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协议的方法。

    • 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
      获取环境变量。
     @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转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转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]
            }
        }
    }
    

    好,我是姜友华,今天就到这里,下次见。

    相关文章

      网友评论

        本文标题:SwiftUI的注意点

        本文链接:https://www.haomeiwen.com/subject/oipyxrtx.html