第二十一節(jié)—KVC(二)原理探索

本文為L(zhǎng)_Ares個(gè)人寫作,以任何形式轉(zhuǎn)載請(qǐng)表明原文出處宣赔。

資料準(zhǔn)備 : AppleDevelopment - KVC文檔

代碼準(zhǔn)備 : 創(chuàng)建一個(gè)Project--->App媳溺。創(chuàng)建JDPerson類。添加NSString類型的成員變量_name罪针,_isNamename黄伊,isName泪酱。

上一節(jié)主要介紹了一些KVC的基本信息,包括知道了KVC本身是一種間接訪問(wèn)機(jī)制还最,提供的是直接訪問(wèn)實(shí)例變量的settergetter墓阀,還有一些常見(jiàn)或者常用的API

本節(jié)依然從文檔入手拓轻,探索KVC的訪問(wèn)模式是怎樣的斯撮。

首先從最最常見(jiàn)的setValueForKey來(lái)看,在我們對(duì)一個(gè)類的某個(gè)屬性利用KVC進(jìn)行賦值的時(shí)候扶叉,比如說(shuō)JDPerson有個(gè)name屬性勿锅,訪問(wèn)的一般是namesetter或者getter,那么這就會(huì)影響對(duì)KVC本身的探索辜梳,所以為了純凈環(huán)境下探索KVC的訪問(wèn)模式粱甫,我就選擇相對(duì)更純凈一點(diǎn)的成員變量方式,而不是通過(guò)屬性的方式作瞄。

一茶宵、KVC的訪問(wèn)模式——設(shè)值過(guò)程

先看一下官方文檔里面對(duì)于KVC訪問(wèn)模式中的Setter的一些知識(shí)。

圖1.0.0.png

根據(jù)自己的理解宗挥,加上翻譯乌庶,可以將官方文檔給出的三個(gè)知識(shí)點(diǎn)總結(jié) :

【前言】 : setValue:forKey:這個(gè)方法的默認(rèn)實(shí)現(xiàn),給定keyvalue作為輸入?yún)?shù),嘗試將名為key的變量的值設(shè)置為value(對(duì)于非對(duì)象屬性,也就是上一節(jié)中見(jiàn)到過(guò)的結(jié)構(gòu)體挣轨,是需要進(jìn)行一步包裝的)韩肝,設(shè)置的流程如下所述 :

  • 第一,先尋找set_set方法领斥,如果找到了就調(diào)用set或者_set方法進(jìn)行賦值筋帖。
  • 第二趟薄,如果沒(méi)有找到set或者_set方法酗电,并且調(diào)用KVC的對(duì)象的類的accessInstanceVariablesDirectly方法返回值是YES魄藕,那么就按照順序查找具有如下名稱的實(shí)例變量(拿name舉例),_name撵术、_isName背率、nameisName嫩与。如果找到這四個(gè)之一寝姿,直接對(duì)其進(jìn)行賦值為value,并且完成賦值划滋。
  • 第三饵筑,如果第一,第二條全都不滿足古毛,那就調(diào)用setValue:forUndefinedKey:翻翩。本來(lái)默認(rèn)是會(huì)拋出異常的,但是NSObject的一個(gè)子類提供了這個(gè)方法來(lái)處理異常的key稻薇。

按照步驟嫂冻,舉個(gè)例子 :

(1). 驗(yàn)證上面的第1點(diǎn) :

JDPerson.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface JDPerosn : NSObject

{
    @public
    NSString *_name;
    NSString *_isName;
    NSString *name;
    NSString *isName;
}

@end

NS_ASSUME_NONNULL_END

JDPerson.m

#import "JDPerosn.h"

@implementation JDPerosn

#pragma mark - 開(kāi)啟或關(guān)閉實(shí)例變量的賦值
//默認(rèn)就是YES,設(shè)置為NO的話塞椎,如果沒(méi)有set或_set的方法桨仿,那么就無(wú)法對(duì)實(shí)例變量進(jìn)行賦值
+(BOOL)accessInstanceVariablesDirectly
{
    return YES;
}

#pragma mark - KVC - setKey流程
//這就是文檔中說(shuō)的set<key>
- (void)setName:(NSString *)name
{
    NSLog(@"%s---%@",__func__,name);
}
//_set<key>
- (void)_setName:(NSString *)name
{
    NSLog(@"%s---%@",__func__,name);
}

