Runtime簡(jiǎn)介

自從學(xué)習(xí)ios呀页,很長(zhǎng)一段時(shí)間沒(méi)有搞清楚runtime是什么東西颗祝,還好現(xiàn)在隨著ios的資料慢慢的變多著蛙,自己找資料總結(jié)大概搞清楚了

一辉哥、 runtime介紹

runtime幾點(diǎn)認(rèn)識(shí)
  • RunTime簡(jiǎn)稱運(yùn)行時(shí)桦山。OC就是運(yùn)行時(shí)機(jī)制,也就是在運(yùn)行時(shí)候的一些機(jī)制醋旦,其中最主要的是消息機(jī)制恒水。
  • 對(duì)于C語(yǔ)言,函數(shù)的調(diào)用在編譯的時(shí)候會(huì)決定調(diào)用哪個(gè)函數(shù)饲齐。
  • 對(duì)于OC的函數(shù)钉凌,屬于動(dòng)態(tài)調(diào)用過(guò)程,在編譯的時(shí)候并不能決定真正調(diào)用哪個(gè)函數(shù)箩张,只有在真正運(yùn)行的時(shí)候才會(huì)根據(jù)函數(shù)的名稱找到對(duì)應(yīng)的函數(shù)來(lái)調(diào)用甩骏。
寫(xiě)代碼的時(shí)候會(huì)發(fā)現(xiàn):
  • 在編譯階段,OC可以調(diào)用任何函數(shù)先慷,即使這個(gè)函數(shù)并未實(shí)現(xiàn)饮笛,只要聲明過(guò)就不會(huì)報(bào)錯(cuò)。
  • 在編譯階段论熙,C語(yǔ)言調(diào)用未實(shí)現(xiàn)的函數(shù)就會(huì)報(bào)錯(cuò)福青。

二、 學(xué)習(xí)runtime的作用脓诡,也就是能干什么用

1.發(fā)送消息

ios方法調(diào)用的本質(zhì)就是讓對(duì)象發(fā)送消息无午,要導(dǎo)入#import <objc/message.h>
// 創(chuàng)建person對(duì)象
Person *p = [[Person alloc] init];
// 調(diào)用對(duì)象方法
[p eat];

// 本質(zhì):讓對(duì)象發(fā)送消息
objc_msgSend(p, @selector(eat));

// 調(diào)用類方法的方式:兩種
// 第一種通過(guò)類名調(diào)用
[Person eat];
// 第二種通過(guò)類對(duì)象調(diào)用
[[Person class] eat];
// 用類名調(diào)用類方法,底層會(huì)自動(dòng)把類名轉(zhuǎn)換成類對(duì)象調(diào)用
// 本質(zhì):讓類對(duì)象發(fā)送消息
objc_msgSend([Person class], @selector(eat));

2.交換方法

  • 開(kāi)發(fā)使用場(chǎng)景:系統(tǒng)自帶的方法功能不夠祝谚,給系統(tǒng)自帶的方法擴(kuò)展一些功能宪迟,并且保持原有的功能。
  • 方式一:繼承系統(tǒng)的類交惯,重寫(xiě)方法.
  • 方式二:使用runtime,交換方法.
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    // 需求:給imageNamed方法提供功能次泽,每次加載圖片就判斷下圖片是否加載成功。
    // 步驟一:先搞個(gè)分類席爽,定義一個(gè)能加載圖片并且能打印的方法+ (instancetype)imageWithName:(NSString *)name;
    // 步驟二:交換imageNamed和imageWithName的實(shí)現(xiàn)意荤,就能調(diào)用imageWithName,間接調(diào)用imageWithName的實(shí)現(xiàn)只锻。
    UIImage *image = [UIImage imageNamed:@"123"];
    
}
@end

@implementation UIImage (Image)
// 加載分類到內(nèi)存的時(shí)候調(diào)用
+ (void)load
{
    // 交換方法
    
    // 獲取類imageWithName方法地址
    Method imageWithName = class_getClassMethod(self, @selector(imageWithName:));
//    method imageWithName = class_getInstanceMethod(self, @selector(imageWithName:)) //獲取對(duì)象imageWithName方法地址

    // 獲取imageWithName方法地址
    Method imageName = class_getClassMethod(self, @selector(imageNamed:));

    // 交換方法地址玖像,相當(dāng)于交換實(shí)現(xiàn)方式
    method_exchangeImplementations(imageWithName, imageName);
    
    
}
// 不能在分類中重寫(xiě)系統(tǒng)方法imageNamed,因?yàn)闀?huì)把系統(tǒng)的功能給覆蓋掉齐饮,而且分類中不能調(diào)用super
// 既能加載圖片又能打印
+ (instancetype)imageWithName:(NSString *)name
{
   
    // 這里調(diào)用imageWithName捐寥,相當(dāng)于調(diào)用imageName
    UIImage *image = [self imageWithName:name];
    
    if (image == nil) {
        NSLog(@"加載空的圖片");
    }
    
    return image;
}
@end

