Core Data詳細(xì)解析(十一) —— MagicalRecord框架之基本使用(二)

版本記錄

版本號 時間
V1.0 2018.09.29 星期六

前言

數(shù)據(jù)是移動端的重點關(guān)注對象采驻,其中有一條就是數(shù)據(jù)存儲瘪撇。CoreData是蘋果出的數(shù)據(jù)存儲和持久化技術(shù),面向?qū)ο筮M(jìn)行數(shù)據(jù)相關(guān)存儲。感興趣的可以看下面幾篇文章在扰。
1. iOS CoreData(一)
2. iOS CoreData實現(xiàn)數(shù)據(jù)存儲(二)
3. Core Data詳細(xì)解析(三) —— 一個簡單的入門示例(一)
4. Core Data詳細(xì)解析(四) —— 一個簡單的入門示例(二)
5. Core Data詳細(xì)解析(五) —— 基于多上下文的Core Data簡單解析示例(一)
6. Core Data詳細(xì)解析(六) —— 基于多上下文的Core Data簡單解析示例(二)
7. Core Data詳細(xì)解析(七) —— Core Data的輕量級遷移(一)
8. Core Data詳細(xì)解析(八) —— Core Data的輕量級遷移(二)
9. Core Data詳細(xì)解析(九) —— MagicalRecord框架之基本概覽(一)
10. Core Data詳細(xì)解析(十) —— MagicalRecord框架之基本使用(一)

Deleting Entities - 刪除實體

要在默認(rèn)上下文中刪除單個實體:

[myPerson MR_deleteEntity];

從指定上下文中刪除實體:

[myPerson MR_deleteEntityInContext:otherContext];

獲取默認(rèn)上下文中的所有實體:

[Person MR_truncateAll];

獲取指定上下文中所有實體:

[Person MR_truncateAllInContext:otherContext];

Fetching Entities - 獲取實體

1. Basic Finding - 基本查找

MagicalRecord中的大多數(shù)方法都返回NSArray結(jié)果漱逸。

