在程序编写过程中,我们常常需要为已有的类扩展新的属性。通常我们的解决办法是先声明一个Key,然后使用objc_getAssociatedObject 和 objc_setAssociatedObject来设置属性。相对来说比较麻烦,因为扩展属性的需求比较大,所以笔者对这两个方法做了一些封装,减少了很多代码。

使用

首先我们来看看封装后如何使用。

把Property.swift拖到你的项目中

让类/Protocol 继承 Property

声明你的属性,get/set参照如下代码

extension View:Property{

var margin : Int{

get{ return get0() }

set{ set0(newValue)}

}

}

是不是非常简单?不过在使用这个Property之前,一定要看清楚注意事项哦。

Property里面默认封装了设置三个属性的方法。

扩展前三个属性的时候分别是 get0() & set0()、get1() & set1()、get2() & set2()

那么超过三个属性应该如何设置呢?

方案1:扩展Property的方法。

方案2:使用Property默认的get() set(),并且需要传入一个变量指针,参考如下代码:

var test : String{

get{ return get(&keyPoint) }

set{ set(&keyPoint, newValue)}

}

也还是比较简单的,毕竟为一个类扩展超过三个以上的属性的需求还是比较小的。

封装过程

首先我们看看,扩展属性通常使用的代码

struct XKeys {

static var common : String = "common"

}

extension AbstractProtocol{

var common : String{

get{

return objc_getAssociatedObject(self, &XKeys.common) as! String

}

set{

objc_setAssociatedObject(self, &XKeys.common, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)

}

}

在复制粘贴了多次这样的代码之后,我实在厌倦了这样扩展属性的方式,然后开始了自己的封装。

首先我发现声明一个Key之后,可以给多个类共用,没有任何影响,但是如果同一个类的不同属性,使用了相同的Key,就会有问题了。所以首先要保证同一个类,扩展出来的不同属性的key值必须要不同。

所以我想到用一个数组来保存key,不过很可惜失败了。

最开始封装Property的时候是直接声明了一个类,写了一些静态方法。然后在get set中调用。

class Property2 {

static func get(_ key: UnsafeRawPointer) -> T{

return objc_getAssociatedObject(self, key) as! T

}

static func set(_ key: UnsafeRawPointer,_ newValue : T) {

objc_setAssociatedObject(self, key, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)

}

}

不过测试过程中发现一些问题,这个self实际应该使用被扩展的对象的类的self,所以经过修改后,代码如下:

class Property2 {

static func get(_ o : Any, _ key: UnsafeRawPointer) -> T{

return objc_getAssociatedObject(o, key) as! T

}

static func set(_ o : Any, _ key: UnsafeRawPointer,_ newValue : T) {

objc_setAssociatedObject(o, key, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)

}

}

调用的时候:

var common : String{

get{

return Property2.get(self, &XKeys.common)

}

set{

Property2.set(self, &XKeys.common, newValue)

}

}

感觉封装了跟没封装基本差不多啊。

有没有办法能省略Property和self呢,于是我想到了Protocol,然后让类去继承我的Property,这样就可以省略掉这两项了。不过Key还是要传递,所以我默认声明了三个key,再提供一个需要传递key的方法。最后封装好的代码为:

// Property.swift

//

// Created by Fancy on 26/1/18.

// Copyright © 2018年 Artifex Software, Inc. All rights reserved.

import UIKit

struct PropertyKey{

static var key0 : Void?

static var key1 : Void?

static var key2 : Void?

}

protocol Property{}

extension Property{

func get(_ key: UnsafeRawPointer) -> T{

return objc_getAssociatedObject(self, key) as! T

}

func set(_ key: UnsafeRawPointer,_ newValue : T) {

objc_setAssociatedObject(self, key, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)

}

func get0() -> T{

return objc_getAssociatedObject(self, &PropertyKey.key0) as! T

}

func set0(_ newValue : T) {

objc_setAssociatedObject(self, &PropertyKey.key0, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)

}

func get1() -> T{

return objc_getAssociatedObject(self, &PropertyKey.key1) as! T

}

func set1(_ newValue : T) {

objc_setAssociatedObject(self, &PropertyKey.key1, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)

}

func get2() -> T{

return objc_getAssociatedObject(self, &PropertyKey.key2) as! T

}

func set2(_ newValue : T) {

objc_setAssociatedObject(self, &PropertyKey.key2, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)

}

}

结语

整个封装过程没有什么高科技含量的操作,写文章做点记录,希望能给到需要的人帮助。

swift. 扩展类添加属性_Swift快速为类扩展属性相关推荐

  1. dreamweaver后缀名_在 Dreamweaver 中添加或编辑识别的文件扩展名

