iOS學習筆記

以下筆記是邊看視頻課程邊記錄下來的,供以后自己查閱復習使用

Runtime學習筆記1

消息轉(zhuǎn)發(fā)

在OC中,調(diào)用方法其實是給對象發(fā)送消息

    [[Person new] sendMessage:@"gelo"];
    // 等價于
    objc_msgSend([Person new], @selector(sendMessage:), "gelo");

通過對象的isa指針找到class,如果有方法的話,直接調(diào)用。沒有找到的話,通過繼承樹查找,進入消息轉(zhuǎn)發(fā)機制

runtime-forwardflow.png

動態(tài)方法解析,動態(tài)添加方法實現(xiàn)

? resolveInstanceMethod

快速轉(zhuǎn)發(fā),當前的類或者繼承樹沒有該方法的實現(xiàn),在更加廣的范圍尋找

? forwardingTargetForSelector

慢速轉(zhuǎn)發(fā)

? methodSignatureForSelector

? forwardInvocation

doesNotRecognizeSelector:

方法交換 Method Swizzling

用自己寫的方法替換系統(tǒng)方法,通過class_getInstanceMethod方法獲取,通過method_exchangeImplementations交換兩個函數(shù)

字典轉(zhuǎn)模型

遍歷字典獲取key和value

key作為屬性名,value作為屬性值

通過objc_msgSend發(fā)送set方法

模型轉(zhuǎn)字典

字典的key通過模型的屬性列表獲取

字典的value通過調(diào)用get方法獲取

實現(xiàn)KVO

KVO是基于runtime的

A監(jiān)聽B 系統(tǒng)會為B創(chuàng)建一個子類

B的isa指針指向B的子類

在子類中重新set方法

KVO底層實現(xiàn)

KVO的基礎使用

觀察某一個對象的某個屬性

options參數(shù)可以觀察一下幾個值

new 返回變化后的新值

old 返回變化前的舊值

init 注冊的時候就會發(fā)一次通知,改變后的值的時候也會發(fā)送

prior 新值和舊值都會返回

KVO默認是自動模式,每次修改值都會發(fā)送通知

手動發(fā)送通知的時候,對象調(diào)用willchangeValueForKey,改變之后調(diào)用didchangeValueForKey

監(jiān)聽屬性下面的屬性值,只需要在監(jiān)聽path中通過點監(jiān)聽:"dog.age"(屬性依賴)

KVO監(jiān)聽的是set方法。比如監(jiān)聽不到數(shù)組的add方法

要是需要監(jiān)聽容器方法,需要結(jié)合KVC

需要監(jiān)聽對象下多個屬性,只需要監(jiān)聽對象本身,并實現(xiàn)keyPat***ForKey。返回需要的真正監(jiān)聽的內(nèi)部屬性的NSSet

內(nèi)部實現(xiàn)

屬性是對成員變量和set、get方法的封裝

KVO觀察的是set方法(設置成員變量之后,外部通過person->name方法修改,KVO監(jiān)聽不到)通過runtime創(chuàng)建一個觀察者的子類(NSKVONotifying_Person)重寫set方法。修改指針到子類、在重寫的方法里面調(diào)用willchangeValueForKey、superSetName、didchangeValueForKey。

在創(chuàng)建的子類中,沒有父類的set方法!需要重寫set方法

OC的方法中包含SEL(方法編號)、IMP(方法實現(xiàn))一一對應。調(diào)用方法的時候發(fā)送的是SEL

OC的方法調(diào)用里面有兩個默認參數(shù):id self,SEL _cmd。由于sendMsg傳遞了該參數(shù)(調(diào)用者以及SEL)

監(jiān)聽容器類(NSArray、NSDic)

通過KVO觀察容器屬性的變化,利用KVC

通過KVC的mutableArray**ForKey返回一個容器對象,向該對象添加元素可以實現(xiàn)KVO。內(nèi)部新建子類、重寫add方法。

KVO返回的NSDic中,kind類型

觀察set方法 返回1