例如王滤,如果您有一個名為Person的實體與Department實體相關(guān)(如 Apple's Core Data examples中所示)猬腰,您可以使用以下方法從持久性存儲中檢索所有Person實體:

NSArray *people = [Person MR_findAll];

要返回按特定屬性排序的相同實體:

NSArray *peopleSorted = [Person MR_findAllSortedBy:@"LastName"
                                         ascending:YES];

要返回按多個屬性排序的實體:

NSArray *peopleSorted = [Person MR_findAllSortedBy:@"LastName,FirstName"
                                         ascending:YES];

返回由具有不同值的多個屬性排序的結(jié)果。 如果您沒有為任何屬性提供值悍缠,它將默認(rèn)為您在模型中設(shè)置的任何值:

NSArray *peopleSorted = [Person MR_findAllSortedBy:@"LastName:NO,FirstName"
                                         ascending:YES];

// OR

NSArray *peopleSorted = [Person MR_findAllSortedBy:@"LastName,FirstName:YES"
                                         ascending:NO];

如果您有一種從數(shù)據(jù)存儲中檢索單個對象的唯一方法(例如標(biāo)識符屬性)卦绣,則可以使用以下方法:

Person *person = [Person MR_findFirstByAttribute:@"FirstName"
                                       withValue:@"Forrest"];

2. Advanced Finding - 高級查找

如果您想更具體地使用搜索,可以使用謂詞:

NSPredicate *peopleFilter = [NSPredicate predicateWithFormat:@"Department IN %@", @[dept1, dept2]];
NSArray *people = [Person MR_findAllWithPredicate:peopleFilter];

3. Returning an NSFetchRequest - 返回一個NSFetchRequest

NSPredicate *peopleFilter = [NSPredicate predicateWithFormat:@"Department IN %@", departments];
NSFetchRequest *people = [Person MR_requestAllWithPredicate:peopleFilter];

對于這些單行調(diào)用中的每一個飞蚓,都會創(chuàng)建任何排序條件的NSFetchRequestNSSortDescriptors滤港。

4. Customizing the Request - 自定義請求

NSPredicate *peopleFilter = [NSPredicate predicateWithFormat:@"Department IN %@", departments];

NSFetchRequest *peopleRequest = [Person MR_requestAllWithPredicate:peopleFilter];
[peopleRequest setReturnsDistinctResults:NO];
[peopleRequest setReturnPropertiesNamed:@[@"FirstName", @"LastName"]];

NSArray *people = [Person MR_executeFetchRequest:peopleRequest];

5. Find the number of entities - 查找實體數(shù)量

您還可以在持久性存儲中執(zhí)行特定類型的所有實體的計數(shù):

NSNumber *count = [Person MR_numberOfEntities];

或者,如果您正在尋找基于謂詞或某些過濾器的實體計數(shù):

NSNumber *count = [Person MR_numberOfEntitiesWithPredicate:...];

還有一些補(bǔ)充方法可以返回NSUInteger而不是NSNumber實例:

+ (NSUInteger) MR_countOfEntities;
+ (NSUInteger) MR_countOfEntitiesWithContext:(NSManagedObjectContext *)context;
+ (NSUInteger) MR_countOfEntitiesWithPredicate:(NSPredicate *)searchFilter;
+ (NSUInteger) MR_countOfEntitiesWithPredicate:(NSPredicate *)searchFilter
                                     inContext:(NSManagedObjectContext *)context;

6. Aggregate Operations - 聚合操作

NSNumber *totalCalories = [CTFoodDiaryEntry MR_aggregateOperation:@"sum:"
                                                      onAttribute:@"calories"
                                                    withPredicate:predicate];

NSNumber *mostCalories  = [CTFoodDiaryEntry MR_aggregateOperation:@"max:"
                                                      onAttribute:@"calories"
                                                    withPredicate:predicate];

NSArray *caloriesByMonth = [CTFoodDiaryEntry MR_aggregateOperation:@"sum:"
                                                       onAttribute:@"calories"
                                                     withPredicate:predicate
                                                           groupBy:@"month"];

7. Finding entities in a specific context - 在指定上下文中查找實體

所有find趴拧,fetchrequest方法都有一個inContext:方法參數(shù)溅漾,允許您指定要查詢的managed object context

NSArray *peopleFromAnotherContext = [Person MR_findAllInContext:someOtherContext];

Person *personFromContext = [Person MR_findFirstByAttribute:@"lastName"
                                                  withValue:@"Gump"
                                                  inContext:someOtherContext];

NSUInteger count = [Person MR_numberOfEntitiesWithContext:someOtherContext];

Saving Entities - 保存實體

1. When should I save? - 何時使用

通常,當(dāng)數(shù)據(jù)發(fā)生變化時著榴,您的應(yīng)用應(yīng)該保存到持久存儲中添履。 有些應(yīng)用程序選擇在應(yīng)用程序終止時存儲,但在大多數(shù)情況下這不是必需的 - 事實上脑又,如果您只是在應(yīng)用程序終止時保存暮胧,那么您將面臨數(shù)據(jù)丟失的風(fēng)險锐借! 如果你的應(yīng)用程序崩潰會怎么樣? 用戶將失去他們所做的所有改變 - 這是一種糟糕的經(jīng)歷往衷,并且很容易避免钞翔。

如果您發(fā)現(xiàn)保存需要很長時間,那么您應(yīng)該考慮做以下幾件事:

  • 1) Save in a background thread - 在后臺線程中保存MagicalRecord提供了一個簡單席舍,干凈的API嗅战,用于對實體進(jìn)行更改,然后將它們保存在后臺線程中 - 例如:
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {

    // Do your work to be saved here, against the `localContext` instance
    // Everything you do in this block will occur on a background thread

} completion:^(BOOL success, NSError *error) {
    [application endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];
  • 2)Break the task down into smaller saves - 將任務(wù)分解為較小的保存:像導(dǎo)入大量數(shù)據(jù)這樣的任務(wù)應(yīng)該總是分解成更小的塊俺亮。 對于您應(yīng)該一次性保存多少數(shù)據(jù)沒有一刀切的規(guī)則,因此您需要使用Apple's Instruments等工具來衡量應(yīng)用程序的性能并適當(dāng)調(diào)整疟呐。

