---------------------- Java培训、.Net培训、Android培训、IOS培训、期待与您交流! ----------------------
(1) 在不改变原来类模型的前提下,给类扩充一些方法 : a. 继承 b. Category
(2) 继承 和 Category 区别 :
1) 使用思想不同,继承是子类在父类的基础之上拓展功能,子类与父类的逻辑关系明显,Category多用于团队分模块开发,在现有基础之上增加新功能。
2) Category 不能修改成员变量的数目,而继承中子类可以增加成员变量的数目
3) Category重写原生方法后可能会导致原生方法无法访问,而继承重写父类方法仍然可以访问父类的方法。
// Person.h #import <Foundation/Foundation.h> @interface Person : NSObject - (void) test(); @end // Person.m #import "Person.h" @implementation Person - (void) test { NSLog(@"test..."); } @end // Person+Person1.h #import "Person.h" @interface Person (Person1) - (void) test1(); @end // Person+Person1.m #import "Person+Person1.h" @implementation Person (Person1) - (void) test1 { NSLog(@"test1..."); } @end // main.m #import "Person.h" #import "Person+Person1.h" int main(){ Person *p = [[Person alloc] init]; // 优先去分类中查找,然后再去原来类中找,最后再去父类中找 [p test]; // test... [p test1]; // test1... return 0; }
(1) Category 好处是一个庞大的类可以分模块来开发,更利于团队开发
(2) 类对象调用方法的时候优先去分类中查找,然后再去原来类中找,最后再去父类中找
(3) 不建议覆盖原有的方法,因为会导致源有方法无法使用。
(4) 覆盖后该使用哪个方法决定于编译的优先级,查看编译的优先级:build phases->compile sources查看优先级,分类之间同名方法的优先级取决与分类的.m文件编译的顺序,比较靠后的优先级比较高
关键字 | NSLog中的占位符 | 描述 |
__func__ | %s | 当前方法签名 |
__LINE__ | %d | 此代码在源文件中的第几行 |
__FILE | %s | 该源文件的全路径 |
__PRETTY_FUNCTION__ |
%s | 功能跟 __func__ 一样,不过此符号用于C++源文件中 |
表达式 | 占位符 | 描述 |
NSStringFromSelector(__cmd) | %@ | 当前方法签名字符串 |
NSStringFromClass([self class]) | %@ | 当前类名字符串 |
[[[NSString stringWithUTF8String:__FILE__] lastPathComponent] | %@ | 当前源文件的名字字符串 |
[NSThread callStackSymbols] | %@ | 获得程序运行时栈的可读设置数组,只适用于调试 |
OC提供了一种新类型数据对类方法进行操作,源码中的原生定义如下:
typedef struct objc_selector *SEL;
对象调用方法都是通过isa指针去类对象中寻找,因此对象方法存储的位置是类对象中 :
(1) 每个类的方法列表都存储在类对象中
(2) 每个方法都有一个与之对应的SEL类型的对象
(3) 根据一个SEL对象就可以找到方法的地址,进而调用方法
SEL s = @selector(test); SEL s2 = NSSelectorFromString(@"test");
@property是编译器特性,它可以帮助我们自动生成一些代码,其中包括可以自动生成成员变量,自动生成成员变量的setter 和 getter.
(1) @property 如果不加任何参数会根据情况生成 属性 和 普通的 setter,getter
1) 如果已经定义了要生成的属性(默认私有),那么编译器不会去定义
2) 如果已经声明了或者定义了要生成 setter 和 getter 将不会去 声明 和 定义
3) 生成的代码取决于 @property 后面的变量名
#import <Foundation/Foundation.h> @interface Cat : NSObject // @property自动生成如下代码 /* { @private int _age; } -(void) setAge:(int)age; - (int) age; */ // 注意 : 生成的属性名称是在前面加上一条下划线 : _age @property int age; @end @implementation Cat // @property自动生成如下代码 /* 普通的setter 和 getter -(void) setAge:(int)age { _age = age; } - (int) age { return _age; } */ @end
(1) set方法内存管理相关参数:
retain: release旧值,retain新值
assign: 直接赋值 (缺损值)
copy: 释放旧值,copy新值,此属性只对那些实行了NSCopying协议的对象类型有效
// retain @property (retain) NSString *name; /* 生成代码 - (void) setName:(NSString *)name { if ( _name != name ){ [_name release]; _name = [name retain]; } } */ // assign @property (assign) NSString *name; /* 生成代码 - (void) setName:(NSString *)name { _name = name; } */ // copy @property (copy) NSString *name; /* 生成代码 - (void) setName:(NSString *)name { if ( _name != name ){ [_name release]; _name = [name copy]; } } */
(2) set方法是否生成:
readonly: 只生成get方法。
readwrite: set方法和get方法都生成(缺损值)
(3) 多线程管理:
noatomic: 性能高,但线程不安全
atomic: 性能低,但线程安全
(4) set方法和get方法的方法名字:
setter : 决定了set方法的名称,一定要有个冒号 :
getter : 决定了get方法的名称(一般用在BOOL类型)
// setter @property (setter = setNewAge:) int age; /* 生成代码 - (void) setNewAge:(int)age { _age = age; } */ // getter @property (getter = isOk:) BOOL ok; /* 生成代码 - (BOOL) isOk { return _ok; } */
(1) 通常情况下为了性能高一般会加上 noatomic 参数
(2) 对于基本数据类型使用 assign OC对象类型使用 retain
(3) 为了提高可读性建议加上 readwrite 或者 readonly 参数
// 基本数据类型 @property (noatomic,readwrite,assign) int age; // OC对象类型 @property (noatomic,readwrite,retain) NSString *name;
代码块本质上和变量类似。不同的是,代码块存储的数据是一个函数体。使用代码块是,你可以像调用其他标准函数一样,传入参数数,并得到返回值。
block的声明与函数指针声明很像,不过block有它特有的标志(^),如下图 :
#import <Foundation/Foundation.h> int main(){ void (^print)(NSString *str); print = ^(NSString *str){ NSLog(str); }; print(@"hello world"); return 0; }
#import <Foundation/Foundation.h> // 注意递归调用block前要把block的函数体定义出来 int main(){ int (^accumulate)(int) = ^(int a){ int sum = a; if ( a > 0 ){ a--; sum += accumulate( a-- ); } else { return sum; } }; NSLog(@"accumulate 5 = %d",accumulate(5)); return 0; }
#import <Foundation/Foundation.h> /* block代码块访问block之外的变量如果不加任何处理编译会报错 因此如果block要访问外部变量,请给变量加上__block关键字 */ // 这里结合typedef使用block typedef int (^MyBlock)(int); int main(){ __block int a = 10; MyBlock addWithA; // block的声明 addWithA= ^(int b){ b += a; return b; }; int result = addWithA(10); NSLog(@"a + b = %d",result); return 0; }
(1) @protocol,简称协议,主要是用来方便程序员之间交流的一种OC特性,它与java中的接口相似,它的组成是 @protocol + 方法列表 + @end;
(2) 它的结构和使用模板如下 :
1.协议的定义 @protocol 协议名称 <NSObject> @required // 方法声明列表.... @optiuonal // 方法声明列表 @end 2.如何遵守协议 1> 类遵守协议 @interface 类名 : 父类名 <协议名称1, 协议名称2> @end 2> 协议遵守协议 @protocol 协议名称 <其他协议名称1, 其他协议名称2> @end
(3) 协议提供两个关键字用来限定方法是否强制实现 :
1) @required (默认),强制实现,如果不实现会报警告.由于OC是弱语法,因此如果类没有实现required方法编译也不会报错
2) @optional , 可以不实现,如果不实现也不会包警告
(1) 对于协议的定可以放在其他文件中 也可以单独新建文件存放,一般建议会单独新建文件存放
(2) 如果要求类要遵守某个协议,那么必须让这个协议遵守<NSObject>协议,否则该类的实例会失去NSOject的某些方法。
(3) 协议也可以对类的成员变量进行限定
// 以下代码暂时不考虑内存管理 /*------------------------------------------- ClassProtocol.h -------------------------------------------*/ #import <Foundation/Foundation.h> @protocol ClassProtocol <NSObject> @required - (void) test; @optional - (void) test1; @end /************************************************************************************************************/ /*------------------------------------------- PropertyProtocol.h -------------------------------------------*/ #import <Foundation/Foundation.h> @protocol ClassProtocol <PropertyProtocol> - (void) test2; @end /************************************************************************************************************/ /*------------------------------------------- Dog.h -------------------------------------------*/ #import <Foundation/Foundation.h> @protocol PropertyProtocol <NSObject> @interface Dog: NSObject <PropertyProtocol> @end /************************************************************************************************************/ /*------------------------------------------- Dog.m -------------------------------------------*/ #import "Dog.h" #import "PropertyProtocol.h" @implementation Dog - (void) test2 { NSLog(@"PropertyProtocol default required -- test2"); // 实现 PropertyProtocol的 默认 required 方法 } @end /************************************************************************************************************/ /*------------------------------------------- Person.h -------------------------------------------*/ #import <Foundation/Foundation.h> #import "Dog.h" @protocol ClassProtocol // 告诉编译器,Test是一个协议,在使用该协议具体定义的函数时候才把该协议文件import进来,提高编译效率 @protocol PropertyProtocol @interface Person : NSObject <ClassProtocol> @property (nonatomic,retain) Dog<PropertyProtocol> *dog; // 协议对成员变量限定 // @property (nonatomic,retain) id<PropertyProtocol> *dog; //等价于上一句,不过可能会失去Dog特有的方法 @end /************************************************************************************************************/ /*------------------------------------------- Person.m -------------------------------------------*/ #import "Person.h" #import "ClassProtocol.h" @implementation Person - (void) test { NSLog(@"ClassProtocol required -- test"); // 实现 ClassProtocol 的 required 方法 } - (void) test1 { NSLog(@"ClassProtocol optional -- test1"); // 实现 ClassProtocol 的 optional 方法 } @end /************************************************************************************************************/ /*------------------------------------------- main.m -------------------------------------------*/ #import "Person.h" #import "Dog.h" #import "ClassProtocol.h" #import "PropertyProtocol.h" int main{ Person<ClassProtocol> *p = [[Person alloc] init]; // 显式实例化一个遵守 ClassProtocol 的Person对象 // id<ClassProtocol> *p = [[Person alloc] init]; // 显式实例化一个遵守 ClassProtocol 的 OC 对象,该对象只保留了 ClassProtocol 里面的方法,失去了Person特有的方法 Dog *dog = [[Dog alloc] init]; // 实例化一个遵守 PropertyProtocol 的Dog对象 [dog test2]; // 调用实现协议的方法 [p setDog:dog]; // 对协议限定的成员变量赋值,如果dog变量不遵守 PropertyProtocol 编译会报错 [p test]; [p test1]; return 0; } /************************************************************************************************************/
---------------------- Java培训、.Net培训、Android培训、IOS培训、期待与您交流! ----------------------
详情请查看:http://edu.csdn.net/heima