iOS开发 技术集锦

[记]读博客之笔记

2017-03-10  本文已影响12人  iOS_Happy70

每天记一下,日积月累,总会有进步。

以下内容都是摘自各个大牛博客

2017-03-10:

objc_msgSend做了什么?

举个🌰objc_msgSend(obj, foo)是如何执行的:

  1. 首先通过 objc 的 isa 指针找到它的 class ;
  2. 再在 class 的 method list 找到 foo ;
  3. 如果 class 中没有找到 foo ,继续往它的 superclass 中去找;
  4. 只要找到 foo 这个函数, 就会去执行它的 IMP.

其实也并不是每次执行 foo 都会去这样遍历objc_method_list,这样也并合理。那又是怎么做的呢?那就是objc_class中的另一个重要成员objc_cache 。它会把调用过的函数缓存下来。在找到 foo 之后,把 foo 的method_name作为 key ,method_imp作为 value 存起来了。当再次收到 foo 消息时,就可以直接在 cache 里面找到,避免去遍历objc_method_list,从而大大的提高函数查询的效率。

Objective-C 中给一个对象发送消息会经过以下几个步骤:

  1. 在对象类的 dispatch table 中尝试找到该消息。如果找到了,跳到相应的函数IMP中执行代码;
  2. 如果没找到,Runtime 会发送+resolveInstanceMethod: (实例方法) 或者resolveClassMethod: (类方法) 尝试去 resolve (解决) 这个消息;
  3. 如果 resolve 方法返回NO,Runtime 就会发送-forwardingTargetForSelector:允许你把这个消息转发给另外一个对象;
  4. 如果没新的目标对象返回,Runtime 就会发送-methodSignatureForSelector:-forwardInvocation:消息。你可以发送-invokeWithTarget:消息来手动转发消息或者发送-doesNotRecognizeSelector:抛出异常。

摘自Objective-C Runtime

2017-03-24:

对于OC中的类来说,在runtime中会有两个方法被调用:

+load
+initialize
这两个方法看起来都是在类初始的时候调用的,但其实还是有一些异同,从而可以用来做一些行为。

+load

首先,load方法是一定会在runtime中被调用的,只要类被添加到runtime中了,就会调用load方法,所以我们可以自己实现laod方法来在这个时候执行一些行为。

而且有意思的一点是,load方法不会覆盖。也就是说,如果子类实现了load方法,那么会先调用父类的load方法,然后又去执行子类的load方法。同样的,如果分类实现了load方法,也会先执行主类的load方法,然后又会去执行分类的load方法。所以父类的load会执行很多次,这一点需要注意。而且执行顺序是 类 -> 子类 ->分类。而不同类之间的顺序不一定。

+initialize

与load不同的是,initialize方法不一定会执行。只有当一个类第一次被发送消息的时候会执行,注意是第一次。什么叫发送消息呢,就是执行类的一些方法的时候。也就是说这个方法是懒加载,没有用到这个类就不会调用,可以节省系统资源。

还有一点截然相反,却更符合我们预期的就是,initialize方法会覆盖。也就是说如果子类实现了initialize方法,就不会执行父类的了,直接执行子类本身的。如果分类实现了initialize方法,也不会再执行主类的。所以initialize方法的执行覆盖顺序是 分类 -> 子类 ->类。且只会有一个initialize方法被执行。

摘自OC中load方法和initialize方法的异同

2017-03-15:

一个拓展,获取任意ViewController的navigationController

@implementation UIViewController (IMYPublic)
- (UINavigationController*)imy_navigationController {
    UINavigationController* nav = nil;    
    if ([self isKindOfClass:[UINavigationController class]]) {
        nav = (id)self;
    }  
    else {        
        if ([self isKindOfClass:[UITabBarController class]]) {
            nav = [((UITabBarController*)self).selectedViewController imy_navigationController];
        }  
        else {
            nav = self.navigationController;
        }
    }   
    return nav;
}
@end

摘自CocoChina

2017-07-04

为什么IBOutlet属性是weak的?

因为当我们将控件拖到Storyboard上,相当于新创建了一个对象,而这个对象是加到视图控制器的view上,view有一个subViews属性,这个属性是一个数组,里面是这个view的所有子view,而我们加的控件就位于这个数组中,那么说明,实际上我们的控件对象是属于view的,也就是说view对加到它上面的控件是强引用。当我们使用Outlet属性的时候,我们是在viewController里面使用,而这个Outlet属性是有view来进行强引用的,我们在viewController里面仅仅是对其使用,并没有必要拥有它,所以是weak的

2017-07-06

weakSelf和strongSelf

weakSelf 是为了block不持有self,避免Retain Circle循环引用。在 Block 内如果需要访问 self 的方法、变量,建议使用 weakSelf。

strongSelf的目的是因为一旦进入block执行,假设不允许self在这个执行过程中释放,就需要加入strongSelf。block执行完后这个strongSelf 会自动释放,没有不会存在循环引用问题。如果在 Block 内需要多次 访问 self,则需要使用 strongSelf

摘自深入研究Block用weakSelf、strongSelf、@weakify、@strongify解决循环引用

2017-07-31

block的生命周期?

block是一个对象,它的生命周期很简单,只要看持有block的对象是不是也被block持有。如果没有持有,就不用担心循环引用的问题。

如何解决blcok产生的循环引用?

可以用__weak(ARC)__block(MRC)来解决。

block对于参数形式传进来的对象,会不会强引用?

其实block与函数一样,对于传进来的参数,并不会持有。

摘自让我们来深入浅出block吧

上一篇下一篇

猜你喜欢

热点阅读