第三遍看Core Data Programming Guide

雖然從接觸iOS開發(fā)開始湾趾,做的每一個(gè)項(xiàng)目都在用Core Data芭商,但是一些比較底層的東西都是boss寫的或者用的是Restkit這個(gè)開源項(xiàng)目。所以雖然之前看過兩遍Core Data Programming Guide搀缠,還有很多不理解或者不熟練或者做得不好的地方铛楣。所以第三遍看,想要把以前不理解的地方弄得清晰一點(diǎn)艺普。

Core Data框架是獨(dú)立于Cocoa的簸州,所以對(duì)于沒有界面的程序,也可以應(yīng)用Core Data歧譬。為了方便勿侯,這里我自己試驗(yàn)的代碼都是在一個(gè)Command Line tool工程里的0.0


關(guān)于Persistent Stack



對(duì)象和外部數(shù)據(jù)存儲(chǔ),這兩者之間的媒介缴罗,被整體叫做persistence stack。其中祭埂,managed object context位于棧頂面氓,persistent object store位于棧底,中間的是persistent store coordinator蛆橡。

Persistent stack

實(shí)際上舌界,是persistent store coordinator決定著這個(gè)棧。它使用了facade模式泰演,使得棧底的多個(gè)persistent store呻拌,在呈現(xiàn)給context的時(shí)候,就像一個(gè)整體一樣睦焕。
一個(gè)coordinator只能和一個(gè)managed object model相關(guān)聯(lián)藐握。


關(guān)于Managed Object Model



一個(gè)managed object model是NSManagedObjectModel類的實(shí)例。它描述了第三方app中需要使用到的一系列entity垃喊,和多個(gè)entity之間的關(guān)系猾普。
一個(gè)model中可能有很多NSEntityDescription對(duì)象來代表這個(gè)model的各個(gè)entity。對(duì)于每個(gè)entity來說本谜,有兩個(gè)很重要的特性初家,一個(gè)是這個(gè)entity的名字,另一個(gè)是在運(yùn)行時(shí),表示這個(gè)entity的類的名字溜在。

一個(gè)entity可能會(huì)有attribute陌知、relationship,也可能有fetched property掖肋,這三者統(tǒng)稱為property仆葡。需要注意的是,property不能和NSObject或NSManagedObject已有的方法名重疊培遵,比如浙芙,不能給某個(gè)property起名為“description”。
比較特殊的一種property叫做transient property籽腕,它是不會(huì)被保存到persistent store中去的嗡呼。

多個(gè)entity之間可能會(huì)有繼承關(guān)系,也可能某個(gè)entity會(huì)被指定為抽象的皇耗。

大多數(shù)model中的元素(比如entity南窗、attribute、relationship)都會(huì)有一個(gè)對(duì)應(yīng)的user info郎楼。


創(chuàng)建一個(gè)model


使用Xcode創(chuàng)建model



在Xcode中万伤,選擇File->New->File->Core Data->Data Model就可以創(chuàng)建一個(gè)擴(kuò)展名為.xcdatamodeld的“源文件”了(實(shí)際上應(yīng)該是一個(gè)目錄)。其中包含了一個(gè)擴(kuò)展名為.xcdatamodel的“源文件”呜袁〉新颍可以使用Xcode的Core Data model editor,在xcdatamodel文件中編輯model的內(nèi)容阶界,比如其中包含什么樣的entity虹钮,每個(gè)entity中有什么樣的attribute,以及各個(gè)entity之間的關(guān)系膘融,等等芙粱。

如果App更新時(shí),需要對(duì)model進(jìn)行改動(dòng)氧映,就需要?jiǎng)?chuàng)建一個(gè)新的model version春畔。在Xcode中,選中xcdatamodeld岛都,選擇Editor->Add Model Version律姨,可以繼續(xù)創(chuàng)建其中的xcdatamodel“源文件”。

