看YYModel源码的一些收获

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

第一层:熟练使用;

第二层:读懂代码;

第三层:通晓原理;

第四层:如何设计;

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

关于分享

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/247933.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IDEA提交项目到SVN

一.提交步骤 VCS--Enable...-->点击项目右键-->subversion-->share directory-->commit 二.IDEA SVN 忽略文件的设置 1》share .使用idea在将项目提交到svn的过程中遇到这样的问题 将项目share之后再设置ignore files &#xff0c;在commit的时候&#xff0c;不会将…

小程序基础 (二)

小程序开发框架 小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。 整个小程序框架系统分为两部分&#xff1a;逻辑层&#xff08;App Service&#xff09;和 视图层&#xff08;View&#xff09;。 小程序提供了自己的视…

项目ITP(五) spring4.0 整合 Quartz 实现任务调度

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主同意不得转载。https://blog.csdn.net/u010378410/article/details/26016025 2014-05-16 22:51 by Jeff Li 前言 系列文章&#xff1a;[传送门] 项目需求&#xff1a; 二维码推送到一体机上&#xff0c;给学生签到扫…

喜欢用Block的值得注意-Block的Retain Cycle的解决方法

本文不讲block如何声明及使用&#xff0c;只讲block在使用过程中暂时遇到及带来的隐性危险。 主要基于两点进行演示&#xff1a; 1.block 的循环引用(retain cycle) 2.去除block产生的告警时&#xff0c;需注意问题。 有一次&#xff0c;朋友问我当一个对象中的block块中的访问…

小程序基础 (三)

5. 使用 slot 使用单个slot // 页面 <Test><view>自定义内容</view> </Test>// 组件 <view><view>前面的内容</view><slot></slot><view>后面的内容</view> </view>使用多个slot - 具名 // 页面 &…

【PyQt5】QT designer + eclipse 集成开发

【写在前面的话】 考虑将pyqt5的界面开发qt designer 集成在eclipse中&#xff0c;并且&#xff0c;不利用cmd命令行进行转换。 【工具】 1、pyqt5 2、qt designer 3、eclipse pydy 【步骤】 1、首先配置Qt designer。 菜单 run-->external Tools-->External tools confi…

iOS UIlabel文字排版(改变字间距行间距)分类

在iOS开发中经常会用到UIlabel来展示一些文字性的内容&#xff0c;但是默认的文字排版会觉得有些挤&#xff0c;为了更美观也更易于阅读我们可以通过某些方法将UIlabel的行间距和字间距按照需要调节。 比如一个Label的默认间距效果是这样&#xff1a; 然后用一个封装起来的Cat…

MySQL查询之聚合查询

为了快速得到统计数据&#xff0c;提供了5个聚合函数&#xff1a; count(*)表示计算总行数&#xff0c;括号中写星与列名&#xff0c;结果是相同的 查询学生总数 select count(*) from students; max(列)表示求此列的最大值 查询女生的编号最大值 select max(id) from students…

React基础学习(第一天)

React 概述 : React 是一个用于 构建用户界面 的 JavaScript 库因为框架是有一整套解决方案的&#xff0c;React就是纯粹写UI组件的 没有什么异步处理机制、模块化、表单验证这些。React和react-router, react-redux结合起来才叫框架&#xff0c;而React本身只是充当一个前端…

iOS 富文本风格NSMutableParagraphStyle、定制UITextView插入图片和定制复制

问题一 开发过程中&#xff0c;经常会遇到动态计算行高的问题&#xff0c; - (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(nullableNSDictionary<NSString *, id> *)attributes context:(nullable NSStringDrawingC…

day24 01 初识继承

day24 01 初识继承 面向对象的三大特性&#xff1a;继承&#xff0c;多态&#xff0c;封装 一、继承的概念 继承&#xff1a;是一种创建新类的方式&#xff0c;新建的类可以继承一个或者多个父类&#xff0c;父类又可称基类或超类&#xff0c;新建的类称为派生类或者子类 class…

React基础学习(第二天)

虚拟DOM JSX 涉及到 虚拟DOM ,简单聊一下 定时器渲染问题 // 方法 function render() {//2. 创建react对象let el (<div><h3>时间更新</h3><p>{ new Date().toLocaleTimeString()}</p></div>)//3. 渲染ReactDOM.render(el, document.g…

iOS 去除字符串中的空格或多余空格(适合英文单词)

NSString -stringByTrimmingCharactersInSet: 是个你需要牢牢记住的方法。它经常会传入 NSCharacterSet whitespaceCharacterSet 或 whitespaceAndNewlineCharacterSet 来删除输入字符串的头尾的空白符号。 需要重点注意的是&#xff0c;这个方法 仅仅 去除了 开头 和 结尾 的…

华为交换机在Telnet登录下自动显示接口信息

因为用console连接交换机&#xff0c;默认是自动显示接口信息的&#xff0c;比如down掉一个接口后&#xff0c;会自动弹出接口被down掉的信息&#xff0c;但是在telnet连接下&#xff0c;默认是不显示这些信息的&#xff0c;需要开启后才可显示。 1、首先开启info-center(默认是…

React基础学习(第三天)

条件渲染 1. if / else render () {if (this.state.isLoading) { // 正在加载中return <h1>Loading...</h1>}return <div>这就是我们想要的内容</div>} // 钩子函数 五秒钟之后 修改状态值componentDidMount () { setTimeout(() > {this.setState(…

componentsJoinedByString 和 componentsSeparatedByString 的方法的区别

将string字符串转换为array数组 NSArray *array [Str componentsSeparatedByString:","]; &#xff1d;&#xff1d;反向方法 将array数组转换为string字符串 NSString *tempString [mutableArray componentsJoinedByString:","];--,是分隔符 可不加分隔…

java中的各种数据类型在内存中存储的方式

转载别人的附上链接&#xff1a;https://blog.csdn.net/zj15527620802/article/details/80622314 1.java是如何管理内存的 java的内存管理就是对象的分配和释放问题。&#xff08;其中包括两部分&#xff09; 分配&#xff1a;内存的分配是由程序完成的&#xff0c;程序员需要通…

vscode的 jsonp 配置文件

{ // 工具-字体大小 “editor.fontSize”: 15, // 工具-tab缩进 “editor.tabSize”: 2, // 工具-在视区宽度换行 “editor.wordWrap”: “on”, // 工具-缩放 “window.zoomLevel”: 1, // 工具-编写tab识别语言格式 “emmet.includeLanguages”: { “vue-html”: “html”, “…

NSString拼接字符串和NSPredicate详解

NSString* string; // 结果字符串 02 NSString* string1, string2; //已存在的字符串&#xff0c;需要将string1和string2连接起来 03 04 //方法1. 05 string [[NSString alloc]initWithFormat:"%,%", string1, string2 ]; 06 07 //方法2. 08 string [string1 …

线程模块

信号量 from threading import Semaphore,Thread import timedef func(a,b):time.sleep(1)sem.acquire()print(ab)sem.release()sem Semaphore(4) for i in range(10):t Thread(targetfunc,args(i,i5))t.start() 信号量事件 # 事件被创建的时候&#xff0c;默认为False状态 #…