关于源码学习自己的一些感悟

第一层:熟练使用;

第二层:读懂代码;

第三层:通晓原理;

第四层:如何设计;

自己学到了什么,还留有什么问题;

关于分享

关于线下演讲分享和线上文章分享,我一直觉得技术领域要学东西的话线上文章分享是最好的形式,一是它传播广,触达用户多;二是耗时少,写一篇文章或看一篇文章都比听一个分享花的时间少很多;三是可沉淀,读者可以反复看细节,可以沉淀下来不断被人搜索到。 – Bang (JSPatch 作者)

YYModel 作者性能优化的几个 Tip:

缓存Model JSON 转换过程中需要很多类的元数据,如果数据足够小,则全部缓存到内存中。

查表当遇到多项选择的条件时,要尽量使用查表法实现,比如 switch/case,C Array,如果查表条件是对象,则可以用 NSDictionary 来实现。

避免 KVCKey-Value Coding 使用起来非常方便,但性能上要差于直接调用 Getter/Setter,所以如果能避免 KVC 而用 Getter/Setter 代替,性能会有较大提升。

避免 Getter/Setter 调用如果能直接访问 ivar,则尽量使用 ivar 而不要使用 Getter/Setter 这样也能节省一部分开销。

避免多余的内存管理方法在 ARC 条件下,默认声明的对象是  strong 类型的,赋值时有可能会产生 retain/release 调用,如果一个变量在其生命周期内不会被释放,则使用  unsafe_unretained 会节省很大的开销。访问具有  weak 属性的变量时,实际上会调用 objc_loadWeak() 和 objc_storeWeak() 来完成,这也会带来很大的开销,所以要避免使用  weak 属性。创建和使用对象时,要尽量避免对象进入 autoreleasepool,以避免额外的资源开销。

遍历容器类时,选择更高效的方法相对于 Foundation 的方法来说,CoreFoundation 的方法有更高的性能,用 CFArrayApplyFunction() 和 CFDictionaryApplyFunction() 方法来遍历容器类能带来不少性能提升,但代码写起来会非常麻烦。

尽量用纯 C 函数、内联函数使用纯 C 函数可以避免 ObjC 的消息发送带来的开销。如果 C 函数比较小,使用 inline 可以避免一部分压栈弹栈等函数调用的开销。

减少遍历的循环次数在 JSON 和 Model 转换前,Model 的属性个数和 JSON 的属性个数都是已知的,这时选择数量较少的那一方进行遍历,会节省很多时间。

YYModel 源码学习篇

把不熟练的一些代码挑出来,弄清楚

NS_ASSUME_NONNULL_BEGIN / NS_ASSUME_NONNULL_END

为了防止写一大堆 nonnull(不可为nil),Foundation 还提供了一对儿宏,包在里面的对象默认加 nonnull 修饰符,只需要把 nullable 的指出来就行

1 NS_ASSUME_NONNULL_BEGIN
2 @interface Sark : NSObject@property (nonatomic, copy, nullable) NSString *workingCompany;
3 @property (nonatomic, copy) NSArray *friends;
4 - (nullable NSString *)gayFriend;
5 @end
6 NS_ASSUME_NONNULL_END

#define force_inline inline attribute((always_inline))

1 __attribute__((always_inline))的意思是强制内联,所有加了__attribute__((always_inline))的函数再被调用时不会被编译成函数调用而是直接扩展到调用函数体内,比如我定义了函数2 __attribute__((always_inline)) void a()3 void b(){a();}4 b调用a函数的汇编代码不会是跳转到a执行,而是a函数的代码直接在b内成为b的一部分。

普通函数

调用时,会出现流程跳转来回

调用时,直接 将内联函数的代码全部复制到调用的地点;

内联函数的定义必须出现在调用之前;

牺牲内存空间,来提高函数执行速度;

内联函数的不足

通常,编译器比程序设计者更清楚对于一个特定的函数是否合适进行内联扩展;一些情况下,对于程序员指定的某些内联函数,编译器可能更倾向于不使用内联甚至根本无法完成内联。

代码比较长的,即使声明为inline,也不会最终内联

而有的一些比较短的小函数,即使没有声明inline,也会由c/c++编译器最终内联

而如果函数使用强制内联,那么最终就一定是内联

对于一些开发中的函数,它们可能从原来的不适合内联扩展变得适合或者倒过来。尽管内联函数或者非内联函数的转换易于宏的转换,但增加的维护开支还是使得它的优点显得更不突出了。