除了model中關(guān)于entity和property的各種信息臼疫,xcdatamodel還會(huì)包含一些其他信息线召,比如繪制的圖表的寬高排列之類的,但這些信息在運(yùn)行時(shí)并沒有什么意義多矮。所以缓淹,model文件的編譯工具momc會(huì)把運(yùn)行時(shí)沒有意義的信息去掉哈打,將xcdatamodel文件編譯成mom文件,將xcdatamodeld目錄編譯成momd目錄讯壶。

在Xcode中找到編譯好的.app文件料仗,右鍵Show in Finder,打開里面的內(nèi)容后伏蚊,可以看到其中的.momd文件夾立轧,和這個(gè)文件夾里面的.mom文件。

如果寫的是iOS上的app躏吊,則在需要程序員自己加載model文件氛改。有這樣兩種方法:

  1. 使用NSManagedObjectModel的initWithContentOfURL:方法。
    這是一種比較普遍使用的方法比伏。
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:modelName withExtension:@"momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
  1. 使用mergedModelFromBundles:方法.
    如果參數(shù)是nil胜卤,則會(huì)搜索main bundle,把其中的所有model給merge起來赁项。
在代碼中創(chuàng)建\修改model



在model被一個(gè)managed object context或者一個(gè)persistent store coordinator使用之前葛躏,這個(gè)model是可以在代碼中被修改的。這允許程序員動(dòng)態(tài)的創(chuàng)建或修改model悠菜。

試了一下在代碼中創(chuàng)建model:

NSManagedObjectModel *model = [[NSManagedObjectModel alloc] init];
NSEntityDescription *launchInfoEntity = [[NSEntityDescription alloc] init];
[launchInfoEntity setName:@"LaunchInfo"];

NSAttributeDescription *dateAttribute = [[NSAttributeDescription alloc] init];
[dateAttribute setName:@"date"];
[dateAttribute setAttributeType:NSDateAttributeType];
[dateAttribute setOptional:NO];

[launchInfoEntity setProperties:@[dateAttribute]];

[model setEntities:@[launchInfoEntity]];

如果model是在被一個(gè)managed object context或者一個(gè)persistent store coordinator使用之后舰攒,受到改動(dòng),則會(huì)拋出exception:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Can't modify an immutable model.'

Fetch Request Template



程序員可以使用NSFetchRequest類來描述從持久化存儲(chǔ)中取得一些對(duì)象的請(qǐng)求悔醋。在實(shí)際的開發(fā)中摩窃,同樣或相似的請(qǐng)求往往會(huì)被執(zhí)行多次,所以芬骄,程序員可以自定義一些fetch request template猾愿,并把它們存到model中〉旅担可以使用Xcode的Core Data model editor,也可以在代碼中定義椎麦。

使用Core Date model editor定義fetch request template



Editor->Add FetchRequest來新建一個(gè)fetch request宰僧。

填寫Predicate,可以使用變量观挎。右邊欄還可以指定一些高級(jí)選項(xiàng)琴儿。

指定Predicate

在需要使用時(shí),只要在代碼中取出對(duì)應(yīng)的fetch request template:

NSManagedObjectModel *managedObjectModel = [[context persistentStoreCoordinator] managedObjectModel];
NSFetchRequest *fetchRequest = [managedObjectModel fetchRequestFromTemplateWithName:@"fetchLaunchInfoBeforeSomeDate"
                                                              substitutionVariables:@{@"DATE" : [NSDate date]}];
NSArray *fetchResult = [context executeFetchRequest:fetchRequest error:&error];

就可以正常使用了嘁捷。

直接在代碼中創(chuàng)建fetch request template



也可以完全動(dòng)態(tài)的創(chuàng)建fetch request template:

NSManagedObjectModel *managedObjectModel = [[context persistentStoreCoordinator] managedObjectModel];
NSFetchRequest *fetchRequestTemplate = [[NSFetchRequest alloc] initWithEntityName:@"LaunchInfo"];
[fetchRequestTemplate setPredicate:[NSPredicate predicateWithFormat:@"date > $DATE"]];
[managedObjectModel setFetchRequestTemplate:fetchRequestTemplate forName:@"fetchLaunchInfoAfterSomeDate"];