    如果您要对 Dreamweaver 中的以下问题进行故障诊断,请阅读本文: 打开文件时,出现此错误消息:"找不到此文件扩展名的有效编辑器." 代码视图中的颜色编码与所需文件类型的颜 ...

  2. swift. 扩展类添加属性_Swift中用到extension的一些基本的扩展功能讲解

    现有的类,结构或枚举类型的功能可以在扩展的帮助下加入.类型的功能可以使用扩展加入,但重写的功能不能使用扩展. Swift 扩展功能: 添加计算属性并计算类型属性 定义实例和类型的方法 提供了新的初始化 ...

  3. swift. 扩展类添加属性_swift中的声明关键字详解

    原起 学习swift,swift中的关键字当然要了解清楚了,最近在网上看到了关于声明关键字的文章,整理记录一下. 关键字是类似于标识符的保留字符序列,除非用重音符号(`)将其括起来,否则不能用作标识符 ...

  4. 请确保此代码文件中定义的类与“inherits”属性匹配,并且该类扩展的基类(例如Page 或UserControl)是正确的。...

    编译ASP.NET时,提示"请确保此代码文件中定义的类与"inherits"属性匹配,并且该类扩展的基类(例如Page 或UserControl)是正确的.", ...

  5. 【转】分享:c#和javascript函数的相互调用(ObjectForScripting 的类必须对 COM 可见。请确认该对象是公共的,或考虑向您的类添加 ComVisible 属性。)...

    在webBrowser使用过程中为了C#和JS通讯,webBrowser必须设置ObjectForScripting的属性,它是一个object,这个object可以提供给webBrowser控件载入 ...

  6. c#和javascript函数的相互调用(ObjectForScripting 的类必须对 COM 可见。请确认该对象是公共的,或考虑向您的类添加 ComVisible 属性。)...

    在webBrowser使用过程中为了C#和JS通讯,webBrowser必须设置ObjectForScripting的属性,它是一个object,这个object可以提供给webBrowser控件载入 ...

  7. python-类的装饰器-主要给类添加属性用途

    类的装饰器,主要功能可以给类添加属性(类属性) >例子,类的装饰器,给类添加了一个类属性 由该类实例出来的对象,都具备文件保存的能力 def deco(item):def inner():pri ...

  8. python 给类添加属性_python – 如何动态添加属性到类中?

    我想我应该扩大这个答案,现在我年纪大了,更聪明,知道发生了什么.迟到总比不到好. 您可以动态地向类添加属性.但是这是catch:你必须将它添加到类. >>> class Foo(ob ...

  9. Swift UIColor 添加从十六进制值初始化的扩展

    在实际开发中,我们拿到的设计图上的颜色往往标注的是十六进制的,而在不添加第三方库的情况下 UIColor 并不支持从十六进制数字初始化,手动将十六进制颜色转化为 RGB 形式十分浪费精力,我们可以通过 ...

最新文章

  1. hdu 3046(最小割)
  2. Codeforces Round #483 (Div. 2) [Thanks, Botan Investments and Victor Shaburov!]
  3. iccar conference oral presentation
  4. awk -f 分隔符 命令_千面 awk
  5. Visual Studio 即时窗口实用技巧
  6. Java中BigDecimal的8种舍入模式
  7. html:web前端开发规范
  8. “不翻身,就要翻船”!帆软独家:制造业数字化转型解决方案
  9. python模拟登录获取Cookie
  10. jetty9配置指南及jetty9部署jenkins
  11. jquery值ajaxForm
  12. n个labeled顶点k棵树森林计数
  13. bochs运行xp_bochs xp镜像完整版
  14. Oracle定时任务使用
  15. 联想e550笔记本怎么样_摄像头是亮点 — Lenovo 联想 ThinkPad E550C 笔记本 简单评测...
  16. 北方直播卖货搞钱“第一城“,竟然是临沂,200万人发家快手电商
  17. PTA 习题3.6 一元多项式的乘法与加法运算
  18. Unity 3D基础入门编程_艾孜尔江撰稿
  19. Linux下发送邮件
  20. Python爬虫获取股票信息代码分享

热门文章

  1. sublime3使用笔记
  2. php实现最简单的MVC框架实例教程
  3. hdu 4970 Killing Monsters(数学题)
  4. Ubuntu下 VirtualBox的卸载和升级 (转载)
  5. sqlserver连接及设置
  6. nuxt服务端php,nuxt服务端部署上线
  7. node升级命令_Vue CLI 4 发布:自动化升级过程,支持自定义包管理器
  8. delphi switch语句例子_「GCTT 出品」Go 系列教程——10. switch 语句
  9. pci内存控制器是什么驱动_以微软的技术实力, win10还会出现硬盘100%占用的问题,为什么呢?...
  10. android http 慢,android httpurlconnection數據連接速度慢