ReactiveCocoa 中 集合類RACSequence 和 RACTuple底層實現分析
前言
在OOP的世界裡使用FRP的思想來程式設計,光有函式這種一等公民,還是無法滿足我們一些需求的。因此還是需要引用變數來完成各式各樣的類的操作行為。
在前幾篇文章中詳細的分析了RACStream中RACSignal的底層實現。RACStream還有另外一個子類,RACSequence,這個類是RAC專門為集合而設計的。這篇文章就專門分析一下RACSequence的底層實現。
目錄
- 1.RACTuple底層實現分析
- 2.RACSequence底層實現分析
- 3.RACSequence操作實現分析
- 4.RACSequence的一些擴充套件
一. RACTuple底層實現分析
在分析RACSequence之前,先來看看RACTuple的實現。RACTuple是ReactiveCocoa的元組類。
1. RACTuple
123456789101112131415 | @interfaceRACTuple:NSObject@property(nonatomic,readonly)NSUInteger count;@property(nonatomic,readonly)id first;@property(nonatomic,readonly)id second;@property(nonatomic,readonly)id third;@property(nonatomic,readonly)id fourth;@property |
RACTuple的定義看上去很簡單,底層實質就是一個NSArray,只不過封裝了一些方法。RACTuple繼承了NSCoding, NSCopying, NSFastEnumeration這三個協議。
1234567891011 | -(id)initWithCoder:(NSCoder *)coder{self=[selfinit];if(self==nil)returnnil;self.backingArray=[coder decodeObjectForKey:@keypath(self.backingArray)];returnself;}-(void)encodeWithCoder:(NSCoder *)coder{if(self.backingArray!=nil)[coder encodeObject:self.backingArray forKey:@keypath(self.backingArray)];} |
這裡是NSCoding協議。都是對內部的backingArray進行decodeObjectForKey:和encodeObject: 。
12 | -(instancetype)copyWithZone:(NSZone *)zone{// we're immutable, bitches! |
上面這是NSCopying協議。由於內部是基於NSArray的,所以是immutable不可變的。
123 | -(NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained[])buffer count:(NSUInteger)len{return[self.backingArray countByEnumeratingWithState:state objects:buffer count:len];} |
上面是NSFastEnumeration協議,快速列舉也都是針對NSArray進行的操作。
123456789 | // 三個類方法+(instancetype)tupleWithObjectsFromArray:(NSArray *)array;+(instancetype)tupleWithObjectsFromArray:(NSArray *)arrayconvertNullsToNils:(BOOL)convert;+(instancetype)tupleWithObjects:(id)object,...NS_REQUIRES_NIL_TERMINATION;-(id)objectAtIndex:(NSUInteger)index;-(NSArray *)allObjects;-(instancetype)tupleByAddingObject:(id)obj; |
RACTuple的方法也不多,總共就6個方法,3個類方法,3個例項方法。
先看類方法:
12345678910111213141516171819 | +(instancetype)tupleWithObjectsFromArray:(NSArray *)array{return[selftupleWithObjectsFromArray:arrayconvertNullsToNils:NO];}+(instancetype)tupleWithObjectsFromArray:(NSArray *)arrayconvertNullsToNils:(BOOL)convert{RACTuple *tuple=[[selfalloc]init];if(convert){NSMutableArray *newArray=[NSMutableArray arrayWithCapacity:array.count];for(id objectinarray){[newArray addObject:(object==NSNull.null?RACTupleNil.tupleNil:object)];}tuple.backingArray=newArray;}else{tuple.backingArray=[arraycopy];}returntuple;} |
先看這兩個類方法,這兩個類方法的區別在於是否把NSNull轉換成RACTupleNil型別。根據入參array初始化RACTuple內部的NSArray。
RACTuplePack( ) 和 RACTuplePack_( )這兩個巨集的實現也是呼叫了tupleWithObjectsFromArray:方法
12345 | #define RACTuplePack(...) \RACTuplePack_(__VA_ARGS__)#define RACTuplePack_(...) \([RACTuple tupleWithObjectsFromArray:@[metamacro_foreach(RACTuplePack_object_or_ractuplenil,,__VA_ARGS__)]]) |
這裡需要注意的是RACTupleNil
123456789 | +(RACTupleNil *)tupleNil{staticdispatch_once_t onceToken;staticRACTupleNil *tupleNil=nil;dispatch_once(&onceToken,^{tupleNil=[[selfalloc]init];});returntupleNil;} |
RACTupleNil是一個單例。
重點需要解釋的是另外一種類方法:
123456789101112131415161718192021222324252627282930 | +(instancetype)tupleWithObjects:(id)object,...{RACTuple *tuple=[[selfalloc]init];va_list args;va_start(args,object);NSUInteger count=0;for(id currentObject=object;currentObject!=nil;currentObject=va_arg(args,id)){++count;}va_end(args);if(count==0){tuple.backingArray=@[];returntuple;}NSMutableArray *objects=[[NSMutableArray alloc]initWithCapacity:count];va_start(args,object);for(id currentObject=object;currentObject!=nil;currentObject=va_arg(args,id)){[objects addObject:currentObject];}va_end(args);tuple.backingArray=objects;returntuple;} |
這個類方法的引數是可變引數型別。由於用到了可變引數型別,所以就會用到va_list,va_start,va_arg,va_end。
123456789101112 | #ifndef _VA_LIST_T#define _VA_LIST_Ttypedef__darwin_va_list va_list;#endif /* _VA_LIST_T */#ifndef _VA_LISTtypedef__builtin_va_list va_list;#define _VA_LIST#endif#define va_start(ap, param) __builtin_va_start(ap, param)#define va_end(ap) __builtin_va_end(ap)#define va_arg(ap, type) __builtin_va_arg(ap, type) |
- va_list用於宣告一個變數,我們知道函式的可變引數列表其實就是一個字串,所以va_list才被宣告為字元型指標,這個型別用於宣告一個指向引數列表的字元型指標變數,例如:va_list ap;//ap:arguement pointer
- va_start(ap,v),它的第一個引數是指向可變引數字串的變數,第二個引數是可變引數函式的第一個引數,通常用於指定可變引數列表中引數的個數。
- va_arg(ap,t),它的第一個引數指向可變引數字串的變數,第二個引數是可變引數的型別。
- va_end(ap) 用於將存放可變引數字串的變數清空(賦值為NULL)。
剩下的3個例項方法都是對陣列的操作,沒有什麼難度。
一般使用用兩個巨集,RACTupleUnpack( ) 用來解包,RACTuplePack( ) 用來裝包。
1234567891011121314 | RACTupleUnpack(NSString *string,NSNumber *num)=[RACTuple tupleWithObjects:@"foo",@5,nil];RACTupleUnpack(NSString *string,NSNumber *num)=RACTuplePack(@"foo",@(5));NSLog(@"string: %@",string);NSLog(@"num: %@",num);/* 上面的做法等價於下面的 */RACTuple *t=[RACTuple tupleWithObjects:@"foo",@5,nil];NSString *string=t[0];NSNumber *num=t[1];NSLog
相關推薦ReactiveCocoa 中 集合類RACSequence 和 RACTuple底層實現分析前言 在OOP的世界裡使用FRP的思想來程式設計,光有函式這種一等公民,還是無法滿足我們一些需求的。因此還是需要引用變數來完成各式各樣的類的操作行為。 在前幾篇文章中詳細的分析了RACStream中RACSignal的底層實現。RACStream還有另外一個子類,RACS java中的類鎖和物件鎖對比分析說到鎖機制,不得不提到Thread執行緒,而又不得不提到synchronized關鍵字,這個單詞的意思是表示“同步”的意思。用它去修飾方法函式的時候,如果有多個執行緒同時呼叫這個方法函式的時候,那麼當一個執行緒獲得鎖的時候,其他的執行緒只 Java中集合類set、List和map的遍歷方式Java中集合類的遍歷方式 Java中集合分為set、List和map。 1.set集合 set集合常用的有兩種遍歷方式: Set<String> set = new HashSet<String>(); 第一種利用for迴圈: for(S 集合類 Java中的集合類解析和一些有深入的面試題第一題: 現有的程式程式碼模擬產生了16個日誌物件,並且需要執行16秒才能列印完這些日誌,請在程式中增加4個執行緒去呼叫parseLog()方法來分頭列印 這16個日誌物件,程式只需要執行4秒即可列印完這些日誌物件。 原始程式碼: pub ReactiveCocoa 中 RACSignal 冷訊號和熱訊號底層實現分析前言 關於ReactiveCocoa v2.5中冷訊號和熱訊號的文章中,最著名的就是美團的臧成威老師寫的3篇冷熱訊號的文章: 由於最近在寫關於RACSignal底層實現分析的文章,當然也逃不了關於冷熱訊號操作的分析。這篇文章打算分析分析如何從冷訊號轉成熱訊號的底層實現。 Java中集合類容器初步了解equals treemap 輸入 strong 字符串數組 通過 system 結構 shm 容器(Collection) 數組是一種容器,集合也是一種容器 java編程中, 裝其他各種各樣的對象(引用類型)的一種東西, 叫容器 (圖書 12. 集合類Collection和Mapsid 並且 當前 ria static indexof tran alt -i html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,addr 23.python中的類屬性和實例屬性ash ron huang ant pass iou cli ict bin %E5%9C%A8myeclipse%E4%B8%AD%E4%BD%BF%E7%94%A8maven%E5%89%8D%E5%B8%B8%E8%A7%81%E9%94%99%E8%AF%AF%E5 第十一課 集合類Collection和Map什麽是 基本數據類型 16px 開始 有序 面向對象 style 數據 取出 集合類 面向對象語言對事物的體現都是以對象的形式,所以為了方便對多個對象的操作,就對對象進行存儲,集合就是存儲對象最常用的方式。 數組和集合類都是容器,他們有什麽不同? 數組雖然也可以存儲對象,但 JS中值類型和引用類型另一個 bsp 引用類型 nbsp 對象 logs 包括 方式 console 一.值類型 例子: 1 var a=10; 2 var b=a; 3 a=20; 4 console.log(b); //10 例子中,將a的值賦給了b,b=10,然後改變a的值不會 ReactiveCocoa有關集合類的使用pro tsig 獲取 acs mod set instance 遍歷 end Sequences 集合 表示一個不可變的序列值且不能包含空值, 1.實現NSArray的快速遍歷 NSArray *numbers = @[@1, @2, @3, @4, @5, @6]; objc中的類方法和實例方法有什麽本質區別和聯系實例 屬於 通過 實例對象 對象方法 self 類方法 緩存 變量 類方法: 類方法是屬於類對象的 類方法只能通過類對象調用 類方法中的self是類對象 類方法可以調用其他的類方法 類方法中不能訪問成員變量 類方法中不能直接調用對象方法 類方法是存儲在元類對象的方法緩存 SSM-MyBatis-07:Mybatis中SqlSession的insert和delete底層到底做了什麽src batis mit image updating obj color idea快捷鍵 手動 先點進去看一下insert方法 用ctrl加鼠標左鍵點進去看 發現是一個接口SqlSession的方法,沒有實現 ,但是通過裏氏替換原則的想法,他是接口接收了實現類,所 【cocos2dx中Node類getParent和getChildByTag()】學習體會mil 提高 cos cleanup HR -c ldr 12px 而不是 參考http://cn.cocos2d-x.org/doc/cocos2d-x-3.0/ 在JavaScript中引用類型和值類型的區別AC 存儲方式 說明 添加 asc TE num style src 一、存儲方式不一樣 基本數據類型 變量存儲的是簡單的數據段,存儲的是具體的值,是輕量級的數據存儲方式 引用類型 引用類型的值,可以由多個值構成的對象,引用類型的變量存儲的是對象引用地址。引用類型是重量的數 Python中的類屬性和物件屬性作者:黎智煊 ,叩丁狼高階講師。本文為原創文章,轉載請註明出處。 在瞭解了類基本的東西之後,下面看一下python中這幾個概念的區別 先來談一下類屬性和例項屬性 在前面的例子中我們接觸到的就是例項屬性(物件屬性),顧名思義,類屬性就是類 Python中的類方法和靜態方法作者:黎智煊 ,叩丁狼高階講師。本文為原創文章,轉載請註明出處。 類方法 是類物件所擁有的方法,需要用修飾器@classmethod來標識其為類方法,對於類方法,第一個引數必須是類物件,一般以cls作為第一個引數(當然可以用其他名稱的變數作 c++中string類物件和字元陣列之間的相互轉換string類在c++中是一個模板類,位於名字空間std中,注意這裡不是string.h,string.h是C字串標頭檔案。 將string型別轉換為字元陣列char arr[10];string s("ABCDEFG");int len = s.copy(arr,&nb .集合Set,HashSet,TreeSet及其底層實現HashMap和紅黑樹;Collection總結ONE.Set集合 one.Set集合的特點 無序,唯一 TWO.HashSet集合 1.底層資料結構是雜湊表(是一個元素為連結串列的陣列) 2.那麼HashSet如何來實現元素的唯一性的呢? 通過一HashSet新增字串的案例檢視HashSet中add()的原始碼, Python 中的類變數和例項變數(關鍵詞:Python/類變數/例項變數)類變數: class 語句的頂層進行賦值的變數,會被附加在類中,被所有例項所共享; 例項變數:附加在例項上的變數,不被共享,可通過這 2 種方式建立或修改: aInstance.name = sth 的形式; 類的例項方法中,self.name = sth 的形式。 |