美文网首页
iOS开发进阶(唐巧)阅读笔记

iOS开发进阶(唐巧)阅读笔记

作者: 木子影 | 来源:发表于2017-02-28 17:32 被阅读129次

一、iOS开发底层原理

1:类也是一个对象,所以它必须是另一个类的实例,这个类就是元类(metaclass)。

CE4585C9-10C0-481A-AEA6-6A00B6AC200B.png

我们可以从图中看出:

(1)NSObject的类中定义了实例方法。

(2)NSObject的元类中定义了类方法。

(3)NSObject的元类继承自NSObject类,所以NSObject类是所 有类的根,因此NSObject中定义的实例放阿飞可以被多有对象调用。

(4)NSObject的元类的isa指向自己。

2、因为对象在内存中的排布可以看成一个结构体,该结构体的大小并不能动态变化,所以无法再运行时动态的给对象增加成员变量。

 相应的,对象的方法都定义保存在类的可变区域中。Objective-C 2.0并未在头文件中将实现暴露出来,但在Objective-1.0,中,我们可以看到方法的定义列表是为一个名为methoLists的指针的指针,这也是Category实现的原理。同时也说明了为什么Category只可为对象增加成员方法,却不能增加成员变量。

3、动态的创建对象

我们可以使用Objective-C语言提供的与runtime相关的函数,动态地创建一个新的类,并且通过相关的方法来获得isa的值,从而了解对象的内部结构。

动态创建类的代码:

 - (void)viewDidLoad {
     [super viewDidLoad];
     // Do any additional setup after loading the view, typically from a nib.
    //创建一个新类,名为LRGCustomView,是UIView的子类
     Class newClass=objc_allocateClassPair([UIView class], "LRGCustomView", 0);
      //为该类增加一个名为report的方法
     class_addMethod(newClass, @selector(report), (IMP)ReportFunction,"v@:");
     //注册该类
      objc_registerClassPair(newClass);
      //创建一个LRGCustomView的实例
       id instanceOfNewClass=[[newClass alloc] init];
        //调用report方法
        [instanceOfNewClass performSelector:@selector(report)];
}
void ReportFunction(id self,SEL _cmd)
{
       NSLog(@"This object is %p.",self);
       NSLog(@"Class is %@,and super is %@ ",[self class],[self superclass]);
       Class currentClass=[self class];
       for(int i=1;i<5;i++){
                NSLog(@"Following the isa pointer %d times gives %p",i,currentClass);
                currentClass=object_getClass(currentClass);
}
        NSLog(@"NSObject's class is %p",[NSObject class]);
          NSLog(@"NSObject's class is %p"),object_getClass([NSObject class]);
}

该代码中重要的地方:

1、import runtime相关的头文件:objc/runtime.h。
2、使用objc_allocateClassPair方法创建新的类。
3、使用class_addMethod方法来给类增加新的方法。
4、使用objc_registerClassPair来注册新的类。
5、使用object_getClass方法来获得对象的isa指针所指向的对象。

54DE3BAA-58BE-4AD7-8778-5533EAA468F4.png

分析:

1、从LRGCustomView对象开始,在我们连续取了3次isa指针所指向的对象后,isa指针所指的地址变成了NSObject元类的地址,第四次起取isa指针所指的对象时的结果说明了NSObject元类的isa指针指向了他自己。
2、作为对比,再代码最后取NSObject类的isa指针地址,我们可以看到其值与其他元类对象的isa只针对值一样,都是指向NSObject元类的。

03358EF1-1150-4797-B54A-9A7147F2F744.png

isa swizzling的应用

  系统提供的KVO的实现,就利用了动态的修改isa指针的值的技术。

Method Swizzling API说明

Objective-C提供了以下API来动态替换类方法或者实例方法的实现:

class_replaceMethod替换类方法的定义。当该类中没有想替换的原方法时,该方法会调用class_addMethod来为该类增加换一个新方法。
使用场景:当需要替换的方法可能不存在时,可以考虑使用该方法。
method_exchangeImplementations交换两个方法的实现。
使用场景:当需要交换两个方法的实现时使用。
method_setImplementation设置一个方法的实现。
使用场景:是最简单的用法,当仅仅需要为一个方法设置其实现方式时使用。
一下是唐巧的案例:

024B7BF8-6319-45C6-A6FD-7D9769B8BE0B.png

用clang分析block实现

      clang提供一个命令,可以将Objective-C的源码改写成C语言,借此可以研究具体的源码实现方式。该命令是:
     clang -rewrite-objc block.c

NSConcreteGlobalBlock类型的block的实现
先新建一个名为“block.c”的源文件:

#include<stdio.h>
int main(){
   ^{printf("Hello,World\n");}();
   return 0;
}

再命令行中输入 clang -rewrite-objc block.c,即可在目录中看到clang输出了一个名为"block1.cpp"的文件,该文件就是block在C语言中的实现

