Swift & SwiftUI Tips 01

swift_swiftui_tips_cover

记录最近学习到的一些 Swift 和 Swift UI 的知识。

Swift

defer 关键字

类似 try … catch … finally 语法中的 finally 代码块,defer 后面的代码块在当前代码块结束时一定会被执行。参考:https://www.hackingwithswift.com/new-syntax-swift-2-defer

大写 Self 和 小写 self 的区别

Swift 大写的 Self。用来指代当前类型(运行时的当前类型)。

1
2
3
4
5
6
7
8
extension Sequence where Element: Numeric {
func squareAll() -> [Self.Element] {
return self.map { $0 * $0 }
}
}

print((0...10).squareAll())
// Output: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

参考:https://blog.csdn.net/iCloudEnd/article/details/108972151

在 protocol 中声明只读属性

1
2
3
protocol DataController {    
var viewContext: NSManagedObjectContext { get } // 定义只读属性,需要显式声明 { get }
}

获取字符串长度

获取字符串长度,参考: Swift 中如何正确的获取字符串的长度 | Bruce’s Blog

日期格式化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

extension Date {

// yyyy-MM-dd 格式
func formatDate() -> String {
return formatted(.iso8601
.month()
.day()
.year()
.dateSeparator(.dash)
)
}

// HH:MM:ss 格式
func formatTime() -> String {
return formatted(.dateTime
.locale(.init(identifier: "zh")) // 24小时制格式化依赖locale的格式,https://docs.microsoft.com/en-us/globalization/locale/time-formatting 大部分欧洲和亚洲使用24小时制,这里使用中国
.hour(.twoDigits(amPM: .omitted))
.minute(.twoDigits)
.second(.twoDigits)
)
}
}

获取所有可用的 Locale 的 identify

1
print(Locale.availableIdentifiers)

SwiftUI

在 init 方法中初始化 @State 属性

View 中,如果 @State 属性的初始化需要依赖 init 方法的参数,那么需要在 init 方法中初始化 @State 属性,此时无法直接赋值。

1
2
3
4
5
@State var name: String

init(name: String) {
_name = State(initialValue: name)
}

@State @StateObject @ObservedObject @EnvironmentObject 的区别和使用场景。

  • @State 适用于私有轻量数据。只有当该属性的地址发生变化才会变更,所以 class 引用类型不适用。
  • @StateObject 同样适用于私有数据,但是支持 ObservableObjec 引用类型。引用生命周期依赖 View。
    • @StateObject 声明的属性不会在View初始化的时候初始化,而是在body方法调用前初始化
  • @ObservedObject 用于引用类型的数据。
  • @EnvironmentObject 用于全局数据。

隐藏 List 的 Row 的默认样式

1
2
3
4
5
6
7
8
List {
ForEach(1..<100) { index in
Text("Row \(index)")
.listRowSeparator(.hidden) // 隐藏分割线
.listRowBackground(Color.clear) // 隐藏背景
.listRowInsets(EdgeInsets()) // 取消默认缩进
}
}

其他

Core Data 三种代码生成模式的区别

  • Manual/None: 在项目中生成Entity的NSManagedObject子类,开发者自己管理

  • ClassDefinition: 在build目录中生成同上的NSManagedObject的子类,由XCode管理

  • Category/Extension: 自动生成 CoreDataProperties 文件,但是不会生成 CoreDataClass文件,需要手动编码。(只会生成扩展,但是不会生成类文件)

生成的文件:

  • Xxx+CoreDataClass:类定义
  • Xxx+CoreDataProperties: 由 extension 定义的类的属性

参考:Core Data Codegen Explained!. Compare the differences of each core… | by Lee Kah Seng | Medium

Core Data 如何保存 Date 类型?

时间戳。

NSDate 只是⼀个与基准时间的间隔距离的双精度值的封装,它是⾃ UTC 时间 2001 年 1 ⽉ 1 ⽇午夜以来的秒数。所以 Core Data 在存储⽇期的时候,也只是直接在数据库⾥存储这个双精 度值。NSDate 值⾥不包含时区,所以如果你需要存储时区信息,你还需要为它添加⼀个单独 的属性。但是在⼤多数情况下,只存储 NSDate 值应该就⾜够了。之后在你需要的时候,你可 以使⽤⽤⼾当前的时区,来在 UI ⾥展⽰⽇期。

来自:《Core Data》 objc.io