iOS 常用的runtime方法

本篇文章在《iOS開發(fā)之Runtime常用示例總結(jié)》基礎(chǔ)上修改,地址是
「:」http://www.cocoachina.com/ios/20170301/18804.html
本篇文章主要創(chuàng)建的類如下:


首先我們先創(chuàng)建一個實例類TestClass

這個類實現(xiàn)了NSCopying和NSCoding協(xié)議,包含公共的成員屬性,和實例方法以及類方法,
在.m文件中

我們有私有成員變量和成員屬性选侨,和私有方法鱼鼓。
下面我們來具體介紹一下runtime的常用方法
1钉跷、利用runtime來獲取類名

/**
          獲取類名
          @param class 相應類
          @return NSString:類名
    */
    + (NSString *)fetchClassName:(Class)class
   {
       const char *className = class_getName(class);
       return [NSString stringWithUTF8String:className];
   }

2灶伊、利用runtime來獲取成員變量

/**
 獲取成員變量

 @param class Class
 @return NSArray
 */
+(NSArray *)fetchIvarList:(Class)class
{
    unsigned int count = 0;
    Ivar *ivarList = class_copyIvarList(class, &count);//獲取成員變量的個數(shù)count疆前,以及數(shù)組內(nèi)容
    
    NSMutableArray *mutableList = [NSMutableArray arrayWithCapacity:count];
    for (unsigned int i = 0; i < count; i ++) {
        NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:2];
        const char *ivarName = ivar_getName(ivarList[i]);//獲取成員變量的名稱
        const char *ivarType = ivar_getTypeEncoding(ivarList[i]);//獲取成員變量的類型
        dic[@"type"] = [NSString stringWithUTF8String:ivarType];
        dic[@"ivarName"] = [NSString stringWithUTF8String:ivarName];
        [mutableList addObject:dic];
    }
    free(ivarList);
    return [NSArray arrayWithArray:mutableList];
}

其輸出結(jié)果如下:


    • 注意,如果用這個來獲取類的成員變量聘萨,是不分私有和公有之分的竹椒,都會獲取出來,意思也就是不管是成員變量米辐,還是成員屬性胸完,都可以獲取的到,并且獲取到的成員屬性的名稱是有下劃線的
      3翘贮、獲取類的成員屬性
/**
 獲取類的屬性列表赊窥,包括私有和公有屬性,以及定義再延展中的屬性
 @param class Class
 @return 屬性列表數(shù)組
 */
+(NSArray *)fetchPropertyList:(Class)class
{
    unsigned int count = 0;
    objc_property_t *propertyList = class_copyPropertyList(class, &count);
    NSMutableArray *mutableList = [NSMutableArray arrayWithCapacity:count];
    for (unsigned int i = 0; i < count; i ++) {
        const char *propertyName = property_getName(propertyList[i]);
        [mutableList addObject:[NSString stringWithUTF8String:propertyName]];
        
    }
    free(propertyList);
    return mutableList;
}

其輸出結(jié)果如下:


    • 注意狸页,獲取的成員屬性名稱是沒有下劃線的锨能,此處也不分私有和公有
      4、獲取類的實例方法列表
/**
 獲取類的實例方法列表:getter芍耘,setter址遇,對象方法等。但不能獲取類方法斋竞,也就是加號方法
 @param class class
 @return 類的實例方法列表
 */
+ (NSArray *)fetchMethodList:(Class)class
{
    unsigned int count = 0;
    Method *methodList = class_copyMethodList(class, &count);
    NSMutableArray *mutableList = [NSMutableArray arrayWithCapacity:count];
    for (unsigned int i = 0 ; i < count; i ++) {
        Method method = methodList[i];
        SEL methodName = method_getName(method);
        [mutableList addObject:NSStringFromSelector(methodName)];
    }
    free(methodList);
    return mutableList;
}

其輸出結(jié)果如下:

    • 注意傲隶,其中類的成員屬性的getter,setter方法也獲取不到的窃页,但是類方法是獲取不到
      5跺株、獲取類的協(xié)議列表