- (void)setIsName:(NSString *)name
{
    NSLog(@"%s---%@",__func__,name);
}
@end

ViewController.m

- (void)viewDidLoad {
    
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    JDPerosn *person = [[JDPerosn alloc] init];
    
    //1. KVC - 設(shè)置值的過(guò)程
    [person setValue:@"LJD" forKey:@"name"];
    NSLog(@"%@-%@-%@-%@",person->_name,person->_isName,
                         person->name,person->isName);
    NSLog(@"%@-%@-%@",person->_isName,person->name,person->isName);
    NSLog(@"%@-%@",person->name,person->isName);
    NSLog(@"%@",person->isName);
    
}

執(zhí)行結(jié)果 :


圖1.0.1.png

可以再把- (void)setName:(NSString *)name方法注釋掉,會(huì)發(fā)現(xiàn)調(diào)用- (void)_setName:(NSString *)name案狠,如果把它也注釋掉服傍,則會(huì)調(diào)用- (void)setIsName:(NSString *)name。4個(gè)實(shí)例變量的值依然都是null骂铁。

這就驗(yàn)證了上面說(shuō)的第一點(diǎn)吹零,在利用KVC設(shè)置值的時(shí)候,會(huì)先找到set或者_set方法對(duì)其進(jìn)行賦值拉庵。

(2). 驗(yàn)證上面的第二點(diǎn) :

JDPerson.m中的有關(guān)set的3個(gè)方法全部注釋掉灿椅,然后讓accessInstanceVariablesDirectly變成return NO。其余代碼不變钞支,再執(zhí)行茫蛹。結(jié)果如下圖 :

圖1.0.2.png

所以驗(yàn)證了第二點(diǎn)中,沒(méi)有set_set方法的時(shí)候烁挟,accessInstanceVariablesDirectly要設(shè)置成YES才可以婴洼。

然后將accessInstanceVariablesDirectly重新設(shè)置成YES。再執(zhí)行撼嗓。結(jié)果如下圖 :

圖1.0.2.png

驗(yàn)證了第二點(diǎn)中會(huì)先給_name賦值柬采。
然后依次的注釋掉JDPerson.h中的成員變量_name欢唾、_isNamename警没。
就會(huì)驗(yàn)證第二點(diǎn)中匈辱,KVC賦值同名變量的順序是_name_isName杀迹、nameisName押搪。

第三點(diǎn)我就不驗(yàn)證了树酪,因?yàn)榻?jīng)常會(huì)用到,比如字典轉(zhuǎn)模型的時(shí)候大州,大家應(yīng)該常用续语。

另外,KVC為什么有第二點(diǎn)這種設(shè)計(jì)呢厦画?因?yàn)樵诰幾g期的時(shí)候疮茄,底層也會(huì)生成一些這樣的變量,比如之前我們?cè)谇懊娴恼鹿?jié)進(jìn)行clang.m文件編譯成.cpp文件的時(shí)候根暑,有一些屬性就會(huì)變成了_xxx的形式的成員變量力试,或者BOOL類型的值會(huì)變成isXXX的形式,這也是因?yàn)檫\(yùn)行時(shí)的特性造成的排嫌。

總結(jié) :

KVC設(shè)值流程.png

二畸裳、KVC的訪問(wèn)模式——取值過(guò)程

一樣先來(lái)查閱官方文檔,然后根據(jù)自己的理解加上翻譯淳地,再做總結(jié)怖糊。

圖2.0.0.png

明顯getter的過(guò)程比較多。還是按照官方的分成六點(diǎn)颇象。

