四.使用关联引用为分类添加数据

  虽然不能在分类中创建实例变量,但是可以创建关联引用(associative reference)。通过关联引用,你可以向任何对象中添加键-值(key-value)数据。

  假如有一个Person类,这个person类可能会被用在其他程序中,有些电子邮件地址(emailAddress)这个字段是有意义的,有些时候这个字段是没有用的。一个比较好的解决方案就是使用分类为Person类添加一个名为emailAddress的属性,这样可以避免不需要emailAddress时的开销。或许Person类并不是你写的,改类的维护者也不会为你添加这个属性。这种情况下,要怎么解决问题看?首先看一下Person类的定义:

  @interface Person:NSObject

  @property (nonatomic, readwrite, copy) NSString *name;

  @end;

  @implementation Person

  @end

  现在使用关联引用在分类中添加一个emailAddress属性:

  #import<objc/runtime.h>

  @interface Person(EmailAddress)

  @property (nonatomic, readwrite, copy) NSString *emailAddress;

  @end

  @implementation Person (EmailAddress)

  static char emailAddressKey;

  - (NSString *)emailAddress{

    return objc_getAssociatedObject(self, &emailAddressKey);

  }

  - (void)setEmailAddress:(NSString *)emailAddress{

    objc_setAssociatedObject(self, &emailAddressKey,emailAddress,OBJC_ASSOCIATION_COPY);

  }

  @end

  可以看出,关联引用是基于键(key)的内存地址的,而不是键的值。在emailAddressKey中储存的内容并不重要,但是它需要一个唯一地址,所以通常使用一个未赋值的static char 作为键。

  如果要在警告面板中关联一个对象,使用关联引用是一个非常好的方式。例:

#import "ViewController.h"

#import <objc/runtime.h>

@implementation ViewController

static const char kRepresentedObject;

- (IBAction)doSomething:(id)sender {

UIAlertView *alert = [[UIAlertViewalloc]

initWithTitle:@"Alert" message:nil

delegate:self

cancelButtonTitle:@"OK"

otherButtonTitles:nil];

objc_setAssociatedObject(alert, &kRepresentedObject,

sender,

OBJC_ASSOCIATION_RETAIN_NONATOMIC);

[alert show];

}

- (void)alertView:(UIAlertView *)alertView

clickedButtonAtIndex:(NSInteger)buttonIndex {

UIButton *sender = objc_getAssociatedObject(alertView,

&kRepresentedObject);

self.buttonLabel.text = [[sender titleLabel] text];

}

@end

五.类扩展(class extension)

  类扩展的声明方式跟分类很像,只不过括号内的名字是空的:

  @interface MyObject()

  - (void)doSomething;

  @end

  类扩展是在.m文件中声明私有方法的一个很棒的方式。不同于分类,在类扩展中声明的方法与在类中声明的方法是完全一致的,这些方法必须全部实现(分类的方法不必全都实现),且在编译时被添加到类中,而分类是在运行时添加。在类扩展中也可以声明合成属性。

六.协议

  协议跟类一样可以继承。协议应该总是继承<NSObject>,就像类总是继承NSObject一样。委托协议(delegate protocol)的第一个参数总是委托对象。正是因此,一个委托才能管理多个委托对象。比如,一个控制器就可以作为多个UIAlertView实例的委托来使用。注意在委托对象之外是否还有其他参数,这对命名约定有一定影响。如果没有参数,类名应该最后出现(numberOfSectionsInTableView:);如果有其他参数,类名要首先出现,作为它自身的参数(tableView:numberOfRowsInSection:)。

  创建协议之后,通常还需要一个属性以便于操作它,通常使用id<Protocol>的方式来声明:

  @property(nonatomic, readwrite, weak) id<MyDelegate> delegate;

  这表示“与MyDelegate协议相容的任何对象”。同事使用类和协议声明一个属性也是可以的,而且可以使用多个协议:

  @property(nonatomic, readwrite, weak) MyClass *<MyDelegate,UITableViewDelegate> delegate;

  这个属性声明是说delegate必须是MyClass或其子类的对象,而且必须同时与<MyDelegate>和<UITableViewDelegate>协议相容。