GCD

  Grand Central Dispatch(GCD)比NSThread、NSOperationQueue、NSInvocationOperation等技术用起来更加方便。
      //后台执行:
      dispatch_async(dispatch_get_global_queue(0,0),^{  });
     //主线程执行:
     dispatch_async(dispatch_get_main_queue(),^{   });
      //一次性执行:
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken,^{ });
      //延迟2秒执行:
      double delayInSeconds = 2.0;
      dispatch_time_t popTime=dispatch_time(DISPATCH_TIME_NOW,delayInSeconds * NSEC_PER_SEC);
      dispatch_after(popTime,dispatch_get_main_queue(),^(void){ });
       dispatch_queue_t也可以自己定义,如要自定义queue,可以用dispatch_queue_create方法示例如下:
       dispatch_queue_t urls_queue = dispatch_queue_create("blog.devtang.com",NULL);
      dispatch_async(urls_queue,^{  };
       dispatch_release(urls_queue);
      另外,GCD还有一些高级用法,例如让后台两个线程并行执行,然后等两个线程都结合素后,再汇总执行结果。这个可以用dispatch_group、dispatch_group_async和dispatch_group_notify来实现,示例如下:
      dispatch_group_t group = dispatch_group_create();
      dispatch_group_async(group,dispatch_get_global_queue(0,0),^{ //并行执行的线程一});
      dispatch_group_async(group,dispatch_get_global_queue(0,0),^{ //并行执行的线程二});
      dispatch_group_notify(group,dispatch_get_global_queue(0,0),^{ //汇总结果});

后台运行

< 使用block的另一个用处是可以让程序再后台较长久地运行。以前当按Home键退出后,应用仅有最多5秒钟的时间做一些保存或者清理资源的工作。但是应该可以调用UIApplication的beginBackgroundTaskWithExpirationHandler方法,让应用最多有十分钟的时间在后台长久运行。这个时间可以用来做清理本地缓存、发送统计数据等工作。但是应用可以调用UIApplication的beginBackgroundTaskWithExpirationHandler方法,让应用最多有十分钟的时间在后台长久运行。

让程序再后台长久运行的示例代码如下:

//AppDelegate.h文件
   @property (assign,nonatomic) UIBackgroundTaskidentifier backgroundUpdateTask;
//AppDelegate.m文件
-(void)applicationDidenterBackground:(UIApplication *)application
{
        [self beginBackgroundUpdateTask];
        //在这里加上你需要长久运行的代码
        [self beginBackgroundUpdateTask];
}
-(void)beingBackgroundUpdateTask{
     self.backgroundUpdateTask=[[UIApplication shareApplication] beginBackgroundTaskWithExpirationHandler:^{
           [self endBackgroundUpdateTask];
      }];
}

-(void)endBackgroundUpadateTask{
        [[UIApplication shareApplication] endBackgroundTask:self.backgroundUpdateTask];
       self.backgroundUpdateTask=UIBackgroundTaskInvalid;
}

UIWindow使用

通常有两种方法给UIWindow增加UIview

1.通过调用addsubView方法。UIWindow是UIView的子类,可以用addSubView的方法给自己增加子UIView。
2.通过设置其特有的rootViewController属性。通过设置该属性为要添加view对应的UIViewController,UIWindow将会自动将其view添加到当前window中,同事负责维护ViewController和view的生命周期。
UIWindow有一个类型为"UIWindowLevel"的属性,该属性定义了UIwindow的层级,系统定义的WindowLevel一共有三种取值,如下所示:

   UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal;
   UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert;
   UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar;

UIWindow的层级是UIWindowLevelNormal,当系统需要在其上面覆盖UIAlertView时,就会创建一个层级是UIWindowLevelAlter的UIWindow,因为其WindowLevel值更高,所以就覆盖在上面了。

手工创建UIWindow

UIWindow一旦被创建,它就自动被添加到整个界面上了
如果我们创建的UIWidnow需要处理键盘事件,那就需要将其试着为keyWindow。keyWindow是被系统设计用来接收键盘和其他非触摸事件的UIWindow。通过makeKeyWindow和resignKeyWindow方法来将自己创建的UIWindow实例设置成keyWindow.

相关文章

  • <> 读书随笔

    最近在读唐巧老师的<< iOS开发进阶>> 记点笔记,方便以后使用. 没有的朋友可以点击下载iOS开发进阶 完整版...

  • CoreText的简单使用(一)

    CoreText的简单使用(一) 介绍: 读唐巧的《iOS开发进阶》,关于CoreText的笔记。借用介绍:“使用...

  • 2018国庆读书笔记之一: iOS面试之道

    2018 国庆读书笔记之一: iOS面试之道 之前看过一本唐巧的书“iOS开发进阶”以介绍技巧和工具为主...

  • iOS开发进阶(唐巧)阅读笔记

    一、iOS开发底层原理 1:类也是一个对象,所以它必须是另一个类的实例,这个类就是元类(metaclass)。 我...

  • CocoaPods 使用笔记

    这篇文章算是我自己学习使用CocoaPods的笔记。唐巧的《iOS开发进阶》,第二章:使用CocoaPods做依赖...

  • iOS 内存管理

    前言 本篇是看唐巧写的「iOS开发进阶」书籍的「理解内存管理」知识点汇总笔记总结 Objective-C 和 Sw...

  • Mac环境下搭建Octopress博客

    最近看了两本书:1.唐巧的《IOS开发进阶》。2.Matt Galloway的《Effective Objecti...

  • ios开发进阶---唐巧

    项目地址:https://github.com/tangqiaoboy/iOS-Pro 一、如何提高开发技能 1、...

  • 《iOS进阶-唐巧》阅读记录

    2019.1.7 略看目录结构:引言、iOS开发工具(介绍多种开发工具的实际使用)、iOS开发实践(内存管理及各种...

  • iOS开发常用之博客

    开发博客列表 唐巧整理 - 猿题库唐巧整理。 11个超棒的iOS开发学习国外网站 - 11个超棒的iOS开发学...

网友评论

      本文标题:iOS开发进阶(唐巧)阅读笔记

      本文链接:https://www.haomeiwen.com/subject/kszxgttx.html