1、属性只想让外界访问,而不想让他们修改
// 属性只想让外界访问,而不想让他们修改,此时需要 public private(set) var name
csharp
public private(set) var name: String
2、智能排序localizedStandardCompare的用法
比较带有数字的字符串时,可以考虑使用localizedStandardCompare,避免挨个字符比较
swift
/*--------------- 智能排序localizedStandardCompare的用法 -------------------*/
// 比较带有数字的字符串时,可以考虑使用localizedStandardCompare,避免挨个字符比较
let fileNames = [
"File 100.txt",
"File 5.txt",
"File 20.txt"
]
// (1) 数组排序
let resultArr = fileNames.sorted {
$0.localizedStandardCompare($1) == .orderedAscending
}
print(resultArr)
// (2) 排序
let string1 = "File2.txt"
let string2 = "File10.txt"
let res = string1.localizedStandardCompare(string2)
switch res {
case .orderedAscending:
print("(string1) 在 (string2) 之前")
case .orderedDescending:
print("(string1) 在 (string2) 之后")
case .orderedSame:
print("(string1) 在 (string2) 相同")
}
//(3)自定义类型
let fileItem = [
FileItem(name: "File2.txt", size: 100),
FileItem(name: "File10.txt", size: 200),
FileItem(name: "File1.txt", size: 50)
]
let sortedItem = fileItem.sorted()
print(sortedItem)
struct FileItem: Comparable {
let name: String
let size: Int
static func < (lhs: FileItem, rhs: FileItem) -> Bool {
return lhs.name.localizedStandardCompare(rhs.name) == .orderedAscending
}
}
// 文件管理
class FileManagerViewModel: ObservableObject {
@Published var files: [String] = []
func loadFiles() {
let fileManager = FileManager.default
let documentsURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
do {
let allFiles = try fileManager.contentsOfDirectory(atPath: documentsURL.path)
// 智能排序
files = allFiles.sorted {
$0.localizedStandardCompare($1) == .orderedAscending
}
} catch {
}
}
}
3、能用guard的地方尽量使用guard,不要使用if let绑定语法
过多的if let会造成代码缩进,形成类似地狱式回调的代码。同时也影响了可读性,会很难匹配哪个else对应哪个if 可以多使用guard语法,guard会将变量的作用域提升到top level,从而提升可读性,也能使逻辑处理更清晰
javascript
func guardDemo(name: String) {
guard let captureDevice = AVCaptureDevice.default(for: .video) else {
return
}
// 自动白平衡
if captureDevice.isWhiteBalanceModeSupported(.continuousAutoWhiteBalance) {
do {
try captureDevice.lockForConfiguration()
captureDevice.whiteBalanceMode = .continuousAutoWhiteBalance
captureDevice.unlockForConfiguration()
} catch {
}
}
// 自动对焦
if captureDevice.isFocusModeSupported(.continuousAutoFocus) {
do {
try captureDevice.lockForConfiguration()
captureDevice.focusMode = .continuousAutoFocus
captureDevice.unlockForConfiguration()
} catch {
}
}
// 自动曝光
if captureDevice.isExposureModeSupported(.continuousAutoExposure) {
do {
try captureDevice.lockForConfiguration()
captureDevice.exposureMode = .continuousAutoExposure
captureDevice.unlockForConfiguration()
} catch {}
}
}
4、Measurement和MeasurementFormatter的用法
Measurement是swift中用于处理物理测量的强大类型,它结合了数值和单位,提供了类型安全、单位转换和国际化的支持
scss
// 1、创建带有单位的测量值
let distance = Measurement(value: 100, unit: UnitLength.meters)
let temperature = Measurement(value: 20, unit: UnitTemperature.celsius)
let speed = Measurement(value: 60, unit: UnitSpeed.kilometersPerHour)
// 2、长度单位
let length = Measurement(value: 30, unit: UnitLength.kilometers)
let miles = Measurement(value: 10, unit: UnitLength.miles)
let weitht = Measurement(value: 10, unit: UnitMass.kilograms)
// 3、不同单位进行换算(自动换算)
let meters = Measurement(value: 1000, unit: UnitLength.meters)
let kilometers = Measurement(value: 1, unit: UnitLength.kilometers)
let totalLength = meters + kilometers // 2000.0m(kilometers自动转换为m)
// 4、使用MeasurementFormatter格式化显示
let formatter = MeasurementFormatter()
formatter.unitOptions = .providedUnit
formatter.unitStyle = .medium
let dis = Measurement(value: 5.2, unit: UnitLength.kilometers)
print(formatter.string(from: dis)) // 5.2km
// 本地化显示
formatter.locale = Locale(identifier: "zh_CN")
print(formatter.string(from: dis)) // 5.2公里
// 温度格式化
let tempFormatter = MeasurementFormatter()
tempFormatter.numberFormatter.maximumFractionDigits = 1
let temperae = Measurement(value: 23.5, unit: UnitTemperature.celsius)
print(formatter.string(from: temperae)) // 23.5°C
5、CollectionOfOne和CollectionDifference的用法
ColletionOfOne是一个只包含单个元素的集合类型,实现了Collection协议
CollectionDifference表示两个集合之间的差异
在Swift中,applying是CollectionDifference的一个方法,它用于将一个差异(difference)应用到集合上从而生成一个新的集合。这个方法通常用于更新一个数组(或其他集合)以反映另一个数组的状态,而不需要完全替换。
swift
func applying(_ difference: CollectionDifference<Element>) -> [Element]?
let diffArr = newArray.difference(from: oldArray)
let allArr = oldArray.applying(diffArr)
scss
/----- ColletionOfOne是一个只包含单个元素的集合类型,实现了Collection协议---------/
let singleCollection = CollectionOfOne(88)
print(singleCollection.first!) // 88
print(singleCollection.count) // 1
/---------CollectionDifference表示两个集合之间的差异-------------------------/
let oldArray = ["A","B","C","D"]
let newArray = ["A","C","D","E"];
let diffArr = newArray.difference(from: oldArray)
let allArr = oldArray.applying(diffArr)
print("最终结果:(String(describing: allArr))") // 最终结果:Optional(["A", "C", "D", "E"])
for change in diffArr {
switch change {
case .remove(let offset,let element,let associatedWith):
// 移除:索引 1 处的元素 B associatedWith: -1
print("移除:索引 (offset) 处的元素 (element) associatedWith: (associatedWith ?? -1)")
case .insert(let offset,let element,let associatedWith):
// 插入:索引 3 处的元素 E associatedWith: -1
print("插入:索引 (offset) 处的元素 (element) associatedWith: (associatedWith ?? -1)")
}
}
let oldItems = ["a", "b", "c", "d"]
let newItems = ["a", "c", "d", "e"]
let difference = newItems.difference(from: oldItems)
tableView.beginUpdates()
for change in difference {
switch change {
case .remove(let offset, _, _):
tableView.deleteRows(at: [IndexPath(row: offset, section: 0)], with: .fade)
case .insert(let offset, _, _):
tableView.insertRows(at: [IndexPath(row: offset, section: 0)], with: .fade)
}
}
tableView.endUpdates()
6、Swift 中的 #error 用法详解
#error是一个编译时指令,用于在编译过程中生成错误信息并停止编译
csharp
// 强制要求条件
struct API {
#error("请设置 API Key")
static let apiKey = ""
}
// 检查配置
enum Environment {
case development, production
static var current: Environment {
#error("请设置环境变量")
return .development
}
}
// 版本检查
#if swift(<5.0)
#error("此项目需要 Swift 5.0 或更高版本")
#endif
// 框架开发中标记未实现功能
class MyFramework {
func requiredMethod() {
// 标记为必须实现的方法
#error("子类必须重写此方法")
}
}
class CustomImplementation: MyFramework {
override func requiredMethod() {
// 如果不实现,编译会报错
print("实现自定义逻辑")
}
}
#error与 fatalError()这两个都是用于强制停止程序执行,但工作在不同的阶段,有着本质区别:
核心区别总结
| 特性 | #error |
fatalError() |
|---|---|---|
| 执行阶段 | 编译时 | 运行时 |
| 位置 | 代码中任何地方 | 只能在函数/方法体内 |
| 可执行代码 | 不能包含 | 可以包含其他代码 |
| 条件检查 | 编译时条件(#if) |
运行时条件(if, guard) |
| 错误类型 | 编译错误 | 运行时错误 |
| 可捕获 | 否 | 否(但可以设置错误处理) |
| 信息显示 | 编译错误信息 | 运行时崩溃信息 |
7、dump和print的区别
- print: 用于输出一个或多个值到控制台,适合用于简单的调试和日志记录。print函数会添加换行符
- dump: 主要用于输出对象的内部结构,包含其属性(包括私有属性)以及嵌套对象的结构。它会递归地输出一个对象的镜像,显示所有子成员。通常用于调试复杂的对象,比如数组、字典、自定义实例灯