2. Handling Long-running Saves - 處理長時間運(yùn)行的保存

On iOS

當(dāng)應(yīng)用程序在iOS上終止時脚曾,會給它一個小的機(jī)會窗口來整理并將任何數(shù)據(jù)保存到磁盤。 如果您知道保存操作可能需要一段時間启具,最好的方法是請求延長應(yīng)用程序的到期時間本讥,如下所示:

UIApplication *application = [UIApplication sharedApplication];

__block UIBackgroundTaskIdentifier bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
    [application endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {

    // Do your work to be saved here

} completion:^(BOOL success, NSError *error) {
    [application endBackgroundTask:bgTask];
    bgTask = UIBackgroundTaskInvalid;
}];

請務(wù)必仔細(xì)閱讀read the documentation for beginBackgroundTaskWithExpirationHandler的文檔,因為不恰當(dāng)或不必要地延長應(yīng)用程序的生命周期可能會使您的應(yīng)用程序被App Store拒絕鲁冯。

On OS X

OS X Mavericks(10.9)及更高版本中拷沸,App Nap可以使您的應(yīng)用程序在后臺運(yùn)行時有效終止。 如果您知道保存操作可能需要一段時間薯演,最好的方法是暫時禁用自動和突然終止(假設(shè)您的應(yīng)用支持這些功能):

NSProcessInfo *processInfo = [NSProcessInfo processInfo];

[processInfo disableSuddenTermination];
[processInfo disableAutomaticTermination:@"Application is currently saving to persistent store"];

[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {

    // Do your work to be saved here

} completion:^(BOOL success, NSError *error) {
    [processInfo enableSuddenTermination];
    [processInfo enableAutomaticTermination:@"Application has finished saving to the persistent store"];
}];

與iOS方法一樣撞芍,在應(yīng)用程序中實現(xiàn)此方法之前,請務(wù)必閱讀read the documentation on NSProcessInfo跨扮。


Importing Data - 引入數(shù)據(jù)

MagicalRecord可以幫助將標(biāo)準(zhǔn)NSObject實例(如NSArrayNSDictionary)中的數(shù)據(jù)直接導(dǎo)入到Core Data存儲中序无。

使用MagicalRecord將數(shù)據(jù)從外部源導(dǎo)入持久性存儲是一個兩步過程:

  • 1) 使用您的數(shù)據(jù)模型定義您導(dǎo)入的數(shù)據(jù)如何映射到您的存儲(它幾乎沒有代碼!)
  • 2) 執(zhí)行數(shù)據(jù)導(dǎo)入

1. Define Your Import - 定義你的引入

來自外部來源的數(shù)據(jù)在質(zhì)量和結(jié)構(gòu)上可能會發(fā)生巨大變化衡创,因此我們已盡最大努力使MagicalRecord的導(dǎo)入流程變得靈活帝嗡。

MagicalRecord可以從任何符合鍵值編碼(KVC)的對象導(dǎo)入數(shù)據(jù)。 我們通常會發(fā)現(xiàn)人們使用NSArrayNSDictionary實例璃氢,但它適用于任何符合KVC標(biāo)準(zhǔn)的NSObject子類哟玷。

MagicalRecord利用Xcode數(shù)據(jù)建模工具的User Info值,允許配置導(dǎo)入選項和映射一也,而無需編輯任何代碼巢寡。

供參考:用戶信息鍵和值保存在NSDictionary中,該NSDictionary附加到數(shù)據(jù)模型中的每個實體塘秦,屬性和關(guān)系讼渊,并且可以通過NSEntityDescription實例上的userInfo方法訪問。

Xcode的數(shù)據(jù)建模工具使您可以通過數(shù)據(jù)模型檢查器的User Info組訪問該字典尊剔。 編輯數(shù)據(jù)模型時爪幻,可以使用Xcode的菜單 - View > Utilities > Show Data Model Inspector或按鍵盤上的??3菱皆。