【前言】 : valueForKey:的默認(rèn)實(shí)現(xiàn)伍伤,給定key作為輸入?yún)?shù),執(zhí)行下列程序遣钳,從接收valueForKey:調(diào)用的類實(shí)例的內(nèi)部操作扰魂。

  • 第一,按照順序查找耍贾,是否有get<Key>, <key>, is<Key>,_<key>這些方法阅爽。如果找到了就調(diào)用它,并且在下面的第五點(diǎn)中處理結(jié)果荐开。如果找不到就進(jìn)入第二點(diǎn)付翁。
  • 第二,如果第一點(diǎn)中的4個(gè)get方法都沒(méi)實(shí)現(xiàn)晃听,在實(shí)例方法中查找countOf<Key>百侧、objectIn<Key>AtIndex:還有<key>AtIndexes:方法砰识。
    • 如果countOf<Key>存在,并且objectIn<Key>AtIndex:<key>AtIndexes:中至少一個(gè)方法存在佣渴,那么創(chuàng)建一個(gè)響應(yīng)所有的NSArray方法的集合代理對(duì)象辫狼,并且返回這個(gè)集合代理對(duì)象
    • 否則進(jìn)入第三點(diǎn)辛润。
    • 集合代理對(duì)象隨后會(huì)將所有接收到的NSArray的消息都轉(zhuǎn)換為countOf膨处、objectInAtIndex:AtIndexes:的一些組合,這些組合將消息發(fā)送給創(chuàng)建它的符合KVC機(jī)制的對(duì)象砂竖。
    • 如果原始對(duì)象還實(shí)現(xiàn)了一個(gè)名為get:range:的可選方法真椿,代理對(duì)象也會(huì)在適當(dāng)?shù)臅r(shí)候使用它。
    • 實(shí)際上乎澄,代理對(duì)象與和KVC兼容的對(duì)象一起工作突硝,允許底層屬性像NSArray一樣工作,即使它不是NSArray置济。
  • 第三解恰,如果沒(méi)有找到第二點(diǎn)中的3個(gè)方法,則同時(shí)查找countOf <Key>浙于,enumeratorOf<Key>和memberOf<Key>這三個(gè)方法护盈,
    • 如果這三個(gè)方法都找到了,創(chuàng)建一個(gè)響應(yīng)所有NSSet方法的集合代理對(duì)象路媚,并將集合代理對(duì)象返還黄琼。
    • 如果這三個(gè)方法也沒(méi)找到,那么就直接進(jìn)入第四點(diǎn)整慎。
    • 集合代理對(duì)象隨后將它接收到的任何NSSet消息轉(zhuǎn)換為countOf脏款、enumeratorOfmemberOf:消息的組合,并發(fā)送給創(chuàng)建它的對(duì)象裤园。
    • 實(shí)際上撤师,代理對(duì)象與遵循KVC的對(duì)象一起工作,允許底層屬性像NSSet一樣運(yùn)行拧揽,即使它不是NSSet剃盾。
  • 第四,如果get方法和集合方法都沒(méi)找到淤袜,并且接收者的類方法accessinstancevariables返回YES痒谴,則按照順序查找_<key>, _is<Key>, <key>, is<Key>變量。如果找到铡羡,直接獲取實(shí)例變量的值并進(jìn)入第五點(diǎn)积蔚。否則,進(jìn)入第六點(diǎn)烦周。
  • 第五尽爆,根據(jù)搜索到的屬性值的類型怎顾,返回不同的結(jié)果
    • 如果是對(duì)象指針,則直接返回結(jié)果漱贱。
    • 如果值是NSNumber支持的標(biāo)量類型槐雾,將其存儲(chǔ)在NSNumber實(shí)例中并返回。
    • 如果結(jié)果是NSNumber不支持的標(biāo)量類型幅狮,轉(zhuǎn)換為NSValue對(duì)象并返回它募强。
  • 第六,如果上面的所有方法都沒(méi)有找到彪笼,調(diào)用setValue:forUndefinedKey:钻注。默認(rèn)情況下會(huì)拋出異常,可以執(zhí)行這個(gè)方法來(lái)處理配猫。

因?yàn)檫@里明顯的能看出來(lái),簡(jiǎn)單類型取值和集合類型是不一樣的杏死,先看簡(jiǎn)單類型泵肄,按照步驟,舉個(gè)例子 :

(1). 驗(yàn)證上面的第1點(diǎn)和第4點(diǎn) :

JDPerson.h不發(fā)生改變淑翼。

JDPerson.m

#pragma mark - 開(kāi)啟或關(guān)閉實(shí)例變量的賦值
//默認(rèn)就是YES腐巢,設(shè)置為NO的話,如果沒(méi)有set或_set的方法玄括,那么就無(wú)法對(duì)實(shí)例變量進(jìn)行賦值
+(BOOL)accessInstanceVariablesDirectly
{
    return YES;
}

#pragma mark - KVC - getKey流程
//文檔中說(shuō)的get<key>
- (NSString *)getName
{
    return NSStringFromSelector(_cmd);
}
//\<key>
- (NSString *)name
{
    return NSStringFromSelector(_cmd);
}
//is<key>
- (NSString *)isName
{
    return NSStringFromSelector(_cmd);
}
//_<key>
- (NSString *)_name
{
    return NSStringFromSelector(_cmd);
}