關(guān)于Configuration



如果程序員想要把不同的entity存放到不同的persistent store中去造成,應(yīng)該怎么做呢?一個(gè)coordinator只能對(duì)應(yīng)一個(gè)managed object model雄嚣,所以在默認(rèn)情況下晒屎,每一個(gè)與這個(gè)coordinator相關(guān)聯(lián)的persistent store喘蟆,都存放了同樣的entity。為了避免這樣的限制鼓鲁,可以使用Configuration來指定每個(gè)persistent store中應(yīng)該存放哪些entity蕴轨。
指定了Configuration之后,當(dāng)程序員取這些對(duì)象的時(shí)候骇吭,它們會(huì)自動(dòng)從不同的文件中被取出橙弱;保存時(shí),它們也會(huì)被自動(dòng)保存到不同的文件燥狰。

一個(gè)configuration由名字和若干entity組成棘脐。可以在代碼中用

setEntities:forConfiguration:

方法動(dòng)態(tài)的定義configuration龙致;

也可以在Core Data editor tool中定義:


指定Configuration

每當(dāng)給coordinator增加persistent store的時(shí)候蛀缝,只用在configuration參數(shù)中指定對(duì)應(yīng)的configuration即可以使用:

if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType
                               configuration:@"ExitInfoConfiguration"
                                         URL:exitInfoStoreURL
                                     options:nil
                                       error:&error]) {
    //Handle error
}

if (![coordinator addPersistentStoreWithType:NSSQLiteStoreType
                               configuration:@"LaunchInfoConfiguration"
                                         URL:launchInfoStoreURL
                                     options:nil
                                       error:&error]) {
    //Handle error
}

關(guān)于Managed Object



一個(gè)managed object代表的是一個(gè)entity的實(shí)例。

每個(gè)managed object與一個(gè)managed object context相關(guān)聯(lián)净当。在一個(gè)特定的context中内斯,持久化存儲(chǔ)中的一個(gè)特定的記錄,只能有一個(gè)對(duì)應(yīng)的managed object像啼,這種技術(shù)叫做Uniquing俘闯。但是,也可能有多個(gè)context忽冻,每個(gè)context都持有一個(gè)表示同一條記錄的managed object真朗。


關(guān)于accessor方法



可以使用Xcode根據(jù)xcdatamodel中的內(nèi)容自動(dòng)生成NSManagedObject的子類。在子類的實(shí)現(xiàn)中僧诚,我們能看到遮婶,property被@dynamic修飾了。那是因?yàn)镃ore Data會(huì)在運(yùn)行時(shí)動(dòng)態(tài)生成accessor方法湖笨,這樣生成的accessor方法是比較高效的旗扑,也就是說,程序員一般不需要寫自定義的accessor方法慈省。

也可以通過key-value的形式來獲取或設(shè)置attributes的值臀防,但是在性能上KVC不如accessor方法,所以只應(yīng)該在必要的情況下使用边败。

如果這個(gè)managed object有to-many relationship袱衷,很多時(shí)候,程序員可能會(huì)需要增添笑窜、刪除或改動(dòng)這個(gè)to-many relationship中的某幾個(gè)元素致燥,這個(gè)時(shí)候則應(yīng)該使用mutableSetValueForKey:方法或者動(dòng)態(tài)生成的relationship mutator方法。


關(guān)于Managed Object的生命周期



一個(gè)managed object的生命周期和標(biāo)準(zhǔn)的Cocoa對(duì)象的生命周期不太一樣排截,因?yàn)槟鞘怯蒀ore Data來管理的嫌蚤。一個(gè)managed object表示的數(shù)據(jù)的生命周期辐益,和這個(gè)manged object的實(shí)例的生命周期是獨(dú)立的。

