Runtime系列三:Runtime在項(xiàng)目中使用場景

前言:

關(guān)于Runtime的資料網(wǎng)上一搜很多,但總是寫的只言片語,不太全面。最近花了一個星期的時間重新學(xué)習(xí)Runtime,并整理了一個系列文章生音,并發(fā)表出來,同時也感謝開源貢獻(xiàn)的開發(fā)者窒升。這里共有三篇文章:

Runtime系列一:Runtime的前世今生

Runtime系列二:Runtime的原理

Runtime系列三:Runtime在項(xiàng)目中使用場景

一缀遍、方法交換Swizzling

使用場景:系統(tǒng)自帶的方法功能不夠,給系統(tǒng)自帶的方法擴(kuò)展一些功能饱须,并且保持原有的功能域醇。

方式一:繼承系統(tǒng)的類,重寫方法.

方式二:使用runtime,交換方法.

在Objective-C中調(diào)用一個方法蓉媳,其實(shí)是向一個對象發(fā)送消息譬挚,而查找消息的唯一依據(jù)是selector的名字。所以酪呻,我們可以利用Objective-C的runtime機(jī)制减宣,實(shí)現(xiàn)在運(yùn)行時交換selector對應(yīng)的方法實(shí)現(xiàn)以達(dá)到我們的目的。每個類都有一個方法列表玩荠,存放著selector的名字和方法實(shí)現(xiàn)的映射關(guān)系蚪腋。IMP有點(diǎn)類似函數(shù)指針丰歌,指向具體的Method實(shí)現(xiàn)

我們先看看SEL與IMP之間的關(guān)系圖:


交換圖1


從上圖可以看出來姨蟋,每一個SEL與一個IMP一一對應(yīng)屉凯,正常情況下通過SEL可以查找到對應(yīng)消息的IMP實(shí)現(xiàn)。

但是眼溶,現(xiàn)在我們要做的就是把鏈接線解開悠砚,然后連到我們自定義的函數(shù)的IMP上。當(dāng)然堂飞,交換了兩個SEL的IMP灌旧,還是可以再次交換回來了。交換后變成這樣的绰筛,如下圖


交換圖2

從圖中可以看出枢泰,我們通過swizzling特性,將selectorC的方法實(shí)現(xiàn)IMPc與selectorN的方法實(shí)現(xiàn)IMPn交換了铝噩,當(dāng)我們調(diào)用selectorC衡蚂,也就是給對象發(fā)送selectorC消息時,所查找到的對應(yīng)的方法實(shí)現(xiàn)就是IMPn而不是IMPc了骏庸。

#import"UIViewController+swizzling.h"

#import@implementationUIViewController(swizzling)//load方法會在類第一次加載的時候被調(diào)用//調(diào)用的時間比較靠前毛甲,適合在這個方法里做方法交換