ViewController.m

- (void)viewDidLoad {
    
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    [self jd_kvc_getter];
    
    
}

- (void)jd_kvc_getter
{
    JDPerosn *person = [[JDPerosn alloc] init];
    person->_name   = @"_name";
    person->_isName = @"_isName";
    person->name    = @"name";
    person->isName  = @"isName";
    NSLog(@"KVC取值---%@",[person valueForKey:@"name"]);
}

- (void)jd_kvc_setter
{
    JDPerosn *person = [[JDPerosn alloc] init];
    
    //1. KVC - 設(shè)置值的過(guò)程
    [person setValue:@"LJD" forKey:@"name"];
    NSLog(@"%@-%@-%@-%@",person->_name,person->_isName,
                         person->name,person->isName);
    NSLog(@"%@-%@-%@",person->_isName,person->name,person->isName);
    NSLog(@"%@-%@",person->name,person->isName);
    NSLog(@"%@",person->isName);
}

執(zhí)行結(jié)果 :

圖2.0.1.png

然后依次注釋掉4個(gè)get方法冯丙,就可以驗(yàn)證第一點(diǎn),并且全部注釋掉以后會(huì)走到第四點(diǎn)遭京,順便把第四點(diǎn)也驗(yàn)證了胃惜。

從驗(yàn)證可以看出,valueForKey先找的不是我們對(duì)變量的賦值哪雕,而是先找的getter方法船殉,只有getter方法沒(méi)有實(shí)現(xiàn)的情況下,才會(huì)找到變量直接拿值斯嚎。簡(jiǎn)單類型也就是非集合類型的只會(huì)找到第一點(diǎn)第四點(diǎn)如果有錯(cuò)誤會(huì)直接到第六點(diǎn)利虫。

(1). 驗(yàn)證上面的第2點(diǎn)和第3點(diǎn) :

因?yàn)榈诙谌c(diǎn)的原理是一樣的堡僻,這里就拿更常見(jiàn)的數(shù)組來(lái)說(shuō)明糠惫,NSSet的例子會(huì)放出來(lái),但是就不說(shuō)明了钉疫。

JDPerson.h

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface JDPerosn : NSObject

{
    @public
    NSString *_name;
    NSString *_isName;
    NSString *name;
    NSString *isName;
    NSArray  *arr;
    NSSet    *set;
}

@end

NS_ASSUME_NONNULL_END

JDPerson.m

#pragma mark - KVC - 正常的數(shù)組取值
- (NSUInteger)countOfArr
{
    NSLog(@"%s",__func__);
    return [arr count];
}

- (id)objectInArrAtIndex:(NSUInteger)index
{
    NSLog(@"%s",__func__);
    return [NSString stringWithFormat:@"objectInArrAtIndex : %lu",index];
}

#pragma mark - KVC - 正常的集合取值
- (NSUInteger)countOfSet
{
    NSLog(@"%s",__func__);
    return [set count];
}

- (id)memberOfSet:(id)object
{
    NSLog(@"%s",__func__);
    return [set containsObject:object] ? object : nil;
}

- (id)enumeratorOfSet
{
    NSLog(@"%s",__func__);
    return [set objectEnumerator];
}



#pragma mark - KVC - 沒(méi)有Pens硼讽,但是我有方法,一樣可以取值數(shù)組
- (NSUInteger)countOfPens
{
    NSLog(@"%s",__func__);
    return [arr count];
}

- (id)objectInPensAtIndex:(NSUInteger)index
{
    NSLog(@"%s",__func__);
    return [NSString stringWithFormat:@"objectInPensAtIndex %lu", index];
}

- (id)pensAtIndexes:(NSUInteger)index
{
    NSLog(@"%s",__func__);
    return [NSString stringWithFormat:@"pensAtIndexes %lu", index];
}

#pragma mark - KVC - 沒(méi)有books陌选,但是我有方法理郑,一樣可以取值集合
// 個(gè)數(shù)
- (NSUInteger)countOfBooks{
    NSLog(@"%s",__func__);
    return [arr count];
}

// 是否包含這個(gè)成員對(duì)象
- (id)memberOfBooks:(id)object {
    NSLog(@"%s",__func__);
    return [set containsObject:object] ? object : nil;
}

