http://blog.csdn.net/shulianghan/article/details/48876843 这个漂亮的文字阴影,搞不到啊,求指教
一. Objective-C 对象简单处理
1. 包装类
(1) 包装类简介
NSValue 和 NSNumber :
-- 通用包装类 NSValue : NSValue 包装单个 short, int, long, float, char, id, 指针 等数据;
-- NSNumber 包装类 : 用于包装 C 语言数据类型;
NSNumber 方法 :
-- "+ numberWithXxx :" : 将特定类型的值包装成 NSNumber;
-- "- initWithXxx :" : 先创建一个 NSNumber 对象, 再用一个基本类型的值来初始化 NSNumber;
-- "- xxxValue :" : 返回 NSNumber 对象包装的基本类型的值;
(2) 包装类代码示例
代码示例 :
- /*************************************************************************
- > File Name: OCNSNumberDemo.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 六 10/ 3 12:50:15 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- NSNumber * num_int = [NSNumber numberWithInt : 10];
- NSNumber * num_double = [NSNumber numberWithDouble : 10];
- NSNumber * num_char = [NSNumber numberWithChar : 'A'];
- NSLog(@"number_int : %d, number_double : %g, num_char : %c",
- [num_int intValue], [num_double doubleValue], [num_char charValue]);
- NSNumber * num_int1 = [[NSNumber alloc] initWithInt : 10];
- NSNumber * num_double1 = [[NSNumber alloc] initWithDouble : 10];
- NSNumber * num_char1 = [[NSNumber alloc] initWithChar : 'A'];
- NSLog(@"number_int1 : %d, number_double1 : %g, num_char1 : %c",
- [num_int1 intValue], [num_double1 doubleValue], [num_char1 charValue]);
- }
- }
-- 执行结果 :
- localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation OCNSNumberDemo.m
- localhost:oc_object octopus$ ./a.out
- 2015-10-03 13:00:46.465 a.out[887:507] number_int : 10, number_double : 10, num_char : A
- 2015-10-03 13:00:46.468 a.out[887:507] number_int1 : 10, number_double1 : 10, num_char1 : A
2. description 方法
(1) description 方法简介
description 方法简介 : 类似于 Java 中 Object 的 toString() 方法;
-- 方法来源 : description 是 NSObject 中定义的, 所有的方法都有该方法;
-- 默认方法 : description 默认方法返回 <类名: 地址>;
-- 输出对象 : NSLog() 函数输出一个对象, 其实输出的是该对象的 description 方法;
-- 示例 : OCPerson * person, 打印 [person description] 和 person 输出结果是一样的;
(2) description 示例代码
示例代码 :
- /*************************************************************************
- > File Name: OCDescriptionDemo.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 六 10/ 3 14:25:28 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface OCDescriptionDemo : NSObject
- @property (nonatomic, copy) NSString * name;
- @property (nonatomic, assign) int age;
- - (id) initWithNameAndAge : (NSString *) set_name setAge : (int) set_age;
- @end
- @implementation OCDescriptionDemo
- @synthesize name;
- @synthesize age;
- - (id) initWithNameAndAge : (NSString *) set_name setAge : (int) set_age
- {
- self.name = set_name;
- self.age = set_age;
- return self;
- }
- - (NSString *) description
- {
- NSString * des = [NSString stringWithFormat :
- @"<OCDescription[name = %@, age = %d]>", self.name, self.age];
- return des;
- }
- @end
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- OCDescriptionDemo * description = [[OCDescriptionDemo alloc] initWithNameAndAge : @"Tom" setAge : 18];
- NSLog(@"%@", description);
- }
- }
-- 执行结果 :
- localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation OCDescriptionDemo.m
- localhost:oc_object octopus$ ./a.out
- 2015-10-03 14:50:18.665 a.out[970:507] <OCDescription[name = Tom, age = 18]>
3. == 或 isEqual : 方法
(1) "==" 运算符
"==" 简介 :
-- 作用 : 判断两个变量是否相等;
-- 前提 : 两个变量都是基本类型, 两个变量相等返回 true; 指针类型变量比较地址没有任何意义;
(2) 常量池
常量池 :
-- 作用 : 保证相同的字符串常量至右一个, 不能出现多个相同的副本;
-- 例外 : 使用 [NSString stringWithFormat] 方法创建的字符串不会放入常量池;
(3) isEqual 方法
"isEqual" 方法简介 :
-- 来源 : isEqual 方法是 NSObject 类提供的实例方法, 用于判断相同类型的两个变量是否相等;
-- 默认 : 默认方法还是比较地址, 需要开发者重写这个方法;
-- NSString 的 isEqual 方法 : NSString 的 isEqual 方法是判断两个字符串是否相等, 包含的字符串相同就会返回 true;
-- isEqualToString 方法 : 方法 : NSString 中定义的 isEqualToString 方法用于判断当前字符串 与 另一个字符串的字符串序列是否相等;
重写 isEqual 方法标准 :
-- 自反性 : 对象 x, [x isEqual : x] 必须返回 true;
-- 对称性 : 对象 x 和 y, 如果 [x isEqual : y] 返回值 必须与 [y isEqual : x] 返回值相同;
-- 传递性 : 对象 x , y 和 z, [x isEqual : y] = true, [y isEqual : z] = true, 那么 x z 也相等;
-- 一致性 : x , y 对象无论调用多少次, 返回值结果都应该保持一致;
-- nil 对比 : 如果 x 不是 nil, [x isEqual : nil] 必须返回 false;
(4) "==" 和 "isEqual" 示例源码
示例源码 :
- /*************************************************************************
- > File Name: OCEqual.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 六 10/ 3 16:07:56 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface OCEqual : NSObject
- @property (nonatomic, copy) NSString * name;
- @property (nonatomic, assign) int age;
- - (id) initWithName : (NSString *) set_name setAge : (int) set_age;
- @end
- @implementation OCEqual
- @synthesize name;
- @synthesize age;
- - (id) initWithName : (NSString *) set_name setAge : (int) set_age
- {
- self.name = set_name;
- self.age = set_age;
- return self;
- }
- - (BOOL) isEqual : (id) other
- {
- if(self == other)
- return YES;
- if(other != nil && [other isMemberOfClass : OCEqual.class])
- {
- OCEqual * equal = (OCEqual *) other;
- return [self.name isEqual : equal.name] && (self.age == equal.age);
- }
- return NO;
- }
- @end
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- int int_a = 10;
- int double_a = 10.0;
- NSLog(@"int_a == double_a : %d", (int_a == double_a));
- NSString * str_a = @"Octopus";
- NSString * str_b = @"Octopus";
- NSString * str_c = [NSString stringWithFormat : @"Octopus"];
- NSString * str_d = [NSString stringWithFormat : @"Octopus"];
- NSLog(@"str_a == str_b : %d, str_c == str_d : %d, [str_c isEqual : str_d] : %d",
- str_a == str_b, str_c == str_d, [str_c isEqual : str_d]);
- OCEqual * equal_a = [[OCEqual alloc] initWithName : @"Tom" setAge : 18];
- OCEqual * equal_b = [[OCEqual alloc] initWithName : @"Jerry" setAge : 20];
- OCEqual * equal_c = [[OCEqual alloc] initWithName : @"Jerry" setAge : 20];
- NSLog(@"[equal_a isEqual : equal_b] : %d, [equal_b isEqual : equal_c] : %d",
- [equal_a isEqual : equal_b], [equal_b isEqual : equal_c]);
- }
- }
-- 执行结果 :
- localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation OCEqual.m
- localhost:oc_object octopus$ ./a.out
- 2015-10-03 16:58:35.690 a.out[1168:507] int_a == double_a : 1
- 2015-10-03 16:58:35.693 a.out[1168:507] str_a == str_b : 1, str_c == str_d : 0, [str_c isEqual : str_d] : 1
- 2015-10-03 16:58:35.693 a.out[1168:507] [equal_a isEqual : equal_b] : 0, [equal_b isEqual : equal_c] : 1
二. 类别 与 扩展
1. Category 类别
(1) 扩展类簇需求
类簇扩展需求 : 开发过程中有时需要扩展类行为;
-- 继承 : 通过继承, 子类在父类基础上添加方法 或者 重写父类方法;
-- 问题 : 如果想要为父类增加一个方法, 子类同时也继承这些方法, 此时使用继承就满足不了这个功能了;
-- 类簇 : OC 中没有接口, 需要接口时, 就会选择定义一个父类, 以该父类派生 N 个子类, 该系列的类被成为 类簇;
-- 类簇扩展方法 : 为父类增加方法, 类簇中得子类同时也增加该方法, 扩展类簇中得父类是最合适的方法;
(2) Category 类别
类别 (category) 简介 :
-- 作用 : 为现有类添加方法, 不需要访问原有类代码, 不需要继承;
-- 有点 : 动态地为现有类添加方法, 将类定义模块化 分布到多个文件中;
(3) Category 类别 接口 语法格式
类别 (category) 接口部分语法格式 :
-- 接口文件类命名 : "类名+类别名.h", 如 要扩展 OCPerson 类, 类别名为 SB, 那么接口文件名就是 "OCPerson+SB.h";
-- 示例 :
- @interface 已有类 (类别名)
- //方法定义
- ...
- @end
-- 类别名 : 必须是项目中没有的类, 定义类别时使用的类名, 必须是已有的类;
-- 圆括号 : 类别名 定义在 需要扩展的已有类之后, 必须使用圆括号括起来;
-- 定义内容 : 类别中一般情况下只定义方法;
(4) Category 类别 实现类 语法格式
类别 (category) 实现部分语法格式 :
-- 实现类文件命名 : "类名+类别名.m", 如 要扩展 OCPerson 类, 类别名为 SB, 那么接口文件名就是 "OCPerson+SB.m";
-- 示例 :
- @implementation 已有类 (类别名)
- //方法定义
- ...
- @end
(5) Category 类别 注意点
注意事项 :
-- 影响范围 : 通过 category 添加新方法后, 会影响到 指定的被扩展的类, 同时也会影响到其子类;
-- 多个类别 : 一个类可以 对应多个类别, 这些类别都可以为类增加方法定义;
-- 类别优点 : 进行模块化设计, 调用私有方法, 实现非正式协议;
(6) Category 扩展 NSNumber 示例
NSNumber 扩展示例 : 为其添加一个计算圆面积的方法;
-- NSNumber+SB.h :
- /*************************************************************************
- > File Name: NSNumber+SB.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 六 10/ 3 18:58:53 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface NSNumber (SB)
- - (NSNumber *) circleAera : (double) radius;
- @end
-- NSNumber+SB.m :
- /*************************************************************************
- > File Name: NSNumber+SB.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 六 10/ 3 19:02:05 2015
- ************************************************************************/
- #import "NSNumber+SB.h"
- @implementation NSNumber (SB)
- - (NSNumber *) circleAera : (double) radius
- {
- double aera = 3.1415926 * radius * radius;
- return [NSNumber numberWithDouble : aera];
- }
- @end
-- NSNumber+SBTest.m :
- /*************************************************************************
- > File Name: NSNumber+SBTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 六 10/ 3 19:08:19 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- #import "NSNumber+SB.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- NSNumber * num = [NSNumber numberWithInt : 3];
- NSNumber * circleAera = [num circleAera : 1];
- NSLog(@"%@", circleAera);
- }
- }
-- 执行结果 :
- localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation NSNumber+SB.m NSNumber+SBTest.m
- localhost:oc_object octopus$ ./a.out
- 2015-10-03 19:18:13.625 a.out[1333:507] 3.1415926
2. Category 类别实际用法
(1) 类的模块化设计
模块化设计简介 :
-- 实现部分唯一 : 定义一个类是, 使用 "类名.h" 定义接口部分, 使用 "类名.m" 定义实现部分, 不能将实现部分定义在多个 ".m" 后缀 文件中;
-- 文件臃肿 : 如果类很大, 将所有的代码放在一个 "类名.m" 文件中, 非常难维护;
(2) 调用私有方法
私有方法调用简介 :
-- 私有方法 : 接口中没有定义, 在实现部分定义的方法是 私有方法, 不允许被外部调用;
-- 调用私有方法一 : 使用 NSObject 的 "performSelector :"执行调用, 也是可以调用私有方法的, 不过此方法会避开语法检查, 导致未知问题;
(3) 调用私有方法 代码示例
代码示例 :
-- OCPrivate.h :
- /*************************************************************************
- > File Name: OCPrivate.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 06:55:34 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface OCPrivate : NSObject
- @property (nonatomic, copy) NSString * name;
- -(void) info;
- @end
-- OCPrivate.m :
- /*************************************************************************
- > File Name: OCPrivate.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 06:57:48 2015
- ************************************************************************/
- #import "OCPrivate.h"
- @implementation OCPrivate
- @synthesize name;
- - (void) info
- {
- NSLog(@"name : %@", self.name);
- }
- - (void) speak
- {
- NSLog(@"Hello World !");
- }
- @end
-- OCPrivate+SB.h :
- /*************************************************************************
- > File Name: OCPrivate+SB.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 07:19:35 2015
- ************************************************************************/
- #import "OCPrivate.h"
- @interface OCPrivate (SB)
- - (void) speak;
- @end
-- OCPrivateTest.m :
- /*************************************************************************
- > File Name: OCPrivateTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 07:22:04 2015
- ************************************************************************/
- #import "OCPrivate+SB.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool
- {
- OCPrivate * priva = [[OCPrivate alloc] init];
- priva.name = @"Tom";
- [priva info];
- [priva speak];
- }
- }
3. extension 扩展
(1) extension 简介
extension 简介 :
-- 作用 : 扩展相当于匿名类别;
-- 语法 :
- @interface 已有类 ()
- {
- //实例变量 ...
- }
- // 方法定义 ...
- @end
-- 用法 : 定义两个头文件, OCExtension.h 和 OCExtension+speak.h, OCExtension.m 导入 OCExtension+speak.h 头文件;
(2) extension 源码示例
源码示例 :
-- OCExtension.h :
- /*************************************************************************
- > File Name: OCExtension.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 08:18:43 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface OCExtension : NSObject
- @property (nonatomic, copy) NSString * name;
- @property (nonatomic, assign) int age;
- - (void) info;
- @end
-- OCExtension+speak.h :
- /*************************************************************************
- > File Name: OCExtension+speak.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 08:31:37 2015
- ************************************************************************/
- #import "OCExtension.h"
- @interface OCExtension ()
- @property (nonatomic, copy) NSString * home;
- - (void) speak : (NSString *) content;
- @end
-- OCExtension.m :
- /*************************************************************************
- > File Name: OCExtension.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 08:27:50 2015
- ************************************************************************/
- #import "OCExtension+speak.h"
- @implementation OCExtension
- @synthesize name;
- @synthesize age;
- @synthesize home;
- - (void) info
- {
- NSLog(@"info : name : %@ , age : %d", self.name, self.age);
- }
- - (void) speak : (NSString *) content
- {
- NSLog(@"%@ speak %@", self.name, content);
- }
- @end
-- OCExtensionTest.m :
- /*************************************************************************
- > File Name: OCExtensionTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 13:20:42 2015
- ************************************************************************/
- #import "OCExtension+speak.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- OCExtension * extension = [[OCExtension alloc] init];
- extension.name = @"Tom";
- extension.age = 18;
- extension.home = @"China";
- [extension info];
- [extension speak : @"Are you fucking kidding me"];
- }
- }
三. 协议 与 委托
1. 类别实现非正式协议
(1) 非正式协议简介
协议简介 :
-- 作用 : OC 中得协议作用相当于其它语言中得接口;
-- 协议表现 : 协议定义的是 多个类 共同的行为规范, 通常定义一组公用方法, 这些方法都没有实现, 方法由类来实现;
非正式协议简介 :
-- 创建 NSObject 类别 : 以 NSObject 为基础, 为 NSObject 创建类别, 为该类别指定新增方法, 即给所有的 NSObject 子类增加了新方法;
-- 实现 NSObject 类别 : 实现 NSObject 类别时, 实现该列别下地所有方法, 即之前在 NSObject 类别中定义的方法;
(2) 非正式协议代码示例
非正式协议代码示例 :
-- NSObject+speak.h : 为 NSObject 定义的类别接口, 所有的继承 NSObject 的类都必须实现该类别中得抽象方法;
- /*************************************************************************
- > File Name: NSObject+speak.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 08:55:48 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface NSObject (speak)
- - (void) speak;
- @end
-- OCNSObjectProtocal.h : NSObject 子类接口, 该接口继承 NSObject 类, 注意 需要导入 NSObject+speak.h 头文件;
- /*************************************************************************
- > File Name: OCNSObjectProtocal.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:00:37 2015
- ************************************************************************/
- #import "NSObject+speak.h"
- @interface OCNSObjectProtocal : NSObject
- @end
-- OCNSObjectProtocal.m : OCNSObjectProtocal 实现类, 在该实现类中必须实现 类别中定义的 speak 方法;
- /*************************************************************************
- > File Name: OCNSObjectProtocal.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:02:03 2015
- ************************************************************************/
- #import "OCNSObjectProtocal.h"
- @implementation OCNSObjectProtocal
- - (void) speak
- {
- NSLog(@"Speak Hello World");
- }
- @end
-- OCNSObjectProtocalTest.m : 测试类, 测试以上代码是否可以执行;
- /*************************************************************************
- > File Name: OCNSObjectProtocalTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:04:31 2015
- ************************************************************************/
- #import "OCNSObjectProtocal.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- OCNSObjectProtocal * obj = [[OCNSObjectProtocal alloc] init];
- [obj speak];
- }
- }
-- 执行结果 :
- bogon:oc_object octopus$ clang -fobjc-arc -framework Foundation OCNSObjectProtocal.m OCNSObjectProtocalTest.m
- bogon:oc_object octopus$ ./a.out
- 2015-10-05 09:06:44.895 a.out[2100:507] Speak Hello World
2. 定义正式协议
(1) 正式协议语法
正式协议语法 :
-- 语法 :
- @protocol 协议名称 <父类协议1, 父类协议2 ...>
- // N 个协议方法
- @end
-- 协议名称规范 : 采用与类名相同的命名规则;
-- 继承规则 : 一个协议 可以有 多个父类协议, 协议只能继承协议, 不能继承类;
-- 方法规则 : 协议中只能定义抽象方法, 不能定义方法实现, 既可以定义类方法, 也可以定义实例方法;
(2) 实现协议
实现协议语法 :
-- 语法 :
- @interface 类名 : 父类 <协议1, 协议2...>
(3) 声明协议变量
变量声明 :
-- 使用原变量声明 : "变量名 * 对象名" , 如 "OCCat * cat";
-- 使用协议定义 : "NSObject <协议1, 协议2 ...> * 对象名", 如 "NSObject<OCProtocolCat> * cat";
-- 使用 id 类型定义 : "id<OCProtocolCat> 对象名", 如 "id<OCProtocolCat> cat", 注意此处没有指针标识;
(4) 正式协议实现代码
代码示例 :
-- OCAnimalProtocol.h : 最基础的协议1;
- /*************************************************************************
- > File Name: OCAnimalProtocol.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:25:41 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @protocol OCAnimalProtocol
- - (void) name;
- - (void) age;
- @end
-- OCProtocolBord.h : 最基础的协议2;
- /*************************************************************************
- > File Name: OCProtocolBord.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:40:08 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @protocol OCProtocolBord
- - (void) fly;
- @end
-- OCProtocolCat.h : 该协议实现了 上面的两个协议;
- /*************************************************************************
- > File Name: OCProtocolCat.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:45:17 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- #import "OCAnimalProtocol.h"
- #import "OCProtocolBord.h"
- @protocol OCProtocolCat <OCAnimalProtocol, OCProtocolBord>
- - (void) purr;
- @end
-- OCCat.h : OCCat 类接口部分, 生命了该类 实现协议 OCProtocolCat 协议;
- /*************************************************************************
- > File Name: OCCat.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:50:21 2015
- ************************************************************************/
- #import "OCProtocolCat.h"
- @interface OCCat : NSObject <OCProtocolCat>
- @end
-- OCCat.m : OCCat 类实现部分;
- /*************************************************************************
- > File Name: OCCat.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:52:45 2015
- ************************************************************************/
- #import "OCCat.h"
- @implementation OCCat
- - (void) name
- {
- NSLog(@"name : cat");
- }
- - (void) age
- {
- NSLog(@"age : 18");
- }
- - (void) fly
- {
- NSLog(@"cat fly");
- }
- - (void) purr
- {
- NSLog(@"cat purr");
- }
- @end
-- OCProtocolTest.m : 以上类的功能测试类;
- /*************************************************************************
- > File Name: OCProtocolTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 10:14:38 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- #import "OCCat.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- OCCat * cat = [[OCCat alloc] init];
- [cat name];
- [cat age];
- [cat fly];
- [cat purr];
- NSObject<OCProtocolCat> * cat1 = [[OCCat alloc] init];
- [cat1 name];
- [cat1 age];
- [cat1 fly];
- [cat1 purr];
- id<OCAnimalProtocol> cat2 = [[OCCat alloc] init];
- [cat2 name];
- [cat2 age];
- }
- }
-- 执行结果 :
- bogon:6.4 octopus$ clang -fobjc-arc -framework Foundation OCCat.m OCProtocolTest.m
- bogon:6.4 octopus$ ./a.out
- 2015-10-05 10:24:20.099 a.out[2271:507] name : cat
- 2015-10-05 10:24:20.101 a.out[2271:507] age : 18
- 2015-10-05 10:24:20.102 a.out[2271:507] cat fly
- 2015-10-05 10:24:20.102 a.out[2271:507] cat purr
- 2015-10-05 10:24:20.102 a.out[2271:507] name : cat
- 2015-10-05 10:24:20.103 a.out[2271:507] age : 18
- 2015-10-05 10:24:20.103 a.out[2271:507] cat fly
- 2015-10-05 10:24:20.104 a.out[2271:507] cat purr
- 2015-10-05 10:24:20.104 a.out[2271:507] name : cat
- 2015-10-05 10:24:20.104 a.out[2271:507] age : 18
3. 委托
委托概念 : 定义协议的类 将 定义协议的方法 委托给 实现协议的类;
-- 好处 : 类具有更好地通用性, 具体的动作交给实现类完成;
创建工程 :
-- 欢迎界面, 选择 Create a new xcode project;
-- 创建一个 OS 下地 Cocoa Application :
-- 创建 工程 :
项目中得源文件 :
-- main.m : main() 函数入口;
-- OCAppDelegate.h : OCAppDelegate 类接口文件;
-- OCAppDelegate.m : OCAppDelegate 类实现部分;
代码示例 :
-- 前置操作 : 删除 MainMenu.xib 文件, 删除 Hello-Info.plist 中的 MainMenu 选项;
-- OCAppDelegate.h :
- //
- // OCAppDelegate.h
- // Hello
- //
- // Created by octopus on 15-10-5.
- // Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
- //
- #import <Cocoa/Cocoa.h>
- //该接口 实现 NSApplicationDelegate 协议
- @interface OCAppDelegate : NSObject <NSApplicationDelegate>
- //定义窗口
- @property (strong) NSWindow *window;
- @end
-- OCAppDelegate.m :
- //
- // OCAppDelegate.m
- // Hello
- //
- // Created by octopus on 15-10-5.
- // Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
- //
- #import "OCAppDelegate.h"
- @implementation OCAppDelegate
- @synthesize window;
- //应用加载完成时回调的方法
- - (void)applicationWillFinishLaunching:(NSNotification *)notification
- {
- //设置窗口属性
- self.window = [[NSWindow alloc] initWithContentRect :
- NSMakeRect(300, 300, 320, 200)
- styleMask:(NSTitledWindowMask | NSMiniaturizableWindowMask |NSClosableWindowMask)
- backing:NSBackingStoreBuffered
- defer:NO];
- self.window.title = @"Hello World";
- //设置文本框属性
- NSTextField * label = [[NSTextField alloc] initWithFrame:NSMakeRect(60, 120, 200, 60)];
- [label setSelectable:YES];
- [label setBezeled:YES];
- [label setDrawsBackground:YES];
- [label setStringValue:@"HELLO WORLD"];
- //设置按钮属性
- NSButton * button = [[NSButton alloc] initWithFrame:NSMakeRect(120, 40, 80, 30)];
- button.title = @"OCTOPUS";
- [button setBezelStyle:NSRoundedBezelStyle];
- [button setBounds:NSMakeRect(120, 40, 80, 30)];
- //将 文本框 和 按钮 添加到窗口中
- [self.window.contentView addSubview:label];
- [self.window.contentView addSubview:button];
- }
- //加载完成时回调的方法
- - (void) applicationDidFinishLaunching:(NSNotification *)notification
- {
- //显示窗口
- [self.window makeKeyAndOrderFront:self];
- }
- @end
-- main.m :
- //
- // main.m
- // Hello
- //
- // Created by octopus on 15-10-5.
- // Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
- //
- #import <Cocoa/Cocoa.h>
- #import "OCAppDelegate.h"
- int main(int argc, const charchar * argv[])
- {
- @autoreleasepool {
- //创建一个实现了 NSApplicationDelegate 协议的对象
- OCAppDelegate * delegate = [[OCAppDelegate alloc] init];
- //获取 NSApplication 单例对象
- [NSApplication sharedApplication];
- //设置代理, 将处理方法委托给 delegate
- [NSApp setDelegate : delegate];
- //开始运行程序
- return NSApplicationMain(argc, argv);
- }
- }
-- 运行结果 :
四. 异常处理
1. @try ... @catch ... @finally ... 异常捕捉
(1) Objective-C 异常机制
Objective-C 异常机制 :
-- 作用 : 开发者将引发异常的代码放在 @try 代码块中, 程序出现异常 使用 @catch 代码块进行捕捉;
-- 每个代码块作用 : @try 代码块存放可能出现异常的代码, @catch 代码块 异常处理逻辑, @finally 代码块回收资源;
-- 语法示例 :
- @try
- {
- // 业务逻辑
- }
- @catch (异常类型名1 ex)
- {
- //异常处理代码
- }
- @catch (异常类型名2 ex)
- {
- //异常处理代码
- }
- // 可以捕捉 N 个 异常 ...
- @finally
- {
- //回收资源
- }
(2) Objective-C 异常处理过程
异常处理过程 :
-- 生成异常对象 : @try 中出现异常, 系统会生成一个异常对象, 该对象提交到系统中 系统就会抛出异常;
-- 异常处理流程 : 运行环境接收到 异常对象时, 如果存在能处理该异常对象的 @catch 代码块, 就将该异常对象交给 @catch 处理, 该过程就是捕获异常, 如果没有 @catch 代码块处理异常, 程序就会终止;
-- @catch 代码块捕获过程 : 运行环境接收到 异常对象 时, 会依次判断该异常对象类型是否是 @catch 代码块中异常或其子类实例, 如果匹配成功, 被匹配的 @catch 就会处理该异常, 都则就会跟下一个 @catch 代码块对比;
-- @catch 处理异常 : 系统将异常对象传递给 @catch 形参, @catch 通过该形参获取异常对象详细信息;
其它注意点 :
-- @try 与 @catch 对应关系 : 一个 @try 代码块 可以对应 多个 @catch 代码块;
-- {} 省略问题 : 异常捕获的 @try @catch @finally 的花括号不可省略;
NSException 异常类 :
-- 简介 : NSException 是 OC 中所有异常的父类;
-- 位置永远在最后 : @catch 代码块捕获异常时查看 异常对象类型是否是 捕获的异常类型 或者其子类, 一旦放在开头, 后面的异常永远不可能捕获;
(3) 异常信息访问
异常信息访问 :
-- name : 返回异常的详细名称;
-- reason : 返回异常引发的原因;
-- userInfo : 返回异常的用户信息, 一个 NSDictionary 对象;
(4) 使用 finally 回收资源
回收物理资源 : @try 代码块中打开物理资源, 数据库 网络连接 文件等, 都需要回收, 在 @finally 中回收最好;
-- 回收位置分析 : 如果再 @try 中回收, 出现异常, 异常后面的代码无法执行, @catch 中回收, 如果不出现异常, 该代码块就不会执行; 因此 finally 中是必执行的代码, 在这里回收最合适;
(5) 异常代码示例
异常代码示例 :
-- OCAnimal.h : 定义协议;
- /*************************************************************************
- > File Name: OCAnimal.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:30:02 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @protocol OCAnimal
- @optional
- - (void) run;
- @end
-- OCCat.h : 定义 OCCat 接口;
- /*************************************************************************
- > File Name: OCCat.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:33:59 2015
- ************************************************************************/
- #import "OCAnimal.h"
- @interface OCCat : NSObject <OCAnimal>
- @end
-- OCCat.m : 定义 OCCat 实现类;
- /*************************************************************************
- > File Name: OCCat.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:36:36 2015
- ************************************************************************/
- #import "OCCat.h"
- @implementation OCCat
- @end
-- OCCatTest.m : 测试类;
- /*************************************************************************
- > File Name: OCCatTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:38:01 2015
- ************************************************************************/
- #import "OCCat.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- OCCat * cat = [[OCCat alloc] init];
- [cat run];
- }
- }
-- 执行结果 :
- bogon:6.5 octopus$ clang -fobjc-arc -framework Foundation OCCat.m OCCatTest.m
- bogon:6.5 octopus$ ./a.out
- 2015-10-05 16:39:23.589 a.out[2985:507] -[OCCat run]: unrecognized selector sent to instance 0x7fd7a3401870
- 2015-10-05 16:39:23.611 a.out[2985:507] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[OCCat run]: unrecognized selector sent to instance 0x7fd7a3401870'
- *** First throw call stack:
- (
- 0 CoreFoundation 0x00007fff903dd25c __exceptionPreprocess + 172
- 1 libobjc.A.dylib 0x00007fff8ecdbe75 objc_exception_throw + 43
- 2 CoreFoundation 0x00007fff903e012d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
- 3 CoreFoundation 0x00007fff9033b044 ___forwarding___ + 452
- 4 CoreFoundation 0x00007fff9033adf8 _CF_forwarding_prep_0 + 120
- 5 a.out 0x0000000108575efd main + 109
- 6 libdyld.dylib 0x00007fff851f35fd start + 1
- )
- libc++abi.dylib: terminating with uncaught exception of type NSException
- Abort trap: 6
(6) 异常捕获代码示例
异常捕获取示例 : 该示例扔使用上面的 OCAnimal.h, OCCat.h, OCCat.m 示例;
-- OCCatTest.m :
- /*************************************************************************
- > File Name: OCCatTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:38:01 2015
- ************************************************************************/
- #import "OCCat.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- @try
- {
- OCCat * cat = [[OCCat alloc] init];
- [cat run];
- }
- @catch (NSException * ex)
- {
- NSLog(@"exception name : %@, reason : %@", ex.name, ex.reason);
- }
- @finally
- {
- NSLog(@"finally execute");
- }
- NSLog(@"success");
- }
- }
-- 执行结果 :
- bogon:6.5 octopus$ clang -fobjc-arc -framework Foundation OCCat.m OCCatTest.m
- bogon:6.5 octopus$ ./a.out
- 2015-10-05 16:53:46.850 a.out[3008:507] -[OCCat run]: unrecognized selector sent to instance 0x7f884bc018b0
- 2015-10-05 16:53:46.853 a.out[3008:507] exception name : NSInvalidArgumentException, reason : -[OCCat run]: unrecognized selector sent to instance 0x7f884bc018b0
- 2015-10-05 16:53:46.853 a.out[3008:507] finally execute
- 2015-10-05 16:53:46.854 a.out[3008:507] success
2. 抛出自定义异常
(1) 自定义异常语法
自定义异常抛出 :
-- 语法 :
- @throw 异常对象;
(2) 自定义异常代码示例
自定义异常代码示例 :
-- OCException.h 接口 :
- /*************************************************************************
- > File Name: OCException.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:58:24 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface OCException : NSException
- @end
-- OCException.m 实现类 :
- /*************************************************************************
- > File Name: OCException.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 17:03:15 2015
- ************************************************************************/
- #import "OCException.h"
- @implementation OCException
- @end
-- OCCatTest.m 测试类 :
- /*************************************************************************
- > File Name: OCCatTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:38:01 2015
- ************************************************************************/
- #import "OCException.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool
- {
- @throw [[OCException alloc]
- initWithName : @"OCException"
- reason : @"this reason is imporant"
- userInfo : nil nil];
- }
- }
-- 执行结果 :
- bogon:6.5 octopus$ clang -fobjc-arc -framework Foundation OCException.m OCCatTest.m
- bogon:6.5 octopus$ ./a.out
- 2015-10-05 17:04:12.432 a.out[3040:507] *** Terminating app due to uncaught exception 'OCException', reason: 'this reason is imporant'
- *** First throw call stack:
- (
- 0 CoreFoundation 0x00007fff903dd25c __exceptionPreprocess + 172
- 1 libobjc.A.dylib 0x00007fff8ecdbe75 objc_exception_throw + 43
- 2 a.out 0x00000001062abef7 main + 135
- 3 libdyld.dylib 0x00007fff851f35fd start + 1
- )
- libc++abi.dylib: terminating with uncaught exception of type OCException
- Abort trap: 6
五. Objective-C 反射
1. 获取 Class
(1) 程序 与 环境 交互方式
程序 与 运行环境交互方式 :
-- 通过 OC 源码 : 编写 OC 源码, 编译器编译, 运行在运行环境中;
-- 通过 NSObject 动态编程 : NSObject 是所有类的基类, 所有对象都可以直接调用 NSObject 方法;
-- 调用 运行时函数 动态编程 : 运行时系统是动态库, 可以直接调用这些动态共享库;
(2) 获取 Class 方式
获取 Class 方式 :
-- 通过类名 : 使用 "Class NSClassFromString (NSString * aClassName)" 函数获取 Class 对象, 传入 类名 字符串;
-- class 类方法 : 调用类方法 class, 调用方式 [NSString class];
-- class 对象方法 : 调用对象的 class 方法, 调用方式 [@"hello" class];
-- 推荐使用第二种方式 : 代码更安全, 编译阶段就可以检查 Class 是否存在, 程序性能高;
(3) 获取 Class 代码示例
代码示例 :
- /*************************************************************************
- > File Name: OCGetClass.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 23:31:51 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- //通过 NSClassFromString 方法传入 类名字符串 获取 Class 对象
- Class clazz = NSClassFromString(@"NSDate");
- NSLog(@"%@", clazz);
- id date = [[clazz alloc] init];
- NSLog(@"date : %@", date);
- NSString * str = @"hello";
- // 通过调用 类 或 对象的 class 方法
- NSLog(@"[str class] : %@, [NSString class] : %@", [str class], [NSString class]);
- // 通过调用 类 或 对象的 getter 方法获取, 即用 . 方法获取
- NSLog(@"str.class : %@, NSString.class : %@", str.class, NSString.class);
- }
- }
-- 执行结果 :
- bogon:6.6 octopus$ clang -fobjc-arc -framework Foundation OCGetClass.m
- bogon:6.6 octopus$ ./a.out
- 2015-10-05 23:39:28.692 a.out[3237:507] NSDate
- 2015-10-05 23:39:28.699 a.out[3237:507] date : 2015-10-05 15:39:28 +0000
- 2015-10-05 23:39:28.700 a.out[3237:507] [str class] : __NSCFConstantString, [NSString class] : NSString
- 2015-10-05 23:39:28.700 a.out[3237:507] str.class : __NSCFConstantString, NSString.class : NSString
2. 检查继承关系
(1) 继承关系判断
继承关系判断方法 :
-- 判断类 : isMemberOfClass 方法, 传入 Class 对象, 判断该对象是否是 Class 对象对应类的实例;
-- 判断类或子类 : isKindOfClass 方法, 传入 Class 对象, 判断该对象是否是 Class 对象对应类 或 子类的实例;
-- 判断协议 : conformsToProtocol 犯法, 传入 Protocol 参数, 传入方法 "@protocol(协议名称)" 或者 "Protocol * NSProtocolFromString(NSString * @"协议名称")" 两种方法获取协议参数;
(2) 继承关系判断代码示例
源码示例 :
-- OCAnimal.h : 定义协议;
- /*************************************************************************
- > File Name: OCAnimal.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 23:54:14 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @protocol OCAnimal
- - (void) name;
- @end
-- OCCat.h : 定义接口;
- /*************************************************************************
- > File Name: OCCat.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 23:56:16 2015
- ************************************************************************/
- #import "OCAnimal.h"
- @interface OCCat : NSObject <OCAnimal>
- @end
-- OCCat.m : 定义实现类;
- /*************************************************************************
- > File Name: OCCat.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 23:58:47 2015
- ************************************************************************/
- #import "OCCat.h"
- @implementation OCCat
- - (void) name
- {
- NSLog(@"My name is Tom");
- }
- @end
-- OCCatMain.m : 测试类;
- /*************************************************************************
- > File Name: OCCatMain.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 二 10/ 6 00:00:01 2015
- ************************************************************************/
- #import "OCCat.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- OCCat * cat = [[OCCat alloc] init];
- NSLog(@"%@", cat.class);
- NSLog(@"cat isMemberOfClass OCCat : %d", [cat isMemberOfClass : OCCat.class]);
- NSLog(@"cat isMemberOfClass NSObject : %d", [cat isMemberOfClass : NSObject.class]);
- NSLog(@"cat isKindOfClass OCCat : %d", [cat isKindOfClass : OCCat.class]);
- NSLog(@"cat isKindOfClass OCCat : %d", [cat isKindOfClass : NSObject.class]);
- NSLog(@"cat conformsToProtocol OCAnimal : %d", [cat conformsToProtocol : @protocol(OCAnimal)]);
- }
- }
-- 执行结果 :
- bogon:6.6 octopus$ clang -fobjc-arc -framework Foundation OCCat.m OCCatMain.m
- bogon:6.6 octopus$ ./a.out
- 2015-10-06 00:07:56.838 a.out[3337:507] OCCat
- 2015-10-06 00:07:56.840 a.out[3337:507] cat isMemberOfClass OCCat : 1
- 2015-10-06 00:07:56.840 a.out[3337:507] cat isMemberOfClass NSObject : 0
- 2015-10-06 00:07:56.841 a.out[3337:507] cat isKindOfClass OCCat : 1
- 2015-10-06 00:07:56.841 a.out[3337:507] cat isKindOfClass OCCat : 1
- 2015-10-06 00:07:56.842 a.out[3337:507] cat conformsToProtocol OCAnimal : 1
3. 动态调用方法
(1) 动态调用成员变量
KVC 机制 : 通过该机制可以动态调用对象的 getter 和 setter 方法, 不论 该变量定义位置 (接口 | 实现) 和 使用何种访问控制符 (private | public), 都可以使用 KVC 访问;
(2) 判断方法是否可调用
判断对象是否可以调用方法 : NSObject 中定义了 respondsToSelector : 方法, 该方法传入 SEL 参数, 该参数代表方法, 如果可以调用 返回 YES, 反之 返回 NO;
获取 SEL 对象方法 :
-- 指令获取 : 使用 @selector 指令获取当前类中指定的方法, 参数是 完整的方法签名关键字, 只有方法名不够;
- @selector(setAge:) withObject
-- 方法获取 : 使用 SEL NSSelectorFromString(NSString * aSelectorName) 函数, 根据方法签名关键字字符串获取对应方法;
- NSSelectorFromString(@"setAge:")
(3) SEL 动态调用方法
动态调用对象方法 :
-- 动态调用一 : NSObject 的 performSelector : 方法可以调用方法, 需要传入 SEL 对象, 传入参数 可以通过 withObject: 标签传入参数;
- [student performSelector : @selector(setAge:) withObject : [NSNumber numberWithInt : 18]];
- [student performSelector : NSSelectorFromString(@"setAge:") withObject : [NSNumber numberWithInt : 19]];
-- 动态调用二 : objc_msgSend(receiver, selector, ...) 函数调用方法, 参数一 方法调用者, 参数二 调用的方法, 剩余参数 方法参数;
- objc_msgSend (student, @selector(setAge:), [NSNumber numberWithInt : 20]);
- objc_msgSend (student, NSSelectorFromString(@"setAge:"), [NSNumber numberWithInt : 21]);
-- 注意 : 使用第二种方法需要导入包 "#import <objc/message.h>", 返回浮点数时调用 objc_msgSend_fpret(), 返回结构体数据时 使用 objc_msgSend_stret() 函数;
(4) IMP 动态调用方法
IMP 动态调用方法 简介 :
-- 获取 IMP 对象 : NSObject 定义了 "- (IMP) methodForSelector : (SEL) aSelector :" 方法, 该方法传入 SEL 参数, 返回 IMP 对象;
-- IMP 作用 : IMP 是 OC 方法函数指针变量, 代表函数入口, 通过 IMP 也可以调用函数;
-- IMP 调用方法语法 : "返回值类型 (*指针变量) (id, SEL, ...)" , 参数一 方法调用者, 参数二 方法 SEL 对象, 后面参数是方法参数;
(5) 动态调用方法 示例代码
示例代码 :
-- OCStudent.m : 接口实现类主函数一体;
- /*************************************************************************
- > File Name: OCStudent.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 二 10/ 6 11:19:49 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- #import <objc/message.h>
- @interface OCStudent : NSObject
- @end
- @implementation OCStudent
- - (void) setAge : (NSNumber *) age
- {
- int age_num = [age intValue];
- NSLog(@"age is : %d", age_num);
- }
- @end
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool
- {
- OCStudent * student = [[OCStudent alloc] init];
- [student performSelector : @selector(setAge:) withObject : [NSNumber numberWithInt : 18]];
- [student performSelector : NSSelectorFromString(@"setAge:") withObject : [NSNumber numberWithInt : 19]];
- objc_msgSend (student, @selector(setAge:), [NSNumber numberWithInt : 20]);
- objc_msgSend (student, NSSelectorFromString(@"setAge:"), [NSNumber numberWithInt : 21]);
- }
- }
-- 执行结果 : 有报警;
- bogon:6.6 octopus$ clang -fobjc-arc -framework Foundation OCStudent.m
- OCStudent.m:29:12: warning: performSelector may cause a leak because its selector is unknown [-Warc-performSelector-leaks]
- [student performSelector : NSSelectorFromString(@"setAge:") withObject : [NSNumber numberWithInt : 19]];
- ^
- OCStudent.m:29:30: note: used here
- [student performSelector : NSSelectorFromString(@"setAge:") withObject : [NSNumber numberWithInt : 19]];
- ^
- 1 warning generated.
- bogon:6.6 octopus$ ./a.out
- 2015-10-06 12:00:41.669 a.out[747:507] age is : 18
- 2015-10-06 12:00:41.671 a.out[747:507] age is : 19
- 2015-10-06 12:00:41.671 a.out[747:507] age is : 20
- 2015-10-06 12:00:41.672 a.out[747:507] age is : 21
(1) 包装类简介
NSValue 和 NSNumber :
-- 通用包装类 NSValue : NSValue 包装单个 short, int, long, float, char, id, 指针 等数据;
-- NSNumber 包装类 : 用于包装 C 语言数据类型;
NSNumber 方法 :
-- "+ numberWithXxx :" : 将特定类型的值包装成 NSNumber;
-- "- initWithXxx :" : 先创建一个 NSNumber 对象, 再用一个基本类型的值来初始化 NSNumber;
-- "- xxxValue :" : 返回 NSNumber 对象包装的基本类型的值;
(2) 包装类代码示例
代码示例 :
- /*************************************************************************
- > File Name: OCNSNumberDemo.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 六 10/ 3 12:50:15 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- NSNumber * num_int = [NSNumber numberWithInt : 10];
- NSNumber * num_double = [NSNumber numberWithDouble : 10];
- NSNumber * num_char = [NSNumber numberWithChar : 'A'];
- NSLog(@"number_int : %d, number_double : %g, num_char : %c",
- [num_int intValue], [num_double doubleValue], [num_char charValue]);
- NSNumber * num_int1 = [[NSNumber alloc] initWithInt : 10];
- NSNumber * num_double1 = [[NSNumber alloc] initWithDouble : 10];
- NSNumber * num_char1 = [[NSNumber alloc] initWithChar : 'A'];
- NSLog(@"number_int1 : %d, number_double1 : %g, num_char1 : %c",
- [num_int1 intValue], [num_double1 doubleValue], [num_char1 charValue]);
- }
- }
-- 执行结果 :
- localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation OCNSNumberDemo.m
- localhost:oc_object octopus$ ./a.out
- 2015-10-03 13:00:46.465 a.out[887:507] number_int : 10, number_double : 10, num_char : A
- 2015-10-03 13:00:46.468 a.out[887:507] number_int1 : 10, number_double1 : 10, num_char1 : A
2. description 方法
(1) description 方法简介
description 方法简介 : 类似于 Java 中 Object 的 toString() 方法;
-- 方法来源 : description 是 NSObject 中定义的, 所有的方法都有该方法;
-- 默认方法 : description 默认方法返回 <类名: 地址>;
-- 输出对象 : NSLog() 函数输出一个对象, 其实输出的是该对象的 description 方法;
-- 示例 : OCPerson * person, 打印 [person description] 和 person 输出结果是一样的;
(2) description 示例代码
示例代码 :
- /*************************************************************************
- > File Name: OCDescriptionDemo.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 六 10/ 3 14:25:28 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface OCDescriptionDemo : NSObject
- @property (nonatomic, copy) NSString * name;
- @property (nonatomic, assign) int age;
- - (id) initWithNameAndAge : (NSString *) set_name setAge : (int) set_age;
- @end
- @implementation OCDescriptionDemo
- @synthesize name;
- @synthesize age;
- - (id) initWithNameAndAge : (NSString *) set_name setAge : (int) set_age
- {
- self.name = set_name;
- self.age = set_age;
- return self;
- }
- - (NSString *) description
- {
- NSString * des = [NSString stringWithFormat :
- @"<OCDescription[name = %@, age = %d]>", self.name, self.age];
- return des;
- }
- @end
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- OCDescriptionDemo * description = [[OCDescriptionDemo alloc] initWithNameAndAge : @"Tom" setAge : 18];
- NSLog(@"%@", description);
- }
- }
-- 执行结果 :
- localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation OCDescriptionDemo.m
- localhost:oc_object octopus$ ./a.out
- 2015-10-03 14:50:18.665 a.out[970:507] <OCDescription[name = Tom, age = 18]>
3. == 或 isEqual : 方法
(1) "==" 运算符
"==" 简介 :
-- 作用 : 判断两个变量是否相等;
-- 前提 : 两个变量都是基本类型, 两个变量相等返回 true; 指针类型变量比较地址没有任何意义;
(2) 常量池
常量池 :
-- 作用 : 保证相同的字符串常量至右一个, 不能出现多个相同的副本;
-- 例外 : 使用 [NSString stringWithFormat] 方法创建的字符串不会放入常量池;
(3) isEqual 方法
"isEqual" 方法简介 :
-- 来源 : isEqual 方法是 NSObject 类提供的实例方法, 用于判断相同类型的两个变量是否相等;
-- 默认 : 默认方法还是比较地址, 需要开发者重写这个方法;
-- NSString 的 isEqual 方法 : NSString 的 isEqual 方法是判断两个字符串是否相等, 包含的字符串相同就会返回 true;
-- isEqualToString 方法 : 方法 : NSString 中定义的 isEqualToString 方法用于判断当前字符串 与 另一个字符串的字符串序列是否相等;
重写 isEqual 方法标准 :
-- 自反性 : 对象 x, [x isEqual : x] 必须返回 true;
-- 对称性 : 对象 x 和 y, 如果 [x isEqual : y] 返回值 必须与 [y isEqual : x] 返回值相同;
-- 传递性 : 对象 x , y 和 z, [x isEqual : y] = true, [y isEqual : z] = true, 那么 x z 也相等;
-- 一致性 : x , y 对象无论调用多少次, 返回值结果都应该保持一致;
-- nil 对比 : 如果 x 不是 nil, [x isEqual : nil] 必须返回 false;
(4) "==" 和 "isEqual" 示例源码
示例源码 :
- /*************************************************************************
- > File Name: OCEqual.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 六 10/ 3 16:07:56 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface OCEqual : NSObject
- @property (nonatomic, copy) NSString * name;
- @property (nonatomic, assign) int age;
- - (id) initWithName : (NSString *) set_name setAge : (int) set_age;
- @end
- @implementation OCEqual
- @synthesize name;
- @synthesize age;
- - (id) initWithName : (NSString *) set_name setAge : (int) set_age
- {
- self.name = set_name;
- self.age = set_age;
- return self;
- }
- - (BOOL) isEqual : (id) other
- {
- if(self == other)
- return YES;
- if(other != nil && [other isMemberOfClass : OCEqual.class])
- {
- OCEqual * equal = (OCEqual *) other;
- return [self.name isEqual : equal.name] && (self.age == equal.age);
- }
- return NO;
- }
- @end
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- int int_a = 10;
- int double_a = 10.0;
- NSLog(@"int_a == double_a : %d", (int_a == double_a));
- NSString * str_a = @"Octopus";
- NSString * str_b = @"Octopus";
- NSString * str_c = [NSString stringWithFormat : @"Octopus"];
- NSString * str_d = [NSString stringWithFormat : @"Octopus"];
- NSLog(@"str_a == str_b : %d, str_c == str_d : %d, [str_c isEqual : str_d] : %d",
- str_a == str_b, str_c == str_d, [str_c isEqual : str_d]);
- OCEqual * equal_a = [[OCEqual alloc] initWithName : @"Tom" setAge : 18];
- OCEqual * equal_b = [[OCEqual alloc] initWithName : @"Jerry" setAge : 20];
- OCEqual * equal_c = [[OCEqual alloc] initWithName : @"Jerry" setAge : 20];
- NSLog(@"[equal_a isEqual : equal_b] : %d, [equal_b isEqual : equal_c] : %d",
- [equal_a isEqual : equal_b], [equal_b isEqual : equal_c]);
- }
- }
-- 执行结果 :
- localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation OCEqual.m
- localhost:oc_object octopus$ ./a.out
- 2015-10-03 16:58:35.690 a.out[1168:507] int_a == double_a : 1
- 2015-10-03 16:58:35.693 a.out[1168:507] str_a == str_b : 1, str_c == str_d : 0, [str_c isEqual : str_d] : 1
- 2015-10-03 16:58:35.693 a.out[1168:507] [equal_a isEqual : equal_b] : 0, [equal_b isEqual : equal_c] : 1
二. 类别 与 扩展
1. Category 类别
(1) 扩展类簇需求
类簇扩展需求 : 开发过程中有时需要扩展类行为;
-- 继承 : 通过继承, 子类在父类基础上添加方法 或者 重写父类方法;
-- 问题 : 如果想要为父类增加一个方法, 子类同时也继承这些方法, 此时使用继承就满足不了这个功能了;
-- 类簇 : OC 中没有接口, 需要接口时, 就会选择定义一个父类, 以该父类派生 N 个子类, 该系列的类被成为 类簇;
-- 类簇扩展方法 : 为父类增加方法, 类簇中得子类同时也增加该方法, 扩展类簇中得父类是最合适的方法;
(2) Category 类别
类别 (category) 简介 :
-- 作用 : 为现有类添加方法, 不需要访问原有类代码, 不需要继承;
-- 有点 : 动态地为现有类添加方法, 将类定义模块化 分布到多个文件中;
(3) Category 类别 接口 语法格式
类别 (category) 接口部分语法格式 :
-- 接口文件类命名 : "类名+类别名.h", 如 要扩展 OCPerson 类, 类别名为 SB, 那么接口文件名就是 "OCPerson+SB.h";
-- 示例 :
- @interface 已有类 (类别名)
- //方法定义
- ...
- @end
-- 类别名 : 必须是项目中没有的类, 定义类别时使用的类名, 必须是已有的类;
-- 圆括号 : 类别名 定义在 需要扩展的已有类之后, 必须使用圆括号括起来;
-- 定义内容 : 类别中一般情况下只定义方法;
(4) Category 类别 实现类 语法格式
类别 (category) 实现部分语法格式 :
-- 实现类文件命名 : "类名+类别名.m", 如 要扩展 OCPerson 类, 类别名为 SB, 那么接口文件名就是 "OCPerson+SB.m";
-- 示例 :
- @implementation 已有类 (类别名)
- //方法定义
- ...
- @end
(5) Category 类别 注意点
注意事项 :
-- 影响范围 : 通过 category 添加新方法后, 会影响到 指定的被扩展的类, 同时也会影响到其子类;
-- 多个类别 : 一个类可以 对应多个类别, 这些类别都可以为类增加方法定义;
-- 类别优点 : 进行模块化设计, 调用私有方法, 实现非正式协议;
(6) Category 扩展 NSNumber 示例
NSNumber 扩展示例 : 为其添加一个计算圆面积的方法;
-- NSNumber+SB.h :
- /*************************************************************************
- > File Name: NSNumber+SB.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 六 10/ 3 18:58:53 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface NSNumber (SB)
- - (NSNumber *) circleAera : (double) radius;
- @end
-- NSNumber+SB.m :
- /*************************************************************************
- > File Name: NSNumber+SB.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 六 10/ 3 19:02:05 2015
- ************************************************************************/
- #import "NSNumber+SB.h"
- @implementation NSNumber (SB)
- - (NSNumber *) circleAera : (double) radius
- {
- double aera = 3.1415926 * radius * radius;
- return [NSNumber numberWithDouble : aera];
- }
- @end
-- NSNumber+SBTest.m :
- /*************************************************************************
- > File Name: NSNumber+SBTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 六 10/ 3 19:08:19 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- #import "NSNumber+SB.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- NSNumber * num = [NSNumber numberWithInt : 3];
- NSNumber * circleAera = [num circleAera : 1];
- NSLog(@"%@", circleAera);
- }
- }
-- 执行结果 :
- localhost:oc_object octopus$ clang -fobjc-arc -framework Foundation NSNumber+SB.m NSNumber+SBTest.m
- localhost:oc_object octopus$ ./a.out
- 2015-10-03 19:18:13.625 a.out[1333:507] 3.1415926
2. Category 类别实际用法
(1) 类的模块化设计
模块化设计简介 :
-- 实现部分唯一 : 定义一个类是, 使用 "类名.h" 定义接口部分, 使用 "类名.m" 定义实现部分, 不能将实现部分定义在多个 ".m" 后缀 文件中;
-- 文件臃肿 : 如果类很大, 将所有的代码放在一个 "类名.m" 文件中, 非常难维护;
(2) 调用私有方法
私有方法调用简介 :
-- 私有方法 : 接口中没有定义, 在实现部分定义的方法是 私有方法, 不允许被外部调用;
-- 调用私有方法一 : 使用 NSObject 的 "performSelector :"执行调用, 也是可以调用私有方法的, 不过此方法会避开语法检查, 导致未知问题;
(3) 调用私有方法 代码示例
代码示例 :
-- OCPrivate.h :
- /*************************************************************************
- > File Name: OCPrivate.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 06:55:34 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface OCPrivate : NSObject
- @property (nonatomic, copy) NSString * name;
- -(void) info;
- @end
-- OCPrivate.m :
- /*************************************************************************
- > File Name: OCPrivate.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 06:57:48 2015
- ************************************************************************/
- #import "OCPrivate.h"
- @implementation OCPrivate
- @synthesize name;
- - (void) info
- {
- NSLog(@"name : %@", self.name);
- }
- - (void) speak
- {
- NSLog(@"Hello World !");
- }
- @end
-- OCPrivate+SB.h :
- /*************************************************************************
- > File Name: OCPrivate+SB.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 07:19:35 2015
- ************************************************************************/
- #import "OCPrivate.h"
- @interface OCPrivate (SB)
- - (void) speak;
- @end
-- OCPrivateTest.m :
- /*************************************************************************
- > File Name: OCPrivateTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 07:22:04 2015
- ************************************************************************/
- #import "OCPrivate+SB.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool
- {
- OCPrivate * priva = [[OCPrivate alloc] init];
- priva.name = @"Tom";
- [priva info];
- [priva speak];
- }
- }
3. extension 扩展
(1) extension 简介
extension 简介 :
-- 作用 : 扩展相当于匿名类别;
-- 语法 :
- @interface 已有类 ()
- {
- //实例变量 ...
- }
- // 方法定义 ...
- @end
-- 用法 : 定义两个头文件, OCExtension.h 和 OCExtension+speak.h, OCExtension.m 导入 OCExtension+speak.h 头文件;
(2) extension 源码示例
源码示例 :
-- OCExtension.h :
- /*************************************************************************
- > File Name: OCExtension.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 08:18:43 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface OCExtension : NSObject
- @property (nonatomic, copy) NSString * name;
- @property (nonatomic, assign) int age;
- - (void) info;
- @end
-- OCExtension+speak.h :
- /*************************************************************************
- > File Name: OCExtension+speak.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 08:31:37 2015
- ************************************************************************/
- #import "OCExtension.h"
- @interface OCExtension ()
- @property (nonatomic, copy) NSString * home;
- - (void) speak : (NSString *) content;
- @end
-- OCExtension.m :
- /*************************************************************************
- > File Name: OCExtension.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 08:27:50 2015
- ************************************************************************/
- #import "OCExtension+speak.h"
- @implementation OCExtension
- @synthesize name;
- @synthesize age;
- @synthesize home;
- - (void) info
- {
- NSLog(@"info : name : %@ , age : %d", self.name, self.age);
- }
- - (void) speak : (NSString *) content
- {
- NSLog(@"%@ speak %@", self.name, content);
- }
- @end
-- OCExtensionTest.m :
- /*************************************************************************
- > File Name: OCExtensionTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 日 10/ 4 13:20:42 2015
- ************************************************************************/
- #import "OCExtension+speak.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- OCExtension * extension = [[OCExtension alloc] init];
- extension.name = @"Tom";
- extension.age = 18;
- extension.home = @"China";
- [extension info];
- [extension speak : @"Are you fucking kidding me"];
- }
- }
三. 协议 与 委托
1. 类别实现非正式协议
(1) 非正式协议简介
协议简介 :
-- 作用 : OC 中得协议作用相当于其它语言中得接口;
-- 协议表现 : 协议定义的是 多个类 共同的行为规范, 通常定义一组公用方法, 这些方法都没有实现, 方法由类来实现;
非正式协议简介 :
-- 创建 NSObject 类别 : 以 NSObject 为基础, 为 NSObject 创建类别, 为该类别指定新增方法, 即给所有的 NSObject 子类增加了新方法;
-- 实现 NSObject 类别 : 实现 NSObject 类别时, 实现该列别下地所有方法, 即之前在 NSObject 类别中定义的方法;
(2) 非正式协议代码示例
非正式协议代码示例 :
-- NSObject+speak.h : 为 NSObject 定义的类别接口, 所有的继承 NSObject 的类都必须实现该类别中得抽象方法;
- /*************************************************************************
- > File Name: NSObject+speak.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 08:55:48 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface NSObject (speak)
- - (void) speak;
- @end
-- OCNSObjectProtocal.h : NSObject 子类接口, 该接口继承 NSObject 类, 注意 需要导入 NSObject+speak.h 头文件;
- /*************************************************************************
- > File Name: OCNSObjectProtocal.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:00:37 2015
- ************************************************************************/
- #import "NSObject+speak.h"
- @interface OCNSObjectProtocal : NSObject
- @end
-- OCNSObjectProtocal.m : OCNSObjectProtocal 实现类, 在该实现类中必须实现 类别中定义的 speak 方法;
- /*************************************************************************
- > File Name: OCNSObjectProtocal.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:02:03 2015
- ************************************************************************/
- #import "OCNSObjectProtocal.h"
- @implementation OCNSObjectProtocal
- - (void) speak
- {
- NSLog(@"Speak Hello World");
- }
- @end
-- OCNSObjectProtocalTest.m : 测试类, 测试以上代码是否可以执行;
- /*************************************************************************
- > File Name: OCNSObjectProtocalTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:04:31 2015
- ************************************************************************/
- #import "OCNSObjectProtocal.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- OCNSObjectProtocal * obj = [[OCNSObjectProtocal alloc] init];
- [obj speak];
- }
- }
-- 执行结果 :
- bogon:oc_object octopus$ clang -fobjc-arc -framework Foundation OCNSObjectProtocal.m OCNSObjectProtocalTest.m
- bogon:oc_object octopus$ ./a.out
- 2015-10-05 09:06:44.895 a.out[2100:507] Speak Hello World
2. 定义正式协议
(1) 正式协议语法
正式协议语法 :
-- 语法 :
- @protocol 协议名称 <父类协议1, 父类协议2 ...>
- // N 个协议方法
- @end
-- 协议名称规范 : 采用与类名相同的命名规则;
-- 继承规则 : 一个协议 可以有 多个父类协议, 协议只能继承协议, 不能继承类;
-- 方法规则 : 协议中只能定义抽象方法, 不能定义方法实现, 既可以定义类方法, 也可以定义实例方法;
(2) 实现协议
实现协议语法 :
-- 语法 :
- @interface 类名 : 父类 <协议1, 协议2...>
(3) 声明协议变量
变量声明 :
-- 使用原变量声明 : "变量名 * 对象名" , 如 "OCCat * cat";
-- 使用协议定义 : "NSObject <协议1, 协议2 ...> * 对象名", 如 "NSObject<OCProtocolCat> * cat";
-- 使用 id 类型定义 : "id<OCProtocolCat> 对象名", 如 "id<OCProtocolCat> cat", 注意此处没有指针标识;
(4) 正式协议实现代码
代码示例 :
-- OCAnimalProtocol.h : 最基础的协议1;
- /*************************************************************************
- > File Name: OCAnimalProtocol.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:25:41 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @protocol OCAnimalProtocol
- - (void) name;
- - (void) age;
- @end
-- OCProtocolBord.h : 最基础的协议2;
- /*************************************************************************
- > File Name: OCProtocolBord.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:40:08 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @protocol OCProtocolBord
- - (void) fly;
- @end
-- OCProtocolCat.h : 该协议实现了 上面的两个协议;
- /*************************************************************************
- > File Name: OCProtocolCat.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:45:17 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- #import "OCAnimalProtocol.h"
- #import "OCProtocolBord.h"
- @protocol OCProtocolCat <OCAnimalProtocol, OCProtocolBord>
- - (void) purr;
- @end
-- OCCat.h : OCCat 类接口部分, 生命了该类 实现协议 OCProtocolCat 协议;
- /*************************************************************************
- > File Name: OCCat.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:50:21 2015
- ************************************************************************/
- #import "OCProtocolCat.h"
- @interface OCCat : NSObject <OCProtocolCat>
- @end
-- OCCat.m : OCCat 类实现部分;
- /*************************************************************************
- > File Name: OCCat.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 09:52:45 2015
- ************************************************************************/
- #import "OCCat.h"
- @implementation OCCat
- - (void) name
- {
- NSLog(@"name : cat");
- }
- - (void) age
- {
- NSLog(@"age : 18");
- }
- - (void) fly
- {
- NSLog(@"cat fly");
- }
- - (void) purr
- {
- NSLog(@"cat purr");
- }
- @end
-- OCProtocolTest.m : 以上类的功能测试类;
- /*************************************************************************
- > File Name: OCProtocolTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 10:14:38 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- #import "OCCat.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- OCCat * cat = [[OCCat alloc] init];
- [cat name];
- [cat age];
- [cat fly];
- [cat purr];
- NSObject<OCProtocolCat> * cat1 = [[OCCat alloc] init];
- [cat1 name];
- [cat1 age];
- [cat1 fly];
- [cat1 purr];
- id<OCAnimalProtocol> cat2 = [[OCCat alloc] init];
- [cat2 name];
- [cat2 age];
- }
- }
-- 执行结果 :
- bogon:6.4 octopus$ clang -fobjc-arc -framework Foundation OCCat.m OCProtocolTest.m
- bogon:6.4 octopus$ ./a.out
- 2015-10-05 10:24:20.099 a.out[2271:507] name : cat
- 2015-10-05 10:24:20.101 a.out[2271:507] age : 18
- 2015-10-05 10:24:20.102 a.out[2271:507] cat fly
- 2015-10-05 10:24:20.102 a.out[2271:507] cat purr
- 2015-10-05 10:24:20.102 a.out[2271:507] name : cat
- 2015-10-05 10:24:20.103 a.out[2271:507] age : 18
- 2015-10-05 10:24:20.103 a.out[2271:507] cat fly
- 2015-10-05 10:24:20.104 a.out[2271:507] cat purr
- 2015-10-05 10:24:20.104 a.out[2271:507] name : cat
- 2015-10-05 10:24:20.104 a.out[2271:507] age : 18
3. 委托
委托概念 : 定义协议的类 将 定义协议的方法 委托给 实现协议的类;
-- 好处 : 类具有更好地通用性, 具体的动作交给实现类完成;
创建工程 :
-- 欢迎界面, 选择 Create a new xcode project;
-- 创建一个 OS 下地 Cocoa Application :
-- 创建 工程 :
项目中得源文件 :
-- main.m : main() 函数入口;
-- OCAppDelegate.h : OCAppDelegate 类接口文件;
-- OCAppDelegate.m : OCAppDelegate 类实现部分;
代码示例 :
-- 前置操作 : 删除 MainMenu.xib 文件, 删除 Hello-Info.plist 中的 MainMenu 选项;
-- OCAppDelegate.h :
- //
- // OCAppDelegate.h
- // Hello
- //
- // Created by octopus on 15-10-5.
- // Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
- //
- #import <Cocoa/Cocoa.h>
- //该接口 实现 NSApplicationDelegate 协议
- @interface OCAppDelegate : NSObject <NSApplicationDelegate>
- //定义窗口
- @property (strong) NSWindow *window;
- @end
-- OCAppDelegate.m :
- //
- // OCAppDelegate.m
- // Hello
- //
- // Created by octopus on 15-10-5.
- // Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
- //
- #import "OCAppDelegate.h"
- @implementation OCAppDelegate
- @synthesize window;
- //应用加载完成时回调的方法
- - (void)applicationWillFinishLaunching:(NSNotification *)notification
- {
- //设置窗口属性
- self.window = [[NSWindow alloc] initWithContentRect :
- NSMakeRect(300, 300, 320, 200)
- styleMask:(NSTitledWindowMask | NSMiniaturizableWindowMask |NSClosableWindowMask)
- backing:NSBackingStoreBuffered
- defer:NO];
- self.window.title = @"Hello World";
- //设置文本框属性
- NSTextField * label = [[NSTextField alloc] initWithFrame:NSMakeRect(60, 120, 200, 60)];
- [label setSelectable:YES];
- [label setBezeled:YES];
- [label setDrawsBackground:YES];
- [label setStringValue:@"HELLO WORLD"];
- //设置按钮属性
- NSButton * button = [[NSButton alloc] initWithFrame:NSMakeRect(120, 40, 80, 30)];
- button.title = @"OCTOPUS";
- [button setBezelStyle:NSRoundedBezelStyle];
- [button setBounds:NSMakeRect(120, 40, 80, 30)];
- //将 文本框 和 按钮 添加到窗口中
- [self.window.contentView addSubview:label];
- [self.window.contentView addSubview:button];
- }
- //加载完成时回调的方法
- - (void) applicationDidFinishLaunching:(NSNotification *)notification
- {
- //显示窗口
- [self.window makeKeyAndOrderFront:self];
- }
- @end
-- main.m :
- //
- // main.m
- // Hello
- //
- // Created by octopus on 15-10-5.
- // Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
- //
- #import <Cocoa/Cocoa.h>
- #import "OCAppDelegate.h"
- int main(int argc, const charchar * argv[])
- {
- @autoreleasepool {
- //创建一个实现了 NSApplicationDelegate 协议的对象
- OCAppDelegate * delegate = [[OCAppDelegate alloc] init];
- //获取 NSApplication 单例对象
- [NSApplication sharedApplication];
- //设置代理, 将处理方法委托给 delegate
- [NSApp setDelegate : delegate];
- //开始运行程序
- return NSApplicationMain(argc, argv);
- }
- }
-- 运行结果 :
四. 异常处理
1. @try ... @catch ... @finally ... 异常捕捉
(1) Objective-C 异常机制
Objective-C 异常机制 :
-- 作用 : 开发者将引发异常的代码放在 @try 代码块中, 程序出现异常 使用 @catch 代码块进行捕捉;
-- 每个代码块作用 : @try 代码块存放可能出现异常的代码, @catch 代码块 异常处理逻辑, @finally 代码块回收资源;
-- 语法示例 :
- @try
- {
- // 业务逻辑
- }
- @catch (异常类型名1 ex)
- {
- //异常处理代码
- }
- @catch (异常类型名2 ex)
- {
- //异常处理代码
- }
- // 可以捕捉 N 个 异常 ...
- @finally
- {
- //回收资源
- }
(2) Objective-C 异常处理过程
异常处理过程 :
-- 生成异常对象 : @try 中出现异常, 系统会生成一个异常对象, 该对象提交到系统中 系统就会抛出异常;
-- 异常处理流程 : 运行环境接收到 异常对象时, 如果存在能处理该异常对象的 @catch 代码块, 就将该异常对象交给 @catch 处理, 该过程就是捕获异常, 如果没有 @catch 代码块处理异常, 程序就会终止;
-- @catch 代码块捕获过程 : 运行环境接收到 异常对象 时, 会依次判断该异常对象类型是否是 @catch 代码块中异常或其子类实例, 如果匹配成功, 被匹配的 @catch 就会处理该异常, 都则就会跟下一个 @catch 代码块对比;
-- @catch 处理异常 : 系统将异常对象传递给 @catch 形参, @catch 通过该形参获取异常对象详细信息;
其它注意点 :
-- @try 与 @catch 对应关系 : 一个 @try 代码块 可以对应 多个 @catch 代码块;
-- {} 省略问题 : 异常捕获的 @try @catch @finally 的花括号不可省略;
NSException 异常类 :
-- 简介 : NSException 是 OC 中所有异常的父类;
-- 位置永远在最后 : @catch 代码块捕获异常时查看 异常对象类型是否是 捕获的异常类型 或者其子类, 一旦放在开头, 后面的异常永远不可能捕获;
(3) 异常信息访问
异常信息访问 :
-- name : 返回异常的详细名称;
-- reason : 返回异常引发的原因;
-- userInfo : 返回异常的用户信息, 一个 NSDictionary 对象;
(4) 使用 finally 回收资源
回收物理资源 : @try 代码块中打开物理资源, 数据库 网络连接 文件等, 都需要回收, 在 @finally 中回收最好;
-- 回收位置分析 : 如果再 @try 中回收, 出现异常, 异常后面的代码无法执行, @catch 中回收, 如果不出现异常, 该代码块就不会执行; 因此 finally 中是必执行的代码, 在这里回收最合适;
(5) 异常代码示例
异常代码示例 :
-- OCAnimal.h : 定义协议;
- /*************************************************************************
- > File Name: OCAnimal.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:30:02 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @protocol OCAnimal
- @optional
- - (void) run;
- @end
-- OCCat.h : 定义 OCCat 接口;
- /*************************************************************************
- > File Name: OCCat.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:33:59 2015
- ************************************************************************/
- #import "OCAnimal.h"
- @interface OCCat : NSObject <OCAnimal>
- @end
-- OCCat.m : 定义 OCCat 实现类;
- /*************************************************************************
- > File Name: OCCat.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:36:36 2015
- ************************************************************************/
- #import "OCCat.h"
- @implementation OCCat
- @end
-- OCCatTest.m : 测试类;
- /*************************************************************************
- > File Name: OCCatTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:38:01 2015
- ************************************************************************/
- #import "OCCat.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- OCCat * cat = [[OCCat alloc] init];
- [cat run];
- }
- }
-- 执行结果 :
- bogon:6.5 octopus$ clang -fobjc-arc -framework Foundation OCCat.m OCCatTest.m
- bogon:6.5 octopus$ ./a.out
- 2015-10-05 16:39:23.589 a.out[2985:507] -[OCCat run]: unrecognized selector sent to instance 0x7fd7a3401870
- 2015-10-05 16:39:23.611 a.out[2985:507] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[OCCat run]: unrecognized selector sent to instance 0x7fd7a3401870'
- *** First throw call stack:
- (
- 0 CoreFoundation 0x00007fff903dd25c __exceptionPreprocess + 172
- 1 libobjc.A.dylib 0x00007fff8ecdbe75 objc_exception_throw + 43
- 2 CoreFoundation 0x00007fff903e012d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
- 3 CoreFoundation 0x00007fff9033b044 ___forwarding___ + 452
- 4 CoreFoundation 0x00007fff9033adf8 _CF_forwarding_prep_0 + 120
- 5 a.out 0x0000000108575efd main + 109
- 6 libdyld.dylib 0x00007fff851f35fd start + 1
- )
- libc++abi.dylib: terminating with uncaught exception of type NSException
- Abort trap: 6
(6) 异常捕获代码示例
异常捕获取示例 : 该示例扔使用上面的 OCAnimal.h, OCCat.h, OCCat.m 示例;
-- OCCatTest.m :
- /*************************************************************************
- > File Name: OCCatTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:38:01 2015
- ************************************************************************/
- #import "OCCat.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- @try
- {
- OCCat * cat = [[OCCat alloc] init];
- [cat run];
- }
- @catch (NSException * ex)
- {
- NSLog(@"exception name : %@, reason : %@", ex.name, ex.reason);
- }
- @finally
- {
- NSLog(@"finally execute");
- }
- NSLog(@"success");
- }
- }
-- 执行结果 :
- bogon:6.5 octopus$ clang -fobjc-arc -framework Foundation OCCat.m OCCatTest.m
- bogon:6.5 octopus$ ./a.out
- 2015-10-05 16:53:46.850 a.out[3008:507] -[OCCat run]: unrecognized selector sent to instance 0x7f884bc018b0
- 2015-10-05 16:53:46.853 a.out[3008:507] exception name : NSInvalidArgumentException, reason : -[OCCat run]: unrecognized selector sent to instance 0x7f884bc018b0
- 2015-10-05 16:53:46.853 a.out[3008:507] finally execute
- 2015-10-05 16:53:46.854 a.out[3008:507] success
2. 抛出自定义异常
(1) 自定义异常语法
自定义异常抛出 :
-- 语法 :
- @throw 异常对象;
(2) 自定义异常代码示例
自定义异常代码示例 :
-- OCException.h 接口 :
- /*************************************************************************
- > File Name: OCException.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:58:24 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @interface OCException : NSException
- @end
-- OCException.m 实现类 :
- /*************************************************************************
- > File Name: OCException.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 17:03:15 2015
- ************************************************************************/
- #import "OCException.h"
- @implementation OCException
- @end
-- OCCatTest.m 测试类 :
- /*************************************************************************
- > File Name: OCCatTest.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 16:38:01 2015
- ************************************************************************/
- #import "OCException.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool
- {
- @throw [[OCException alloc]
- initWithName : @"OCException"
- reason : @"this reason is imporant"
- userInfo : nil nil];
- }
- }
-- 执行结果 :
- bogon:6.5 octopus$ clang -fobjc-arc -framework Foundation OCException.m OCCatTest.m
- bogon:6.5 octopus$ ./a.out
- 2015-10-05 17:04:12.432 a.out[3040:507] *** Terminating app due to uncaught exception 'OCException', reason: 'this reason is imporant'
- *** First throw call stack:
- (
- 0 CoreFoundation 0x00007fff903dd25c __exceptionPreprocess + 172
- 1 libobjc.A.dylib 0x00007fff8ecdbe75 objc_exception_throw + 43
- 2 a.out 0x00000001062abef7 main + 135
- 3 libdyld.dylib 0x00007fff851f35fd start + 1
- )
- libc++abi.dylib: terminating with uncaught exception of type OCException
- Abort trap: 6
五. Objective-C 反射
1. 获取 Class
(1) 程序 与 环境 交互方式
程序 与 运行环境交互方式 :
-- 通过 OC 源码 : 编写 OC 源码, 编译器编译, 运行在运行环境中;
-- 通过 NSObject 动态编程 : NSObject 是所有类的基类, 所有对象都可以直接调用 NSObject 方法;
-- 调用 运行时函数 动态编程 : 运行时系统是动态库, 可以直接调用这些动态共享库;
(2) 获取 Class 方式
获取 Class 方式 :
-- 通过类名 : 使用 "Class NSClassFromString (NSString * aClassName)" 函数获取 Class 对象, 传入 类名 字符串;
-- class 类方法 : 调用类方法 class, 调用方式 [NSString class];
-- class 对象方法 : 调用对象的 class 方法, 调用方式 [@"hello" class];
-- 推荐使用第二种方式 : 代码更安全, 编译阶段就可以检查 Class 是否存在, 程序性能高;
(3) 获取 Class 代码示例
代码示例 :
- /*************************************************************************
- > File Name: OCGetClass.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 23:31:51 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- //通过 NSClassFromString 方法传入 类名字符串 获取 Class 对象
- Class clazz = NSClassFromString(@"NSDate");
- NSLog(@"%@", clazz);
- id date = [[clazz alloc] init];
- NSLog(@"date : %@", date);
- NSString * str = @"hello";
- // 通过调用 类 或 对象的 class 方法
- NSLog(@"[str class] : %@, [NSString class] : %@", [str class], [NSString class]);
- // 通过调用 类 或 对象的 getter 方法获取, 即用 . 方法获取
- NSLog(@"str.class : %@, NSString.class : %@", str.class, NSString.class);
- }
- }
-- 执行结果 :
- bogon:6.6 octopus$ clang -fobjc-arc -framework Foundation OCGetClass.m
- bogon:6.6 octopus$ ./a.out
- 2015-10-05 23:39:28.692 a.out[3237:507] NSDate
- 2015-10-05 23:39:28.699 a.out[3237:507] date : 2015-10-05 15:39:28 +0000
- 2015-10-05 23:39:28.700 a.out[3237:507] [str class] : __NSCFConstantString, [NSString class] : NSString
- 2015-10-05 23:39:28.700 a.out[3237:507] str.class : __NSCFConstantString, NSString.class : NSString
2. 检查继承关系
(1) 继承关系判断
继承关系判断方法 :
-- 判断类 : isMemberOfClass 方法, 传入 Class 对象, 判断该对象是否是 Class 对象对应类的实例;
-- 判断类或子类 : isKindOfClass 方法, 传入 Class 对象, 判断该对象是否是 Class 对象对应类 或 子类的实例;
-- 判断协议 : conformsToProtocol 犯法, 传入 Protocol 参数, 传入方法 "@protocol(协议名称)" 或者 "Protocol * NSProtocolFromString(NSString * @"协议名称")" 两种方法获取协议参数;
(2) 继承关系判断代码示例
源码示例 :
-- OCAnimal.h : 定义协议;
- /*************************************************************************
- > File Name: OCAnimal.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 23:54:14 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- @protocol OCAnimal
- - (void) name;
- @end
-- OCCat.h : 定义接口;
- /*************************************************************************
- > File Name: OCCat.h
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 23:56:16 2015
- ************************************************************************/
- #import "OCAnimal.h"
- @interface OCCat : NSObject <OCAnimal>
- @end
-- OCCat.m : 定义实现类;
- /*************************************************************************
- > File Name: OCCat.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 一 10/ 5 23:58:47 2015
- ************************************************************************/
- #import "OCCat.h"
- @implementation OCCat
- - (void) name
- {
- NSLog(@"My name is Tom");
- }
- @end
-- OCCatMain.m : 测试类;
- /*************************************************************************
- > File Name: OCCatMain.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 二 10/ 6 00:00:01 2015
- ************************************************************************/
- #import "OCCat.h"
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool {
- OCCat * cat = [[OCCat alloc] init];
- NSLog(@"%@", cat.class);
- NSLog(@"cat isMemberOfClass OCCat : %d", [cat isMemberOfClass : OCCat.class]);
- NSLog(@"cat isMemberOfClass NSObject : %d", [cat isMemberOfClass : NSObject.class]);
- NSLog(@"cat isKindOfClass OCCat : %d", [cat isKindOfClass : OCCat.class]);
- NSLog(@"cat isKindOfClass OCCat : %d", [cat isKindOfClass : NSObject.class]);
- NSLog(@"cat conformsToProtocol OCAnimal : %d", [cat conformsToProtocol : @protocol(OCAnimal)]);
- }
- }
-- 执行结果 :
- bogon:6.6 octopus$ clang -fobjc-arc -framework Foundation OCCat.m OCCatMain.m
- bogon:6.6 octopus$ ./a.out
- 2015-10-06 00:07:56.838 a.out[3337:507] OCCat
- 2015-10-06 00:07:56.840 a.out[3337:507] cat isMemberOfClass OCCat : 1
- 2015-10-06 00:07:56.840 a.out[3337:507] cat isMemberOfClass NSObject : 0
- 2015-10-06 00:07:56.841 a.out[3337:507] cat isKindOfClass OCCat : 1
- 2015-10-06 00:07:56.841 a.out[3337:507] cat isKindOfClass OCCat : 1
- 2015-10-06 00:07:56.842 a.out[3337:507] cat conformsToProtocol OCAnimal : 1
3. 动态调用方法
(1) 动态调用成员变量
KVC 机制 : 通过该机制可以动态调用对象的 getter 和 setter 方法, 不论 该变量定义位置 (接口 | 实现) 和 使用何种访问控制符 (private | public), 都可以使用 KVC 访问;
(2) 判断方法是否可调用
判断对象是否可以调用方法 : NSObject 中定义了 respondsToSelector : 方法, 该方法传入 SEL 参数, 该参数代表方法, 如果可以调用 返回 YES, 反之 返回 NO;
获取 SEL 对象方法 :
-- 指令获取 : 使用 @selector 指令获取当前类中指定的方法, 参数是 完整的方法签名关键字, 只有方法名不够;
- @selector(setAge:) withObject
-- 方法获取 : 使用 SEL NSSelectorFromString(NSString * aSelectorName) 函数, 根据方法签名关键字字符串获取对应方法;
- NSSelectorFromString(@"setAge:")
(3) SEL 动态调用方法
动态调用对象方法 :
-- 动态调用一 : NSObject 的 performSelector : 方法可以调用方法, 需要传入 SEL 对象, 传入参数 可以通过 withObject: 标签传入参数;
- [student performSelector : @selector(setAge:) withObject : [NSNumber numberWithInt : 18]];
- [student performSelector : NSSelectorFromString(@"setAge:") withObject : [NSNumber numberWithInt : 19]];
-- 动态调用二 : objc_msgSend(receiver, selector, ...) 函数调用方法, 参数一 方法调用者, 参数二 调用的方法, 剩余参数 方法参数;
- objc_msgSend (student, @selector(setAge:), [NSNumber numberWithInt : 20]);
- objc_msgSend (student, NSSelectorFromString(@"setAge:"), [NSNumber numberWithInt : 21]);
-- 注意 : 使用第二种方法需要导入包 "#import <objc/message.h>", 返回浮点数时调用 objc_msgSend_fpret(), 返回结构体数据时 使用 objc_msgSend_stret() 函数;
(4) IMP 动态调用方法
IMP 动态调用方法 简介 :
-- 获取 IMP 对象 : NSObject 定义了 "- (IMP) methodForSelector : (SEL) aSelector :" 方法, 该方法传入 SEL 参数, 返回 IMP 对象;
-- IMP 作用 : IMP 是 OC 方法函数指针变量, 代表函数入口, 通过 IMP 也可以调用函数;
-- IMP 调用方法语法 : "返回值类型 (*指针变量) (id, SEL, ...)" , 参数一 方法调用者, 参数二 方法 SEL 对象, 后面参数是方法参数;
(5) 动态调用方法 示例代码
示例代码 :
-- OCStudent.m : 接口实现类主函数一体;
- /*************************************************************************
- > File Name: OCStudent.m
- > Author: octopus
- > Mail: octopus_truth.163.com
- > Created Time: 二 10/ 6 11:19:49 2015
- ************************************************************************/
- #import <Foundation/Foundation.h>
- #import <objc/message.h>
- @interface OCStudent : NSObject
- @end
- @implementation OCStudent
- - (void) setAge : (NSNumber *) age
- {
- int age_num = [age intValue];
- NSLog(@"age is : %d", age_num);
- }
- @end
- int main(int argc, charchar * argv[])
- {
- @autoreleasepool
- {
- OCStudent * student = [[OCStudent alloc] init];
- [student performSelector : @selector(setAge:) withObject : [NSNumber numberWithInt : 18]];
- [student performSelector : NSSelectorFromString(@"setAge:") withObject : [NSNumber numberWithInt : 19]];
- objc_msgSend (student, @selector(setAge:), [NSNumber numberWithInt : 20]);
- objc_msgSend (student, NSSelectorFromString(@"setAge:"), [NSNumber numberWithInt : 21]);
- }
- }
-- 执行结果 : 有报警;
- bogon:6.6 octopus$ clang -fobjc-arc -framework Foundation OCStudent.m
- OCStudent.m:29:12: warning: performSelector may cause a leak because its selector is unknown [-Warc-performSelector-leaks]
- [student performSelector : NSSelectorFromString(@"setAge:") withObject : [NSNumber numberWithInt : 19]];
- ^
- OCStudent.m:29:30: note: used here
- [student performSelector : NSSelectorFromString(@"setAge:") withObject : [NSNumber numberWithInt : 19]];
- ^
- 1 warning generated.
- bogon:6.6 octopus$ ./a.out
- 2015-10-06 12:00:41.669 a.out[747:507] age is : 18
- 2015-10-06 12:00:41.671 a.out[747:507] age is : 19
- 2015-10-06 12:00:41.671 a.out[747:507] age is : 20
- 2015-10-06 12:00:41.672 a.out[747:507] age is : 21