SwiftUI的认识与使用

SwiftUI简介

SwiftUI是苹果推出的一个新的UI框架,它使用了声明的方式,通过视图,基础控件和布局控件来进行页面的开发。

SwiftUI具有跨平台性,一份SwiftUI代码可以同时跑在iOS、macOS、tvOS、watchOS平台上。

SwiftUI编写的页面代码更简洁,广泛使用链式调用。

SwiftUI视图和UIKit视图可以互相转换,对于将旧的项目过度到新布局方式比较友好。

SwiftUI的运行速度优于UIKit,他减少了界面的层次结构,因此可以减少绘制步骤,并且他完全绕过了CoreAnimation,直接进入Metal,可以有优秀的渲染性能。

其实声明式页面布局前端已经出现了很久,像React, Vue都是使用的声明式布局,声明式布局与命令式布局相比有很多优势,

如:单向数据流,双向数据绑定,只要数据状态改变使用了这些数据的视图就会自动更新等。

声明式布局是UI布局方式的未来,这次苹果从命令式编程过度到声明式编程算是一个大的进步。

设计模式

采用Struct组成的树形结构组织页面。叶子节点是基本控件。

这棵Struct树类似于React的抽象语法树,它会在编译阶段将这些描述信息翻译成真实的UIKit中的UI控件。

视图结构

APP根入口

APP的根入口是一个Struct结构体,它遵守APP协议

1

2

3

4

5

6

7

8

@main

struct WorldLandMarkAppApp {

    var bodysome Scene {

        WindowGroup {

            ContentView()

        }

    }

}

App协议

1

2

3

4

5

6

7

8

public protocol App {

    associatedtype Body Scene

  

    @SceneBuilder @MainActor var bodySelf.Body get }

  

    @MainActor init()

}

页面结构体

some表示返回的是一个遵守了View协议的不透明类型,也就是var body: some View {} 这个计算属性中,只能return一种类型,不能出现if a {Text()} else {List{}} 这样的2种类型。

1

2

3

4

5

struct LandmarkListView {

    var bodysome View {

        Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)

    }

}

View协议

associatedtype Body : View 表示协议中定义了一个新类型Body,这个Body遵守View协议。

Self.Body 表示协议中的Body类型。Self表示类型本身,self表示实例变量本身

1

2

3

4

public protocol View {

    associatedtype Body View

    @ViewBuilder @MainActor var bodySelf.Body get }

}

每个页面swift文件中都有2个结构体,一个表示要开发的页面,另一个是使用Canvas进行展示出来的视图,其中struct ContentView_Previews: PreviewProvider可以根据Debug需要在外层嵌套导航条,展示Group组。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

import SwiftUI

  

struct ContentViewView {

    var bodysome View {

        Text("Hello, world!")

            .padding()

    }

}

  

struct ContentView_PreviewsPreviewProvider {

    static var previewssome View {

        ContentView()

    }

}

它们不一定保持一致,如:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

struct LandmarkList_PreviewsPreviewProvider {

    struct DeviceTypeIdentifiable {

        var id UUID()

        var nameString

    }

      

    static var previewssome View {

        //使用ForEach展示多个设备

        ForEach([DeviceType(name"iPhone 12"),DeviceType(name"iPhone 13")]){ deviceItem in

            LandmarkList().previewDevice(PreviewDevice(rawValuedeviceItem.name))

                .previewDisplayName(deviceItem.name)

        }

          

    }

}

状态双向绑定

@State单页面状态绑定

通过@State修饰的变量是做了双向绑定的,如果这个变量数据发生了改变,所有使用这个变量的视图都会自动更新。但是@State的修饰范围是当前的一个视图,如果想一个状态修改,整个APP范围内使用这个变量的视图全部都更新,则需要使用全局环境变量的模式。

1

2

3

4

5

6

7

@State private var isOpen

struct LandmarkListView {

      

    @State private var isOpenBool false

    //@ObservedObject: 全局环境变量绑定

    @ObservedObject var userDataUserData UserData()

}