默認(rèn)情況下,MagicalRecord將自動嘗試將屬性和關(guān)系名稱與導(dǎo)入數(shù)據(jù)中的鍵匹配挨稿。如果模型中的屬性或關(guān)系名稱與數(shù)據(jù)中的鍵匹配仇轻,則無需執(zhí)行任何操作 - 將自動導(dǎo)入附加到鍵的值。

例如奶甘,如果實體上的屬性名稱為'firstName'篷店,則MagicalRecord將假定要導(dǎo)入的數(shù)據(jù)中的鍵也將具有'firstName'鍵 - 如果是,則實體的firstName屬性將設(shè)置為該值您的數(shù)據(jù)中的firstName鍵臭家。

通常疲陕,您導(dǎo)入的數(shù)據(jù)中的鍵和結(jié)構(gòu)與實體的屬性和關(guān)系不匹配。在這種情況下钉赁,您需要告訴MagicalRecord如何將導(dǎo)入數(shù)據(jù)的鍵映射到數(shù)據(jù)模型中的正確屬性或關(guān)系蹄殃。

我們在Core Data中處理的三個關(guān)鍵對象中的每一個 - Entities, Attributes and Relationships - 都有可能需要通過user info鍵指定的選項:

Attributes

Entities

Relationships

2. Importing Objects - 引入對象

要使用MagicalRecord將數(shù)據(jù)導(dǎo)入你的存儲,您需要了解兩件事:

  • 1) 您要導(dǎo)入的數(shù)據(jù)的格式以及它的方式

MagicalRecord導(dǎo)入背后的基本思想是你知道應(yīng)該導(dǎo)入數(shù)據(jù)的實體你踩,然后你編寫一行代碼將這個實體與要導(dǎo)入的數(shù)據(jù)聯(lián)系起來诅岩。 有幾個選項可以啟動導(dǎo)入過程。

要從對象自動創(chuàng)建新實例带膜,可以使用以下更短的方法:

NSDictionary *contactInfo = // Result from JSON parser or some other source

Person *importedPerson = [Person MR_importFromObject:contactInfo];

您還可以使用兩階段方法:

NSDictionary *contactInfo = // Result from JSON parser or some other source

Person *person = [Person MR_createEntity]; // This doesn't have to be a new entity
[person MR_importValuesForKeysWithObject:contactInfo];

如果您希望通過覆蓋其屬性來更新現(xiàn)有對象吩谦,則兩步方法可能會有所幫助。

+ MR_importFromObject:將根據(jù)配置的查找值查找現(xiàn)有對象(請參閱relatedByAttributeattributeNameID)膝藕。 還要注意這是如何遵循在Cocoa中導(dǎo)入鍵值對列表的內(nèi)置范例式廷,以及遵循導(dǎo)入數(shù)據(jù)的安全方式。

+ MR_importFromObject:類方法使用前面提到的-MR_importValuesForKeysWithObject:實例方法提供創(chuàng)建新對象的包裝器芭挽,并返回填充了數(shù)據(jù)的新創(chuàng)建的對象懒棉。

值得注意的一個關(guān)鍵項是這兩種方法都是同步的。 雖然某些導(dǎo)入將比其他導(dǎo)入更長時間览绿,但仍然強(qiáng)烈建議在后臺執(zhí)行所有導(dǎo)入策严,以免影響用戶交互。 如前所述饿敲,MagicalRecord提供了一個方便的API妻导,使后臺線程更易于管理:

[MagicalRecord saveInBackgroundWithBlock:^(NSManagedObjectContext *)localContext {
  Person *importedPerson = [Person MR_importFromObject:personRecord inContext:localContext];
}];

3. Importing Arrays - 導(dǎo)入數(shù)組

通常使用JSON數(shù)組提供數(shù)據(jù)列表,或者導(dǎo)入單個類型數(shù)據(jù)的大型列表怀各。 導(dǎo)入此類列表的詳細(xì)信息將在+ MR_importFromArray:類方法中進(jìn)行處理倔韭。

NSArray *arrayOfPeopleData = /// result from JSON parser
NSArray *people = [Person MR_importFromArray:arrayOfPeopleData];