/**
 獲取協(xié)議列表
 @param class class
 @return 協(xié)議列表
 */
+(NSArray *)fetchProtocolList:(Class)class
{
    unsigned int count = 0;
    __unsafe_unretained Protocol **protocolList = class_copyProtocolList(class, &count);
    NSMutableArray *mutableList = [NSMutableArray arrayWithCapacity:count];
    for (unsigned int i = 0; i < count; i ++) {
        Protocol *protocol = protocolList[i];
        const char *protocolName = protocol_getName(protocol);
        [mutableList addObject:[NSString stringWithUTF8String:protocolName]];

    }
    return mutableList;
}

其輸出結(jié)果是


6、實現(xiàn)方法的交換
/** 方法交換 @param class 交換方法所在的類 @param method1 方法1 @param method2 方法2 */ + (void)methodSwap:(Class)class firstMethod:(SEL)method1 secondMethod:(SEL)method2 { Method firstMethod = class_getInstanceMethod(class, method1); Method secondMethod = class_getInstanceMethod(class, method2); method_exchangeImplementations(firstMethod, secondMethod); }
例如我們在TestClass(SwapMethod)類別中脖卖,寫如下代碼:

    #import "TestClass+SwapMethod.h"
    #import "Runtime.h"
    @implementation TestClass(SwapMethod)
    + (void)load
    {
     [Runtime methodSwap:[self class] firstMethod:@selector(method1) secondMethod:@selector(method2)];
    }
    - (void)method2
{
    NSLog(@"這里實際上調(diào)用的是method1的實現(xiàn)");
}
@end