对于基于C的编译系统,内联函数的使用可能大大增加编译时间,因为每个调用该函数的地方都需要替换成函数体,代码量的增加也同时带来了潜在的编译时间的增加。

函数调用中堆栈的个人理解

NSCoder

iOS开发-数据存储NSCoder NSCoding是一个protocol. 如果实现了NSCoding,需要实现其中的两个方法:

1 - (void)encodeWithCoder:(NSCoder *)aCoder;2 - (id)initWithCoder:(NSCoder *)aDecoder; // NS_DESIGNATED_INITIALIZER

方法中的主要的参数就是NSCoder,它是archivie字节流的抽象类.可以将数据写入一个coder,也可以从coder中读取我们写入的数据. NSCoder是一个抽象类,不能直接使用它来创建对象. 但是可以通过其子类NSKeyedUnarchiver从字节流中读取数据,NSKeyedArchiver将对象写入到字节流。

@package

@package变量,对于framework内部,相当于@protected, 对于framework外部,相当于@privat。

这个特性,很适合用于开发第三方的静态类库,因为多数人并不希望让别人知道自己属性的值。

.(点)和->(箭头)的区别

.(点语法)是访问类的属性,本质是调用set、get方法。

->是访问成员变量,但成员变量默认受保护,所以常常报错,手动设为public即可解决

Core Foundation框架和Cocoa Foundation框架区别

Core Foundation框架 (CoreFoundation.framework) 是一组C语言接口,它们为iOS应用程序提供基本数据管理和服务功能。下面列举该框架支持进行管理的数据以及可提供的服务:

群体数据类型 (数组、集合等)

程序包

字符串管理

日期和时间管理

原始数据块管理

偏好管理

URL及数据流操作

线程和RunLoop

端口和soket通讯Core Foundation框架和Foundation框架紧密相关,它们为相同功能提供接口,但Foundation框架提供Objective-C接口。如果您将Foundation对象和Core Foundation类型掺杂使用,则可利用两个框架之间的 “toll-free bridging”。所谓的Toll-free bridging是说您可以在某个框架的方法或函数同时使用Core Foundatio和Foundation 框架中的某些类型。很多数据类型支持这一特性,其中包括群体和字符串数据类型。每个框架的类和类型描述都会对某个对象是否为 toll-free bridged,应和什么对象桥接进行说明。

CoreFoundation 对于 ios开发的作用

对于corefoundation一直存在疑问,一直感觉他是作为ios开发的底层接口,可是为什么很多开发者习惯于实用corefoundation接口而不是用NS库,比如CFUUIDRef,NSUUID,都可以产生UUID,但是看到的大部分代码都是使用CFUUIDRef,这是为什么呢,直接使用corefoundation接口有什么好处呢?

核心是和其他加框架和架构方便“沟通”。The programming interfaces of Core Foundation objects have been designed for ease of use and reuse. At a general level, Core Foundation:

Enables sharing of code and data among various frameworks and libraries

Makes some degree of operating-system independence possible

Supports internationalization with Unicode strings

Provides common API and other useful capabilities, including a plug-in architecture, XML property lists, and preferences

Core Foundation makes it possible for the different frameworks and libraries on OS X to share code and data. Applications, libraries, and frameworks can define C routines that incorporate Core Foundation types in their external interfaces; they can thus communicate data—as Core Foundation objects—to each other through these interfaces.

__bridge 相关知识点

bridge,bridge_transfer和__bridge_retained详解

__bridge只做类型转换,但是不修改对象(内存)管理权;

__bridge_retained(也可以使用CFBridgingRetain)将Objective-C的对象转换为Core Foundation的对象,同时将对象(内存)的管理权交给我们,后续需要使用CFRelease或者相关方法来释放对象;

__bridge_transfer(也可以使用CFBridgingRelease)将Core Foundation的对象转换为Objective-C的对象,同时将对象(内存)的管理权交给ARC。

CFMutableDictionaryRef with ARC

如何创建并使用一个 CFMutableDictionaryRef

1 CFMutableDictionaryRef myDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);2 NSString *key = @"someKey";3 NSNumber *value = [NSNumber numberWithInt: 1];4 CFDictionarySetValue(myDict, (__bridge void *)key, (__bridge void *)value);5 id dictValue = (__bridge id)CFDictionaryGetValue(myDict, (__bridge void *)key);6 CFDictionaryRemoveValue(myDict, (__bridge void *)key);

如何根据 NSMutableDictionary 创建 CFMutableDictionaryRef