可以通過一個(gè)managed object得到它所在的context搬葬,也可以通過一個(gè)context得到其中的managed object荷腊。但是默認(rèn)情況下,managed object和context之間的引用是弱引用急凰。然而有一種例外情況女仰,context會(huì)對(duì)“被改動(dòng)過的”managed object持強(qiáng)引用,這里的改動(dòng)包括插入抡锈、刪除和修改疾忍,直到context被save、reset或者rollback床三。同時(shí)一罩,undo manager也會(huì)用強(qiáng)引用來維持被改動(dòng)過的managed object。
可以用setRetainsRegisteredObjects:方法改變這種默認(rèn)情況撇簿,使得context對(duì)managed object持強(qiáng)引用聂渊。

當(dāng)managed object有relationship的時(shí)候,它會(huì)對(duì)這個(gè)關(guān)聯(lián)的對(duì)象持強(qiáng)引用四瘫,這也意味著可能有強(qiáng)引用循環(huán)出現(xiàn)汉嗽。所以,當(dāng)使用完一個(gè)managed object的時(shí)候找蜜,應(yīng)該用refreshObject:mergeChanges:方法讓它成為一個(gè)fault饼暑。

在一個(gè)managed object被創(chuàng)建的時(shí)候,其中每個(gè)property的值是在對(duì)應(yīng)的entity中的default value洗做。如果需要做一些自定義的初始化弓叛,建議重寫:awakeFromInsert或者awakeFromFetch方法。

其中诚纸,awakeFromInsert會(huì)在調(diào)用了initWithEntity:insertIntoManagedObjectContext:或者insertNewObjectForEntityForName:inManagedObjectContext:方法之后立刻被調(diào)用撰筷。所以,重寫這個(gè)方法畦徘,主要是可以為managed object中的property提供特殊的默認(rèn)值毕籽,比如這個(gè)對(duì)象被創(chuàng)建的時(shí)間。

awakeFromFetch方法會(huì)在managed object從一個(gè)持久化存儲(chǔ)中被取出來的時(shí)候調(diào)用旧烧。重寫這個(gè)方法影钉,可以用于建立transient值和緩存画髓。需要注意的是掘剪,如果在這個(gè)方法中,改變了managed object中某些property奈虾,context不會(huì)被認(rèn)為是dirty的夺谁。這也就意味著不應(yīng)該在這個(gè)方法中操縱relationship廉赔,因?yàn)槟繕?biāo)對(duì)象不會(huì)為此做出應(yīng)有的改變。

initWithEntity:insertIntoManagedObjectContext: 這個(gè)方法也可以重寫匾鸥,但是并不鼓勵(lì)這樣做蜡塌。因?yàn)樵谥貙懙倪@個(gè)方法中改變的狀態(tài),可能會(huì)不支持undo和redo勿负。

在需要“析構(gòu)”的時(shí)候馏艾,不應(yīng)該重寫dealloc方法,而是應(yīng)該重寫didTurnInfoFault方法奴愉。這個(gè)方法會(huì)在managed object變成fault的時(shí)候被調(diào)用琅摩,也就是說會(huì)比真正的析構(gòu)早一些。


關(guān)于Relationship



大多數(shù)的relationship天生就是雙向的(一個(gè)主要的例外就是fetched property)锭硼。一般來說房资,在使用Core Data的時(shí)候,也應(yīng)該為relationship指定反向關(guān)系檀头,這樣可以確保object graph的一致性轰异。

一個(gè)relationship是有delete rule的。這指定了當(dāng)這個(gè)對(duì)象即將被刪除的時(shí)候應(yīng)該發(fā)生的行為暑始。有這樣幾種delete rule:

  1. Deny
    如果至少有一個(gè)relationship的目的對(duì)象存在搭独,源對(duì)象是不能被刪除的;

  2. Nullify
    在刪除當(dāng)前對(duì)象的同時(shí)蒋荚,將relationship的目的對(duì)象的反向關(guān)系設(shè)置為null戳稽;

  3. Cascade
    在刪除當(dāng)前對(duì)象的同時(shí),也刪除relationship的目的對(duì)象期升;

  4. No Action
    在刪除當(dāng)前對(duì)象的同時(shí)惊奇,對(duì)relationship的目的對(duì)象不做任何操作。在使用這個(gè)delete rule的時(shí)候播赁,程序員有責(zé)任自行維護(hù)object graph颂郎,所以應(yīng)該將對(duì)應(yīng)的反向關(guān)系設(shè)置成有意義的值。