然后我們?nèi)フ{(diào)用method2乒省,會發(fā)現(xiàn)調(diào)用的方法實際上是method1的方法,調(diào)用method1方法畦木,實際上調(diào)用的是method2的方法
7袖扛、給類添加新的方法與實現(xiàn)

    /**
     給類上添加新的方法與實現(xiàn)
     @param class 相應的類
     @param methodSel 方法的名
     @param methodSelImpl 對應方法實現(xiàn)的方法名
     */
    + (void)addMethod:(Class)class method:(SEL)methodSel method:(SEL)methodSelImpl
    {
    Method method = class_getInstanceMethod(class, methodSelImpl);
    IMP methodIMP = method_getImplementation(method);
    const char *types = method_getTypeEncoding(method);
    class_addMethod(class, methodSel, methodIMP, types);
}
  • *注意,此方法添加的是實例方法十籍,而非類方法
    當我們訪問一個方法時蛆封,如果找不到此方法的實現(xiàn),iOS提供了兩個方法去訪問勾栗,
    + (BOOL)resolveClassMethod:(SEL)sel;//針對訪問不到類方法時惨篱,訪問的方法
    + (BOOL)resolveInstanceMethod:(SEL)sel;//針對訪問不到實例方法時,訪問的方法

我們以實例方法未準围俘,假如我們在TestClass中添加一個方法砸讳,然后不去實現(xiàn)



此時琢融,如果訪問此方法,則系統(tǒng)會找不到此方法的實現(xiàn)簿寂,此時我們重寫resolveInstanceMethod方法漾抬,你會發(fā)現(xiàn)系統(tǒng)會訪問此方法,如果我們在此方法中給未實現(xiàn)的方法添加實現(xiàn)常遂,則系統(tǒng)會去訪問我們提供的實現(xiàn)方法的纳令,例如:

    void addnewMethodIMP(id self,SEL _cmd,NSString *temp)
    {
        NSLog(@"動態(tài)添加實現(xiàn)");
    }
    - (void)addMethodComplete:(NSString *)value
{
    NSLog(@"oc替換的方法:%@",value);
}
//此方法時針對對象方法的
 + (BOOL)resolveInstanceMethod:(SEL)sel
{
#warning mark-- 以下是兩種添加形式
    
    //第一種
    //其中“v@:”代表的是針對誰添加的方法,如果后面帶有參數(shù)克胳,則寫在:后面泊碑,例如下面的 "v@:@"
//    if (sel == @selector(missMethod:)) {
//        class_addMethod([self class], sel, (IMP)addnewMethodIMP, "v@:@");
//        return YES;
//    }
    
    //第二種 此種方法就是我們上面寫的
//     [Runtime addMethod:[self class] method:sel method:@selector(addMethodComplete:)];
//    return YES;
//    return [super resolveInstanceMethod:sel];
    
    return NO;
}

8、屬性關(guān)聯(lián)
在類目中動態(tài)的為我們的類添加相應的屬性毯欣。
下方就是在TestClass的類目中通過objc_getAssociatedObject()和objc_setAssociatedObject()兩個方法為TestClass類添加了一個addNewProperty屬性

    #import "TestClass+AssociatedObject.h"
    @interface TestClass (AssociatedObject)
    @property (nonatomic,strong)NSString *addNewProperty;
    @end
    @implementation TestClass(AssociatedObject)
    #pragma mark-- 動態(tài)屬性關(guān)聯(lián)
    static char addNewProperty;
    /**
     getter方法
     @return 返回關(guān)聯(lián)屬性的值
     */
    - (NSString *)addNewProperty
    {
        return objc_getAssociatedObject(self, &addNewProperty);
    }
    /**
     setter方法
     @param addNewProperty 設(shè)置關(guān)聯(lián)屬性的值
     */
    - (void)setAddNewProperty:(NSString *)addNewProperty
{
    objc_setAssociatedObject(self, &addNewProperty, addNewProperty, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end

此時如果我們再去獲取TestClass的屬性,其輸出結(jié)果就是



其中包含了我們動態(tài)添加的addNewProperty屬性

9臭脓、下面我們用runtime來做一些數(shù)據(jù)解析的應用
首先我們創(chuàng)建一個NSObject(data)的類別酗钞,注意,運用runtime一定要導入頭文件#import <objc/runtime.h>

  • 1 將對象轉(zhuǎn)化為字典
    - (NSDictionary *)objectToDic
{
    unsigned int count = 0;
    objc_property_t *propertyList = class_copyPropertyList([self class], &count);
    NSMutableDictionary *propertyDic = [NSMutableDictionary dictionaryWithCapacity:count];
    for (unsigned int i = 0; i < count; i ++) {
        objc_property_t property = propertyList[i];
        NSString *key = [NSString stringWithUTF8String:property_getName(property)];
        id value = [self valueForKey:key];
        if (value == nil) {
            value = [NSNull null];
        }
        else
        {
            value = [self getObjectInternal:value];
        }
        [propertyDic setObject:value forKey:key];
    }
    return propertyDic;
}
//此方法是針對来累,當如果我們的對象中含有其他對象時砚作,我們可以將其對象也轉(zhuǎn)換為字典的形式
    - (id)getObjectInternal:(id)obj
{
    if ([obj isKindOfClass:[NSString class]]||[obj isKindOfClass:[NSNumber class]]||[obj isKindOfClass:[NSNull class]]) {
        return obj;
    }
    
    if ([obj isKindOfClass:[NSArray class]]) {
        NSArray *objArr = obj;
        NSMutableArray *arr = [NSMutableArray arrayWithCapacity:objArr.count];
        for (int i = 0 ; i < objArr.count; i ++) {
            [arr setObject:[self getObjectInternal:[objArr objectAtIndex:i]] atIndexedSubscript:i];
        }
        return arr;
    }
    if ([obj isKindOfClass:[NSDictionary class]]) {
        NSDictionary *objDic = obj;
        NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:[objDic count]];
        for (NSString *key in objDic.allKeys) {
            [dic setValue:[self getObjectInternal:[objDic objectForKey:key]] forKey:key];
        }
        return dic;
    }
    return [obj objectToDic];
}

其中 - (id)getObjectInternal:(id)obj這個方法,是當我們的對象中含有其他對象時嘹锁,我們也可以將其轉(zhuǎn)換為字典的形式葫录,例如:



Person類中含有Cat類,



當我們用Person對象調(diào)用轉(zhuǎn)換為字典的方法時领猾,Person對象中含有的Cat對象也會被轉(zhuǎn)換為字典的形式米同,例如:

其輸出結(jié)果是:



然后我們將其轉(zhuǎn)化為json字符串
    //將字典轉(zhuǎn)化為json
    - (NSString *)dicToJson
{
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:&error];
    NSString *jsonString;
    if (!jsonData) {
        NSLog(@"%@",error);
    }else{
        jsonString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
    NSMutableString *mutStr = [NSMutableString stringWithString:jsonString];
    NSRange range = {0,jsonString.length};
    //去掉字符串中的空格
    [mutStr replaceOccurrencesOfString:@" " withString:@"" options:NSLiteralSearch range:range];
    NSRange range2 = {0,mutStr.length};
    //去掉字符串中的換行符
        [mutStr replaceOccurrencesOfString:@"\n" withString:@"" options:NSLiteralSearch range:range2];
    return mutStr;
}

如果要將json轉(zhuǎn)化為字典則調(diào)用下面的方法

    //json轉(zhuǎn)化為字典
    - (NSDictionary *)jsonToDic
{
    if (self == nil) {
        return nil;
    }
    NSData *jsonData = [(NSString *)self dataUsingEncoding:NSUTF8StringEncoding];
    NSError *err;
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];
    if (err) {
        return nil;
    }
    return dic;
}
  • 2 字典轉(zhuǎn)化為對象
    /**
     字典轉(zhuǎn)對象
     @param dic 字典
     @return 屬性已經(jīng)有值的對象實例
     */
    - (id)dicToObject:(NSDictionary *)dic
    {
        unsigned int count = 0;
        objc_property_t *propertyList = class_copyPropertyList([self class], &count);
        for (unsigned int i = 0 ; i < count; i ++) {
            objc_property_t property = propertyList[i];
              NSString *propertyName = [NSString     stringWithUTF8String:property_getName(property)];
            NSString *propertyType = [NSString     stringWithUTF8String:property_getAttributes(property)];
            if ([[dic allKeys] containsObject:propertyName])
            {
                id value = [dic valueForKey:propertyName];
                if (![value isKindOfClass:[NSNull class]]&&value!=nil) {
                    if ([value isKindOfClass:[NSDictionary class]]) {
                        id pro = [self cretateInstanceByClassName:[self getClassName:propertyType]];
                        [pro dicToObject:value];
                        [self setValue:pro forKey:propertyName];
                    }
                    else
                    {
                        [self setValue:value forKey:propertyName];
                    }
                }
                else
                {
                    value = [NSNull null];
                    [self setValue:value forKey:propertyName];
                }
            }
        }
        return self;
    }
    //獲取屬性類型名字
    - (NSString *)getClassName:(NSString *)typeString
{
    NSArray * attributes = [typeString componentsSeparatedByString:@","];
//    T@"NSDictionary",&,N,V_tempDic
    if (attributes.count>0) {
        NSString * typeAttribute = [attributes objectAtIndex:0];
        if ([typeAttribute hasPrefix:@"T@"] && [typeAttribute length] > 1) {
            NSString * typeClassName = [typeAttribute substringWithRange:NSMakeRange(3, [typeAttribute length]-4)];              return typeClassName;
        }
    }
    
    return typeString;
}
//下面的方法是我們針對當對象中含有某個類時,做的處理
    //根據(jù)類名稱摔竿,創(chuàng)建一個實例對象
    - (id)cretateInstanceByClassName:(NSString *)className
    {
        NSBundle *bundle = [NSBundle mainBundle];
    
        Class aclass = [bundle classNamed:className];
        
        id anInstance = [[aclass alloc] init];
        return anInstance;
}

例如面粮,當我們用上面的對象轉(zhuǎn)字典輸出的字典,經(jīng)過這個字典轉(zhuǎn)對象的方法继低,



其輸出的結(jié)果是我們賦給的catName的名稱@“bb”


  • 3 利用runtime對象序列化熬苍,當然我們要實現(xiàn)NSCoding協(xié)議
    - (instancetype)initWithCoder:(NSCoder *)decoder
    {
        if (self = [super init]) {
            unsigned int count = 0;
            //獲取類中所有成員變量名
            Ivar *ivar = class_copyIvarList([self class], &count);
            for (int i = 0; i<count; i++) {
                Ivar iva = ivar[i];
                const char *name = ivar_getName(iva);
                NSString *strName = [NSString stringWithUTF8String:name];
                //進行解檔取值
                id value = [decoder decodeObjectForKey:strName];
                //利用KVC對屬性賦值
                [self setValue:value forKey:strName];
            }
            free(ivar);
        }
        return self;
    }
    - (void)encodeWithCoder:(NSCoder *)encoder
    {
        unsigned int count;
        Ivar *ivar = class_copyIvarList([self class], &count);
        for (int i=0; i<count; i++) {
            Ivar iv = ivar[i];
            const char *name = ivar_getName(iv);
            NSString *strName = [NSString stringWithUTF8String:name];
            //利用KVC取值
            id value = [self valueForKey:strName];
            [encoder encodeObject:value forKey:strName];
        }
        free(ivar);
    }
  • 4 利用runtime實現(xiàn)UIAlertView的Block回調(diào)
    平時我們用UIAlertView需要使用其代理方法來確定我們的點擊事件,使用起來不夠方便袁翁,新的sdk中UIAlertViewController是使用block來訪問其點擊事件的柴底,那我們就將UIAlertView也封裝成可以利用block來訪問點擊事件的類別
    首先我們需要一個block屬性值
@interface UIAlertView () <UIAlertViewDelegate>
@property (copy, nonatomic) void (^block)(UIAlertView *UIAlertView, NSInteger buttonIndex);
@end

利用數(shù)組來添加按鈕

   - (instancetype)initWithTitle:(NSString *)title message:(NSString *)message
           cancelButtonTitle:(NSString *)cancelButtonTitle
           otherButtonTitles:(NSArray *)otherButtonTitles
{
   self = [self initWithTitle:title message:message
                     delegate:nil
            cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil];
   if (self) {
       for (NSString *otherButtonTitle in otherButtonTitles) {
           [self addButtonWithTitle:otherButtonTitle];
       }
   }

   return self;
}

將alertView與block關(guān)聯(lián)起來(通過runtime)注意:要導入頭文件

import <objc/runtime.h>

這里也就是動態(tài)給alertView添加了block屬性

    - (void)setBlock:(void (^)(UIAlertView *, NSInteger))block
    {
        objc_setAssociatedObject(self, @selector(block), block, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    - (void (^)(UIAlertView *, NSInteger))block
{
    return objc_getAssociatedObject(self, @selector(block));
}

當點擊alertview 的按鈕時

    - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    {
        if (self.block) {
            self.block(alertView, buttonIndex);
        }
    }

下面的方法就是block回調(diào)

    - (void)showUsingBlock:(void (^)(UIAlertView *, NSInteger))block
{
    self.delegate = self;
    self.block = block;
    [self show];
}

通過調(diào)用此方法,得到的block回調(diào)值來判斷當前點擊的按鈕

UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"" delegate:nil cancelButtonTitle:@"cancel" otherButtonTitles:@"ok", nil];
            [alert showUsingBlock:^(UIAlertView *alertView, NSInteger buttonIndex) {
            }];

當我們需要針對ios8之前和之后的版本做適配時粱胜,我們可以寫出一個公共的方法來調(diào)用alertView柄驻,代碼如下:

    + (void)alertTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:    (NSString *)cancelButtonTitle otherButtonTitles:(NSArray *)otherButtonTitles showInVC:    (UIViewController *)vc index:(void (^)(NSInteger))block
    {
            if (IsIOS8Early) {
                UIAlertView *alert = [[UIAlertView alloc]initWithTitle:title message:message cancelButtonTitle:cancelButtonTitle otherButtonTitles:otherButtonTitles];
                [alert showUsingBlock:^(UIAlertView *alertView, NSInteger buttonIndex) {
                block(buttonIndex);
                }];
            }
            else
            {
              UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
            UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
                block(0);
            }];
            [alertVC addAction:cancelAction];
            
            if (otherButtonTitles&&otherButtonTitles.count>0) {
                for (int i = 0; i < otherButtonTitles.count; i ++)
                {
                    UIAlertAction *okAction = [UIAlertAction actionWithTitle:otherButtonTitles[i] style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                        block(i +1);
                    }];
                    [alertVC addAction:okAction];
                }
            }
            [vc presentViewController:alertVC animated:YES completion:nil];
        }
}

