(1)如何令自己所写的对象具备拷贝功能
实现NSCopying,NSMtableCopying协议并结合runtime的方法实现赋值
- (instance)copyWithZone:(NSZone *)zone{
id model =[[ [self class] allocWithZone:zone]init];
unsigned int count = 0;
objc_property_t *properties = class_copyPropertyList([self classs],&count);
for(int i = 0 ,i < count ,i++){
objc_property_t property = properties[i];
NSString *propertyName = [NSStirng stringWithUTF8String:property_getName(property)];
id value = [self valueForKey:propertyName];
if(value){
[model setValue:value forKey:propertyName];
}
}
free(properties);
return model;
}
对于,model中有数组,数组内又有model的
- (instance)copyWithZone:(NSZone *)zone{
id model =[[ [self class] allocWithZone:zone]init];
unsigned int count = 0;
objc_property_t *properties = class_copyPropertyList([self classs],&count);
for(int i = 0 ,i < count ,i++){
objc_property_t property = properties[i];
NSString *propertyName = [NSStirng stringWithUTF8String:property_getName(property)];
NSString *propertyAttribute = [NSString stringWithUTF8String:property_getAttributes(property)];
id value ;
if([propertyAttribute rangeOfString:@"NSMutableArray"].location != NSNotFound || [propertyAttribute rangeOfString:@"NSArray"].location != NSNotFound){
value = [[NSMutableArray alloc]initWithArray:value copyItems:YES];
}else{
value = [self valueForKey:propertyName];
}
if(value){
[model setValue:value forKey:propertyName];
}
}
free(properties);
return model;
}
(2)weak属性,以及为什么被weak修饰的对象不用置为nil
A:一般情况下,为了防止出现循环引用,使用weak关键字
B:runtime是如何实现weak的:
weak对象会被放在hash表中,用weak所指向的对象的内存地址当作key,被weak修饰的对象作为value
当weak所指向的对象的引用计数为0时,根据key找到左右的value并置为nil
NSObject *obj1;
NSObject *obj2 = [NSObject new];
__weak obj1 = obj2;
__weak obj1 = obj2;这句代码实际是调用的objc_storeWeak(&obj1,obj2)【objc_storeWeak(value,key)】;
(3)UIView和UILayer
点此查看
(4)@synthesize和@dynamic的区别
点此查看
(5)动态绑定
OC的动态性体现在3个方面:动态类型,动态绑定,动态加载
A:动态类型:id修饰的对象为动态类型对象,(其他在编译器指明类型的对象为静态类型对象),
instancetype和id都可以用来代表任意类型,将对象的类型确定往后推迟,用于体现OC语言的动态性,使其声明的对象具有运行时的特性。
instancetype只能作为返回值类型,但在编译期instancetype会进行类型检测
id类型既可以作为返回值类型,也可以作为参数类型,也可以作为变量的类型,但id类型在编译期不会进行类型检测。
B:动态绑定:动态绑定指的是方法确定的动态性,具体指的是利用OC的消息传递机制要执行的方法推迟到运行时,主要处理应对一些接受者无法处理的消息,此时有机会将消息转发给其他接收者处理
动态绑定的核心就该是在运行时动态的为类添加属性和方法,以及方法的最后处理或转发
C:动态加载,动态加载主要包括两个方面,一个是动态资源加载,一个是一些可执行代码模块的加载,
这些资源在运行时根据需要动态的选择性的加入到程序中,是一种代码和资源的‘懒加载’模式,可以降低内存需求,提高整个程序的性能,另外也大大提高了可扩展性。
(6)category, extension,和继承的区别点此查看,转自他人
category为类添加方法和属性(添加的属性只是声明set和get方法,并无实现,但是可以使用关联对象为其动态添加实现方法);
如果分类和原来的类出现同名的方法,优先调用分类中的,如果一个类有多个分类,每个分类中都有A方法,A方法的实际调用依据编译顺序来定,最后编译的文件被调用(依据为:类的结构中rw的category_t **的添加顺序,点击查看类结构)
形式上看:extension 是匿名的category
extension中声明的方法需要在implementation中实现,而category 不做强制要求
extension 可以添加属性、成员变量,而category 一般不可以。
extension
(1)在编译器决定的,是类的一部分,在编译器和头文件的@interface和实现文件里的@implement一起形成了一个完整的类。.伴随着类的产生而产生,也随着类的消失而消失。
(2)extension一般用来隐藏类的私有消息,你必须有一个类的源码才能添加一个类的extension,所以对于系统一些类,如nsstring,就无法添加类扩展
category
(1)是运行期决议的
(2)类扩展可以添加实例变量,分类不能添加实例变量
原因:因为在运行期,对象的内存布局已经确定,如果添加实例变量会破坏类的内部布局,这对编译性语言是灾难性的。
继承和Category的区别:
1.类别是对方法的扩展,不能添加成员变量。继承可以在原来父类的成员变量的基础上,添加新的成员变量
2.类别只能添加新的方法,不能修改和删除原来的方法。继承可以增加、修改和删除方法。
3.类别不提倡对原有的方法进行重载。继承可以通过使用super对原来方法进行重载。
4.类别可以被继承,如果一个父类中定义了类别,那么其子类中也会继承此类别。
共同点:都是给一个类进行扩展
(7)为什么代理要用weak,delegate和dataSource的区别,block和代理的区别
点击查看