@ObservableObject+@Published全局状态变量

要使用全局状态变量,则需要创建一个class,并遵守ObservableObject协议。 然后在这个类中定义一个@Published修饰的变量 @Published var userLandmarks, 当@Published修饰的变量更新时,那么使用了@Published修饰的变量的视图就会对应更新。

定义一个UserData,遵守ObservableObject协议

1

2

3

4

5

6

7

import SwiftUI

import Combine

  

class UserDataObservableObject {

    @Published var userLandmarks:[Landmark] = landmarks

      

}

使用时,也要在对应的视图中加上 @ObservedObject修饰符,然后更新这个变量self.userData.userLandmarks[self.userLandmarkIndex].isFeatured.toggle()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

struct LandmarkDetailView {

    var landmarkLandmark

    @ObservedObject var userDataUserData

      

    var userLandmarkIndexInt {

        userData.userLandmarks.firstIndex(where: {$0.id == landmark.id})!

    }

  

    var bodysome View {

        Button(action: {

            self.userData.userLandmarks[self.userLandmarkIndex]

                .isFeatured.toggle()

        }){

            if landmark.isFeatured {

                Image("icon_rcxinhua_selected")

                    .resizable().frame(width20height20alignment: .center)

            else {

                Image("icon_rcxinhua_defaultselected")

                    .resizable().frame(width20height20alignment: .center)

            }

        }

    }

}

单向数据流

用户操作导致@State变量发生了改变,

@State变量改变导致使用了@State变量的UI视图就会自动更新

继续等待用户操作触发@State变量发生变化

 

UIKit控件与SwiftUI中控件的转换

UIKit转SwiftUI

通过UIViewRepresentable协议将UIView包装成SwifUI的View来使用。

1

2

3

4

5

6

7

8

9

struct MapViewUIViewRepresentable {

    let viewUIView UIView()

    func makeUIView(contextContext) -> some UIView {

        return view

    }

    func updateUIView(_ uiViewUIViewTypecontextContext) {

        view.backgroundColor = .red

    }

}

SwiftUI转UIKit

通过UIHostingController将SwiftUI包装成UIView

1

UIHostingController(rootViewContentView())

Model模型定义

List,ForEach等要求被循环的每个元素都要有一个唯一的标识

这样数据变更时,可以迅速定位刷新对应的UI,提高性能

所以,元素要遵循Identifiable协议(实现id协议)

1

2

3

4

struct LandmarkIdentifiable {

    var id UUID()

    let nameString

}

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
【课程特点】1、231节大容量课程:包含了SwiftUI的大部分知识点,详细讲解SwiftUI的方方面面;2、15个超级精彩的实例:包含美食、理财、健身、教育、电子商务等各行业的App实例;3、创新的教学模式:手把手教您SwiftUI用户界面开发技术,一看就懂,一学就会;4、贴心的操作提示:让您的眼睛始终处于操作的焦点位置,不用再满屏找光标;5、语言简洁精练:瞄准问题的核心所在,减少对思维的干扰,并节省您宝贵的时间;6、视频短小精悍:即方便于您的学习和记忆,也方便日后对功能的检索;7、齐全的学习资料:提供所有课程的源码,在Xcode 11 + iOS 13环境下测试通过; 更好的应用,更少的代码!SwiftUI是苹果主推的下一代用户界面搭建技术,具有声明式语法、实时生成界面预览等特性,可以为苹果手机、苹果平板、苹果电脑、苹果电视、苹果手表五个平台搭建统一的用户界面。SwiftUI是一种创新、简单的iOS开发中的界面布局方案,可以通过Swift语言的强大功能,在所有的Apple平台上快速构建用户界面。 仅使用一组工具和API为任何Apple设备构建用户界面。SwiftUI具有易于阅读和自然编写的声明式Swift语法,可与新的Xcode设计工具无缝协作,使您的代码和设计**同步。自动支持动态类型、暗黑模式、本地化和可访问性,意味着您的**行SwiftUI代码已经是您编写过的非常强大的UI代码了。 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

野生的狒狒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值