六.单例

  建议使用Grand Center Dispatch(CCD):

  + (MYSingleton *)sharedSingleton{

    static dispatch_once_t pred;

    static MYSingleton *instance = nil;

    dispatch_once(&pred, ^{instance = [[self alloc] init];});

    return instance;

  }

  这样编写方便、快速,而且线程安全。其他方法要在+sharedSingleton中添加一个@synchronize以达到线程安全的目的,但是这种做法在每次调用+sharedSingleton时都会导致性能显著下降。另外,还可以使用+initialize,但使用GCD的方法最简单。

  强制执行单例:

  + (MYSingleton *)sharedSingleton{

    static dispatch_once_t pred;

    static MYSingleton *instance = nil;

    dispatch_once(&pred, ^{instance = [[self alloc] init];});

    return instance;

  }

  - (id)init{

    //禁用调用-init或new

    NSAssert(NO, @"Cannot create instance of Singleton");

    //在这里,你可以返回nil或[self initSingleton],由你来决定是返回nil还是返回[self...]

    return nil;

   }

  //真正的(私有)init方法

  - (id)initSingleton{

    self = [super init];

    if(self){

      //初始化代码

    }

    return self;

  }

IOS6学习笔记(二)的更多相关文章

  1. WPF的Binding学习笔记(二)

    原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...

  2. AJax 学习笔记二(onreadystatechange的作用)

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  3. [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计

    源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...

  4. JMX学习笔记(二)-Notification

    Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...

  5. java之jvm学习笔记二(类装载器的体系结构)

    java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...

  6. Java IO学习笔记二

    Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...

  7. 《SQL必知必会》学习笔记二)

    <SQL必知必会>学习笔记(二) 咱们接着上一篇的内容继续.这一篇主要回顾子查询,联合查询,复制表这三类内容. 上一部分基本上都是简单的Select查询,即从单个数据库表中检索数据的单条语 ...

  8. NumPy学习笔记 二

    NumPy学习笔记 二 <NumPy学习笔记>系列将记录学习NumPy过程中的动手笔记,前期的参考书是<Python数据分析基础教程 NumPy学习指南>第二版.<数学分 ...

  9. Learning ROS for Robotics Programming Second Edition学习笔记(二) indigo tools

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  10. Redis学习笔记二 (BitMap算法分析与BitCount语法)

    Redis学习笔记二 一.BitMap是什么 就是通过一个bit位来表示某个元素对应的值或者状态,其中的key就是对应元素本身.我们知道8个bit可以组成一个Byte,所以bitmap本身会极大的节省 ...

随机推荐

  1. 为Ubuntu笔记本电脑设置WiFi热点共享上网

    该文由土木坛子转译而来,说是转译,其实看截图就可以方便的设置,没有任何命令,全是图形界面,方便容易.我们都知道怎样在 windows 7 系统上如何设计 Wifi 热点,当你只有一条网线,多台计算机的 ...

  2. java之final关键字

    final关键字(可以读不可以写.只读) 1.final的变量的值不能够被改变 ①.final的成员变量 ②.final的局部变量(形参) //意思是“实参”一旦传进我的方法里面,就不允许改变 2.f ...

  3. 页面头部title、description、keywords标签的优化

    页面头部优化<Head></Head>中间的区域中间的区域,我们称为网页的头部.在网页的头部中,通常存放一些介绍页面内容的信息,例如页面标题.描述及关键字等等.在头部优化中,除 ...

  4. 超实用的JavaScript技巧及最佳实践(上)

    在这篇文章中,作者将会向大家分享JavaScript开发的小技巧.最佳实践等非常实用的内容,不管你是前端开发者还是服务端开发者,都应该来看看这些小技巧,它们绝对会让你受益的. 文中所提供的代码片段都已 ...

  5. ruby 除法运算

    在Ruby中根据运算对象的值的不同进行不同的操作.除法运算符"/"的两边同为Interger对象时运算符进行整除运算,其中任意一方为Float对象时进行实数的除法运算. 7 / 2 ...

  6. Machine Learning : Pre-processing features

    from:http://analyticsbot.ml/2016/10/machine-learning-pre-processing-features/ Machine Learning : Pre ...

  7. (转)linux文件读写的流程

    转自http://hi.baidu.com/_kouu/item/4e9db87580328244ef1e53d0 在<linux内核虚拟文件系统浅析>这篇文章中,我们看到文件是如何被打开 ...

  8. Xcode_cocoaPods-超详细傻瓜式安装教程

    一.Ruby环境: 下载cocoaPods需要Ruby环境. 1. Mac os 10.5以后只带Ruby环境.为了确保万无一失还是查看一下吧. 打开终端 (1)ruby -v (2)更新tuby g ...

  9. iOS-上拉刷新,下拉加载-----------详解

    一.使用的第三方库 1.AFNetworking       ----> 网络请求 2. MJRefresh           ----> 刷新 3. MBProgressHUD  -- ...

  10. iOS-UIButton-设置button标题和图片位置

    一.效果图 1.Button被点击之前 2.Button被点击之后 二.代码 - (void)createBtn3 { UIImage * buttonImage = [UIImage imageNa ...