1 NSMutableDictionary *myDict = [NSMutableDictionary dictionary];2 NSString *key = @"someKey";3 NSNumber *value = [NSNumber numberWithInt: 1];4 [myDict setObject:value forKey:key];5 CFMutableDictionaryRef myCFDict = CFBridgingRetain(myDict);6 // use myCFDict here7 CFRelease(myCFDict);

CoreFoundation、CFDictionaryApplyFunction

Context

1 typedef struct {
2     void* object;3     void* value;4  }MyConext;

回调c函数

1 static void MyContextCllbackFunc(const void *_key, const void *_value, void *context) {2     NSLog(@"%@", _key);3     NSLog(@"%@", _value);4     NSLog(@"%p", context);}

示例

1 NSDictionary *dict = @{
2                          @"key1" : @"value",
3                          @"key2" : @"value",
4                          @"key3" : @"value",
5                         };6 User *user = [User new];7 MyConext context = {0};8 context.object = (__bridge void *)(user);9 context.value = @"value";10 CFDictionaryApplyFunction((CFDictionaryRef)dict, MyContextCllbackFunc, &context);

输出

2016-07-13 16:07:29.556 LJFSourceCodeLearn[5521:241563] key1
2016-07-13 16:07:29.556 LJFSourceCodeLearn[5521:241563] value
2016-07-13 16:07:29.556 LJFSourceCodeLearn[5521:241563] 0x7fff51eb8b88
2016-07-13 16:07:29.557 LJFSourceCodeLearn[5521:241563] key3
2016-07-13 16:07:29.557 LJFSourceCodeLearn[5521:241563] value
2016-07-13 16:07:29.557 LJFSourceCodeLearn[5521:241563] 0x7fff51eb8b88
2016-07-13 16:07:29.557 LJFSourceCodeLearn[5521:241563] key2
2016-07-13 16:07:29.557 LJFSourceCodeLearn[5521:241563] value
2016-07-13 16:07:29.557 LJFSourceCodeLearn[5521:241563] 0x7fff51eb8b88

类似还有CFArrayApplyFunction使用

1 NSMutableArray *array = [NSMutableArray new];2    for (int i = 0; i < 3; i++) {3        RuntimeViewController *user = [RuntimeViewController new];4        user.name = [NSString stringWithFormat:@"%d%d%d", i,i,i];5        [array addObject:user];
6     }7   //Context结构体实例
8    MyConext context = {0};9    context.object = @"hahaha";10    context.value = @"hello world...";11    //遍历Array数组元素,每一次传入一个函数中进行处理12    CFArrayApplyFunction((CFArrayRef)array,
13                         CFRangeMake(0, CFArrayGetCount((CFArrayRef)array)),
14                         MyContextCllbackFunc2,
15                         &context);

C函数

1 static void MyContextCllbackFunc2(const void *user, void *context) {2    RuntimeViewController *aUser = (__bridge RuntimeViewController *)(user);3     MyConext *ctx = context;4    NSLog(@"aUser.name = %@", aUser.name);5    NSLog(@"ctx = %p", ctx);6  }

输出

2016-07-13 16:07:29.557 LJFSourceCodeLearn[5521:241563] aUser.name = 0002016-07-13 16:07:29.558 LJFSourceCodeLearn[5521:241563] ctx = 0x7fff51eb8bd82016-07-13 16:07:29.558 LJFSourceCodeLearn[5521:241563] aUser.name = 1112016-07-13 16:07:29.558 LJFSourceCodeLearn[5521:241563] ctx = 0x7fff51eb8bd82016-07-13 16:07:29.558 LJFSourceCodeLearn[5521:241563] aUser.name = 2222016-07-13 16:07:29.558 LJFSourceCodeLearn[5521:241563] ctx = 0x7fff51eb8bd8

__unsafe_unretained 修饰符

ARC 修饰符 相关知识点 而 unsafe_unretained是跟 weak类似的用法,但是__unsafe_unretained会更易造成野指针,

并且需要注意的是,尽管ARC式的内存管理是编译器的工作,但是附有_unsafe_unretained修饰符的变量不属于编译器的内存管理对象

kCFNull

Nil NSNull NULL kCFNull

kCFNull,其宏定义,其实就是NSNull的单例

1 const CFNullRef kCFNull; // the singleton null instance

测试下

1 NSNull *null1 = (id)kCFNull;2 NSNull *null2 = [NSNull null];

输出信息

1 NSNull *) null1 = 0x0000000107b10af02 (NSNull *) null2 = 0x0000000107b10af0