關(guān)于Object ID



一個(gè)NSManagedObjectID對(duì)象是managed object的全局ID容为。Object ID有臨時(shí)和持久之分乓序。當(dāng)一個(gè)managed object剛剛被創(chuàng)建時(shí),它將獲得一個(gè)臨時(shí)的object ID坎背;只有當(dāng)它被保存到持久化存儲(chǔ)中時(shí)替劈,它才會(huì)被賦予一個(gè)持久的ID。

Object ID也可以被轉(zhuǎn)化成URI得滤≡上祝可以使用 managedObjectIDForURIRepresentation:方法或objectWithID:方法通過URI或ID獲取對(duì)應(yīng)的managed object。


關(guān)于Validation



Validation機(jī)制用于檢驗(yàn)managed object的property的值是否滿足一定條件懂更。有兩種validation的類型眨业,分別是:

  1. property層次的validation
  2. property之間的validation

Core Data允許程序員在managed object model中設(shè)定簡單的validation邏輯急膀。比如,可以設(shè)置數(shù)字和日期的最大最小值龄捡,可以設(shè)置字符串的最大最小長度卓嫂、需要匹配的正則表達(dá)式,還可以設(shè)置to-many relationship中數(shù)目的最大最小值聘殖。

在Core Data Model editor中可以設(shè)置一些validation邏輯

除了可以對(duì)model設(shè)置這些validation邏輯晨雳,還可以在代碼中進(jìn)行自定義。

如果想要自定義property層次的validation奸腺,程序員不應(yīng)該重寫validateValue:forKey:error:方法悍募,而是應(yīng)該實(shí)現(xiàn)validate<Key>:error:方法。
然而洋机,如果想要自行檢查某個(gè)property是否符合規(guī)定坠宴,應(yīng)該調(diào)用的是validateValue:forKey:error:方法,這個(gè)方法會(huì)將定義在managed object model中的validation邏輯也考慮進(jìn)去绷旗。

也可以自定義property之間的validation喜鼓。這可以通過重寫validateForUpdate:validateForInsert:validateForDelete:方法來實(shí)現(xiàn)衔肢。在重寫的這三個(gè)方法中庄岖,應(yīng)該首先調(diào)用父類的實(shí)現(xiàn)。

所有的validation限制都只有在保存操作的過程中會(huì)被應(yīng)用角骤。因?yàn)閙anaged object context的本意就是一塊草稿板隅忿,所以應(yīng)該允許其中的對(duì)象有臨時(shí)性的“不合理”。


關(guān)于Faulting



一個(gè)managed object通常會(huì)用于表示被持久化存儲(chǔ)的數(shù)據(jù)邦尊,但是在有些情況下背桐,一個(gè)managed object可能是fault的,也就是說它的property還沒有從外部數(shù)據(jù)存儲(chǔ)中載入進(jìn)來蝉揍。這是Core Data用于減少內(nèi)存占用的一種機(jī)制链峭。

當(dāng)訪問到一個(gè)managed object的某個(gè)持久化的property的時(shí)候,fault被觸發(fā)了又沾,如果內(nèi)存中的cache沒有被擊中的話弊仪,數(shù)據(jù)會(huì)被自動(dòng)從持久化存儲(chǔ)中取過來,這里的開銷是比較昂貴的杖刷。

需要注意的是励饵,description方法是不會(huì)觸發(fā)fault的,所以打印剛剛?cè)〕鰜淼膍anaged object可以看到“<fault>”字樣滑燃。
比如這樣:

"<LaunchInfo: 0x10060b450> (entity: LaunchInfo; id: 0x40000b <x-coredata://4973AB39-0CD8-4480-AA07-7A3A877BE87D/LaunchInfo/p1> ; data: <fault>)"

