SwiftUI(2)

目录

一、Stepper

二、日期选择器

1.常规选择器

2.改进

(1).labelsHidden()

(2).displayedComponents:.hourAndMinute()

(3)范围

(4)特定日期组件

(5)转换字符串

三、计算按钮

1.打印按钮

​编辑

2.轻按钮

四、URL

1.加载网络图片

2.发起网络请求

3.打开网页

4.例子

五、KPI

1.视图(Views)

2.布局(Layout)

3.修饰符(Modifiers)

4.状态管理(State Management)

5.环境值(Environment Values)

6.视图控制器和导航(View Controllers and Navigation)

7.数据流(Data Flow)

8.列表和集合(Lists and Collections)

10.访问权限和生命周期(Access and Lifecycle)

六、字符串

1.字符串的拆分

2.字符串的检查

3.字符串的一些方法

1..lowercased()

2.trimmingCharacters(in:)

七、动画

1.基本动画

2.改进

1.减缓画面(弹簧画面)

2.动画持续

3.重复

4.动态

5.动画绑定

6.3D旋转

7.手势动画

(1)拖拽

(2)跟踪

8.过渡修饰符

9.旋转2.0


一、Stepper

一个允许用户通过点击来增加或减少值的控件。通常用于设置数量、等级或其他可以递增或递减的数值。

例上图:value:$sleepAmount,中value表示一个可以绑定到控件的值的引用。

$sleepAmount正式提供了这样一个绑定引用,使得Stepper可以读取当前的值。

in表示范围,step表示增加/减少的个数。

Text用于显示,specifier:"%g"是一个格式字符串,用于告诉Swift以自动选择定点或科学计数法(自动删除无关紧要的内容)来格式化浮点数。

二、日期选择器

绑定到date属性,是Swift具有专用的日期和日期类型。

1.常规选择器

2.改进

(1).labelsHidden()

隐藏该点标签。

(2).displayedComponents:.hourAndMinute()

精确时间显示小时和分钟。

(3)范围

1.addingTimeInterval(86400) 方法被用来给这个日期时间对象加上一个时间间隔。这里的时间间隔是 86400 秒,这恰好是一天的秒数(24小时 × 60分钟/小时 × 60秒/分钟 = 86400秒)。所以,tomorrow 变量存储的是从当前时间算起,正好一天后的日期和时间。

2.let range = now ... tomorrow

使用了 范围运算符 ... 来创建一个范围,从 now 到 tomorrow。这个范围包了 now 和 tomorrow 两个端点。range 的类型是 ClosedRange<Date>,表示一个闭区间范围,即范围包括其定义的所有值。

最后有一个in参数与stepper一样,可以为其停供一个日期范围/。