+ (void)load{//方法交換應(yīng)該被保證,在程序中只會執(zhí)行一次staticdispatch_once_tonceToken;dispatch_once(&onceToken, ^{

//獲得viewController的生命周期方法的selector

SEL systemSel =@selector(viewWillAppear:);

//自己實(shí)現(xiàn)的將要被交換的方法的selector

SEL swizzSel =@selector(swiz_viewWillAppear:);

//兩個方法的Method

Method ? systemMethod = class_getInstanceMethod([selfclass], systemSel); ? ??

? Method swizzMethod = class_getInstanceMethod([selfclass], swizzSel);

//首先動態(tài)添加方法具被,實(shí)現(xiàn)是被交換的方法玻募,返回值表示添加成功還是失敗BOOLisAdd = class_addMethod(self, systemSel, method_getImplementation(swizzMethod), method_getTypeEncoding(swizzMethod));

if(isAdd) {

//如果成功,說明類中不存在這個方法的實(shí)現(xiàn)//將被交換方法的實(shí)現(xiàn)替換到這個并不存在的實(shí)現(xiàn)class_replaceMethod(self,swizzSel,method_getImplementation(systemMethod), method_getTypeEncoding(systemMethod));? ? ? ? }

else{

//否則一姿,交換兩個方法的實(shí)現(xiàn)method_exchangeImplementations(systemMethod, swizzMethod);? ? ? ? }? ? });}

- (void)swiz_viewWillAppear:(BOOL)animated{/

/這時候調(diào)用自己七咧,看起來像是死循環(huán)//但是其實(shí)自己的實(shí)現(xiàn)已經(jīng)被替換了

[self ?swiz_viewWillAppear:animated];

NSLog(@"swizzle");}

@end

在一個自己定義的viewController中重寫viewWillAppear

- (void)viewWillAppear:(BOOL)animated{

? ? [super viewWillAppear:animated];? ?

? ? NSLog(@"viewWillAppear");

}

二、設(shè)置關(guān)聯(lián)值

使用場景:現(xiàn)在你準(zhǔn)備用一個系統(tǒng)的類叮叹,但是系統(tǒng)的類并不能滿足你的需求艾栋,你需要額外添加一個屬性。給一個類聲明屬性衬横,其實(shí)本質(zhì)就是給這個類添加關(guān)聯(lián)裹粤,并不是直接把這個值的內(nèi)存空間添加到類存空間。分類只能添加方法

1.設(shè)置關(guān)聯(lián)值

這種情況的一般解決辦法就是繼承蜂林。

但是遥诉,只增加一個屬性,就去繼承一個類噪叙,總是覺得太麻煩類矮锈。

這個時候,runtime的關(guān)聯(lián)屬性就發(fā)揮它的作用了睁蕾。

1苞笨、添加關(guān)聯(lián)對象

-(void)addAssociatedObject:(id)object{objc_setAssociatedObject(self,@selector(getAssociatedObject), object, OBJC_ASSOCIATION_RETAIN_NONATOMIC);}//獲取關(guān)聯(lián)對象-(id)getAssociatedObject{returnobjc_getAssociatedObject(self, _cmd);}

注意:這里面我們把getAssociatedObject方法的地址作為唯一的key债朵,_cmd代表當(dāng)前調(diào)用方法的地址。

參數(shù)說明:

object:與誰關(guān)聯(lián)瀑凝,通常是傳self

key:唯一鍵序芦,在獲取值時通過該鍵獲取,通常是使用static

const void *來聲明

value:關(guān)聯(lián)所設(shè)置的值

policy:內(nèi)存管理策略粤咪,比如使用copy

voidobjc_setAssociatedObject(idobject,constvoid*key, idvalue, objc _AssociationPolicy policy)

2.獲取關(guān)聯(lián)值

參數(shù)說明:

object:與誰關(guān)聯(lián)谚中,通常是傳self,在設(shè)置關(guān)聯(lián)時所指定的與哪個對象關(guān)聯(lián)的那個對象

key:唯一鍵寥枝,在設(shè)置關(guān)聯(lián)時所指定的鍵

idobjc_getAssociatedObject(idobject,constvoid*key)

3.取消關(guān)聯(lián)

voidobjc_removeAssociatedObjects(idobject)

關(guān)聯(lián)策略

typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy){OBJC_ASSOCIATION_ASSIGN =0,// 表示弱引用關(guān)聯(lián)宪塔,通常是基本數(shù)據(jù)類型OBJC_ASSOCIATION_RETAIN_NONATOMIC =1,// 表示強(qiáng)引用關(guān)聯(lián)對象,是線程安全的OBJC_ASSOCIATION_COPY_NONATOMIC =3,// 表示關(guān)聯(lián)對象copy囊拜,是線程安全的OBJC_ASSOCIATION_RETAIN =01401,// 表示強(qiáng)引用關(guān)聯(lián)對象某筐,不是線程安全的OBJC_ASSOCIATION_COPY =01403// 表示關(guān)聯(lián)對象copy,不是線程安全的};

@implementationViewController

- (void)viewDidLoad {?

? [super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.

// 給系統(tǒng)NSObject類動態(tài)添加屬性name

NSObject*objc = [[NSObjectalloc] init];?

? objc.name =@"123";NSLog(@"%@",objc.name);}

@end

// 定義關(guān)聯(lián)的key static const char*key ="name";

@implementationNSObject(Property)

- (NSString*)name{// 根據(jù)關(guān)聯(lián)的key冠跷,獲取關(guān)聯(lián)的值南誊。returnobjc_getAssociatedObject(self, key);}

- (void)setName:(NSString*)name{

// 第一個參數(shù):給哪個對象添加關(guān)聯(lián)/

/ 第二個參數(shù):關(guān)聯(lián)的key,通過這個key獲取

// 第三個參數(shù):關(guān)聯(lián)的value

// 第四個參數(shù):關(guān)聯(lián)的策略objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);}

@end

三蔽莱、動態(tài)添加方法

使用場景:如果一個類方法非常多弟疆,加載類到內(nèi)存的時候也比較耗費(fèi)資源,需要給每個方法生成映射表盗冷,可以使用動態(tài)給某個類怠苔,添加方法解決。

@implementationViewController

- (void)viewDidLoad {?

? [superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.

Person *p = [[Person alloc] init];// 默認(rèn)person仪糖,沒有實(shí)現(xiàn)eat方法柑司,可以通過performSelector調(diào)用,但是會報(bào)錯锅劝。

// 動態(tài)添加方法就不會報(bào)錯[p performSelector:@selector(eat)];}

@end

@implementationPerson//

void(*)()// 默認(rèn)方法都有兩個隱式參數(shù)攒驰,

void eat(idself,SEL sel){NSLog(@"%@ %@",self,NSStringFromSelector(sel));}

// 當(dāng)一個對象調(diào)用未實(shí)現(xiàn)的方法,會調(diào)用這個方法處理,并且會把對應(yīng)的方法列表傳過來.// 剛好可以用來判斷故爵,未實(shí)現(xiàn)的方法是不是我們想要動態(tài)添加的方法

+ (BOOL)resolveInstanceMethod:(SEL)sel{

if(sel ==@selector(eat)) {

// 動態(tài)添加eat方法// 第一個參數(shù):給哪個類添加方法

// 第二個參數(shù):添加方法的方法編號

// 第三個參數(shù):添加方法的函數(shù)實(shí)現(xiàn)(函數(shù)地址)

// 第四個參數(shù):函數(shù)的類型玻粪,(返回值+參數(shù)類型) v:void @:對象->self :表示SEL->_cmdclass_addMethod(self,@selector(eat), eat,"v@:");? ? }return[superresolveInstanceMethod:sel];}

@end


四、字典轉(zhuǎn)模型

設(shè)計(jì)模型

模型屬性诬垂,通常需要跟字典中的key一一對應(yīng)

問題:一個一個的生成模型屬性劲室,很慢?

需求:能不能自動根據(jù)一個字典结窘,生成對應(yīng)的屬性很洋。

解決:提供一個分類,專門根據(jù)字典生成對應(yīng)的屬性字符串隧枫。

@implementation ?NSObject(Log)// 自動打印屬性字符串

+ (void)resolveDict:(NSDictionary*)dict{

// 拼接屬性字符串代碼NSMutableString*strM = [NSMutableString string];

// 1.遍歷字典喉磁,把字典中的所有key取出來谓苟,生成對應(yīng)的屬性代碼

[dict enumerateKeysAndObjectsUsingBlock:^(id_Nonnull key,id_Nonnull obj,BOOL* _Nonnull stop) {

// 類型經(jīng)常變,抽出來

NSString*type;

if([obj isKindOfClass:NSClassFromString(@"__NSCFString")]) {? ?

? ? ? ? type =@"NSString";? ? ? ? }

else if([obj isKindOfClass:NSClassFromString(@"__NSCFArray")]){?

? ? ? ? ? type =@"NSArray";? ? ? ? }

else if([obj isKindOfClass:NSClassFromString(@"__NSCFNumber")]){? ? ? ?

? ? type =@"int";? ? ? ? }

else if([obj isKindOfClass:NSClassFromString(@"__NSCFDictionary")]){? ? ? ?

? ? type =@"NSDictionary";? ? ? ? }

// 屬性字符串NSString*str;

if([type containsString:@"NS"]) {? ?

? str = [NSStringstringWithFormat:@"@property (nonatomic, strong) %@ *%@;",type,key];? ? ? ? }

else{? ? ? ? ? ?

str = [NSStringstringWithFormat:@"@property (nonatomic, assign) %@ %@;",type,key];? ? ? ? }

// 每生成屬性字符串协怒,就自動換行涝焙。

[strM appendFormat:@"\n%@\n",str];? ? }];

// 把拼接好的字符串打印出來,就好了斤讥。NSLog(@"%@",strM);}

@end

字典轉(zhuǎn)模型的方式一:KVC

@implementation Status

+ (instancetype)statusWithDict:(NSDictionary *)dict{

?Status*status= [[self alloc] init];?

? [status setValuesForKeysWithDictionary:dict];

return ?status;

}

@end

KVC字典轉(zhuǎn)模型弊端:必須保證纱皆,模型中的屬性和字典中的key一一對應(yīng)。

如果不一致芭商,就會調(diào)用[ setValue:forUndefinedKey:]

報(bào)key找不到的錯。

分析:模型中的屬性和字典的key不一一對應(yīng)搀缠,系統(tǒng)就會調(diào)用setValue:forUndefinedKey:報(bào)錯铛楣。

解決:重寫對象的setValue:forUndefinedKey:,把系統(tǒng)的方法覆蓋,

就能繼續(xù)使用KVC艺普,字典轉(zhuǎn)模型了簸州。

-(void)setValue:(id)valueforUndefinedKey:(NSString*)key{}

字典轉(zhuǎn)模型的方式二:Runtime

思路:利用運(yùn)行時,遍歷模型中所有屬性歧譬,根據(jù)模型的屬性名岸浑,去字典中查找key,取出對應(yīng)的值瑰步,給模型的屬性賦值矢洲。

步驟:提供一個NSObject分類,專門字典轉(zhuǎn)模型缩焦,以后所有模型都可以通過這個分類轉(zhuǎn)读虏。

@implementation ?ViewController

- (void)viewDidLoad {? ?

[superviewDidLoad];// Do any additional setup after loading the view, typically from a nib.//

解析Plist文件

NSString*filePath = [[NSBundlemainBundle]pathForResource:@"status.plist"ofType:nil];

NSDictionary*statusDict = [NSDictionary ?dictionaryWithContentsOfFile:filePath];

// 獲取字典數(shù)組NSArray*dictArr = statusDict[@"statuses"];

// 自動生成模型的屬性字符串//?

? [NSObject resolveDict:dictArr[0][@"user"]];

_statuses = [NSMutableArray array];/

/ 遍歷字典數(shù)組

for(NSDictionary*dictindict Arr)

{? ? ? ? Status *status = [Status modelWithDict:dict];? ? ?

? [_statuses addObject:status];? ?

}

// 測試數(shù)據(jù)NSLog(@"%@ %@",_statuses,[_statuses[0] user]);}

@end

@implementation ?NSObject(Model)

+ (instancetype)modelWithDict:(NSDictionary*)dict

{

// 思路:遍歷模型中所有屬性-》使用運(yùn)行時

// 0.創(chuàng)建對應(yīng)的對象id objc = [[selfalloc] init];

// 1.利用runtime給對象中的成員屬性賦值

// class_copyIvarList:獲取類中的所有成員屬性

// Ivar:成員屬性的意思

// 第一個參數(shù):表示獲取哪個類中的成員屬性

// 第二個參數(shù):表示這個類有多少成員屬性,傳入一個Int變量地址袁滥,會自動給這個變量賦值

// 返回值Ivar *:指的是一個ivar數(shù)組盖桥,會把所有成員屬性放在一個數(shù)組中,通過返回的數(shù)組就能全部獲取到题翻。/* 類似下面這種寫法

Ivar ivar;

Ivar ivar1;

Ivar ivar2;

// 定義一個ivar的數(shù)組a

Ivar a[] = {ivar,ivar1,ivar2};

// 用一個Ivar *指針指向數(shù)組第一個元素

Ivar *ivarList = a;

// 根據(jù)指針訪問數(shù)組第一個元素

ivarList[0];

*/unsignedintcount;

// 獲取類中的所有成員屬性Ivar *ivarList = class_copyIvarList(self, &count);

for(inti =0; i < count; i++) {

// 根據(jù)角標(biāo)揩徊,從數(shù)組取出對應(yīng)的成員屬性Ivar ivar = ivarList[i];

// 獲取成員屬性名

NSString*name = [NSString stringWithUTF8String:ivar_getName(ivar)];

// 處理成員屬性名->字典中的key

// 從第一個角標(biāo)開始截取

NSString*key = [name substringFromIndex:1];

// 根據(jù)成員屬性名去字典中查找對應(yīng)的value

id value = dict[key];

// 二級轉(zhuǎn)換:如果字典中還有字典,也需要把對應(yīng)的字典轉(zhuǎn)換成模型

// 判斷下value是否是字典

if([value isKindOfClass:[NSDictionaryclass]]) {

// 字典轉(zhuǎn)模型// 獲取模型的類對象嵌赠,調(diào)用modelWithDict

// 模型的類名已知塑荒,就是成員屬性的類型

// 獲取成員屬性類型

NSString*type = [NSString ?stringWithUTF8String:ivar_getTypeEncoding(ivar)];

// 生成的是這種@"@\"User\"" 類型 -》 @"User"? 在OC字符串中 \" -> ",\是轉(zhuǎn)義的意思猾普,不占用字符// 裁剪類型字符串NSRangerange = [type rangeOfString:@"\""];? ? ?

? ? type = [type substringFromIndex:range.location + range.length];? ? ?

? ? ? range = [type rangeOfString:@"\""];// 裁剪到哪個角標(biāo)袜炕,不包括當(dāng)前角標(biāo)type = [type substringToIndex:range.location];

// 根據(jù)字符串類名生成類對象

Class modelClass =NSClassFromString(type);

if(modelClass) {

// 有對應(yīng)的模型才需要轉(zhuǎn)

// 把字典轉(zhuǎn)模型value? =? [modelClass modelWithDict:value];? ? ? ? ? ? }? ? ? ? }

// 三級轉(zhuǎn)換:NSArray中也是字典,把數(shù)組中的字典轉(zhuǎn)換成模型

// 判斷值是否是數(shù)組

if([value isKindOfClass:[NSArrayclass]]) {

// 判斷對應(yīng)類有沒有實(shí)現(xiàn)字典數(shù)組轉(zhuǎn)模型數(shù)組的協(xié)議

if([self respondsToSelector:@selector(arrayContainModelClass)]) {/

/ 轉(zhuǎn)換成id類型初家,就能調(diào)用任何對象的方法id

id Self =self;

// 獲取數(shù)組中字典對應(yīng)的模型

NSString*type =? [id ?Self arrayContainModelClass][key];

// 生成模型

Class classModel =NSClassFromString(type);

NSMutableArray*arrM = [NSMutableArray ?array];

// 遍歷字典數(shù)組偎窘,生成模型數(shù)組for(NSDictionary*dict in value) {

// 字典轉(zhuǎn)模型id model =? [classModel modelWithDict:dict];? ? ? ? ? ? ?

? ?[arrM addObject:model];? ? ? ? ? ? ? ? }

// 把模型數(shù)組賦值給value ?value = arrM;? ? ? ? ? ? }? ? ? ? }

if(value) {

// 有值乌助,才需要給模型的屬性賦值

// 利用KVC給模型中的屬性賦值[objc setValue:value forKey:key];? ? ? ? }? ?

}return ? objc;}

@end

五、參考文章

http://www.reibang.com/p/e071206103a4

http://www.reibang.com/p/adf0d566c887

http://www.reibang.com/p/927c8384855a

http://chun.tips/2014/11/05/objc-runtime-1/#more

http://blog.sunnyxx.com/2016/08/13/reunderstanding-runtime-0/

http://blog.csdn.net/wzzvictory/article/details/8624057

http://www.cocoachina.com/ios/20151208/14595.html

http://www.reibang.com/p/46dd81402f63

六陌知、后記

說實(shí)話他托,剛開始做開發(fā)是后,也一直聽說runtime,但項(xiàng)目中用的少仆葡,直到最近項(xiàng)目不是太忙赏参,才重新看看蘋果的runtime機(jī)制,有一種驀然回首沿盅,茅塞頓開的感覺把篓,學(xué)會runtime,一是可以更好的幫助你理解OC的運(yùn)行機(jī)制。還有一點(diǎn)就是可以裝-B

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腰涧,一起剝皮案震驚了整個濱河市韧掩,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌窖铡,老刑警劉巖疗锐,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異费彼,居然都是意外死亡滑臊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門箍铲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雇卷,“玉大人,你說我怎么就攤上這事虹钮×郑” “怎么了?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵芙粱,是天一觀的道長祭玉。 經(jīng)常有香客問我,道長春畔,這世上最難降的妖魔是什么脱货? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮律姨,結(jié)果婚禮上振峻,老公的妹妹穿的比我還像新娘。我一直安慰自己择份,他們只是感情好扣孟,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著荣赶,像睡著了一般凤价。 火紅的嫁衣襯著肌膚如雪鸽斟。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天利诺,我揣著相機(jī)與錄音富蓄,去河邊找鬼。 笑死慢逾,一個胖子當(dāng)著我的面吹牛立倍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播侣滩,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼口注,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了胜卤?” 一聲冷哼從身側(cè)響起疆导,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎葛躏,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悠菜,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舰攒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了悔醋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摩窃。...
    茶點(diǎn)故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖芬骄,靈堂內(nèi)的尸體忽然破棺而出猾愿,到底是詐尸還是另有隱情,我是刑警寧澤账阻,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布蒂秘,位于F島的核電站,受9級特大地震影響淘太,放射性物質(zhì)發(fā)生泄漏姻僧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一蒲牧、第九天 我趴在偏房一處隱蔽的房頂上張望撇贺。 院中可真熱鬧,春花似錦冰抢、人聲如沸松嘶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翠订。三九已至巢音,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蕴轨,已是汗流浹背港谊。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留橙弱,地道東北人歧寺。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像棘脐,于是被迫代替她去往敵國和親斜筐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 對于從事 iOS 開發(fā)人員來說蛀缝,所有的人都會答出【runtime 是運(yùn)行時】什么情況下用runtime?大部分人能...
    夢夜繁星閱讀 3,697評論 7 64
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉顷链,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,681評論 0 9
  • OC最實(shí)用的runtime總結(jié),面試构哺、工作你看我就足夠了革答! 前言runtime的資料網(wǎng)上有很多了,部分有些晦澀難懂...
    small_Sun閱讀 926評論 1 12
  • 原:還原曙强,把事情還原到對方所處的那個身份残拐,狀態(tài),背景碟嘴。 涼:諒解溪食,把自己放下,諒解自己臀防。 人特別怕的狀態(tài):拿不起眠菇,...
    黃羅海燕閱讀 650評論 0 1
  • 1、 do what yow say,say what you do.
    魂歸瀟湘閱讀 134評論 0 0