- Effective Objective-C 2.0 读书笔记
- Effective Objective-C 2.0笔记(二)
- Effective Objective-C 2.0笔记(一)
- Effective Objective-C 2.0笔记(三)
- Effective Objective-C 2.0笔记(五)
- 《Effective Objective-C 2.0 》 阅读笔
- Effective Objective-C 2.0 无废话精简篇
- Effective Objective-C 2.0 脑图- [O
- iOS开发读书笔记:Effective Objective-C
- iOS开发读书笔记:Effective Objective-C
第二章
第6条 理解“属性”这一概念
在文件中声明一个全局变量有一下两种方法
@interface ViewController ()
{
NSString * _name;
}
@property (nonatomic, copy) NSString * gender;
_name 是在编译期确定了对象的布局 如果添加一个相同声明方式的变量,对象布局的偏移量会发生改变,从而造成数据混乱。所以编译器需要重新编译确定正确的对象布局。
使用property 声明的变量系统回自动为其生成set方法和get方法。而变量的内存偏移会交给 class object 管理。这样在运行期也可以查找对象正确的偏移量了。
要访问属性也可以使用点语法,编译器会把“点语法“转换为对存取方法的调用。
关于@property和@synthesize的进一步理解
这篇文章较为全面的讲解了这两个关键字的联系。
@dynamic关键字 联想到的是动态绑定
iOS @property、@synthesize和@dynamic
Nullability 也是iOS的特性之一 nonull nullable null_resettable _Null_unspecified 这里只做一下延伸
其他修饰符的作用不在赘述
第7条在对象内部尽量直接访问实例变量
直接访问实例变量和通过属性来访问成员变量的区别
1.由于不经过OBject-C的“方法派发”步骤,所以直接访问实例变量额速度淡然比较快。在这种情况下,编译器所生成的代码会直接访问保存对象实例变量的那块内存。
2.直接访问实例变量,不会调用其set方法,这就绕过了为相关属性所定义的“内存管理语意”。比方说,如果在ARC下直接反问一个声明为copy的属性,那么并不会拷贝该属性,只会保留新值并释放旧值。
3.如果直接访问实例变量,那么不会触发“键值观测”(Key-Value Observing,KVO)通知。这样做会产生问题,还取决于具体对象行为。
4.通过属性来访问有助于排查与之相关的错误,因为给可以“获取方法”和/或“设置方法“中新增“断点”,监控该属性的调用者及其访问时机。
总结:
1.在对象内部读取数据时,应该直接通过适量变量来读,而写入数据时,则应该通过属性来写。
2.在初始化方法及dealloc方法中,总是应该直接通过实例变量来读写数据。
3.有时会使用惰性初始化技术配置某份数据,这种情况下,需要通过属性来读去数据。
第8条 理解”对象等同性“这一概念
本条中主要讲解了两个方法
-(BOOL)isEquale:(id)objece;
-(NSUinteger)hash;
一般判断连个用户model 是否相同我们只需重写model的isEqual方法判断用户的ID是否相等即可 如果内存地址相同那么这连个对象也相同。
- (BOOL)isEqual:(id)object {
//判断内存地址是否相同
if (self == object) {
return YES;
}
//判断是否是相同的类
if (![object isKindOfClass:[UserPicInfoModel class]]) {
return NO;
}
//判断uin是否相同 因为一般用户的id是唯一的这可以作为判断的依据
UserPicInfoModel *tekubaEntity = (UserPicInfoModel *)object;
if (tekubaEntity.uin == self.uin) {
return YES;
} else {
return NO;
}
}
与isEqual 连同使用的是hash方法。获取到的hash关系:
1.若两个对象相同,则其哈希码(hash)也相等。
2.但是两个哈希码相同的对象却未必相同。
自定义-(NSUinteger)hash; 函数时应该使用计算速度快,碰撞几率低的算法。
不如使用^(按位异或) 这样比单纯的使用加法获得相同hash值的概率大大降低,减少了碰撞几率。
- (NSUInteger)hash{
NSUInteger nameHash = [_name hash];
NSUInteger ageHash = [_age hash];
return nameHash ^ ageHash;
}
容器中的可变类的等同性。
可能看了前面并不理解为什么要重写hash方法呢?
如果重写isEqual方法,一定要重写hash方法。
重写的hash方法一定要简单,因为如果你的对象存在字典或者集中,hash方法会频繁的调用。
相同的对象一定要返回相同的hash值,但是有相同的hash值的对象不一定是同一个对象,这是就是产生了碰撞,但是我们要让产生这种情况的机会尽可能的少。
如果想要了解究竟为什么请看这篇文章,其中提到了hashtable
NSDictionar的底层实现
字典的都看了,去看看那数组的底层。
第9条 以“类族模式”隐藏实现细节
项目中有哪些地方用到了类族呢?
1.UIButton 我们创建没有使用alloc init 而是使用了buttonWithType:方法。
2.数组字典等容器的越界放崩溃。比如NSArray 我们并不是直接处理NSArray的相关方法。而是分别处理__NSArrayI __NSArray0 等类的相关方法。
JJException
3.工厂方法和多态。
第10条:在既有类中使用关联对象存放自定义数据
///此方法以规定的键和策略为某对象设置关联对象值
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,
id _Nullable value, objc_AssociationPolicy policy)
///此方法根据给定的键从某对象中获取相关的关联对象值
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)
///此方法已出指定对象的全部关联对象
objc_removeAssociatedObjects(id _Nonnull object)
设置关联对象值时,通常使用静态全局变量,以保证两个相同对象的键值是相同的,然后在两个键上调用isEquel:方法返回为YES;
关联对象面试中对多闻到的就是 是否可以在category中添加属性。探究iOS分类(category)为什么不能直接添加属性
第11条:理解objc_msgSend的作用
Objec-C是一门动态语言,C语言使用的是“静态绑定”。
1.消息由接收者、选择子、及参数构成。给某对象“发送消息"(invoke a message )也就相当于在该对象上“调用方法”(call a method)。
2.发给某对象的全部消息都要由“动态消息派发系统”(dynamic message dispatch system)来处理,该系统会查出对应的方法并执行其代码。
第12条:理解消息转发机制
当对象接收到无法解读的消息后,就会启动“消息转发”机制,程序猿可以经由此过程告诉对象应该如何处理消息。下面这张图在熟悉不过了
[图片上传中...(屏幕快照 下午10.10.54.png-b5a2e2-1553004688051-0)]
提到消息转发 不得不提到OC中除了NSObject的另一个超类NSProxy。
YYWeakProxy 解决的NSTimer讨厌的强引用问题
- (void)initTimer {
YYWeakProxy *proxy = [YYWeakProxy proxyWithTarget:self];
_timer = [NSTimer timerWithTimeInterval:0.1 target:proxy selector:@selector(tick:) userInfo:nil repeats:YES];
}
第13条:用“方法调配技术”调试“黑盒方法”
#import
@implementation UIViewController (Tracking)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Classclass= [selfclass];
SEL originalSelector = @selector(viewWillAppear:);
SEL swizzledSelector = @selector(xxx_viewWillAppear:);
MethodoriginalMethod=class_getInstanceMethod(class, originalSelector);
MethodswizzledMethod=class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if(didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else{
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
#pragma mark - Method Swizzling
- (void)xxx_viewWillAppear:(BOOL)animated {
[selfxxx_viewWillAppear:animated];
NSLog(@"viewWillAppear: %@", self);
}
@end
简要说明一下以上代码的几个重点:
* 通过在Category的+ (void)load方法中添加Method Swizzling的代码,在类初始加载时自动被调用,load方法按照父类到子类,类自身到Category的顺序被调用.
* 在dispatch_once中执行Method Swizzling是一种防护措施,以保证代码块只会被执行一次并且线程安全,不过此处并不需要,因为当前Category中的load方法并不会被多次调用.
* 尝试先调用class_addMethod方法,以保证即便originalSelector只在父类中实现,也能达到Method Swizzling的目的.
* xxx_viewWillAppear:方法中[self xxx_viewWillAppear:animated];代码并不会造成死循环,因为Method Swizzling之后, 调用xxx_viewWillAppear:实际执行的代码已经是原来viewWillAppear中的代码了.
这是因为class_replaceMethod方法其实能够覆盖到class_addMethod和method_setImplementation两种场景, 对于第一个class_replaceMethod来说, 如果viewWillAppear:实现在父类, 则执行class_addMethod, 否则就执行method_setImplementation将原方法的IMP指定新的代码块; 而第二个class_replaceMethod完成的工作便只是将新方法的IMP指向原来的代码.
[http://www.cocoachina.com/ios/20160826/17422.html](http://www.cocoachina.com/ios/20160826/17422.html) 写的不错
这里唯一可能需要解释的是 class_addMethod 。要先尝试添加原 selector 是为了做一层保护,因为如果这个类没有实现 originalSelector ,但其父类实现了,那 class_getInstanceMethod 会返回父类的方法。这样 method_exchangeImplementations 替换的是父类的那个方法,这当然不是你想要的。所以我们先尝试添加 orginalSelector ,如果已经存在,再用 method_exchangeImplementations 把原方法的实现跟新的方法实现给交换掉。
作者:风之痕_
链接:[https://www](https://www/).[jianshu.com/p/addd4eac54ed](http://jianshu.com/p/addd4eac54ed)
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
第14条:理解“类对象”的用意

书中在58页 在类继承体系中查询类型信息中有的例子中有一处错误
[dict isMemberOfClass:[NSMutableDicitionary class]]; 打印不是YES 而是NO。这就涉及到 前面讲的类簇问题 [dict isMemberOfClass:[__NSDictionaryM class]]; 为YES
(lldb) po [dict isMemberOfClass:[__NSDictionaryM class]]
YES
这里要感谢学伟《Effective Objective-C 2.0》读书:实战笔记一
这才体会到光学不练假把式。惭愧……
还有一道面试题


网友评论