其实 kCFNull这个宏 === [NSNull null]这一句代码

isnan 和 isinf 函数

math.h 文件中定义isnan(x) not a number 此宏返回一个非零值;isinf(x) 当x是正无穷是返回1,当x是负无穷时返回-1。

看YYModel源码的一些收获相关推荐

  1. 记录自己看selenium源码的一些收获(五)RemoteWebDriver类

    记录这个重要类的成员和方法(它是所有其他浏览器driver类的超类) 成员:这些成员有不同的setter getter方法. // Selenium的日志入口private static final ...

  2. iOS读YYModel源码

    序文 在众多的json转model的第三方库中,YYModel可谓是表现出了优异的性能,那到底它是底层是如何实现的呢?带着这份好奇心,开启了我们读取YYModel源码之路 源码解读 YYModel类图 ...

  3. 20种看asp源码的方法及工具

    作者:欧杨飘雪  http://blog.csdn.net/flyingsnowy/ 众所周知windows平台漏洞百出,补丁一个接一个,但总是补也补不净.我把我所知道的20种看asp源码的方法总结了 ...

  4. 一点一点看JDK源码(五)java.util.ArrayList 后篇之forEach

    一点一点看JDK源码(五)java.util.ArrayList 后篇之forEach liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) 代 ...

  5. 最近看Kafka源码,着实被它的客户端缓冲池技术优雅到了

    最近看kafka源码,着实被它的客户端缓冲池技术优雅到了.忍不住要写篇文章赞美一下(哈哈). 注:本文用到的源码来自kafka2.2.2版本. 背景 当我们应用程序调用kafka客户端 produce ...

  6. 面试有没有看过spring源码_如何看Spring源码、Java每日六道面试分享,打卡第二天...

    原标题:如何看Spring源码.Java每日六道面试分享,打卡第二天 想要深入的熟悉了解Spring源码,我觉得第一步就是要有一个能跑起来的极尽简单的框架,下面我就教大家搭建一个最简单的Spring框 ...

  7. 一点一点看JDK源码(四)java.util.ArrayList 中篇

    一点一点看JDK源码(四)java.util.ArrayList 中篇 liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) 1.综述 在前篇中 ...

  8. 一点一点看JDK源码(五)java.util.ArrayList 后篇之removeIf与Predicate

    一点一点看JDK源码(五)java.util.ArrayList 后篇之removeIf与Predicate liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点 ...

  9. 看完源码记不住,是我记性太差了吗?

    都说大厂面试必问源码,尤其是现在最流行的Java 开发技术--Spring的源码.可很多人看完Spring源码记不住,是记性太差了吗? 当然不是!是因为你没有掌握学习源码的技巧. 看完源码的我- 前段 ...

最新文章

  1. 有关scanf输入的问题
  2. Android 依赖注入可以更简单 —— 新版本 Dagger 2 使用教学
  3. 高可用keepalived实例
  4. 用HashMap去重
  5. SQL Server跨server之间訪问
  6. #436. 子串的最大差(单调栈)
  7. Mac声音太小?那你不能错过这款神器Boom 2
  8. 44个基于SaaS的商业智能解决方案
  9. osgb转json_cesuim加载倾斜摄影OSGB三维数据完整过程(超详细)
  10. React fundamental 和 React Router-郭永峰-专题视频课程
  11. 给大家爆个秘密:怎样迅速提高你的校内人人网人气
  12. java进阶知识思维导图
  13. StreamNative翟佳:若无社区,开源项目可能是个死项目
  14. 掌控健身节奏 飞利浦降噪运动耳机A7507 上市
  15. 网络使用工具HttpWatch的使用方法
  16. C语言变量的存储方式和生存期
  17. Linux 内核编译安装
  18. CDLinux U盘启动教程
  19. 书柜例子解释整理表空间碎片
  20. Go语言学习二 语言结构 基础语法 数据类型

热门文章

  1. Java秒杀系统优化(高性能高并发)
  2. 【IT笔试面试题整理】给定二叉树,给每层生成一个链表
  3. 护理方面关于人工智能的构想_如何提出惊人的AI,ML或数据科学项目构想。
  4. 网卡驱动:stmmac DMA接收流程
  5. 他曾经负债2.5亿,如今身价超过500亿
  6. 人工智能、机器学习、深度学习和神经网络的区别
  7. 上半年银行罚单不断,7月越早贷款越有利
  8. 这些贷款冷知识你知道多少?
  9. 北京国际图书博览会暨2007 BIBF
  10. xilinx IP核技术资料