此方法與+ MR_importFromObject:也是同步的,因此對于后臺導(dǎo)入瓢对,請使用前面提到的輔助方法在后臺執(zhí)行block塊寿酌。

如果您的導(dǎo)入數(shù)據(jù)與您的Core Data模型完全匹配,那么請不要繼續(xù)讀取硕蛹,因為您需要將上述方法導(dǎo)入Core Data存儲中醇疼。 但是硕并,如果您的數(shù)據(jù)與大多數(shù)數(shù)據(jù)一樣,沒有什么微小的偏差秧荆,請繼續(xù)讀取倔毙,因為我們將介紹MagicalRecord的一些功能,這些功能將幫助您處理幾個常見的偏差乙濒。

4. Best Practice - 最佳實踐

Handling Bad Data When Importing - 導(dǎo)入時處理錯誤數(shù)據(jù)

API通成略撸可以返回格式或值不一致的數(shù)據(jù)。 處理此問題的最佳方法是在實體類上使用導(dǎo)入類別方法颁股。 提供了三個:

通常么库,如果您的數(shù)據(jù)不好,您將需要修復(fù)導(dǎo)入在嘗試導(dǎo)入任何值后所執(zhí)行的操作甘有。

常見的情況是導(dǎo)入JSON數(shù)據(jù)廊散,其中數(shù)字字符串通常可能被誤解為實際數(shù)字梧疲。 如果要確保將值作為字符串導(dǎo)入,可以執(zhí)行以下操作:

@interface MyGreatEntity

@property(readwrite, nonatomic, copy) NSString *identifier;

@end

@implementation MyGreatEntity

@dynamic identifier;

- (void)didImport:(id)data
{
  if (NO == [data isKindOfClass:[NSDictionary class]]) {
    return;
  }

  NSDictionary *dataDictionary = (NSDictionary *)data;

  id identifierValue = dataDictionary[@"my_identifier"];

  if ([identifierValue isKindOfClass:[NSNumber class]]) {
    NSNumber *numberValue = (NSNumber *)identifierValue;

    self.identifier = [numberValue stringValue];
  }
}

@end

Deleting local records on import update - 在導(dǎo)入更新時刪除本地記錄

有時运准,您需要確保后續(xù)導(dǎo)入操作不僅會更新幌氮,還會刪除未包含在遠(yuǎn)程數(shù)據(jù)集中的本地記錄。 為此胁澳,請通過relatedByAttribute(下例中的id)獲取此更新中未包含的所有本地記錄该互,并在導(dǎo)入新數(shù)據(jù)集之前立即刪除它們。