// 迭代器
- (id)enumeratorOfBooks {
    // objectEnumerator
    NSLog(@"來(lái)了 迭代編譯");
    return [arr reverseObjectEnumerator];
}

ViewController.m

- (void)jd_kvc_array_and_set
{
    JDPerosn *person = [[JDPerosn alloc] init];
    person->arr = @[@"pen0", @"pen1", @"pen2", @"pen3"];
    NSLog(@"正常的數(shù)組取值 : %@",[person valueForKey:@"arr"]);
    NSArray *array = [person valueForKey:@"pens"];
    NSLog(@"就算沒(méi)有pens蹄溉,只要在類中實(shí)現(xiàn)了方法也可以objectAtIndex : %@",[array objectAtIndex:1]);
    NSLog(@"就算沒(méi)有pens,只要在類中實(shí)現(xiàn)了方法也可以containsObject : %d",[array containsObject:@"pen1"]);

    person->set = [NSSet setWithArray:person->arr];
    NSLog(@"正常的集合取值 : %@",[person valueForKey:@"set"]);
    NSSet *set = [person valueForKey:@"books"];
    [set enumerateObjectsUsingBlock:^(id  _Nonnull obj, BOOL * _Nonnull stop) {
        NSLog(@"set遍歷 %@",obj);
    }];
    
}

執(zhí)行結(jié)果就不貼圖了您炉,太長(zhǎng)了柒爵,可以自己運(yùn)行一下,會(huì)發(fā)現(xiàn)count的方法都會(huì)打印兩次赚爵,也證明了的確是存在著代理集合的棉胀。所以驗(yàn)證也是符合的。

總結(jié) :

KVCvalueForKey的流程主要還是分了簡(jiǎn)單對(duì)象和集合對(duì)象冀膝,簡(jiǎn)單對(duì)象的取值和其setValueForKey是一樣的唁奢。而集合對(duì)象則多需要幾步驟,但是可以防止取到不認(rèn)識(shí)的key窝剖,也可以修改取值的結(jié)果麻掸。

kvc-getter簡(jiǎn)單類型流程圖.png

三、KVC的一些特殊功能

1. KVC有自動(dòng)轉(zhuǎn)換類型的功能赐纱。

JDPerson.h :

typedef struct {
    float x, y, z;
} ThreeFloats;

@interface JDPerosn : NSObject

{
    @public
    NSString *_name;
    NSString *_isName;
    NSString *name;
    NSString *isName;
    NSArray  *arr;
    NSSet    *set;
    int      age;
    ThreeFloats  threeFloats;
}

@end
1.1 NSNumber支持的標(biāo)量類型
    //1. NSNumber支持的標(biāo)量類型
    JDPerosn *person = [[JDPerosn alloc] init];
    [person setValue:@18 forKey:@"age"];
    NSLog(@"%@-%@",[person valueForKey:@"age"],[[person valueForKey:@"age"] class]);//__NSCFNumber
    [person setValue:@"20" forKey:@"age"];
    NSLog(@"%@-%@",[person valueForKey:@"age"],[[person valueForKey:@"age"] class]);//__NSCFNumber
圖3.1.0.png

證明了 : KVC在對(duì)已知類型的value設(shè)置的時(shí)候脊奋,如果類型是NSNumber支持的標(biāo)量類型,則會(huì)將value存儲(chǔ)到NSNumber的實(shí)例中疙描,在取值的時(shí)候返回NSNumber實(shí)例诚隙。

1.2 NSNumber不支持的標(biāo)量類型
    //2. NSNumber不支持的標(biāo)量類型
    ThreeFloats floats = {1.f, 2.f, 3.f};
    NSValue *value  = [NSValue valueWithBytes:&floats objCType:@encode(ThreeFloats)];
    [person setValue:value forKey:@"threeFloats"];
    NSLog(@"%@-%@",[person valueForKey:@"threeFloats"],[[person valueForKey:@"threeFloats"] class]);//NSConcreteValue
圖3.1.1.png

證明了 : KVC存儲(chǔ)的類型如果是NSNumber不支持的標(biāo)量類型,那么就要轉(zhuǎn)換為NSValue存儲(chǔ)并且返回起胰。

2. 空值

JDPerson.m中添加KVC監(jiān)控 :

