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

  虽然不能在分类中创建实例变量,但是可以创建关联引用(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. 自定义控件的自定义的属性attrs.xml下的declare-styleable中format详解

    最近在摸索自定义控件,查找到一些自定义属性的一些资料,解决转载记载下来:看了此详解才方便理解! 我们在做项目的时候,由于android自带的属性不能满足需求,android提供了自定义属性的方法,其中 ...

  2. U盘FAT32转换NTFS格式

    运行----cmd----convert x:/fs:ntfs回车 x标识你的U盘或硬盘盘符 比如你的U盘是H盘,那就是h:/fs:ntfs  FAT32----NTFS是不可逆转的转换.

  3. GDC2014免费slide整理下载

    GDC2014图形和程序相关的部分免费slide整理下载:)http://pan.baidu.com/s/1eQzMrxo gdc14_An Indie Approach to procedural ...

  4. ZOJ 2112 Dynamic Rankings(动态区间第 k 大+块状链表)

    题目大意 给定一个数列,编号从 1 到 n,现在有 m 个操作,操作分两类: 1. 修改数列中某个位置的数的值为 val 2. 询问 [L, R] 这个区间中第 k 大的是多少 n<=50,00 ...

  5. Node.js 的module 系统

    相较于原生的JavaScript,不同的JavaScript文件之间很难共享变量.有鉴于此,Node.js在JavaScript的基础上进行了扩充,引入了require,exports,module三 ...

  6. java 动态创建数据库和动态连接数据库

    项目中有一个需求要动态创建数据库并且要动态连接数据库,本来以为还很难实现呢,在网上找了好久,都不是很理想,最后看到有人说创建数据库时,先连接到任意一个数据库,获得连接后用createStatement ...

  7. .NET面试必备(整理)

    1.简述 private. protected. public. internal 修饰符的访问权限. private : 私有成员, 在类的内部才可以访问.public : 公共成员,完全公开,没有 ...

  8. Netty5 + HTTPS 练习

    本次以<Netty权威指南>第十章里面的例子为基础修改而来 HttpsFileServerHandler.java package com.jieli.nettytest.httpsfil ...

  9. 使用Python画ROC曲线以及AUC值

    from:http://kubicode.me/2016/09/19/Machine%20Learning/AUC-Calculation-by-Python/ AUC介绍 AUC(Area Unde ...

  10. ArcGIS平台中PostgreSQL数据连接配置总结

    通常用户在使用要素服务时,要求数据必须是存放在空间数据库中的.同时,需要将数据库注册到ArcGIS for Server,这样在发布服务时就不需要进行数据拷贝,从而可以节省磁盘空间及服务发布时间.以下 ...