NSArray *arrayOfPeopleData = /// result from JSON parser
NSArray *people = [Person MR_importFromArray:arrayOfPeopleData];
NSArray *idList = [arrayOfPeopleData valueForKey:@"id"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT(id IN %@)", idList];
[Person MR_deleteAllMatchingPredicate:predicate];

如果您還想確保在此更新期間刪除相關(guān)記錄韭畸,您可以使用與上面類似的邏輯宇智,但在PersonisImport:方法中實現(xiàn)它

@implementation Person

-(void)willImport:(id)data {
    NSArray *idList = [data[@"posts"] valueForKey:@"id"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT(id IN %@) AND person.id == %@", idList, self.id];
    [Post MR_deleteAllMatchingPredicate:predicate];
}

如果您還想確保在此更新期間刪除相關(guān)記錄,您可以使用與上面類似的邏輯胰丁,但在PersonisImport:方法中實現(xiàn)它

@implementation Person

-(void)willImport:(id)data {
    NSArray *idList = [data[@"posts"] valueForKey:@"id"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT(id IN %@) AND person.id == %@", idList, self.id];
    [Post MR_deleteAllMatchingPredicate:predicate];
}

Logging - 日志

MagicalRecord在與Core Data的大多數(shù)交互中都內(nèi)置了日志記錄随橘。 在獲取或保存數(shù)據(jù)期間發(fā)生錯誤時,會捕獲這些錯誤并(如果已啟用它們)記錄到控制臺锦庸。

日志記錄配置為在調(diào)試版本中默認(rèn)輸出調(diào)試消息(MagicalRecordLoggingLevelDebug)机蔗,并將在發(fā)布版本中輸出錯誤消息(MagicalRecordLoggingLevelError)

可以通過調(diào)用[MagicalRecord setLoggingLevel:]來配置記錄甘萧,使用一個預(yù)定義的日志記錄級別:

  • MagicalRecordLogLevelOff:不記錄任何內(nèi)容
  • MagicalRecordLoggingLevelError:記錄所有錯誤
  • MagicalRecordLoggingLevelWarn:記錄警告和錯誤
  • MagicalRecordLoggingLevelInfo:記錄信息萝嘁,警告和錯誤消息
  • MagicalRecordLoggingLevelDebug:記錄所有調(diào)試,信息扬卷,警告和錯誤消息
  • MagicalRecordLoggingLevelVerbose:記錄詳細(xì)的診斷牙言,信息,警告和錯誤消息

日志記錄級別默認(rèn)為MagicalRecordLoggingLevelWarn怪得。

1. CocoaLumberjack

如果它可用咱枉,MagicalRecord會將其日志指向CocoaLumberjack卑硫。 您需要做的就是確保在導(dǎo)入MagicalRecord之前導(dǎo)入了CocoaLumberjack,如下所示:

// Objective-C
#import <CocoaLumberjack/CocoaLumberjack.h>
#import <MagicalRecord/MagicalRecord.h>
// Swift
import CocoaLumberjack
import MagicalRecord

2. Disabling Logging Completely - 完全禁用日志記錄

對大多數(shù)人來說庞钢,這是不必要的拔恰。 將日志記錄級別設(shè)置為MagicalRecordLogLevelOff將確保不打印日志。

即使使用MagicalRecordLogLevelOff基括,也可以在進(jìn)行日志調(diào)用時執(zhí)行非逞瞻茫快速的檢查。 如果您絕對需要禁用日志記錄风皿,則需要在編譯MagicalRecord時定義以下內(nèi)容:

#define MR_LOGGING_DISABLED 1

請注意河爹,這只有在您將MagicalRecord的源添加到您自己的項目中時才有效。 您也可以將其添加到MagicalRecord項目的OTHER_CFLAGS中桐款,作為-DMR_LOGGING_DISABLED = 1咸这。

其他資源

后記

本篇主要講述了MagicalRecord框架之基本使用,感興趣的給個贊或者關(guān)注~~~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末魔眨,一起剝皮案震驚了整個濱河市媳维,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌遏暴,老刑警劉巖侄刽,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異朋凉,居然都是意外死亡州丹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門杂彭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來墓毒,“玉大人,你說我怎么就攤上這事亲怠∷疲” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵团秽,是天一觀的道長醉箕。 經(jīng)常有香客問我,道長徙垫,這世上最難降的妖魔是什么讥裤? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮姻报,結(jié)果婚禮上己英,老公的妹妹穿的比我還像新娘。我一直安慰自己吴旋,他們只是感情好损肛,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布厢破。 她就那樣靜靜地躺著,像睡著了一般治拿。 火紅的嫁衣襯著肌膚如雪摩泪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天劫谅,我揣著相機(jī)與錄音见坑,去河邊找鬼。 笑死捏检,一個胖子當(dāng)著我的面吹牛荞驴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播贯城,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼熊楼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了能犯?” 一聲冷哼從身側(cè)響起鲫骗,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎踩晶,沒想到半個月后执泰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡合瓢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了透典。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晴楔。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖峭咒,靈堂內(nèi)的尸體忽然破棺而出税弃,到底是詐尸還是另有隱情,我是刑警寧澤凑队,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布则果,位于F島的核電站,受9級特大地震影響漩氨,放射性物質(zhì)發(fā)生泄漏西壮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一叫惊、第九天 我趴在偏房一處隱蔽的房頂上張望款青。 院中可真熱鬧,春花似錦霍狰、人聲如沸抡草。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽康震。三九已至燎含,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間腿短,已是汗流浹背屏箍。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留答姥,地道東北人铣除。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像鹦付,于是被迫代替她去往敵國和親尚粘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360

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