觀察插入方法 返回2

觀察刪除方法 返回3

觀察替換方法 返回4

數(shù)組中count

使用KVO中監(jiān)聽不到數(shù)組中的count、使用KVC同樣取不到[array valueForKey:@"count"]

count是集合運算符,KVC需要用@"@count"取值。

count是只讀屬性

數(shù)組(NSMutableArray)

關于數(shù)組的容量,容量不夠用的時候,會成倍的增加

對象本身是指針,指向該對象的結(jié)構體

x/100xb arr 打印arr 100個內(nèi)存地址

找到count的內(nèi)存地址,修改內(nèi)存地址的值,進而可以修改count的值

Runtime學習筆記2

消息機制

OC代碼會轉(zhuǎn)化為C語言執(zhí)行,使用runtime的時候,需要關閉代碼的嚴格檢測

調(diào)用函數(shù)的方法:

[p eat]

[p performSelector: SEL]

objc_msgSend()

使用runtime創(chuàng)建對象:
類名.class即為對象 Person.class == objc_getClass("Person")

// 在目錄下執(zhí)行
clang --rewrite-objc main.m
// 手動編譯OC代碼生成cpp文件

歸檔/解檔

歸檔和解檔對象,需要遵循NSCoding的協(xié)議,并且實現(xiàn)協(xié)議方法

KVC可以使用id類型為屬性賦值

Ivar:成員變量

Method:成員方法

C語言 基本數(shù)據(jù)類型的指針 函數(shù)內(nèi)部是為了修改外部的值

class_copyIvarList獲取所有屬性數(shù)量

關鍵字copy、new、creat代表著會在堆區(qū)域(malloc)開辟空間

方法執(zhí)行完畢—>方法調(diào)用棧平衡—>內(nèi)部變量指針出?!?gt;但是指針指向的堆區(qū)的值還在—>內(nèi)存泄漏

在OC中使用C的代碼,要手動釋放指針,防止內(nèi)存溢出

OC方法定位以及替換

OC的方法表:返回值類型+參數(shù)類型一樣 編號就一樣

? 類

SEL 編號 ————— IMP實現(xiàn)(地址指針)

SEL 編號 ————— IMP實現(xiàn)(地址指針)

SEL 編號 ————— IMP實現(xiàn)(地址指針)

用HOOK!鉤住系統(tǒng)方法,在調(diào)用之前修改方法的調(diào)用

在分類中的load方法(由于預加載,比main更早執(zhí)行)中交換IMP

#import <objc/runtime.h>

+ (void)load {
    // 獲取替換后的類方法
    Method otherMethod = class_getClassMethod([UIImage class], @selector(imageNameNextWith:));
    // 獲取替換前的類方法
    Method method = class_getClassMethod([UIImage class], @selector(imageNamed:));
    // 然后交換類方法
    method_exchangeImplementations(otherMethod, method);
}

+ (UIImage *)imageNameNextWith:(NSString *)nameString {
    UIImage *image = nil;
    image = [UIImage imageNameNextWith:[nameString stringByAppendingString:@"tupian.jpg"]];
    return image;
}

關于在imageNameNextWith中調(diào)用自身,并不會引起循環(huán)引用。

交換之前

SEL(系統(tǒng)方法:ImageNamed) —————> IMP(系統(tǒng)方法:ImageNamed的實現(xiàn)地址指針)

SEL(自己的方法:ImageNamedNextWith) —————> IMP(自己的方法:ImageNamedNextWith的實現(xiàn)地址指針)

交換之后

SEL(系統(tǒng)方法:ImageNamed) —————> IMP(自己的方法:ImageNamedNextWith的實現(xiàn)地址指針)

SEL(自己的方法:ImageNamedNextWith) —————> IMP(系統(tǒng)方法:ImageNamed的實現(xiàn)地址指針)

交換之后,每當再次調(diào)用imageNameNextWith方法的時候,實際上執(zhí)行的是系統(tǒng)方法ImageNamed指向的方法實現(xiàn),所以不會引起循環(huán)調(diào)用。