(4)特定日期组件

  1. Calendar.current:获取当前日历(通常是基于用户的区域设置)。
  2. dateComponents(_:from:):是一个方法,用于从给定的日期 someDate 中提取特定的日期组件。
  3. [.hour, .minute]:是一个数组,指定了要提取的日期组件。这里,我们要求提取小时和分钟。
  4. from: someDate:指定了要从中提取组件的日期。
  5. components.hour 尝试从 components 对象中获取小时数。但是,如果 components 对象没有小时这个组件(例如,如果它是从一个没有包含小时信息的日期计算得出的),那么 components.hour 的值将是 nil
  6. (扩展).datePickerStyle(wheelDatePickerStyle():日期选择器样式的轮子。

(5)转换字符串

 1.formatter = DateFormatter()

创建了一个新的 DateFormatter 对象,并将其赋值给变量 formatterDateFormatter 是用来将 Date 对象转换为字符串,或者将字符串转换为 Date 对象的工具。

 2.formatter.timeStyle = .short 

设置了 formatter 的时间样式为短格式。DateFormatter 提供了几种预设的样式,包括 .short.medium.long 和 .full,用于快速设置日期或时间的显示格式。这里 .short 样式通常用于显示小时和分钟的缩写形式,例如 "12:34"。

 3.let dateString = formatter.string(from: Date())

  • Date() 创建了一个表示当前日期和时间的 Date 对象。
  • formatter.string(from: Date()) 使用之前设置好的 formatter 对象,将当前的 Date 对象转换为字符串。转换后的字符串将包含当前的日期和时间,具体格式取决于之前设置的 timeStyle(这里是短格式)。

三、计算按钮

1.打印按钮

2.轻按钮

四、URL

URL 是一个非常重要的概念,因为经常用于加载网络资源,如网络图片、JSON 数据或网页内容。SwiftUI 本身并不直接处理 URL 的加载和解析,结合 Swift 的其他部分(如 Foundation 框架)以及 UIKit(在 iOS 应用中)或 AppKit(在 macOS 应用中)来处理 URL。

使用URL的常见场景:

1.加载网络图片

使用 Image 视图结合 Asset 或 URL 来加载网络图片。

2.发起网络请求

对于更复杂的网络交互,如获取 JSON 数据,通常会使用 URLSession

3.打开网页

在应用中打开一个网页,可以用 UIApplication.shared.open(url:options:completionHandler:)(在 iOS 上)或 NSWorkspace.shared.open(url:)(在 macOS 上)。这通常不是直接在 SwiftUI 视图中完成的,而是在一个动作处理器中调用。

4.例子

  1. Bundle.main.url(forResource: "some-file", withExtension: "txt")

    • Bundle.main:这是当前应用程序的主Bundle的引用。Bundle通常用于存储应用程序的资源,如图像、音频文件、文本文件等。
    • url(forResource: "some-file", withExtension: "txt"):这是Bundle类的一个方法,用于获取指定名称和扩展名的资源的URL。在这个例子中,它尝试找到名为“some-file”并且扩展名为“.txt”的文件。
  2. if let fileContents = try? String(contentsOf: fileURL) { ... }

    • try?:这是一个错误处理机制。它尝试执行后面的代码,但如果在执行过程中发生错误,它不会抛出异常或中断程序的执行,而是返回一个nil值。
    • String(contentsOf: fileURL):这是一个初始化器,用于将文件URL所指向的文件的内容读取为一个字符串。如果文件不存在或无法读取,那么它会失败并返回nil
    • if let fileContents = ...:这是一个条件绑定语句。它尝试将String(contentsOf: fileURL)的结果(可能是一个字符串或nil)绑定到fileContents常量上。如果String(contentsOf: fileURL)成功并返回了一个字符串,那么fileContents就会被赋值为这个字符串,并且if语句的代码块会被执行。如果String(contentsOf: fileURL)失败并返回了nil,那么fileContents就不会被赋值,if语句的代码块也不会被执行。

五、KPI

SwiftUI 提供了大量的 API 来构建用户界面、处理用户交互以及管理状态。下面是一些 SwiftUI 中常见的 API 类别和示例:

1.视图(Views)

SwiftUI 提供了一系列用于构建用户界面的视图组件,如:

  • Text:显示文本。
  • Image:显示图像。
  • Button:可点击的按钮。
  • Slider:滑动条,用于输入一定范围内的值。
  • List 和 ForEach:用于显示列表数据。
  • Stack:将子视图垂直或水平堆叠。
  • ScrollView:可滚动的视图容器。

2.布局(Layout)

SwiftUI 使用布局系统来自动管理视图的排列和尺寸:

  • VStack 和 HStack:垂直和水平堆叠视图。
  • ZStack:在 Z 轴(即堆叠顺序)上排列视图。
  • Frame:设置视图的尺寸和填充。
  • Spacer:在布局中创建空白空间。
  • Padding 和 Insets:添加内边距。

3.修饰符(Modifiers)

修饰符用于配置视图的行为和外观:

  • .background(Color.red):设置背景颜色。
  • .foregroundColor(.white):设置前景颜色(如文本颜色)。
  • .font(.largeTitle):设置字体。
  • .onTapGesture { ... }:添加点击手势。
  • .animation(...):添加动画效果。

4.状态管理(State Management)

SwiftUI 引入了状态的概念,用于管理视图和数据的交互:

  • @State:声明一个可变状态变量。
  • @ObservedObject 或 @StateObject:观察一个对象的状态变化,通常用于视图模型(ViewModels)。
  • @Binding:创建一个双向绑定的状态,允许视图和父视图之间共享和更新数据。

5.环境值(Environment Values)

环境值提供了视图与其环境之间交互的方式:

  • environmentObject:为视图树中的视图提供环境对象。
  • EnvironmentKey:定义环境值的键。

6.视图控制器和导航(View Controllers and Navigation)

虽然 SwiftUI 主要是声明式的,不直接使用传统的视图控制器,但它提供了自己的导航和视图管理方式:

  • NavigationView 和 NavigationLink:实现导航栏和页面间的导航。
  • TabView 和 TabItem:实现标签页导航。
  • Sheet 和 Modal:显示模态视图或表单。

7.数据流(Data Flow)

SwiftUI 支持响应式编程模型,通过数据流来管理视图更新:

  • @Published:在对象内部发布属性更改,通常与 @ObservedObject 或 @StateObject 一起使用。
  • objectWillChange:在对象即将发生变化时通知观察者,这是旧版响应式编程 API 的一部分,但在新代码中通常使用 @Published

8.列表和集合(Lists and Collections)

处理列表数据和集合的 API:

  • List:显示一个动态数组的内容。
  • ForEach:遍历一个数组或集合,为每个元素创建一个视图。
  • Section:在列表中创建分组。

9.访问权限和生命周期(Access and Lifecycle)

SwiftUI 提供了管理视图生命周期和访问权限的 API:

  • onAppear 和 onDisappear:视图出现或消失时调用的回调。
  • init 和 body:视图的初始化和内容定义。
  • updateUIView(对于 UIKit 视图桥接):更新 UIKit 视图的内容。

六、字符串

1.字符串的拆分

将单个字符串转换为字符串数组通常涉及到将字符串按照某种分隔符进行拆分。这可以通过使用components(separatedBy:)方法来实现。这个方法会返回一个包含分割后子字符串的数组。

例子:

  1. let input = " \n\na\n\nb\n\nc\n\n":定义了一个名为 input 的字符串,这个字符串包含了一些空格、换行符和字母。每个字母(a、b、c)都位于自己的行上,并且每行之间都有额外的换行符。

  2. let letters = input.components(separatedBy: "\n"):使用 components(separatedBy:) 方法将 input 字符串按照换行符 "\n" 分割成一个数组。这样,数组 letters 会包含原始字符串中每行分隔出来的部分,包括空行。

  3. let letter = letters.randomElement():使用 randomElement() 方法从 letters 数组中随机选取一个元素。这个方法返回的是 letters 数组中的一个随机元素,如果没有元素则返回 nil。在这个例子中,letter 变量可能会被赋值为 " "(一个空格字符)、"a"、"b"、"c" 或者 nil(如果数组为空),但由于 input 中包含了这些字符,所以更可能的情况是 letter 被赋值为 "a"、"b" 或 "c" 中的一个。

2.字符串的检查

  1. let word = "swift"
    这行代码定义了一个字符串常量 word,并赋值为 "swift"

  2. let checker = UITextChecker()
    这行代码创建了一个 UITextChecker 实例,该实例用于检查字符串中的拼写错误。UITextChecker 是 UIKit 框架中的一个类,用于在 iOS 应用中提供拼写检查功能。

  3. let range = NSRange(location: 0, length: word.utf16.count)
    创建了一个 NSRange 对象,该对象表示 word 字符串的范围。location 参数设置为 0,表示范围的起始位置是字符串的第一个字符;length 参数设置为 word.utf16.count,表示范围的长度等于字符串中 UTF-16 编码的字符数。这里使用 UTF-16 编码是因为 NSRange 通常与基于 UTF-16 的字符串范围一起使用。

  4. let misspelledRange = checker.rangeOfMisspelledWord(in: word, range: range, startingAt: 0, wrap: false, language: "en")
    这行代码调用 checker 实例的 rangeOfMisspelledWord 方法来检查 word 字符串中是否有拼写错误的单词。该方法接受多个参数:

    • in: word 指定要检查的字符串。
    • range: range 指定在 word 中检查的范围。
    • startingAt: 0 表示从范围的起始位置开始检查。
    • wrap: false 表示如果检查到达范围的末尾,不应该回到范围的起始位置继续检查。
    • language: "en" 指定用于拼写检查的语言,这里是英语("en")。

    如果 word 字符串中有拼写错误的单词,misspelledRange 将包含该单词在字符串中的范围;如果没有拼写错误,misspelledRange 的 location 将为 NSNotFound

3.字符串的一些方法

1..lowercased()

返回一个新的小写字符串。

2.trimmingCharacters(in:)

移除字符串两端的空白字符(包括空格、换行符等)。

七、动画

1.基本动画

  1. @State private var animationAmount: CGFloat = 1

    定义了一个私有状态变量 animationAmount,类型为 CGFloat(浮点型,常用于表示图形和动画的数值)。该变量初始化为 1。在 SwiftUI 中,使用 @State 修饰的变量是响应式的,意味着当它的值改变时,与之相关的视图会自动更新。
  2. Button("Tap Me") {

    这行创建了一个按钮,其标签为 "Tap Me"。大括号 { ... } 内是按钮点击时执行的代码块。
  3. self.animationAmount += 1

    当按钮被点击时,animationAmount 的值增加 1。由于 animationAmount 是一个状态变量,这会导致与其相关的视图进行更新。
  4. .padding(50)

    为按钮添加 50 点的内边距。
  5. .scaleEffect(animationAmount)

    应用缩放效果到按钮上,缩放的比例由 animationAmount 决定。随着 animationAmount 的增加,按钮会变得越来越大。
  6. .blur(radius: (animationAmount - 1) * 3)

    应用模糊效果到按钮上,模糊半径由 animationAmount 决定。使用 (animationAmount - 1) * 3 来计算半径,所以当 animationAmount 增加时,模糊效果会更明显。
  7. .animation(.default)

    为上述的动画效果指定默认的动画配置。这确保动画是平滑的,而不是立即完成的。

2.改进

1.减缓画面(弹簧画面)

为前面的动画效果(包括 scaleEffect 和可能的其他动画效果)指定了动画的配置。这里使用了弹簧动画(interpolatingSpring),它模拟了物理世界中弹簧的运动效果。

  • stiffness: 50:这个参数决定了弹簧的刚度。值越大,弹簧越“硬”,即动画回到初始位置的速度越快,动画看起来更加快速和直接。
  • damping: 1:这个参数决定了弹簧的阻尼系数。阻尼决定了弹簧振动时能量损失的速度,即弹簧振动的衰减程度。值越接近 1,振动衰减得越慢,动画的振荡效果越明显;值越小,振动衰减得越快,动画看起来更加平滑。

2.动画持续

  • .animation(...):这是 SwiftUI 中用于设置动画的配置的方法。它告诉 SwiftUI 如何以及以何种速度来执行动画。

  • .easeInOut(...):这是 SwiftUI 提供的一种动画曲线,它表示动画开始时缓慢,然后加速,接着在动画结束时又缓慢下来。这种动画曲线通常给人一种自然且流畅的感觉。

  • duration: 2:这指定了动画的持续时间,单位是秒。在这里,动画会持续 2 秒。

  • .delay(1) 在开始执行动画之前,等待 1 秒。

3.重复

  • .repeatCount(3):这指定了动画应该重复的次数。在这里,动画会重复 3 次。
  • autoreverses: true:这表示动画会在每次执行完毕后自动反转,即动画会按原路返回。如果设置为 false,则动画只会按一个方向执行,不会反转。

  • .repeatForever:这指定了动画应该无限次地重复执行,没有固定的次数限制。
  • autoreverses: true:这表示动画会在每次执行完毕后自动反转,即动画会按原路返回。如果设置为 false,则动画只会按一个方向执行,不会反转。

4.动态

1.overlay:用于在当前视图上叠加另一个视图。叠加的视图会覆盖在原始视图之上,并且可以根据需要进行动画处理。

2..stroke(Color.red):将圆形的边框颜色设置为红色。

3..scaleEffect(animationAmount):应用一个缩放效果到圆形视图上,缩放的比例由 animationAmount 的值决定。随着 animationAmount 的变化,圆形视图的大小也会相应地变化。

4..opacity(Double(2 - animationAmount)):设置圆形视图的透明度。这里使用了 Double(2 - animationAmount) 来计算透明度值,意味着当 animationAmount 增大时,透明度会减小,反之亦然。这种设置可以实现一个视觉上的渐隐效果。

5..animation( Animation.easeInOut(duration:1) .repeatForever(autoreverses:false) ):为前面的动画效果(缩放和透明度变化)指定一个动画配置。动画采用 ease-in-out 的动画曲线,持续时间为 1 秒,并且设置为无限循环,不会自动反转(因为 autoreverses 设置为 false)。

6..onAppear{ self.animationAmount = 2 }:一个视图生命周期修饰符,当视图首次出现在屏幕上时,会执行大括号内的代码。这里,当视图首次出现时,animationAmount 被设置为 2。这个操作将触发上面的动画,因为 animationAmount 的变化会导致视图缩放和透明度改变。

5.动画绑定

  • "Scale amount" 是步进器的标签。
  • value: $animationAmount 表示步进器的当前值绑定到 animationAmount 变量上。$ 符号表示我们正在引用这个变量的响应式绑定。
  • in: 1...10 表示步进器的值范围在 1 到 10 之间。
  • 添加了一个 Spacer(),用于在 Stepper 和 Button 之间创建一些额外的空间,使界面布局更加美观。

-》改进

.animation(Animation.easeInOut(duration: 1).repeatCount(3).autoreverses(true)) 为步进器的值变化添加了一个动画效果。动画是缓入缓出的,持续时间为 1 秒,重复 3 次,并且每次结束后会自动反转。

6.3D旋转

  1. @State private var animationAmount = 0.0 定义了一个私有的状态变量 animationAmount,初始值为 0.0。这个变量用于存储旋转的角度,并且当它的值改变时,任何依赖于它的视图都会更新。

  2. withAnimation(.interpolatingSpring(stiffness: 500, damping: 10)) { ... } 使用一个弹簧动画来执行大括号内的代码块。弹簧动画的刚度(stiffness)设置为 500,阻尼(damping)设置为 10,这会影响动画的响应速度和回弹效果。

  3. self.animationAmount += 360 将 animationAmount 的值增加 360 度,这会导致视图围绕指定的轴旋转一圈。

  4. .rotation3DEffect(.degrees(animationAmount), axis: (x: 0, y: 1, z: 0)) 给按钮添加一个 3D 旋转效果,旋转的角度由 animationAmount 决定,旋转轴是 y 轴(垂直于屏幕向上)。

7.手势动画

(1)拖拽

  1. .offset(dragAmount):这个修饰符用于移动视图的位置。dragAmount 是一个变量,它存储了拖动的偏移量。当 dragAmount 的值改变时,视图会根据这个值在屏幕上移动。

  2. .gesture(...):这个修饰符用于给视图添加一个手势识别器。添加了一个 DragGesture(),它识别拖动手势。

  3. .onChanged { value in ... }:这是一个闭包,当拖动手势发生变化(但还没有结束时)时会被调用。value 参数包含了手势的当前状态信息。

  4. .onEnded { value in ... }:这是另一个闭包,当拖动手势结束时会被调用。在这里,获取了拖动的最终 translation(即拖动的总距离),并将其赋值给 self.dragAmount。这样,视图就会根据这个最终的 dragAmount 值来移动。

(2)跟踪

  1. .offset(self.dragAmount):这个修饰符用于根据 self.dragAmount 的值来移动视图。self.dragAmount 是一个变量,它存储了拖动的偏移量。

  2. .animation(.default.delay(Double(num) * 20)):这个修饰符为接下来的视图更新添加了一个动画效果。动画的延迟时间是 num 乘以 20 的秒数。这意味着,当 self.dragAmount 的值改变时,视图不会立即移动,而是会等待指定的延迟时间后再以动画的形式移动到新的位置。

  3. .gesture(...):这个修饰符用于给视图添加一个手势识别器。

  4. DragGesture():创建一个拖动手势识别器。

  5. .onChanged { value in ... }:这是一个闭包,当拖动手势发生变化(但还没有结束时)时会被调用。在这个闭包中,value.translation 包含了拖动的当前偏移量,这个值被赋给 self.dragAmount,使得视图能够跟随用户的手指移动。

  6. .onEnded { value in ... }:这是另一个闭包,当拖动手势结束时会被调用。在这个闭包中,首先,self.dragAmount 被重置为 .zero,这意味着视图会返回到其原始位置(假设没有其他因素在影响它的位置)。然后,self.enabled.toggle() 被调用,这通常用于切换某个布尔值的状态(例如,从 true 变为 false 或从 false 变为 true)。这可能用于启用或禁用某些功能或视图元素。

8.过渡修饰符

1.withAnimation{ self.isShowingRed.toggle() }:当用户点击按钮时,会执行 withAnimation 块内的代码。withAnimation 用于给状态改变添加动画效果。这里,self.isShowingRed.toggle() 会切换 isShowingRed 这个布尔值的状态,即如果它是 true,则变为 false;如果它是 false,则变为 true

2.transition(.asymmetric(insertion: .scale, removal: .opacity)):设置了矩形在出现(插入)和消失(移除)时的过渡动画效果。insertion: .scale 表示矩形在插入时通过缩放的方式出现,removal: .opacity 表示矩形在移除时通过改变透明度的方式消失。

9.旋转2.0

1..content.rotationEffect(.degrees(amount), anchor: anchor) 用来给 content 视图添加一个旋转效果,旋转的角度是 amount,旋转的中心点是 anchorclipped 是 SwiftUI 中一个常用的修饰符,用来裁剪视图超出其边界的部分。

2.

  • AnyTransition 是 SwiftUI 中用来定义视图转换效果的类型。
  • pivot 是这个扩展中定义的一个静态属性,它的类型是 AnyTransition
  • active 表示转换激活时的状态,这里使用 CornerRotateModifier 创建一个逆时针旋转 90 度(amount: -90)的修饰符,旋转的中心点是视图的左上角(anchor: .topLeading)。
  • identity 表示转换未激活时的状态,这里创建了一个不旋转(amount: 0)的修饰符,同样以视图的左上角为旋转中心点。

  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值