3.動(dòng)態(tài)添加方法

  • 開(kāi)發(fā)使用場(chǎng)景:如果一個(gè)類方法非常多笤昨,加載類到內(nèi)存的時(shí)候也比較耗費(fèi)資源,需要給每個(gè)方法生成映射表上真,可以使用動(dòng)態(tài)給某個(gè)類咬腋,添加方法解決。在OC中,所有的控件(textFiled或者button等控件), 數(shù)組, 數(shù)據(jù)等都是以懶加載的形式加載的.真正使用的時(shí)候才會(huì)加載,或者添加方法.動(dòng)態(tài)添加的方法的作用就是去處理未實(shí)現(xiàn)的實(shí)例方法或者是類方法.它的調(diào)用時(shí)刻: 只要我們調(diào)用了一個(gè)不存在的方法時(shí),它就會(huì)動(dòng)態(tài)添加方法.每個(gè)類都一個(gè)處理為實(shí)現(xiàn)方法的方法.
  • 經(jīng)典面試題:有沒(méi)有使用performSelector睡互,其實(shí)主要想問(wèn)你有沒(méi)有動(dòng)態(tài)添加過(guò)方法。
  • 簡(jiǎn)單使用
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    Person *p = [[Person alloc] init];
    
    // 默認(rèn)person陵像,沒(méi)有實(shí)現(xiàn)eat方法就珠,可以通過(guò)performSelector調(diào)用,但是會(huì)報(bào)錯(cuò)醒颖。
    // 動(dòng)態(tài)添加方法就不會(huì)報(bào)錯(cuò)
    [p performSelector:@selector(eat)];
    
}


@end


@implementation Person
// void(*)()
// 默認(rèn)方法都有兩個(gè)隱式參數(shù)妻怎,
void eat(id self,SEL sel)
{
    NSLog(@"%@ %@",self,NSStringFromSelector(sel));
}

// 當(dāng)一個(gè)對(duì)象調(diào)用未實(shí)現(xiàn)的方法,會(huì)調(diào)用這個(gè)方法處理,并且會(huì)把對(duì)應(yīng)的方法列表傳過(guò)來(lái).
// 剛好可以用來(lái)判斷泞歉,未實(shí)現(xiàn)的方法是不是我們想要?jiǎng)討B(tài)添加的方法
//+resolveClassMethod:(類方法)
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    
    if (sel == @selector(eat)) {
        // 動(dòng)態(tài)添加eat方法
        
        // 第一個(gè)參數(shù):給哪個(gè)類添加方法
        // 第二個(gè)參數(shù):添加方法的方法編號(hào)
        // 第三個(gè)參數(shù):添加方法的函數(shù)實(shí)現(xiàn)(函數(shù)地址)
        // 第四個(gè)參數(shù):函數(shù)的類型逼侦,(返回值+參數(shù)類型) v:void @:對(duì)象->self :表示SEL->_cmd
        class_addMethod(self, @selector(eat), eat, "v@:");
        
    }
    
    return [super resolveInstanceMethod:sel];
}
@end

4.動(dòng)態(tài)添加屬性