如果重寫description方法役听,并在其中訪問了某個(gè)持久化的property,則fault會(huì)被觸發(fā)。所以應(yīng)該盡量避免這樣的做法禾嫉。

可以使用refreshObject:mergeChanges:并傳人參數(shù)no讓一個(gè)managed object變成fault。但是必須保證其中的relationship沒有被改變蚊丐。


關(guān)于Fetching


取得指定的對(duì)象

如果app使用了多個(gè)context熙参,那么程序員可能就需要測(cè)試一個(gè)對(duì)象是否已經(jīng)從persistent store中被刪除了。這時(shí)麦备,可以創(chuàng)建一個(gè)fetch request孽椰,其中這樣指定predicate:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self == %@", targetObject];

這樣就可以通過判斷fetch到的對(duì)象的數(shù)目是否為0來判斷目標(biāo)對(duì)象是否已被刪除。其中的targetObject可以是一個(gè)managed object凛篙,也可以是一個(gè)manged object ID黍匾。
如果一次需要測(cè)試多個(gè)目標(biāo)對(duì)象是否被刪除,可以使用更高效的IN操作符:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self IN %@", arrayOfManagedObjectIDs];
獲取特定的值



有的時(shí)候呛梆,程序員可能不需要獲取整個(gè)managed object锐涯,而是只是需要其中的某個(gè)attribute。NSExpressionDescription可以幫助程序員取得需要的值填物。
這時(shí)纹腌,需要使用setResultType:方法來指定這個(gè)fetch返回的結(jié)果類型是NSDictionaryResultType;還需要?jiǎng)?chuàng)建NSExpressionDescription的實(shí)例滞磺,來指定哪些property是需要取得的升薯。
官方文檔里有示例代碼,偷個(gè)懶击困。


還欠缺的部分



這篇博客真是拖著寫了好久涎劈。
但是還有好多內(nèi)容沒有理解,因?yàn)橥祽?之前在工作中對(duì)這些部分接觸不多沒什么感受阅茶,所以先放在這里蛛枚,等下一遍看的時(shí)候,再慢慢理解好了脸哀。

Localizing a Managed Object Model
Copying and Copy and Paste
Drag and Drop
Undo Management
Ensuring Data Is Up-to-Date
Change and Undo Management
Fetched Properties
Non-Standard Persistent Attributes
Associate Metadata With a Store to Provide Additional Information and Support Spotlight Indexing
Core Data and Cocoa Bindings
Change Management
Persistent Store Features
Core Data Performance
Troubleshooting Core Data
Efficiently Importing Data

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末坤候,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子企蹭,更是在濱河造成了極大的恐慌白筹,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谅摄,死亡現(xiàn)場(chǎng)離奇詭異徒河,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)送漠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門顽照,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事代兵∧崮穑” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵植影,是天一觀的道長裳擎。 經(jīng)常有香客問我,道長思币,這世上最難降的妖魔是什么鹿响? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮谷饿,結(jié)果婚禮上惶我,老公的妹妹穿的比我還像新娘。我一直安慰自己博投,他們只是感情好绸贡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著毅哗,像睡著了一般恃轩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上黎做,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天叉跛,我揣著相機(jī)與錄音,去河邊找鬼蒸殿。 笑死筷厘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宏所。 我是一名探鬼主播酥艳,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼爬骤!你這毒婦竟也來了充石?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤霞玄,失蹤者是張志新(化名)和其女友劉穎骤铃,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坷剧,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惰爬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了惫企。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片撕瞧。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出丛版,到底是詐尸還是另有隱情巩掺,我是刑警寧澤,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布页畦,位于F島的核電站胖替,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏寇漫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一殉摔、第九天 我趴在偏房一處隱蔽的房頂上張望州胳。 院中可真熱鬧,春花似錦逸月、人聲如沸栓撞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓤湘。三九已至,卻和暖如春恩尾,著一層夾襖步出監(jiān)牢的瞬間弛说,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國打工翰意, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留木人,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓冀偶,卻偏偏與公主長得像醒第,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子进鸠,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

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