Swift 属性(保姆级教程)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
  • 《从零手撸:仿小红书(微服务架构)》 已完结,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

在 Swift 开发中,“Swift 属性” 是构建对象模型的核心概念之一。无论是定义一个简单的数据容器,还是创建复杂的交互式应用,开发者都需要通过属性来描述对象的特征、行为和状态。对于编程初学者而言,理解属性的分类、特性及应用场景,能够帮助快速掌握面向对象编程的思维方式;而中级开发者则可以通过深入学习属性的高级用法,提升代码的可维护性和扩展性。本文将从基础到进阶,通过实际案例和代码示例,系统解析 Swift 属性的各个方面。


属性的定义与分类

属性的基本概念

属性(Property)是与类、结构体或枚举关联的值存储点,用于描述对象的特征或状态。例如,一个 Person 类可能包含 nameage 等属性,分别存储姓名和年龄的值。

属性的分类
Swift 中的属性主要分为两类:

  1. 存储属性(Stored Properties):直接存储值的属性。
  2. 计算属性(Computed Properties):通过计算返回值的属性,不直接存储数据。

此外,属性还可以附加 属性观察器(Property Observers),用于在值变化时执行特定操作。


存储属性:对象的“记忆体”

存储属性的作用

存储属性是 Swift 属性中最基础的形式,它直接保存一个具体的值。例如:

struct Rectangle {  
    var width: Double  
    var height: Double  
}  

在这个例子中,widthheight 就是存储属性,它们分别保存矩形的宽和高。

延迟存储属性与 lazy 关键字

当属性的初始值需要复杂计算或依赖外部资源时,可以使用 lazy 关键字声明延迟存储属性。这样,属性的初始化会推迟到第一次被访问时执行。

class Database {  
    lazy var connection = openDatabaseConnection() // 延迟初始化数据库连接  
}  

比喻
延迟属性就像一个懒惰的门卫,只有当有人真正需要他时,才会启动工作,从而节省资源。


计算属性:动态值的“智能管家”

计算属性的核心逻辑

计算属性不直接存储值,而是通过 getset 方法动态计算结果。例如,一个 Circle 结构体可以通过半径计算周长:

struct Circle {  
    var radius: Double  
    var circumference: Double {  
        get {  
            return 2 * .pi * radius  
        }  
        set {  
            radius = newValue / (2 * .pi)  
        }  
    }  
}  

在这个例子中,circumference 是计算属性,它的 get 方法返回周长,而 set 方法允许通过修改周长间接调整半径。

无需 get/set 的简化写法

当计算属性仅需提供 get 方法时,可以省略 get 关键字,直接返回表达式:

var area: Double {  
    radius * radius * .pi  
}  

与存储属性的协同工作

计算属性通常依赖存储属性的值,例如:

class Temperature {  
    private var _celsius: Double  
    init(celsius: Double) {  
        _celsius = celsius  
    }  
    var fahrenheit: Double {  
        get { return _celsius * 1.8 + 32 }  
        set { _celsius = (newValue - 32) / 1.8 }  
    }  
}  

属性观察器:值变化的“监控器”

观察器的类型与用途

属性观察器用于监控属性值的变化,并在值修改前后触发特定操作。Swift 提供两种观察器:

  • willSet:在新值被赋予属性前调用。
  • didSet:在新值被赋予属性后调用。

示例

class Person {  
    var name: String {  
        willSet {  
            print("即将将名字从 '\(name)' 改为 '\(newValue)'")  
        }  
        didSet {  
            print("名字已从 '\(oldValue)' 改为 '\(name)'")  
        }  
    }  
}  

调用 person.name = "Alice" 时,会先后触发 willSetdidSet,并输出对应的日志。

观察器的适用场景

  • 日志记录:记录属性变化的历史。
  • 自动更新界面:当属性值变化时,同步更新 UI 元素。
  • 约束验证:确保新值符合业务规则(如年龄不能为负数)。

静态属性与实例属性:全局与个体的区分