- (void)setNilValueForKey:(NSString *)key{
    NSLog(@"設(shè)置 %@ 是空值",key);
}

- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
    NSLog(@"沒(méi)有這個(gè)key : %@",key);
}

- (id)valueForUndefinedKey:(NSString *)key{
    NSLog(@"沒(méi)有這個(gè)key : %@ - 給你一個(gè)其他的吧,別奔潰了!",key);
    return @"LJD";
}

2.1 key存在久又,value設(shè)置為空

-(void)viewDidLoad中 :

    JDPerosn *person = [[JDPerosn alloc] init];
    [person setValue:nil forKey:@"age"]; // subject不會(huì)走 - 官方注釋里面說(shuō)只對(duì) NSNumber - NSValue
    [person setValue:nil forKey:@"name"];
圖3.2.0.png
圖3.2.1.png

證明了 : KVC中的setNilValueForKey只監(jiān)控NSNumberNSValue的結(jié)構(gòu)體,不會(huì)監(jiān)控到其他類型效五。

2.2 key不存在地消,value設(shè)置為空
[person setValue:nil forKey:@"LJD"];  //LJD不是已知的key

可以實(shí)現(xiàn)這個(gè) :

- (void)setValue:(id)value forUndefinedKey:(NSString *)key

進(jìn)行監(jiān)控。

圖3.2.2.png
2.3 key為空
NSLog(@"%@",[person valueForKey:@"KC"]);  //KC是不存在的key

這個(gè)可以使用 :

- (id)valueForUndefinedKey:(NSString *)key

進(jìn)行監(jiān)控火俄。

圖3.2.3.png

3. 鍵值驗(yàn)證

JDPerson.m中添加 :

- (BOOL)validateValue:(inout id  _Nullable __autoreleasing *)ioValue forKey:(NSString *)inKey error:(out NSError *__autoreleasing  _Nullable *)outError{
    if([inKey isEqualToString:@"name"]){
        [self setValue:[NSString stringWithFormat:@"可以修改一下: %@",*ioValue] forKey:inKey];
        return YES;
    }
    *outError = [[NSError alloc]initWithDomain:[NSString stringWithFormat:@"%@ 不是 %@ 的屬性",inKey,self] code:16688 userInfo:nil];
    return NO;
}

viewDidLoad中 :

    NSError *error;
    NSString *name = @"LJD";
    JDPerosn *person = [[JDPerosn alloc] init];
    if (![person validateValue:&name forKey:@"names" error:&error]) {
        NSLog(@"%@",error);
    }else{
        NSLog(@"%@",[person valueForKey:@"name"]);
    }

結(jié)果 :

圖3.3.0.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末犯建,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瓜客,更是在濱河造成了極大的恐慌适瓦,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谱仪,死亡現(xiàn)場(chǎng)離奇詭異玻熙,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)疯攒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門嗦随,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事枚尼√悖” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵署恍,是天一觀的道長(zhǎng)崎溃。 經(jīng)常有香客問(wèn)我,道長(zhǎng)盯质,這世上最難降的妖魔是什么袁串? 我笑而不...
    開(kāi)封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮呼巷,結(jié)果婚禮上囱修,老公的妹妹穿的比我還像新娘。我一直安慰自己王悍,他們只是感情好破镰,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著压储,像睡著了一般啤咽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上渠脉,一...
    開(kāi)封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音瓶佳,去河邊找鬼芋膘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛霸饲,可吹牛的內(nèi)容都是我干的为朋。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼厚脉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼习寸!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起傻工,我...
    開(kāi)封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤霞溪,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后中捆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體鸯匹,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年泄伪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了殴蓬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蟋滴,死狀恐怖染厅,靈堂內(nèi)的尸體忽然破棺而出痘绎,到底是詐尸還是另有隱情,我是刑警寧澤肖粮,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布孤页,位于F島的核電站,受9級(jí)特大地震影響尿赚,放射性物質(zhì)發(fā)生泄漏散庶。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一凌净、第九天 我趴在偏房一處隱蔽的房頂上張望悲龟。 院中可真熱鬧,春花似錦冰寻、人聲如沸须教。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)轻腺。三九已至,卻和暖如春划乖,著一層夾襖步出監(jiān)牢的瞬間贬养,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工琴庵, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留误算,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓迷殿,卻偏偏與公主長(zhǎng)得像儿礼,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子庆寺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345