類別不能添加屬性,但可以通過(guò)runtime類別可以實(shí)現(xiàn)添加屬性
需要用到這個(gè)方法
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)

  • id object : 源對(duì)象 -指定我們需要綁定的對(duì)象腰耙,e.g ,給一個(gè)字符串添加一個(gè)內(nèi)容
  • const void * key : 設(shè)置一個(gè)靜態(tài)常亮榛丢,也就是Key 值,通過(guò)這個(gè)我們可以找到我們關(guān)聯(lián)對(duì)象的那個(gè)數(shù)據(jù)值
  • id value 這個(gè)是我們打點(diǎn)調(diào)用屬性的時(shí)候會(huì)自動(dòng)調(diào)用set方法進(jìn)行傳值
  • objc_AssociationPolicy policy : 這個(gè)是關(guān)聯(lián)策略挺庞,這幾個(gè)管理策略晰赞,我們看下都有什么,
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
// 第一個(gè)關(guān)聯(lián)策略是基于基本類型的选侨,也就是我們常用的assign 屬性 
OBJC_ASSOCIATION_ASSIGN = 0, 
//關(guān)聯(lián)策略是基于對(duì)象類型的掖鱼,如我們正常的是retain nonatomic (非原子操作)類型 ,retain : 保留一個(gè)引用指針援制,內(nèi)存地址不修改戏挡,指向同一塊內(nèi)存地址
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, 
//這個(gè)相當(dāng)于屬性中對(duì)一些對(duì)象或者字符串進(jìn)行的copy 這個(gè)是拷貝一個(gè)新對(duì)象,內(nèi)存地址不在一起晨仑,還是使用的非原子類型褐墅,
//非原子類型我們也稱之為線程不安全的操作,但是對(duì)于OC里面的數(shù)據(jù)操作寻歧,我們盡量避開(kāi)原子操作掌栅,原子操作是線程安全的,會(huì)影響我們對(duì)數(shù)據(jù)的寫(xiě)入操作
OBJC_ASSOCIATION_COPY_NONATOMIC = 3,
// 簡(jiǎn)單的指針引用码泛, retain 操作
OBJC_ASSOCIATION_RETAIN = 01401,  
//把簡(jiǎn)單的對(duì)象拷貝到一個(gè)新的內(nèi)存地址
OBJC_ASSOCIATION_COPY = 01403 
};

例子猾封,給所有NSObject增加一個(gè)屬性passValue

#import <Foundation/Foundation.h>

@interface NSObject (PassValue)
@property (assign,nonatomic)id passValue;
@end
#import "NSObject+PassValue.h"
#import <objc/runtime.h>
static const char *  passvalueKEY = "passvalueKEY";
@implementation NSObject (PassValue)

-(void)setPassValue:(id)passValue{
    objc_setAssociatedObject(self, passvalueKEY, passValue, OBJC_ASSOCIATION_RETAIN);
}
-(id)passValue{
    return objc_getAssociatedObject(self, passvalueKEY);
}

@end

5.字典轉(zhuǎn)模型

  • 設(shè)計(jì)模型:字典轉(zhuǎn)模型的第一步
    • 模型屬性,通常需要跟字典中的key一一對(duì)應(yīng)
    • 問(wèn)題:一個(gè)一個(gè)的生成模型屬性噪珊,很慢晌缘?
    • 需求:能不能自動(dòng)根據(jù)一個(gè)字典齐莲,生成對(duì)應(yīng)的屬性。
    • 解決:提供一個(gè)分類磷箕,專門根據(jù)字典生成對(duì)應(yīng)的屬性字符串选酗。
    @implementation NSObject (Log)


// 自動(dòng)打印屬性字符串
+ (void)resolveDict:(NSDictionary *)dict{

    // 拼接屬性字符串代碼
    NSMutableString *strM = [NSMutableString string];
    
    // 1.遍歷字典,把字典中的所有key取出來(lái)岳枷,生成對(duì)應(yīng)的屬性代碼
    [dict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        
        // 類型經(jīng)常變芒填,抽出來(lái)
         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 = [NSString stringWithFormat:@"@property (nonatomic, strong) %@ *%@;",type,key];
        }else{
            str = [NSString stringWithFormat:@"@property (nonatomic, assign) %@ %@;",type,key];
        }
        
        // 每生成屬性字符串,就自動(dòng)換行空繁。
        [strM appendFormat:@"\n%@\n",str];
        
    }];
    
    // 把拼接好的字符串打印出來(lái)殿衰,就好了。
    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一一對(duì)應(yīng)闷祥。
    • 如果不一致,就會(huì)調(diào)用[<Status 0x7fa74b545d60> setValue:forUndefinedKey:]
      報(bào)key找不到的錯(cuò)傲诵。
    • 分析:模型中的屬性和字典的key不一一對(duì)應(yīng)凯砍,系統(tǒng)就會(huì)調(diào)用setValue:forUndefinedKey:報(bào)錯(cuò)。
    • 解決:重寫(xiě)對(duì)象的setValue:forUndefinedKey:,把系統(tǒng)的方法覆蓋拴竹,
      就能繼續(xù)使用KVC悟衩,字典轉(zhuǎn)模型了。
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
    
}

  • 字典轉(zhuǎn)模型的方式二:Runtime
    • 思路:利用運(yùn)行時(shí)殖熟,遍歷模型中所有屬性局待,根據(jù)模型的屬性名,去字典中查找key菱属,取出對(duì)應(yīng)的值钳榨,給模型的屬性賦值。
    • 步驟:提供一個(gè)NSObject分類纽门,專門字典轉(zhuǎn)模型薛耻,以后所有模型都可以通過(guò)這個(gè)分類轉(zhuǎn)。

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    // 解析Plist文件
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"status.plist" ofType:nil];
    NSDictionary *statusDict = [NSDictionary dictionaryWithContentsOfFile:filePath];   
    // 獲取字典數(shù)組
    NSArray *dictArr = statusDict[@"statuses"];    
    // 自動(dòng)生成模型的屬性字符串
