SwiftUI基础之枚举enum 、 结构体、类、属性

1.枚举

枚举为一组相关的值定义了一个共同的类型,使你可以在你的代码中以类型安全的方式来使用这些值。 枚举成员可以指定任意类型的关联值存储到枚举成员中,就像其他语言中的联合体(unions)变体(variants)。你可以在一个枚举中定义一组相关的枚举成员,每一个枚举成员都可以有适当类型的关联值
枚举支持IntDoubleString等基础类型,也有默认枚举值String类型默认枚举值为casekey名称,IntDouble数值型默认枚举值为0开始,+1递增。

// 写法一
// 不需要逗号隔开
enum Weak1 {
    case MON
    case TUE
    case WED
    case THU
    case FRI
    case SAT
    case SUN
}

// 写法二
// 也可以直接一个case,然后使用逗号隔开
enum Weak2 {
    case MON, TUE, WED, THU, FRI, SAT, SUN
}

// 定义一个枚举变量
var w: Weak1 = .MON


/*
String类型的enum
- =左边的值是枚举值,例如 MON
- =右边的值在swift中称为 RawValue(原始值),例如 "MON"
- 两者的关系为:case 枚举值 = rawValue原始值
*/
enum Week: String{
    case MON = "MON"
    case TUE = "TUE"
    case WED = "WED"
    case THU = "THU"
    case FRI = "FRI"
    case SAT = "SAT"
    case SUN = "SUN"
}

2.结构体

声明结构体的关键字是struct,使用起来和类相似,但类的成员是引用类型,而结构体的成员是值类型。
值类型在传递和赋值的时候,是进行复制的,那也就是说在修改一处复制体的时候,原来被复制的对象是不受影响的。
引用类型在传递和赋值的时候,是传递引用对象的一个“指向”,所以当对该引用进行修改的时候,是直接直接修改到最原始的对象,即,一旦修改值,则对该原始对象的所有引用都会被同步修改。
在内存中,引用类型的变量是在堆上存储和操作的。值类型的变量是在栈上存储和操作的。两者相比起来,在堆上的变量操作会比较复杂和耗时。所以苹果官方推荐使用结构体,这样可以提高App的运行效率。
结构体的优势:
结构较小,适用于复制,相比一个class的实例被多次引用,struct结构体更加安全。
无须担心内存泄漏或者多线程冲突安全。

 struct student {
        var name = "name"
        var index = 202100
        var height = 160.00
        var profession = "profession"
        var sex = "男"
    }
    var xiaoMing = student()
    xiaoMing.name = "xiaoMing"
    xiaoMing.index = 202101
    xiaoMing.height = 172.5
    xiaoMing.profession = "计算机科学与技术"
    xiaoMing.sex = "男"
    print("\(xiaoMing)")


运行结果:

student(name: "xiaoMing", index: 202101, height: 172.5, profession: "计算机科学与技术", sex: "男")

3.类

类是引用类型。也就意味着一个类类型的变量并不直接存储具体的实例对象,是对当前存储具体 实例内存地址的引用。

// 定义一个类
class PhoneClass {
    
    // 定义价格属性
    var price: Int = 0
    
    // 定义品牌属性
    var brand: String = ""
    
    // 定义型号属性
    var model: String = ""
    
    // 定义降价促销方法
    func discount() {
        price -= 800
    }
    
    // 当三个属性都有默认值的时候,可以不写 init
    init(price: Int, brand: String, model: String) {
        self.price = price
        self.brand = brand
        self.model = model
    }
}
// 创建 class 实例
var huaweiPhone = PhoneClass(price: 5999, brand: "huawei", model: "p40 pro")

// 类属于引用类型,变量传递后,修改值会影响引用的变量
let huaweiNewPhone = huaweiPhone
huaweiPhone.price += 1000

// 值修改后会影响原变量的值,huaweiPhone.price: 6999, huaweiNewPhone.price: 6999
print("huaweiPhone.price: \(huaweiPhone.price), huaweiNewPhone.price: \(huaweiNewPhone.price)")
       

4.属性

存储属性就是存储在特定类或结构体实例里的一个常量或变量。存储属性可以是变量存储属性(用关键字 var 定义),也可以是常量存储属性(用关键字 let 定义)。

// Swift5 存储属性
class Phone {
    var system = "iOS"
    
    // 常量存储属性,一旦实例化,不能修改
    let brand: String
    
    // 存储属性,可以修改
    var price: Int
    
    // 当类被实例化时,要保证所有的属性都初始化完成,除非属性有默认值
    init(brand: String, price: Int) {
        self.brand = brand
        self.price = price
        print("brand: (brand), price: (price)")
    }
}

// 修改类的属性值
let iPhone = Phone(brand: "iPhone", price: 5999)
iPhone.price -= 600

// 延时存储属性:当类初始化时,延时存储属性不被初始化,当被调用时才初始化
class Consumer {
    var money: Int
    lazy var phone: Phone = Phone(brand: "iPhone", price: 6999)
    
    init(money: Int) {
        self.money = money
    }
}

// 只初始化了money
var richMan = Consumer(money: 100_000)
// 延时属性 phone 被初始化
print(richMan.phone) // brand: iPhone, price: 6999

  • 计算属性

特征:仅有get(readOnly语义)或有get+set的属性是计算型属性,有get+set的属性仅作为其他属性的外部接口
计算型属性本身不占用内存内控,所以不能赋值
get+set为计算型属性的原因:
真正赋值的过程是存在于set方法中并被底层包装掉的,如果我们手动实现了set方法,就无法进行正确的赋值
get+set正确的使用方法:作为其他属性的外部接口

// Swift5 计算属性
class Android {
    // 常量存储属性,一旦实例化,不能修改
    let system: String = "android"
    // 存储属性
    var version = "12"
    // api 级别
    var apiLevel: String = "31"
    
    // 计算属性,向外提供接口访问类实例的某种状态,这种状态和类实例的属性值相关联
    var info: String {
        get {
            return "system: (system), version: (version), level: (apiLevel)"
        }
        set {
            // 默认使用 newValue 指代新值
            version = newValue.split(separator: "-").first?.description ?? ""
            apiLevel = newValue.split(separator: "-").last?.description ?? ""
        }
    }
    
    // 计算属性 价格,简单模拟
    var price: ClosedRange<Int> {
        get {
            // 当版本高于30时,价格在[4000,6999]之间
            if (apiLevel > "30") {
                return 4000...6999
            } else {
                return 1000...3999
            }
        }
        // 自定义传值名称 newPrice
        set(newPrice) {
            // 当价格高于3999时,版本为31
            if (newPrice.lowerBound > 3999) {
                apiLevel = "31"
                version = "12"
            } else {
                apiLevel = "30"
                version = "11"
            }
        }
    }

}

var newPhone = Android()
print(newPhone.info) // system: android, version: 12, level: 31

newPhone.info = "11-30"
print(newPhone.info) // system: android, version: 11, level: 30

newPhone.price = 4000...4999
print(newPhone.info) // system: android, version: 12, level: 31

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容