OC對象本質(zhì)上是指針占用8個字節(jié)

OC方法調(diào)用順序:消息發(fā)送——>SEL——>IMP——>代碼——>函數(shù)——>匯編

函數(shù)響應式編程RAC

RAC的代理

RAC里面內(nèi)部實現(xiàn)類似于通知

  1. 創(chuàng)建信號 提供外界訂閱

創(chuàng)建了一個容量為1的可變數(shù)組_subscribers

支持多個訂閱者訂閱該信號

RACSubject *subject = [RACSubject subject];
  1. 訂閱信號(注冊通知)

創(chuàng)建訂閱者對象

將Block放到訂閱者對象中

將訂閱者對象放入_subscribers里面

[subject subscribeNext:^(id){
  // 函數(shù)式編程,免除了遵循協(xié)議,引用方法的步驟
}];
  1. 發(fā)送信號(發(fā)起通知)

遍歷_subscribers取出中的訂閱者對象

執(zhí)行訂閱者對象中的Block

[subject sentNext:@"hahha];

RAC中可以使用Selector通過方法名稱創(chuàng)建信號,直接訂閱

RAC中的KVO

RAC可以直接用Block回調(diào),在觀察多個屬性的時候,可以避免在回調(diào)函數(shù)中判斷。

RAC同樣不能觀察到數(shù)組的count

RAC監(jiān)聽事件

將按鈕的點擊事件包裝成信號,訂閱

RAC中的Timer

使用NSTimer的時候,創(chuàng)建完之后需要添加到NSRunLoop中

在NSTread子線程中需要手動啟動NSRunLoop

[[NSRunLoop currentRunLoop] run]

RAC中通過信號創(chuàng)建子線程并發(fā)Timer,底層使用GCD創(chuàng)建

RAC中的宏定義

當輸入框內(nèi)容發(fā)生變化,相應更新到_label上

RAC(_label, text) = _textField.rac_textSignal;

只要對象的屬性發(fā)生改變,就會產(chǎn)生信號

RACObserver(self, name) sub....

關于Block中的循環(huán)引用,但是在特殊情況下是允許循環(huán)應用的出現(xiàn)

NSURLSession中的delegate是強引用,目的是發(fā)送請求的時候只需要一個對象。是單例

使用強引用,并不會銷毀,導致內(nèi)存泄漏

Socket探索

IP地址可以在網(wǎng)絡上定位到一臺終端設備

端口號可以訪問到設備上的服務:比如80端口為Apache端口服務

網(wǎng)絡的七層協(xié)議從上至下:應用層、表示層、會話層、傳輸層、網(wǎng)絡層、數(shù)據(jù)鏈路層、物理層

標準幀格式數(shù)據(jù)包

socket處于傳輸層、IP/TCP協(xié)議在網(wǎng)絡層

TCP與UDP協(xié)議的區(qū)別

UDP(用戶數(shù)據(jù)報協(xié)議)短信

? 只管發(fā)送,不確認對方是否收到

? 將數(shù)據(jù)及源和目的封裝成數(shù)據(jù)包中,不需要建立連接

? 每個數(shù)據(jù)報大小限制在64k

? 因為無需連接,因此是不可靠協(xié)議

? 不需要連接,速度快

TCP(傳輸控制協(xié)議)電話

? 建立連接,形成傳輸數(shù)據(jù)通道

? 在連接中進行大數(shù)據(jù)傳輸(數(shù)據(jù)大小不受限制)

? 通過三次握手連接,是可靠的協(xié)議,安全送達

? 必須建立連接,效率稍低

直播推流、游戲是UDP協(xié)議,下載的過程是TCP協(xié)議

Socket

類比插座,socket需要兩端的IP+端口號建立連接

  1. 創(chuàng)建socket
/*
     domain:  協(xié)議域 AF_INET = IPV4   IPV6
     type:    Socket類型 SOCK_STREAM(TCP)/SOCK_DGRAM(UDP)
     protocol: IPPROTO_TCP, 傳入0, 會自動根據(jù)第二個值選擇合適的協(xié)議
*/
int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
  1. 連接服務器
/*
    客戶端socket
    服務器IP地址結(jié)構體指針
    結(jié)構體長度
*/
struct sockaddr_in serverAddr;
serverAddr.sin_family = AF_INET;//IPV4
serverAddr.sin_port = htons(80);//端口號
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");//IP地址

int connectResult = connect();
// 返回0代表連接成功

netcat工具,用于監(jiān)聽本地端口

  1. 發(fā)送數(shù)據(jù)
/*
    客戶端socket
    發(fā)送內(nèi)容地址
    發(fā)送內(nèi)容長度
    發(fā)送方式標志,一般為0
    
    返回值
    發(fā)送成功之后返回發(fā)送字節(jié)長度,失敗返回error
*/
send();
  1. 讀取數(shù)據(jù)
/*
    客戶端socket
    接受內(nèi)容緩沖區(qū)域地址
    接受內(nèi)容緩沖區(qū)長度
    接受方式標志,0表示阻塞,必須等待服務器返回數(shù)據(jù)
    
    返回值
    接受成功之后返回發(fā)送字節(jié)長度,失敗返回error
*/

uint8_t buffer[1024];
recv();

通過data數(shù)據(jù)讀取二進制數(shù)組,解析返回字節(jié)流
  1. 關閉socket
close();

HTTP訪問

通過向百度的IP地址,發(fā)送"GET HTTP/1.1\n Host: www.baidu.com\n\n"可以接收到百度服務器返回的百度首頁數(shù)據(jù)。

手寫了一個HTTP協(xié)議

Connection被廢棄的原因

異步下載,無法回調(diào)數(shù)據(jù),因為Runloop默認在子線程不開啟

線程管理

線程中有任務才有可能不被釋放

HTTPS協(xié)議

https本身不會對客戶端進行驗證

加密算法:RSA

RSA:公鑰和私鑰

明文+公鑰 = 密文

密文+私鑰 = 明文

第一次請求HTTPS服務器,客戶端安裝證書(下載公鑰并保存),通訊時通過該公鑰加密傳輸

登錄校驗時隨機鹽可以提高安全性

加密詳解

Base64

base64是編碼方式,不屬于加密算法

可以將任意的二進制數(shù)據(jù)進行編碼 編碼成為65中字符的文本文件

0-9,a-z,A-Z,+ / =

對稱加密:

DES

3DES

AES(高級密碼標準)

數(shù)學算法:

哈希函數(shù)MD5

內(nèi)存釋放

free()以及CFRelease()的區(qū)別

單元測試

setup 初始化

tearDown 銷毀

所有的測試用例必須以test開頭

given

when

then

架構模式

MVC解耦

vc代碼過于沉重

代碼耦合性過高 UI與Model的通訊

MVP

面向協(xié)議編程---代理

@synchronized(self)多線程鎖

通過代理使UI與Model通訊

MVVM

雙向綁定:數(shù)據(jù)和UI的綁定,即修改一處另一處隨之修改
異步的一般處理:代理、通知、匿名函數(shù)(Block)

從數(shù)據(jù) -----> UI 通過Block進行通訊
從UI -------> 數(shù)據(jù) 通過KVO監(jiān)聽通訊

NSMutableArray是線程不安全的,在處理里面的數(shù)據(jù)的時候需要加鎖

多線程

進程

線程

NSThread

- alloc init
+ detacNewThread
- self perform
thread-status.png

線程的名稱

線程的優(yōu)先級

多線程的共享資源

線程不安全:獲取的數(shù)據(jù)和預期可能不一樣

互斥鎖:線程同步,@synchronized 當一個線程在操作數(shù)據(jù)的時候,其它線程不得操作該數(shù)據(jù)

原子屬性 atomic

原子屬性是線程安全的,自旋鎖

原子屬性的成員變量,在set方法中會添加@synchronized保護線程安全

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容