如果我們需要對UIActionSheet做出這樣的適配,也可以用上述方法來解決

以上就是runtime的常用示例的介紹焙压,此文轉(zhuǎn)自
「:」http://www.cocoachina.com/ios/20170301/18804.html
若有不理解的凿歼,請?zhí)D(zhuǎn)至此鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末褪迟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子答憔,更是在濱河造成了極大的恐慌味赃,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件虐拓,死亡現(xiàn)場離奇詭異心俗,居然都是意外死亡,警方通過查閱死者的電腦和手機蓉驹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門城榛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人态兴,你說我怎么就攤上這事狠持。” “怎么了瞻润?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵喘垂,是天一觀的道長。 經(jīng)常有香客問我绍撞,道長正勒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任傻铣,我火速辦了婚禮章贞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘非洲。我一直安慰自己鸭限,他們只是感情好,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布两踏。 她就那樣靜靜地躺著里覆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缆瓣。 梳的紋絲不亂的頭發(fā)上喧枷,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音弓坞,去河邊找鬼隧甚。 笑死,一個胖子當著我的面吹牛渡冻,可吹牛的內(nèi)容都是我干的戚扳。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼族吻,長吁一口氣:“原來是場噩夢啊……” “哼帽借!你這毒婦竟也來了珠增?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤砍艾,失蹤者是張志新(化名)和其女友劉穎蒂教,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體脆荷,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡凝垛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蜓谋。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片梦皮。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖桃焕,靈堂內(nèi)的尸體忽然破棺而出剑肯,到底是詐尸還是另有隱情,我是刑警寧澤观堂,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布让网,位于F島的核電站,受9級特大地震影響型将,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜荐虐,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一七兜、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧福扬,春花似錦腕铸、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至汽烦,卻和暖如春涛菠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背撇吞。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工俗冻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人牍颈。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓迄薄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親煮岁。 傳聞我的和親對象是個殘疾皇子讥蔽,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉涣易,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,726評論 0 9
  • 我寶怕是修煉了秒睡神功,前一秒還趴腿上盯著我看冶伞、玩得不亦樂乎新症,下一秒就蹦床上去睡了… 一個不注意還秒換位置 從昨晚...
    不正常生物研究中心閱讀 641評論 0 15
  • 這些事情之前有想到過,但是一下都冒出來碰缔,著實讓人難過了一陣子账劲,同事們覺得90后太年輕,加上剛來公司不會做人金抡,沒有什...
    ppn老頭閱讀 221評論 0 0
  • 原文鏈接 不管是應用秒變幻燈片瀑焦,還是啟動過久被殺,基本都是開發(fā)者必經(jīng)的體驗梗肝。就像沒人希望堵車一樣榛瓮,卡頓永遠是不受用...
    sindri的小巢閱讀 15,698評論 15 152
  • 記得那是九月,剛剛?cè)雽W不久就得選學校干部巫击,一個班選五個禀晓。她成績一般 在班上屬于中上上等,她渴望著能被選上坝锰。恰...
    馬頔的舒傲寒閱讀 254評論 0 0