Swift | 属性包装器
Swift | 属性包装器
1. 什么是 Swift Property Wrapper?
Swift Property Wrapper 是一种特性,它允许我们在声明属性时添加自定义的包装逻辑。通过使用属性包装器,我们可以在不修改类或结构体定义的情况下,定制属性的访问和存储方式。这种特性在很多场景下非常有用,例如:属性验证、类型转换、延迟初始化等。
2. 属性包装器的定义与使用
要定义一个属性包装器,我们需要创建一个实现了特定协议的结构体或类。Swift 提供了 @propertyWrapper 属性包装器特性来帮助我们定义包装器。下面是一个完整的示例:
@propertyWrapper
struct MyWrapper {var wrappedValue: Int {willSet {// 自定义包装逻辑print("Value changing to: \(wrappedValue)")}didSet {// 自定义包装逻辑print("Value changed to: \(wrappedValue)")}}init(wrappedValue: Int) {self.wrappedValue = wrappedValue}var projectedValue: Self {return self}
}struct MyStruct {@MyWrapper(wrappedValue: 10)public var myProperty: Int
}var instance = MyStruct()
instance.myProperty = 20 // 输出:Value changed to: 20
instance.$myProperty // 等于:projectedValue
编程接口
willSet:设置新值之前调用。didSet:新值设置完成调用。projectedValue:可以使用instance.$myProperty拿到projectedValue值,方便我们添加前缀、后缀、验证器验证结果等。
3. 演示
3.1. 范围限制
@propertyWrapper
struct RangeLimited {var wrappedValue: Int {didSet {if wrappedValue < lowerBound {wrappedValue = lowerBound} else if wrappedValue > upperBound {wrappedValue = upperBound}}}let lowerBound: Intlet upperBound: Intinit(wrappedValue: Int, range: ClosedRange<Int>) {self.lowerBound = range.lowerBoundself.upperBound = range.upperBoundself.wrappedValue = wrappedValue}var projectedValue: Self {return self}
}struct MyStruct {@RangeLimited(range: 0...100) var myProperty: Int = 0
}var instance = MyStruct()
instance.myProperty = 150
print("myProperty value: \(instance.myProperty) lowerBound: \(instance.$myProperty.lowerBound) upperBound: \(instance.$myProperty.upperBound)") // 输出: myProperty value: 100 lowerBound: 0 upperBound: 100
3.2. 用户名验证器
@propertyWrapper
struct MyUsernameValidator {var wrappedValue: String {didSet {self.isValided = wrappedValue.count >= self.minLength && wrappedValue.count <= self.maxLength}}var isValided: Bool = falsevar minLength: Intvar maxLength: Intinit(wrappedValue: String, minLength: Int, maxLength: Int) {self.wrappedValue = wrappedValueself.minLength = minLengthself.maxLength = maxLength}var projectedValue: Self { self }
}struct MyStruct {@MyUsernameValidator(wrappedValue: "", minLength: 3, maxLength: 10) public var myUsername: String
}var instance = MyStruct()
print("myUsername: \(instance.myUsername) isValided: \(instance.$myUsername.isValided)") // myUsername: isValided: false
instance.myUsername = "yimt"
print("myUsername: \(instance.myUsername) isValided: \(instance.$myUsername.isValided)") // myUsername: yimt isValided: true
4. 注意事项
在使用属性包装器时,需要注意以下几点:
- 属性包装器只能用于类或结构体的属性,不能用于全局变量或局部变量。
- 尽量保持属性包装器的逻辑简洁明了,不要在包装器中实现复杂的业务逻辑。
- 谨慎使用属性包装器,过度使用可能会增加代码复杂性和难以维护。
相关文章:
Swift | 属性包装器
Swift | 属性包装器 1. 什么是 Swift Property Wrapper? Swift Property Wrapper 是一种特性,它允许我们在声明属性时添加自定义的包装逻辑。通过使用属性包装器,我们可以在不修改类或结构体定义的情况下,定制属性的访问和存储方…...
Android改造CardView为圆形View,Kotlin
Android改造CardView为圆形View,Kotlin 可以利用androidx.cardview.widget.CardView的cardCornerRadius特性,将CardView改造成一个圆形的View,技术实现的关键首先设定CardView为一个宽高相等的View(正方形),…...
Idea下面git的使用:变基、合并、优选、还原提交、重置、回滚、补丁
多分支和分支切换 变基和合并 变基是把本项目的所有提交都列出来按顺序一个个提交到目标分支上去 而合并是把两个分支合并起来,但是旧的分支还是可以启动其他分支,在旧的分支上继续开发 master: A -- B -- C -- M/ feature: D -- Emaster: A -…...
【数据结构】什么是算法
🦄个人主页:修修修也 🎏所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 一.算法的定义 1.算法的概念 2.数据结构与算法的关系 二.算法的特性 输入 输出 有穷性 确定性 可行性 三.算法的设计要求 1.正确性 2.可读性 3.健壮性 4.效…...
复旦大学EMBA:揭秘科创企业,领略未来战略!
智能制造,国之重器。作为制造强国建设的主攻方向,智能制造的发展水平关系到我国未来制造业在全球的地位与影响力。发展智能制造,是加快建设现代化产业体系的重要手段,提升供给体系适配性的有力抓手,也是建设数字中国的…...
根据您的数据量定制的ChatGPT,改变客户服务的方式
在当今竞争激烈的商业环境中,提供优质的客户服务对于保持忠诚的客户群和推动业务增长至关重要。客户满意度已成为各行各企业的首要任务,因为它直接影响客户留存和品牌声誉。随着技术的进步,公司不断探索创新解决方案,以增强客户服…...
《Unity Shader 入门精要》笔记03
UnityShader的内置变量(数学篇) Unity内置的变换矩阵摄像机和屏幕参数float3 _WorldSpaceCameraPosfloat4 _ProjectionParamsfloat4 _ZBufferParamsfloat4 unity_OrthoParamsfloat4x4 unity_CameraProjectionfloat4x4 unity_CameraInvProjectionfloat4 u…...
LINUX系统使用软件异地同步数据(灾备)
rsync是linux系统下的数据镜像备份工具。使用快速增量备份工具Remote Sync可以远程同步,支持本地复制,或者与其他SSH、rsync主机同步 一、宝塔环境: 有宝塔软件商城支持,参考:https://www.bt.cn/bbs/thread-98022-1-1.html 二、…...
IDEA Rogstry中找不到compiler.automake.allow.when.app.running问题解决
网上大部分人教我们 先 File > Settings 然后 勾选 Build 下的 Compiler中的 Build project automatically 这些步骤都不会有问题 然后就会让我们 ctrl shift alt / 点 Rogstry 打开后 我人就麻了 根本没有什么 compiler.automake.allow.when.app.running 也不用慌 我们…...
c#设计模式-行为型模式 之 状态模式
🚀简介 状态模式是一种行为设计模式,它允许对象在其内部状态改变时改变其行为,我们可以通过创建一个状态接口和一些实现了该接口的状态类来实现状态模式。然后,我们可以创建一个上下文类,它会根据其当前的状态对象来改…...
使用Docker安装JupyterHub
安装JupyterHub 拉取Jupyter镜像并运行容器 docker run -d -p 8000:8000 --name jupyterhub jupyterhub/jupyterhub jupyterhub # -d:后台运行 # -p 8000:8000:宿主机的8000端口映射容器中的8000端口 # --name jupyterhub:给运行的容器起名…...
SpringCloudGateway网关整合swagger3+Knife4j3,basePath丢失请求404问题
在集成 Spring Cloud Gateway 网关的时候,会出现没有 basePath 的情况,例如定义的 /jeeplus-auth、/jeeplus-system 等微服务前缀导致访问接口404: maven依赖: swagger2于17年停止维护,现在最新的版本为 Swagger3&am…...
html通过使用图像源的协议(protocol)相对 URL 来防止安全/不安全错误
有人知道使用 protocol relative URLs 是否有问题吗?用于图像源以防止混合内容安全警告。 例如链接一张图片: <img src"//domain.com/img.jpg" /> 代替: <img src"http://domain.com/img.jpg" /> or <img src"https…...
【SpringBoot】| Thymeleaf 模板引擎
目录 Thymeleaf 模板引擎 1. 第一个例子 2. 表达式 ①标准变量表达式 ②选择变量表达式(星号变量表达式) ③链接表达式(URL表达式) 3. Thymeleaf的属性 ①th:action ②th:method ③th:href ④th:src ⑤th:text ⑥th:…...
Vue Router的进阶
进阶 导航守卫 官方文档上面描述的会比较深奥,而守卫类型也比较多,其中包含了全局前置守卫、全局解析守卫、全局后置钩子、路由独享守卫、组件内守卫。每一种守卫的作用和用法都不相同。这会使得大家去学习的时候觉得比较困难,这边主要介绍…...
方案:快递站智能视频监控3大亮点汇总
快递站智能视频监控方案是一种利用先进的技术和设备,来提升快递站安全管理和快递流程监控的解决方案。具体包括哪些方面呢?今天小编就带大家来看看! 1、视频监控系统 在快递站的关键区域安装旭帆科技高清摄像头,如快递仓库、操作…...
Direct3D网格
创建网格 我们可以用D3DXCreateMeshFVF函数创建一个"空"网格对象 ,空网格对象是指我们指定了网格的面片总数和顶点总数,然后由该函数为顶点缓存、索引缓存和属性缓存分配大小合适的内存,之后即可手工填入网格数据。 HRESULT WINA…...
docker安装wiki
1.docker pull mediawiki 2.docker run -d --name mywiki -p 8666:80 mediawiki 访问ip:8666,就可以看到配置页面了 3.docker pull mysql docker run -d --name my-mysql -e MYSQL_ROOT_PASSWORD123456 -p 3307:3306 mysql 4.在配置页面链接ip:3307,连接数据库,接下…...
bigemap在林业勘测规划设计行业的一些应用
选择Bigemap的原因: 主要注重影像的时效性,软件的影像时效性比其他的更新快,更清晰。 使用场景: 1.林业督查,主要是根据国家下发的图斑,结合测绘局的影像以及bigemap的较新影像对比去年和今年的林地变化。…...
设计模式学习
文章目录 前言设计模式的七大原则单一职责原则开放封闭原则里氏替换原则依赖倒转原则接口隔离原则合成复用原则迪米特原则总结 GoF二十三种设计模式创建型模式(五种)结构型模式(七种)行为型模式(十一种) 游…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