实例属性 vs 静态属性

  • 实例属性:每个对象实例独立拥有的属性。例如,Person 类的 name 属于是实例属性,不同 Person 对象的 name 可以不同。
  • 静态属性(Static Properties):通过 static 关键字声明,属于类型本身而非实例。例如:
struct MathConstants {  
    static let pi = 3.141592653589793  
}  

调用时需通过类型名访问:MathConstants.pi

静态属性的局限性

静态属性无法在结构体中使用 lazy 声明,因为它们的生命周期与实例无关。


可选属性与强制解析:安全与风险的平衡

可选属性的声明

若属性可能不包含值,可以将其类型声明为可选类型(如 String?Int?)。例如:

class User {  
    var email: String?  
}  

此时,email 可能为 nil,需通过可选绑定或强制解析(!)访问:

if let userEmail = user.email {  
    print("用户邮箱:\(userEmail)")  
}  

强制解析的陷阱

直接使用 ! 解析可选属性可能导致运行时崩溃,因此需确保值非空:

// 危险操作:若 email 为 nil,会触发崩溃  
let forcedEmail = user.email!  

最佳实践:优先使用可选绑定或默认值,避免强制解析。


属性与内存管理:ARC 的“幕后英雄”

存储属性与内存周期

在 Swift 中,存储属性的内存管理由自动引用计数(ARC)自动处理。例如,当一个对象被释放时,其存储属性的内存也会被回收。

延迟属性的生命周期

延迟属性的 lazy 特性确保其仅在需要时初始化,这有助于节省内存,但需注意其生命周期与所属实例一致。

计算属性的内存优势

由于计算属性不存储值,它们通常占用更少的内存,但需权衡计算开销。例如,频繁访问一个计算复杂的属性可能影响性能。


属性在协议中的应用:约束与扩展

协议中的属性要求

通过协议,可以规定类型必须实现的属性。例如:

protocol Vehicle {  
    var maxSpeed: Double { get set } // 必须实现的读写属性  
    var manufacturer: String { get } // 必须实现的只读属性  
}  

扩展协议添加计算属性

通过协议扩展,可以在协议中提供默认的计算属性实现:

extension Vehicle {  
    var description: String {  
        return "最高速度:\(maxSpeed)km/h"  
    }  
}  

实战案例:综合运用属性特性

案例目标

创建一个 WeatherStation 类,包含以下功能:

  1. 存储当前温度(存储属性)。
  2. 根据温度自动计算天气状态(如“寒冷”或“温暖”)(计算属性)。
  3. 监控温度变化并触发警报(属性观察器)。
class WeatherStation {  
    // 存储属性  
    private(set) var temperature: Double = 20.0 {  
        didSet {  
            if temperature > 35 {  
                print("高温警告!当前温度:\(temperature)℃")  
            } else if temperature < 0 {  
                print("低温警告!当前温度:\(temperature)℃")  
            }  
        }  
    }  
    // 计算属性  
    var weatherCondition: String {  
        switch temperature {  
        case ..<5: return "极寒"  
        case 5..<15: return "寒冷"  
        case 15..<25: return "舒适"  
        case 25..<35: return "炎热"  
        default: return "极端温度"  
        }  
    }  
    // 静态属性  
    static let maxTemperature = 50.0  
}  

通过此案例,读者可以直观理解属性如何协同工作,实现复杂功能。


结论

掌握“Swift 属性”的核心概念和高级用法,是提升代码质量与开发效率的关键。从存储属性的简单值存储,到计算属性的智能计算,再到属性观察器的监控功能,每个特性都在对象模型中扮演着不可或缺的角色。对于开发者而言,理解这些机制不仅能写出更清晰、高效的代码,还能为后续学习泛型、协议扩展等高级主题奠定基础。

在实际开发中,建议根据业务场景灵活选择属性类型,并始终遵循“可选性安全”和“内存友好”原则。通过不断实践与优化,开发者将能够更好地驾驭 Swift 属性的灵活性与强大功能。

最新发布