• iOS的扩展类,扩展属性


      Objective-C有两个扩展机制:Associative和Category。Category用来扩展类方法,Associative用于扩展属性。Associative机制的原理是把两个对象关联起来,让一个对象成为另外一个对象的一部分。它可以在不修改类的定义的前提下为其对象增加存储空间,这在我们无法访问类的源码时(例如给UILable添加一个selected的BOOL属性)是非常有用的。Associative基于关键字的,因此我们可以使用不同的关键字为任何对象添加任意多的Associative。Associative可以保证被关联的对象在对象的整个生命周期都是可用的。Associative基于runtime,是运行时里的东西,所以头文件需要引用#im port<objc/runtime.h>文件。

      Associative提供了三个方法:

    1         objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    2         objc_getAssociatedObject(id object, const void *key)
    3         objc_removeAssociatedObjects(id object)

    详细介绍一下这几个方法,第一个用于设置关联的:

    objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
    注意的是返回值类型为Object类型,注意一些不是Object类型的例如:BOOL是结构类型。当碰到这种情况可以考虑通过中间类型来转换,如设置BOOL类型属性的时候可以转换为NSNumber类型,获取的时候再转换成BOOL类型即可。
    四个参数分别是:源对象,关键字,关联对象和关联策略
    关键字是一个void类型的指针,例如 static void * myKey = (void *)@"MyKey";每一个关联的关键字必须是唯一的。关联策略是枚举类型:
    1     enum{
    2             OBJC_ASSOCIATION_ASSIGN;----------->@property(assign)----------->弱引用关联对象
    3             OBJC_ASSOCIATION_COPY;------------->@property(copy,atomic)------>复制关联对象且为原子操作
    4             OBJC_ASSOCIATION_COPY_NONATOMIC;--->@property(copy,nonatomic)--->复制关联对象且为非原子操作
    5             OBJC_ASSOCIATION_RETAIN;----------->@property(strong,atomic)---->强引用关联对象且为原子操作
    6             OBJC_ASSOCIATION_RETAIN_NONATOMIC;->@property(strong,nonatomic)->强引用且为非原子操作
    7         }

     第二个用于获取关联对象:

            objc_getAssociatedObject(id object, const void *key)
            用于获取关联对象的值。这里需要注意的是返回值类型为Object类型,注意一些不是Object类型的例如:BOOL是结构类型

     第三个 objc_removeAssociatedObjects(id object) 是断开关联,需要注意的是他会断开所有关联,所以不推荐这种方式。需要断开关联的时候使用objc_setAssociatedObject函数,传入nil值即可。

    下面一个示例,我给UILable添加了一个表示选中状态的selected属性,自定义了类似于UIButton的选中非选中状态下设置背景色,字体色的方法。

    .h文件

     1 #import <UIKit/UIKit.h>
     2 #import <objc/runtime.h>
     3 typedef enum{
     4     ControlStateNormal,
     5     ControlStateSelected,
     6 }ControlState;
     7 
     8 @interface UILabel (CellLable)
     9 
    10 
    11 @property(nonatomic,assign)BOOL selected;//设置UILable的选中和非选中状态  default is NO
    12 
    13 -(void)setBackgroundColor:(UIColor *)backgroundColor forState:(ControlState)state ;
    14 
    15 -(void)setTextColor:(UIColor *)textColor forState:(ControlState)state ;
    16 
    17 
    18 @end

    .m文件

      1 #import "UILabel+CellLable.h"
      2 
      3 static    UIColor * normalBackgroundColor = nil ;
      4 static    UIColor * selectedBackgorundColor = nil ;
      5 static    UIColor * normalTextColor = nil ;
      6 static    UIColor * selectedTextColor = nil ;
      7 static    UIColor * firstBackgroundColor = nil ;
      8 static    UIColor * firstTextColor = nil ;
      9 
     10 static    BOOL isHaveSet = NO; //用于在未调用setSelected方法时   设置UILable的默认属性
     11 
     12 //static char const myKey = 'a';
     13 static void * myKey = (void *)@"MyKey";
     14 
     15 @implementation UILabel (CellLable)
     16 
     17 @dynamic selected ;//动态绑定   声明自定义set get 方法,不自动生成
     18 
     19 -(void)setSelected:(BOOL)selected{
     20 
     21 #warning 注意  runtime 里边的objc_setAssociateObject 方法 第三个参数为object类型    BOOL属于结构类型    需要用NSNumber来转换
     22     isHaveSet = YES;
     23     
     24     if (selected) {
     25         
     26         [self setBackgroundColor:nil forState:ControlStateSelected];
     27         
     28         [self setTextColor:nil forState:ControlStateSelected];
     29         
     30     }else if (!selected){
     31         
     32         [self setBackgroundColor:nil forState:ControlStateNormal];
     33         
     34         [self setTextColor:nil forState:ControlStateNormal];
     35     }
     36 
     37     NSNumber * num = [NSNumber numberWithBool:selected];
     38 
     39     objc_setAssociatedObject(self, &myKey, num, OBJC_ASSOCIATION_ASSIGN);
     40 }
     41 
     42 -(BOOL)selected{
     43     
     44     NSNumber * num = objc_getAssociatedObject(self, &myKey);
     45     
     46     return [num boolValue];
     47 }
     48 -(void)setBackgroundColor:(UIColor *)backgroundColor forState:(ControlState )state{
     49     
     50     switch (state) {
     51         case ControlStateNormal:
     52         {
     53             /**  当传递进来的是nil的时候,采取一种保护机制 **/
     54             if (backgroundColor) {
     55                 
     56                 /**   记录上次传递进来的颜色属性   **/
     57                 normalBackgroundColor = backgroundColor ;
     58             }
     59             self.backgroundColor = normalBackgroundColor ;
     60         }
     61             break;
     62         case ControlStateSelected:
     63         {
     64             if (backgroundColor) {
     65                 selectedBackgorundColor = backgroundColor ;
     66             }
     67             self.backgroundColor = selectedBackgorundColor ;
     68         }
     69             break ;
     70         default:
     71             break;
     72     }
     73     
     74     if (!isHaveSet) {
     75         
     76         self.backgroundColor = normalBackgroundColor ;
     77     }
     78 }
     79 
     80 -(void)setTextColor:(UIColor *)textColor forState:(ControlState)state{
     81     
     82     switch (state) {
     83         case ControlStateNormal:
     84         {
     85             if (textColor) {
     86                 normalTextColor = textColor ;
     87             }
     88             self.textColor = normalTextColor ;
     89         }
     90             break;
     91         case ControlStateSelected:
     92         {
     93             if (textColor) {
     94                 selectedTextColor = textColor ;
     95             }
     96             self.textColor = selectedTextColor ;
     97         }
     98             break ;
     99         default:
    100             break;
    101     }
    102     
    103     if (!isHaveSet) {
    104         self.textColor = normalTextColor ;
    105     }
    106 }
    107 
    108 @end

    ViewController.m文件

     1 -(void)viewDidLoad{
     2     UILabel * lable2 =[[UILabel alloc]initWithFrame:CGRectMake(20, 13, 20, 20)];
     3     
     4     lable2.textAlignment = NSTextAlignmentCenter ;
     5     
     6     lable2.layer.masksToBounds = YES ;
     7     
     8     lable2.layer.cornerRadius =10 ;
     9     
    10     lable2.selected = NO ;
    11     
    12     [lable2 setBackgroundColor:[UIColor colorWithRed:48/255.0 green:190/255.0 blue:108/255.0 alpha:1.0] forState:ControlStateSelected];
    13     [lable2 setBackgroundColor:[UIColor clearColor] forState:ControlStateNormal];
    14     
    15     
    16     [lable2 setTextColor:[UIColor whiteColor] forState:ControlStateSelected];
    17     [lable2 setTextColor:[UIColor blackColor] forState:ControlStateNormal];
    18     
    19     
    20     [self.view addSubview:lable2];
    21 }
  • 相关阅读:
    2015上阅读计划
    《梦断代码》读书笔记 第2篇
    四则运算3
    求数组中最大子数组的和(一维)
    四则运算2—单元测试
    四则运算2
    《梦断代码》读书笔记 第1篇
    四组运算2(思路)
    四则运算1
    读书笔记
  • 原文地址:https://www.cnblogs.com/huketianxia/p/5205617.html
Copyright © 2020-2023  润新知