//    [NSObject resolveDict:dictArr[0][@"user"]];
    _statuses = [NSMutableArray array];
    // 遍歷字典數(shù)組
    for (NSDictionary *dict in dictArr) {
        Status *status = [Status modelWithDict:dict];  
        [_statuses addObject:status];
        
    }
    // 測(cè)試數(shù)據(jù)
    NSLog(@"%@ %@",_statuses,[_statuses[0] user]);
    
    
}

@end

@implementation NSObject (Model)

+ (instancetype)modelWithDict:(NSDictionary *)dict
{
    // 思路:遍歷模型中所有屬性-》使用運(yùn)行時(shí)
    
    // 0.創(chuàng)建對(duì)應(yīng)的對(duì)象
    id objc = [[self alloc] init];
    
    // 1.利用runtime給對(duì)象中的成員屬性賦值
    
    // class_copyIvarList:獲取類中的所有成員屬性
    // Ivar:成員屬性的意思
    // 第一個(gè)參數(shù):表示獲取哪個(gè)類中的成員屬性
    // 第二個(gè)參數(shù):表示這個(gè)類有多少成員屬性赏陵,傳入一個(gè)Int變量地址饼齿,會(huì)自動(dòng)給這個(gè)變量賦值
    // 返回值Ivar *:指的是一個(gè)ivar數(shù)組,會(huì)把所有成員屬性放在一個(gè)數(shù)組中蝙搔,通過(guò)返回的數(shù)組就能全部獲取到缕溉。
    /* 類似下面這種寫(xiě)法
     
     Ivar ivar;
     Ivar ivar1;
     Ivar ivar2;
     // 定義一個(gè)ivar的數(shù)組a
     Ivar a[] = {ivar,ivar1,ivar2};
     
     // 用一個(gè)Ivar *指針指向數(shù)組第一個(gè)元素
     Ivar *ivarList = a;
     
     // 根據(jù)指針訪問(wèn)數(shù)組第一個(gè)元素
     ivarList[0];
     
     */
    unsigned int count;
    
    // 獲取類中的所有成員屬性
    Ivar *ivarList = class_copyIvarList(self, &count);
    
    for (int i = 0; i < count; i++) {
        // 根據(jù)角標(biāo),從數(shù)組取出對(duì)應(yīng)的成員屬性
        Ivar ivar = ivarList[i];
        
        // 獲取成員屬性名
        NSString *name = [NSString stringWithUTF8String:ivar_getName(ivar)];
        
        // 處理成員屬性名->字典中的key
        // 從第一個(gè)角標(biāo)開(kāi)始截取
        NSString *key = [name substringFromIndex:1];

        // 根據(jù)成員屬性名去字典中查找對(duì)應(yīng)的value
        id value = dict[key];
        
        // 二級(jí)轉(zhuǎn)換:如果字典中還有字典吃型,也需要把對(duì)應(yīng)的字典轉(zhuǎn)換成模型
        // 判斷下value是否是字典
        if ([value isKindOfClass:[NSDictionary class]]) {
            // 字典轉(zhuǎn)模型
            // 獲取模型的類對(duì)象证鸥,調(diào)用modelWithDict
            // 模型的類名已知,就是成員屬性的類型
            
            // 獲取成員屬性類型
           NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
          // 生成的是這種@"@\"User\"" 類型 -》 @"User"  在OC字符串中 \" -> ",\是轉(zhuǎn)義的意思枉层,不占用字符
            // 裁剪類型字符串
            NSRange range = [type rangeOfString:@"\""];

           type = [type substringFromIndex:range.location + range.length];
            
            range = [type rangeOfString:@"\""];
            
            // 裁剪到哪個(gè)角標(biāo)泉褐,不包括當(dāng)前角標(biāo)
          type = [type substringToIndex:range.location];

            
            // 根據(jù)字符串類名生成類對(duì)象
            Class modelClass = NSClassFromString(type);
            

            if (modelClass) { // 有對(duì)應(yīng)的模型才需要轉(zhuǎn)
                
                // 把字典轉(zhuǎn)模型
                value  =  [modelClass modelWithDict:value];
            }
            
            
        }
        
        // 三級(jí)轉(zhuǎn)換:NSArray中也是字典,把數(shù)組中的字典轉(zhuǎn)換成模型.
        // 判斷值是否是數(shù)組
        if ([value isKindOfClass:[NSArray class]]) {
            // 判斷對(duì)應(yīng)類有沒(méi)有實(shí)現(xiàn)字典數(shù)組轉(zhuǎn)模型數(shù)組的協(xié)議
            if ([self respondsToSelector:@selector(arrayContainModelClass)]) {
                
                // 轉(zhuǎn)換成id類型鸟蜡,就能調(diào)用任何對(duì)象的方法
                id idSelf = self;
                
                // 獲取數(shù)組中字典對(duì)應(yīng)的模型
                NSString *type =  [idSelf 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


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末揉忘,一起剝皮案震驚了整個(gè)濱河市跳座,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌癌淮,老刑警劉巖躺坟,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異乳蓄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)夕膀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門虚倒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人产舞,你說(shuō)我怎么就攤上這事魂奥。” “怎么了易猫?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵耻煤,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我准颓,道長(zhǎng)哈蝇,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任攘已,我火速辦了婚禮炮赦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘样勃。我一直安慰自己吠勘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布峡眶。 她就那樣靜靜地躺著剧防,像睡著了一般。 火紅的嫁衣襯著肌膚如雪辫樱。 梳的紋絲不亂的頭發(fā)上峭拘,一...
    開(kāi)封第一講書(shū)人閱讀 52,785評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼棚唆。 笑死暇赤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宵凌。 我是一名探鬼主播鞋囊,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼瞎惫!你這毒婦竟也來(lái)了溜腐?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瓜喇,失蹤者是張志新(化名)和其女友劉穎挺益,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體乘寒,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡望众,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了伞辛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烂翰。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蚤氏,靈堂內(nèi)的尸體忽然破棺而出甘耿,到底是詐尸還是另有隱情,我是刑警寧澤竿滨,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布佳恬,位于F島的核電站,受9級(jí)特大地震影響于游,放射性物質(zhì)發(fā)生泄漏毁葱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一曙砂、第九天 我趴在偏房一處隱蔽的房頂上張望头谜。 院中可真熱鬧,春花似錦鸠澈、人聲如沸柱告。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)际度。三九已至,卻和暖如春涵妥,著一層夾襖步出監(jiān)牢的瞬間乖菱,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窒所,地道東北人鹉勒。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像吵取,于是被迫代替她去往敵國(guó)和親禽额。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

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

  • 對(duì)于從事 iOS 開(kāi)發(fā)人員來(lái)說(shuō)皮官,所有的人都會(huì)答出【runtime 是運(yùn)行時(shí)】什么情況下用runtime?大部分人能...
    夢(mèng)夜繁星閱讀 3,726評(píng)論 7 64
  • 一脯倒、Runtime簡(jiǎn)介 RunTime簡(jiǎn)稱運(yùn)行時(shí)。OC就是運(yùn)行時(shí)機(jī)制捺氢,也就是在運(yùn)行時(shí)候的一些機(jī)制藻丢,其中最主要的是消...
    竇豆逗閱讀 159評(píng)論 0 0
  • Runtime簡(jiǎn)介以及常見(jiàn)的使用場(chǎng)景 Runtime簡(jiǎn)稱運(yùn)行時(shí),是一套比較底層的純C語(yǔ)言的API,作為OC的核心...
    輕云_閱讀 1,184評(píng)論 5 23
  • RunTime簡(jiǎn)稱運(yùn)行時(shí)摄乒。OC就是運(yùn)行時(shí)機(jī)制悠反,也就是在運(yùn)行時(shí)候的一些機(jī)制,其中最主要的是消息機(jī)制馍佑。對(duì)于C語(yǔ)言问慎,函數(shù)...
    _心暖閱讀 544評(píng)論 1 1
  • 最近項(xiàng)目要用的lua 所以抽空學(xué)習(xí) 記錄一下 IDE有ZeroBrane Studio 我還是用的sublime...
    slimsallen閱讀 655評(píng)論 3 1