看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.pswp.cn/news/247933.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247933.shtml
英文地址,請注明出處:http://en.pswp.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狀態 #…