day10---copy,class,选择器

1.copy(自定义对象)

2.类的本质【理解】—》Class类对象

3.选择器 SEL【重点

一 copy
对某个对象发送copy消息的时候,我们的目的是希望能够拷贝出一份一模一样的对象
【Demo】-【1-copy的使用】

什么是深拷贝和浅拷贝?
深拷贝:真正的复制出一份原来的对象,产生了一个新的对象;
浅拷贝:只拷贝了对象的地址,并没有产生新的对象;(retain就属于浅拷贝)

copy和retain的区别:
1.retain和copy都会让对象的引用计数+1,所以都应该对应的必须有一个release或     autorelease;
2.retain是让原对象引用计数器+1,这里只拷贝了对象的地址,并没有产生新对象,认为是“浅     拷贝”;
3.copy拷贝出了一个新对象,让新对象的引用计数器的值为1,认为是“深拷贝”;

copy的运行机制
//希望能拷贝出一个新对象,跟per1所指向的对象的值一样;
//当一个对象指向copy方法的时候,系统内部会自动的调用copyWithZone:这个方法,这是       一个协议方法,该方法返回的对象就是拷贝出来的新对象;
//以后凡是遇到copy一个自定义的对象,或者遇到属性使用copy修饰的自定义对            象,那么先对该对象遵守一个NSCopying协议,并实现协议方法;
#pragma mark - NSCopying协议方法
-(id)copyWithZone:(NSZone *)zone{
 Person *per = [[Person alloc] initWithAge:self.age andWithName:self.name];

    //在这里属于特殊情况,返回对象的时候不需要加入autorelease
    return per;
}

二 类的本质
当程序一运行起来,系统就会默认吧工程中所有的类都加载一份到内存中(这块内存中保存的是 所有的方法列表),我们可以把这块内存认为是类在内存中的对象,称为“类对象”;
类对象都对应一种类型,Class类型;
Class-》所有的类对象都是Class类型;

类的加载和初始化【了解】
+(void)load;

+(void)initialize;
见【Demo】-【2-类的加载和初始化】

@implementation Dog
//当程序启动的时候,就会加载一次项目中所有的类到内存中,加载完毕后就会调用load方法(只会调用一次),先调用父类,再调用子类;
+(void)load{
NSLog(@"Dog ----load 加载到了内存中");

}

//当第一次使用这个类(类对象)的时候,就会调用initialize这个方法,且只调用一次,先调用父类,再调用子类;
+(void)initialize{
NSLog(@"Dog --- initialize 进行初始化!");

}

@end

类对象:一个类在程序中只有一个类对象;
类的对象:程序中可以有无数个类的对象;


如何获得Class类型的类对象;
1)直接向类的对象发送一个class消息,[per1  class];
2)直接向我们的类名发送class消息,[Person class];

见【Demo】-【3-类对象的使用场合】

    //类对象的使用场合【**掌握下面的几个方法**】
    //1.判断一个类是否是另一个类的子类
    BOOL bl1 = [Person isSubclassOfClass:[NSObject class]];
    if (bl1) {
        NSLog(@"是的");
    }else{
        NSLog(@"不是的");
    }
    
    //2.判断一个指针所指向的对象是否是某种类型
    id obj = [[Person alloc] init];
    BOOL bl2 = [obj isMemberOfClass:[Person class]];
    if (bl2) {
        NSLog(@"是的");
    }else{ 
        NSLog(@"不是的");
    }

    
    //3.判断一个指针所指向的对象是否是某种类型或者它的子类【**常用**】
    id str = @"1111222";
    BOOL bl3 = [str isKindOfClass:[NSString class]];
    if (bl3) {
        NSLog(@"是的");
    }else{
        NSLog(@"不是的");
    }

三 选择器【重点
3.1认识选择器
1)选择器是一种数据类型,这个类型写作SEL
2)SEL声明的变量是用来装“成员方法”的,更确切的说,装“消息”,有点类似于“函数 指针”;

    【作用】
        我们可以通过选择器SEL数据类型实现动态的调用对象的成员方法。

    【Demo】-【4-认识选择器】


数组的排序
见【Demo】-【5-数组的排序】

//        char buf[100];

// printf("请输入您想调用的方法名:\n");
// scanf("%s",buf);
//
// //把C字符串转换成OC字符串
// NSString *str = [NSString stringWithUTF8String:buf];

    //把一个字符串反射出对应的选择器类型

// SEL sel = NSSelectorFromString(str); //***********重点

    Person *per = [[Person alloc] init];
    //定义一个SEL类型的变量;
    //该变量里装的是study这个成员方法;

// SEL sel = @selector(study);
//
//
// //通过选择器调用成员方法;
// [per performSelector:sel];
//
//
//
// SEL sel1 = @selector(setAge:);
// //调用带一个参数的方法;
// [per performSelector:sel1 withObject:@10];
// NSLog(@"per = %d",[per.age intValue]);
//
//
//
// [per performSelector:@selector(setName:) withObject:@"小迪迪"];
// NSLog(@"name = %@",per.name);

    //调用带两个参数的   ,最多只能带两个参数;
    //如果有两个以上的参数,可以考虑重新设计这个方法,比如传数组,或者设计另一个类把这些多个参数都封装在类里面,一起作为参数传过去;

// [per performSelector:<#(SEL)#> withObject:<#(id)#> withObject:<#(id)#>];

    //选择器常用的几个方法
    //1.判断一个“类”是否存在某个方法
    Person *per2 = [[Person alloc] init];
    BOOL bl1 = [Person instancesRespondToSelector:@selector(study)];
    if (bl1) {
        NSLog(@"存在该方法");
        [per2 performSelector:@selector(study)];
    }else{
        NSLog(@"不存在该方法");
    }
    
    
    //2. 判断一个对象是否实现了某个方法  【***常用】
    //常用在调用协议方法的时候,为了保证代码的安全性,在调用代理的协议方法之前,最好是先判断该代理对象是否实现了对应的协议方法;
    BOOL bl2 = [per2 respondsToSelector:@selector(playGame)];
    if (bl2) {
        [per2 playGame];
    }else{
        NSLog(@"你没有实现这个方法!");
    }
    
    //3.协议选择器【了解】
    //协议选择器里面装的是协议
    Protocol *p = @protocol(NSCopying);
    //判断一个对象是否遵守了某个协议
    BOOL bl3 = [per2 conformsToProtocol:p];
    if (bl3) {
        if ([per2 respondsToSelector:@selector(copyWithZone:)]) {
            Person *perCopy = [per2 copy];
            [perCopy release];
        }
    }else{
        NSLog(@"这个类不具备拷贝对象的能力");
    }




数组排序
-(id)initWithAge:(int)age andWithName:(NSString *)name{
if ([super init]) {
    self.age = age;
    self.name = name;
}
return self;

}

-(NSComparisonResult)compareAndName:(Student *)otherStudent{

return [self.name compare:otherStudent.name];

}

-(NSComparisonResult)compareAndAge:(Student *)otherStudent{

if (self.age == otherStudent.age) {
    return [self.name compare:otherStudent.name];
}

// return -[self.age compare:otherStudent.age];
//和上面写法一样的效果
return [@(self.age) compare:@(otherStudent.age)];

}

你可能感兴趣的:(day10---copy,class,选择器)