美文网首页
Swift属性包装器的使用

Swift属性包装器的使用

作者: fantasy028 | 来源:发表于2023-08-14 14:08 被阅读0次

从Swift5.0开始,Swift引入了属性包装器(propertyWrapper),这应该算是苹果原生应用开发上的一次技术思想的突破吧。即便功能限制性很多,但也为我们解决一些问题带来了方便。比如,我们现在要限制一些数值的取值范围的话,在Objc时代,甚至是Swift早些时候。我们要想要实现这种方法,那么久的在赋值或者取值的过程中进行判断。这从代码上来讲还是侵入性比较强的。但是在Swift5.0引入属性包装器之后,这类问题就得到了解决。下面我们就来一步步了解属性包装器的使用吧。
为了更好的来讨论,我们先设定一个场景:在一个用户信息系统中,我们要存储用户的基本信息,但是要求用户信息中的年龄字段取值只能在0~120之间,如果年龄大于120则取120,小于0则取0,要求使用的时候要保证数据取值的安全性。这个问题我们应该怎么解决呢?
在属性包装器概念引入之前,为了数据的安全性我们基本上在每个使用到年龄大地方,都要写一大堆保护性代码,或者调用一个专门的封装函数来进行处理,如果涉及到某些地方用年龄来过滤或做表,可能还存在一些其他更复杂的问题。当然,为了统一,我们可能会写一个如下的方法:

func fixAge(age: Int) -> Int {
  if age > 120 {
    return 120
  }
  if age < 0 {
    return 0
  }
  return age
}

在使用的时候通过fixAge(age: )调用来达到数据修正的目的。但是,这是一个好办法么?如果我们从代码侵入性角度来看肯定是不好的。下面,我们用属性包装器来实现:

@propertyWrapper
struct AgeWrapper {
    var wrappedValue: Int {
        get {
            return age
        }
        set {
            if newValue > max {
                age = max
            } else if newValue < min {
                age = min
            } else {
                age = newValue
            }
        }
    }
    var age: Int = 0
    var min: Int
    var max: Int
    init(min: Int, max: Int) {
        self.min = min
        self.max = max
    }
}

接下来,我们再来定义变量age

@AgeWrapper(min: 0, max: 120) var age: Int

并给一个调用的实例如下:

print("old value -> \(age)")
age = 139
print("new value -> \(age)")

运行代码会得到如下运行结果

old value -> 0
new value -> 120

好想,我们在使用的时候,完全没有做任何修正,但是我们前面的目的已经达到了。不仅如此,为了实现对年龄限制的的通用性,我们对属性包装器做如下修改:

@propertyWrapper
struct AgeWrapper {
    var wrappedValue: Int {
        get {
            return age
        }
        set {
            age = limitHandle(newValue)
        }
    }
    var age: Int = 0
    var limitHandle: (Int) -> Int
    init(limit handle: @escaping (Int) -> Int) {
        self.limitHandle = handle
    }
}

并将初始化修改如下:

@AgeWrapper(limit: { max(0, min($0, 120)) }) var age: Int

继续运行执行结果,我们会发现,执行的结果与之前是一致的。而且这个包函数也变的更灵活了。
有了一个真实的案例,回过来在看看属性包装器的实现逻辑:

  1. 属性包装器的定义基于一个被@propertyWrapper修饰的struct或class的;
  2. 属性包装起有一个必须实现一个名为wrappedValue的属性;该属性实际负责对真实数据进行修正处理
  3. 在使用定义的属性包装器时,将@属性包装器 放在需要修饰的属性前即可;
  4. 最后就是使用被修饰的变量,只需按照我们正常的使用变量的方式使用即可。

回过头来想想,属性包装器,对于我们已有的未做数据安全保护的代码,是不是现在要进行数据安全性保护的话,将变得更容易呢?

相关文章

网友评论

      本文标题:Swift属性包装器的使用

      本文链接:https://www.haomeiwen.com/subject/ctcqmdtx.html