HoRain云--Swift属性详解

张开发
2026/4/17 15:09:26 15 分钟阅读

分享文章

HoRain云--Swift属性详解
HoRain 云小助手个人主页⛺️生活的理想就是为了理想的生活!⛳️ 推荐前些天发现了一个超棒的服务器购买网站性价比超高大内存超划算忍不住分享一下给大家。点击跳转到网站。目录⛳️ 推荐Swift 属性详解1. 存储属性Stored Properties基本存储属性延迟存储属性2. 计算属性Computed Properties3. 属性观察器Property Observers4. 类型属性Type Properties5. 属性包装器Property Wrappers基本属性包装器带参数的属性包装器带 projectedValue 的属性包装器6. 全局和局部变量7. 属性访问控制8. 属性与内存管理weak 引用属性unowned 引用属性9. 属性键路径Key Paths10. 实际应用示例配置管理网络请求包装最佳实践Swift 属性详解属性是 Swift 中与特定类型、结构体、枚举或类实例关联的值。Swift 提供了多种属性类型每种都有不同的用途。1.存储属性Stored Properties基本存储属性struct Person { // 变量存储属性 var name: String var age: Int 0 // 默认值 // 常量存储属性 let id: String // 延迟存储属性 lazy var complexData: ComplexData ComplexData() // 初始化器 init(name: String, id: String) { self.name name self.id id } } // 使用 var john Person(name: John, id: 001) john.age 30 // john.id 002 // 错误id 是常量延迟存储属性延迟属性只在第一次访问时初始化。class DataImporter { var filename data.txt // 假设这是耗时的初始化 init() { print(DataImporter 被初始化) } } class DataManager { lazy var importer DataImporter() var data: [String] [] } let manager DataManager() manager.data.append(Some data) manager.data.append(Some more data) // 此时 importer 还未被创建 print(manager.importer.filename) // 这里才创建 importer2.计算属性Computed Properties计算属性不存储值而是提供 getter 和可选的 setter 来间接获取和设置其他属性。struct Point { var x 0.0, y 0.0 } struct Size { var width 0.0, height 0.0 } struct Rect { var origin Point() var size Size() // 计算属性 var center: Point { get { let centerX origin.x (size.width / 2) let centerY origin.y (size.height / 2) return Point(x: centerX, y: centerY) } set(newCenter) { origin.x newCenter.x - (size.width / 2) origin.y newCenter.y - (size.height / 2) } } // 使用简写 setter var centerShort: Point { get { Point(x: origin.x size.width / 2, y: origin.y size.height / 2) } set { origin.x newValue.x - size.width / 2 origin.y newValue.y - size.height / 2 } } // 只读计算属性可省略 get 关键字 var area: Double { size.width * size.height } }3.属性观察器Property Observers属性观察器监控和响应属性值的变化。class StepCounter { var totalSteps: Int 0 { willSet(newTotalSteps) { print(即将设置 totalSteps 为 \(newTotalSteps)) } didSet { if totalSteps oldValue { print(增加了 \(totalSteps - oldValue) 步) } } } // 使用默认参数名 var anotherProperty: String { willSet { print(新值: \(newValue), 旧值: \(anotherProperty)) } didSet { print(已更改: 从 \(oldValue) 到 \(anotherProperty)) } } } let stepCounter StepCounter() stepCounter.totalSteps 200 stepCounter.totalSteps 3604.类型属性Type Properties类型属性属于类型本身而不是类型的实例。struct SomeStructure { // 存储型类型属性 static var storedTypeProperty Some value. // 计算型类型属性 static var computedTypeProperty: Int { return 6 } } class SomeClass { // 存储型类型属性 static var storedTypeProperty Some value. // 可被子类重写的计算型类型属性 class var overrideableComputedTypeProperty: Int { return 27 } // 只读的静态计算属性 static var computedTypeProperty: Int { return 42 } } // 访问类型属性 print(SomeStructure.storedTypeProperty) // Some value. SomeStructure.storedTypeProperty Another value. print(SomeClass.overrideableComputedTypeProperty) // 275.属性包装器Property Wrappers属性包装器在管理属性存储方式的代码和定义属性的代码之间添加了一个隔离层。基本属性包装器propertyWrapper struct TwelveOrLess { private var number 0 var wrappedValue: Int { get { number } set { number min(newValue, 12) } } } struct SmallRectangle { TwelveOrLess var height: Int TwelveOrLess var width: Int } var rectangle SmallRectangle() rectangle.height 10 print(rectangle.height) // 10 rectangle.height 24 print(rectangle.height) // 12带参数的属性包装器propertyWrapper struct ClampingValue: Comparable { var value: Value let range: ClosedRangeValue init(wrappedValue: Value, _ range: ClosedRangeValue) { self.range range self.value range.clamp(wrappedValue) } var wrappedValue: Value { get { value } set { value range.clamp(newValue) } } } extension ClosedRange { func clamp(_ value: Bound) - Bound { return Swift.min(Swift.max(value, lowerBound), upperBound) } } struct Temperature { Clamping(0...100) var celsius: Double 0 } var temp Temperature() temp.celsius 50 print(temp.celsius) // 50 temp.celsius 150 print(temp.celsius) // 100 temp.celsius -50 print(temp.celsius) // 0带 projectedValue 的属性包装器propertyWrapper struct UserDefaultsWrapperT { let key: String let defaultValue: T let userDefaults: UserDefaults .standard var wrappedValue: T { get { return userDefaults.object(forKey: key) as? T ?? defaultValue } set { userDefaults.set(newValue, forKey: key) } } // projectedValue 可以提供额外功能 var projectedValue: String { Key: \(key), Value: \(wrappedValue) } } struct Settings { UserDefaultsWrapper(key: darkMode, defaultValue: false) var darkMode: Bool UserDefaultsWrapper(key: fontSize, defaultValue: 16) var fontSize: Int } var settings Settings() settings.darkMode true print(settings.darkMode) // true print(settings.$darkMode) // Key: darkMode, Value: true6.全局和局部变量全局变量是定义在任何函数、方法、闭包或类型上下文之外的变量。局部变量是定义在函数、方法或闭包上下文中的变量。// 全局变量 var globalVariable Im global func someFunction() { // 局部变量 var localVariable Im local // 局部变量也可以有属性观察器 var observedVariable: Int 0 { didSet { print(Local variable changed to \(observedVariable)) } } observedVariable 10 }7.属性访问控制public struct TrackedString { public private(set) var numberOfEdits 0 public var value: String { didSet { numberOfEdits 1 } } public init() {} } var stringToEdit TrackedString() stringToEdit.value This string will be tracked. stringToEdit.value This edit will increment numberOfEdits. stringToEdit.value So will this one. print(The number of edits is \(stringToEdit.numberOfEdits)) // 输出: The number of edits is 3 // stringToEdit.numberOfEdits 0 // 错误setter 是私有的8.属性与内存管理weak 引用属性class Person { let name: String weak var spouse: Person? // 弱引用避免循环引用 init(name: String) { self.name name } deinit { print(\(name) 被释放) } } var john: Person? Person(name: John) var jane: Person? Person(name: Jane) john?.spouse jane jane?.spouse john john nil jane nilunowned 引用属性class Customer { let name: String var card: CreditCard? init(name: String) { self.name name } deinit { print(\(name) 被释放) } } class CreditCard { let number: UInt64 unowned let customer: Customer // 无主引用 init(number: UInt64, customer: Customer) { self.number number self.customer customer } deinit { print(卡号 \(number) 被释放) } } var john: Customer? Customer(name: John Appleseed) john!.card CreditCard(number: 1234_5678_9012_3456, customer: john!) john nil9.属性键路径Key Pathsstruct Person { var name: String var age: Int } let people [ Person(name: Alice, age: 30), Person(name: Bob, age: 25), Person(name: Charlie, age: 35) ] // 键路径 let nameKeyPath \Person.name let ageKeyPath \Person.age // 使用键路径 let names people.map(\.name) // [Alice, Bob, Charlie] let totalAge people.reduce(0) { $0 $1[keyPath: ageKeyPath] } // 实例使用 let person Person(name: David, age: 28) print(person[keyPath: nameKeyPath]) // David // 可写键路径 var peopleMutable people peopleMutable[0][keyPath: nameKeyPath] Alicia // 嵌套键路径 struct Company { var name: String var employees: [Person] } let company Company( name: Tech Corp, employees: [ Person(name: Eve, age: 30), Person(name: Frank, age: 40) ] ) let employeeNamesKeyPath \Company.employees[0].name print(company[keyPath: employeeNamesKeyPath]) // Eve10.实际应用示例配置管理propertyWrapper struct UserDefaultT { let key: String let defaultValue: T init(_ key: String, defaultValue: T) { self.key key self.defaultValue defaultValue } var wrappedValue: T { get { UserDefaults.standard.object(forKey: key) as? T ?? defaultValue } set { UserDefaults.standard.set(newValue, forKey: key) } } } struct UserSettings { UserDefault(isLoggedIn, defaultValue: false) static var isLoggedIn: Bool UserDefault(username, defaultValue: ) static var username: String UserDefault(theme, defaultValue: light) static var theme: String }网络请求包装propertyWrapper struct RequestWrapperT: Decodable { let url: String var value: T? var error: Error? var wrappedValue: T? { mutating get { if value nil error nil { loadData() } return value } set { value newValue } } var projectedValue: Error? { error } private mutating func loadData() { // 实际网络请求代码 // 这里简化处理 } } struct UserProfile { RequestWrapper(url: https://api.example.com/profile) var profile: Profile? var isLoading: Bool { profile nil $profile nil } }最佳实践明智使用 lazy只对确实需要延迟初始化的属性使用避免循环引用适当使用weak和unowned属性包装器的使用抽取重复的访问逻辑属性观察器的时机避免在didSet中设置自身造成无限循环类型属性的线程安全考虑使用dispatch_once模式计算属性缓存对耗时的计算考虑缓存结果属性访问控制最小化暴露使用private(set)键路径的优势在需要动态访问属性时使用Swift 的属性系统非常强大通过合理使用各种属性类型可以编写出更安全、更清晰、更易于维护的代码。❤️❤️❤️本人水平有限如有纰漏欢迎各位大佬评论批评指正如果觉得这篇文对你有帮助的话也请给个点赞、收藏下吧非常感谢! Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧

更多文章