SwiftUI 学习笔记

1,020 阅读3分钟

IDE相关

1.canvas预览需要确保macOS 10.15及以上

2.创建项目 - User interface需要选择 SwiftUI

3.cmd + 左键 可以操作视图对象,进行嵌套和属性设置

4.inspector修改属性,代码上会同步更新

5.打开 live preview 进行动态预览

6.pin preview 固定当前预览,便于切换文件


UI特性

1.视图内容默认居中,视图布局使用视图属性

2.文本: Text("文本内容")

 文本颜色需要设置.forgroundColor()

 文字字体: .font()

3.常用容器: Stack

  • VStack:子元素竖直排列
  • HStack:子元素水平排列
  • VStack:子元素叠加排列

4.间隔器: Spacer() 使其包含的视图使用父视图的所有空间

5.padding()修饰符: 控制视图边界

6.offset()修饰符: 视图偏移

7.frame()修饰符: 设置大小(默认父视图大小或内容自适应)

8.图片: Image("图片名")

  • 设置圆角: .clipShape()
  • 分层视图: .overlay() 在这个视图前面分层一个次要视图。可用于设置边框,给图片添加文本等
  • 阴影: .shadow(radius: )

9.分组容器: Group  子视图会作为单独的预览呈现在canvas

10.列表: List 

  • 列表使用可标识数据(identifiable data),可以遵循 Identifiable协议,也可以将数据传递到唯一标识每个元素的键路径
        // 如果landmarkData遵守Identifiable协议,不需要id参数
        List(landmarkData, id: \.id) { landmark in

        }

11.导航视图: NavigationView

标题: .navigationBarTitle() 

页面跳转: NavigationLink(destiation: ) {}

12. 动态列表: ForEach - 在List或其他容器视图中加入ForEach来创建动态列表

import SwiftUI
struct LandmarkList: View {
    @State var showFavoritesOnly = true
    var body: some View {
        NavigationView {
            List {
                ForEach(landmarkData) { landmark in
                    if !self.showFavoritesOnly || landmark.isFavorite {
                        NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
                            LandmarkRow(landmark: landmark)
                        }                    }
                }
            }
            .navigationBarTitle(Text("Landmarks"))
        }
    }
}

13.按钮: Button


14.GeometryReader: 可以获取到当时子视图的大小,位置

15.绘图:Path

  • path.move(to:) 起绘点
  • path.addLine(to:) 绘线到
  • path.addQuadCurve(to:control:) 绘制贝塞尔曲线

            Path { path in
                var width: CGFloat = min(geometry.size.width, geometry.size.height)
                let height = width
                let xScale: CGFloat = 0.832
                let xOffset = (width * (1.0 - xScale)) / 2.0
                width *= xScale
                path.move(
                    to: CGPoint(
                        x: xOffset + width * 0.95,
                        y: height * (0.20 + HexagonParameters.adjustment)
                    )
                )
                 
                HexagonParameters.points.forEach {
                    path.addLine(
                        to: .init(
                            x: xOffset + width * $0.useWidth.0 * $0.xFactors.0,
                            y: height * $0.useHeight.0 * $0.yFactors.0
                        )
                     )
                    
                     path.addQuadCurve(
                        to: .init( 
                           x: xOffset + width * $0.useWidth.1 * $0.xFactors.1,
                           y: height * $0.useHeight.1 * $0.yFactors.1
                        ),
                        control: .init(
                            x: xOffset + width * $0.useWidth.2 * $0.xFactors.2,
                            y: height * $0.useHeight.2 * $0.yFactors.2
                        )
                    )
                }
            }

16.线性渐变色:LinearGradient(gradient:startPoint:endPoint:)

17.aspectRatio(_:contentMode:):根据宽高比,内容缩放模式调整视图

状态管理

1.environmentObject(_:) 视图层级结构中,向下传递数据对象

2.@EnvironmentObject 视图层级结构中,较低位置的视图中使用此属性从较高位置的视图接收数据

3.@binding 包装一个值,使它是地址传递,而非值传递

4.@State 包装一个值,这个值改变时,所在的视图会刷新UI

5.@ObservedObject

6.Self:定义协议时使用,代指实现该协议的类型或该类型的子类;作为类方法的返回值使用

7.UIViewRepresentable:要使UIView在SwifUI中可用,需要用UIViewRepresentable对UIView进行包装,实现makeUIView创建View,实现updateUIView刷新View的状态

8.UIViewControllerRepresentable:在SwiftUI中使用UIViewController,需遵守该协议,同时实现makeUIViewController和updateUIViewController创建和管理控制器

9.Coordinator:SwiftUI和UIKit协调器

桥接UIKit的数据绑定(Delegate, Target/Action,DateSource),7/8两个协议的makeCoordinator方法,返回一个协调器

func makeCoordinator() -> Coordinator {
    Coordinator(self)
}
// 在makeUIViewController中绑定coordinator
func makeUIViewController(context: Context) -> UIPageViewController {
    let pageViewController = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
    pageViewController.dataSource = context.coordinator
    return pageViewController
}

通过自定义协调器的init方法,实现交互

class Coordinator: NSObject, UIPageViewControllerDataSource {
    var parent: PageViewController
    init(_ pageViewController: PageViewController) {
        self.parent = pageViewController
    }
    // 数据源方法
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {    }
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {    }
 }

10.SwiftUI in UIKit

SwiftUI中的View使用UIHostingController包装以后可以给UIKit使用

let vc = UIHostingController(rootView: ContentView())

11.main方法变迁

SwiftUI1.0

// 在SceneDelegate的willConnectTosession方法中
if let windowScene = scene as? UIWindowScene {
    let window = UIWindow(windowScene: windowScene)
    window.rootViewController = UIHostingController(rootView: CategoryHome().environmentObject(UserData()))
    self.window = window
    window.makeKeyAndVisible()
}

SwiftUI2.0

// 苹果第一次仅使用SwiftUI来构建整个应用程序,而不是将SwiftUI嵌入UIKit
@main
Struct HelloWorld: APP {
    var body: some Scene {
        WindowGroup {
            Text("Hello, world!").padding()
        }
    }
}