对象在运行时获取其类型的能力称为内省。内省可以有多种方法实现。
判断对象类型
-(BOOL) isKindOfClass: classObj判断是否是这个类或者这个类的子类的实例
-(BOOL) isMemberOfClass: classObj 判断是否是这个类的实例
-(BOOL) respondsToSelector: selector判读实例是否有这样方法
+(BOOL) instancesRespondToSelector: 判断类是否有这个方法。此方法是类方法,不能用在类的对象
2.1 respondsToSelector的使用
NSAutoreleasePool内部包含一个数组(NSMutableArray),用来保存声明为autorelease的所有对象。如果一个对象声明为autorelease,系统所做的工作就是把这个对象加入到这个数组中去。NSAutoreleasePool自身在销毁的时候,会遍历一遍这个数组,release数组中的每个成员。如果此时数组中成员的retain count为1,那么release之后,retain count为0,
类别:
那的Category的使用场景有那些呢:
1、类包含了很多个方法实现,而这些方法需要不同团队的成员来实现
2、当你在使用基础类库中的类时,你不想继承这些类而只想添加一些方法时。
Category能实现上面的需求,当然也有使用Category是需要注意的问题:
1、Category可以访问原始类的实例变量,但不能添加实例变量,如果想添加变量,那就通过继承创建子类来实现。
2、Category可以重载原始类的方法,不大不推荐这么做,这样会覆盖掉原始类的方法。如果确实要重载,那就通过继承创建子类来实现。
3、和普通接口有所区别的是,在Category的实现文件中的实例方法只要你不去调用它你可以不用实现所有声明的所有方法。
kvo(key values observing)键值观察者模式
主要用于:界面的某些数据发生变化了,界面的显示也跟着发生变化,则需要建立数据和界面的关联
[object addObserver:self forKeyPath:@"courseName" options:NSKeyValuesObservingOPtionOld | NSKeyValueObservingOPtionNew context:nil];
-(void)dealloc
{
[object removeObserver:self forKeyPath:@"courseName",context:nil];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"courseName"]) {
NSLog(@"pageView改变了");
NSLog(@"新值:%@,旧值:%@",[change objectForKey:@"new"],[change objectForKey:@"old"]);
}
}
KVC
除了一般的赋值和取值的方法,我们还可以用Key-Value-Coding(KVC)键值编码来访问你要存取的类的属性。
- @class Course;
- @interface Student : NSObject
- {
- NSString *name;
- Course *course;
- }
- @end
实现还是什么都没有,这里就不贴代码了
在main方法中,我们实验通过键路径访问Course中CourseName的属性
- #import "Student.h"
- #import "Course.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- Student *student = [[[Student alloc]init ]autorelease];
- [student setValue:@"张三" forKey:@"name"];
- NSString *name = [student valueForKey:@"name"];
- NSLog(@"学生姓名:%@",name);
- Course *course = [[[Course alloc]init] autorelease];
- [course setValue:@"语文课" forKey:@"CourseName"];
- [student setValue:course forKey:@"course"];
- NSString *courseName = [student valueForKeyPath:@"course.CourseName"];
- NSLog(@"课程名称:%@", courseName);
- //也可以这样存值
- [student setValue:@"数学课" forKeyPath:@"course.CourseName"];
- courseName = [student valueForKeyPath:@"course.CourseName"];
- NSLog(@"课程名称:%@", courseName);
- }
- return 0;
- }
代码块(block)
void(^printBlock)(NSString * x);
printBlock = ^(NSString * str)
{
NSLog(@"%@,"str);
}
printBlock(@"liuXiaoMin‘sCode");
代码块实现数组排序:
NSArray * strArray = [NSArray arrayWithObjects:@"aa1",@"bb2",@"cc3"];
NSComparator sortBlock = ^(id string1, id string2)
{
return [string1 compare:string2];
}
NSArray * sortArray = [stringArray sortedArrayUsingComparator:sortBlock];
NSLog(@"sortArray:%@",sortArray);
代码块的递归调用
static void (^ const blocks)(int) = ^(int i)
{
if(i > 0)
{
NSLog(@"num%d",i);
blocks(i - 1);
}
}
在代码块中:
而局部变量可以使用,但是不能改变。
在代码块中改变局部变量编译不通过。怎么在代码块中改变局部变量呢?在局部变量前面加上关键字:__block
NSEnumerator * enmuerator = [array objectEnummerator];
id object;
while(object = [enmmuerator nextObject]]){
NSLog(@"数组中的对象:%@",object);
}
[ obj release];