D32:CoreData

目錄

一. CoreData簡介

  1. CoreData是apple自己封裝的數(shù)據(jù)庫操作的一個框架, 是一種面向?qū)ο蟮姆绞絹聿僮鲾?shù)據(jù)的框架, 底層是基于SQLite的
  2. 需要用到的幾個基本類型

二. CoreData使用

  1. 圖形化操作
  2. 常規(guī)的創(chuàng)建表格, 創(chuàng)建Cell
  3. 核心內(nèi)容:創(chuàng)建上下文對象
  4. DBManager類中 "增刪改查" 的方法
  5. 詳情視圖控制器(相冊部分內(nèi)容需要回顧加深)
  6. ViewController.m(在查詢時由于數(shù)據(jù)量可能較大, 因此使用GCD知識; 刪除時方法- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath要注意刪除順序)

三. 當(dāng)CoreData數(shù)據(jù)庫升級時我們需要

  1. 假設(shè)我們添加一個屬性, 首先我們要建立一個新版本的模型, NSManagedObject Subclass也要重新生成
  2. 修改DBManager.m中的- (void)createManagedContext方法
  3. 模擬處理country屬性
  4. 如果原有的數(shù)據(jù)庫文件內(nèi)有數(shù)據(jù)的話, 需要刪除原來的數(shù)據(jù)庫文件, 否則可能會報錯(可能是數(shù)據(jù)結(jié)構(gòu)問題)

一. CoreData簡介

1. CoreData是apple自己封裝的數(shù)據(jù)庫操作的一個框架, 是一種面向?qū)ο蟮姆绞絹聿僮鲾?shù)據(jù)的框架, 底層是基于SQLite的
2. 需要用到的幾個基本類型
  1. NSManagedObjectModel: 對應(yīng)于所有實體類的描述文件, 文件里面包含很多類的屬性和關(guān)系的描述
  • NSManagedObject: 對應(yīng)于一個實體類, 所有的CoreData操作的實體類都是它的子類
  • NSPersistentStoreCoordinator: 用來關(guān)聯(lián)類和對應(yīng)的數(shù)據(jù)庫文件
  • NSmanagedContext: 上下文對象, 用來操作數(shù)據(jù)庫的增刪改查

二. CoreData使用

1. 圖形化操作
新建一個Core Data分類中的Data Model文件, 格式為"xcdatamodeld"
點擊左下角的Add Entity增加Entity
修改Entity名為"Computer", 為"Computer"增加2個屬性("Computer"只是測試用)
選中"Computer"這個Entity, 點擊"Editor -> Create NSManagedObject Subclass"
因為只有一個DataModel, 默認勾選狀態(tài), 直接Next即可
當(dāng)前只有一個Entity, 同樣是默認勾選狀態(tài), 直接Next即可
在Group的選項中要選擇當(dāng)前項目, 選中Target
自動創(chuàng)建了Computer類
創(chuàng)建"User"這個Entity, 為其添加4個屬性
換一種方式用"Command+N"來新建NSManagedObject Subclass
當(dāng)前有2個Entity, 我們選擇需要的"User"
創(chuàng)建完成
2. 常規(guī)的創(chuàng)建表格, 創(chuàng)建Cell
3. 核心內(nèi)容:創(chuàng)建上下文對象
//
//  DBManager.m
//  01_CoreDataDemo

#import "DBManager.h"
#import <CoreData/CoreData.h>

@implementation DBManager
{
#warning 用來處理數(shù)據(jù)庫增刪改查的對象
    NSManagedObjectContext *_context;
}

+ (instancetype)sharedManager
{
    static DBManager *manager = nil;
    
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        manager = [[DBManager alloc] init];
    });
    
    return manager;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self createManagedContext];
    }
    return self;
}

// 創(chuàng)建上下文對象
- (void)createManagedContext
{
    // 1. 創(chuàng)建描述文件的關(guān)聯(lián)對象
    // 文件的路徑
#warning 擴展名不是寫"xcdatamodeld"
    NSString *path = [[NSBundle mainBundle] pathForResource:@"MyUser" ofType:@"momd"];
    
    NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL URLWithString:path]];
    
    // 2. 關(guān)聯(lián)數(shù)據(jù)庫文件(SQLite)
    // 先關(guān)聯(lián)數(shù)據(jù)模型描述文件對應(yīng)的對象
    NSPersistentStoreCoordinator *coor = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    // 再關(guān)聯(lián)數(shù)據(jù)庫
    /*
     第一個參數(shù): 類型(建議用SQLite類型)
     第二個參數(shù): 傳nil即可
     第三個參數(shù): 文件的路徑
     第四個參數(shù): 選項信息
     第五個參數(shù): 錯誤信息
     */
    NSString *filePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/user.sqlite"];
    NSURL *sqliteUrl = [NSURL URLWithString:filePath];
    
    [coor addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:sqliteUrl options:nil error:nil];
    
    // 3. 創(chuàng)建上下文對象, 跟上面的對象關(guān)聯(lián)起來
    _context = [[NSManagedObjectContext alloc] init];
    _context.persistentStoreCoordinator = coor;
}

@end
4. DBManager類中 "增刪改查" 的方法
/*
 在添加數(shù)據(jù)之前, 判斷相同userId的數(shù)據(jù)是否已經(jīng)存在, 如果是, 先刪除以前存在的數(shù)據(jù), 再重新添加
 */
- (void)verifyOldUserData:(NSDictionary *)userDict
{
    // 先判斷是否存在
    // 查詢
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:_context];
    
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    request.entity = entity;
    
    // 設(shè)置查詢條件
    if ([[userDict allKeys] containsObject:kUserId]) {
        
        // 謂詞
        NSPredicate *p = [NSPredicate predicateWithFormat:@"userId == %@", userDict[kUserId]];
        request.predicate = p;
        
        // 執(zhí)行查詢操作
        NSError *error;
        NSArray *array = [_context executeFetchRequest:request error:&error];
        if (error) {
            NSLog(@"%@", error);
        }
        
        if (array.count > 0) {
            // 刪除以前的數(shù)據(jù)
            for (User *tmpUser in array) {
                [_context deleteObject:tmpUser];
            }
            // 保存(可以和上面的操作用同一個error)
            [_context save:&error];
            if (error) {
                NSLog(@"===%@", error);
            }
        }
    }
}

- (void)insertUser:(NSDictionary *)userDict
{
    [self verifyOldUserData:userDict];
    
    // NSEntityDescription
    // 第一個參數(shù): 類名
    // 第二個參數(shù): 上下文
    User *user = [NSEntityDescription insertNewObjectForEntityForName:@"User" inManagedObjectContext:_context];
    if ([[userDict allKeys] containsObject:kUserId]) {
        user.userId = userDict[kUserId];
    }
    if ([[userDict allKeys] containsObject:kUserName]) {
        user.userName = userDict[kUserName];
    }
    if ([[userDict allKeys] containsObject:kHeadImage]) {
        user.headImage = userDict[kHeadImage];
    }
    if ([[userDict allKeys] containsObject:kAge]) {
        user.age = userDict[kAge];
    }
    if ([[userDict allKeys] containsObject:kCountry]) {
        user.country = userDict[kCountry];
    }

    // 存儲
    NSError *error;
    [_context save:&error];
    if (error) {
        NSLog(@"%@", error.localizedDescription);
    }
}

// 查詢所有數(shù)據(jù)
- (NSArray *)searchAllUsers
{
    // 創(chuàng)建一個NSEntityDescription類型的對象
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:_context];
    
    // 查詢對象(包括查詢的數(shù)據(jù)對象所屬的類型等信息)
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    
    request.entity = entity;
    
    // 執(zhí)行查詢操作
    NSError *error;
    NSArray *array = [_context executeFetchRequest:request error:&error];
    if (error) {
        NSLog(@"%@", error);
    }
    
    return array;
}

// 刪除
- (void)deleteUser:(User *)user
{
    [_context deleteObject:user];
    
    // 保存
    NSError *error;
    BOOL flag = [_context save:&error];
    if (error) {
        NSLog(@"%@", error);
    }
    if (flag == NO) {
        NSLog(@"刪除失敗");
    }
}

// 修改數(shù)據(jù)
- (void)updateUser:(NSDictionary *)userDict
{
    // 1. 查詢修改的對象
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:_context];
    // 2. 查詢的對象
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    request.entity = entity;
    
    // 3. 查詢條件
    NSPredicate *p = [NSPredicate predicateWithFormat:@"userId = %@", userDict[kUserId]];
    request.predicate = p;
    
    NSError *error;
    NSArray *array = [_context executeFetchRequest:request error:&error];
    if (error) {
        NSLog(@"%@", error);
    } else {
        // 修改數(shù)據(jù)
        for (User *tmpUser in array) {
            // 修改屬性值
            if ([[userDict allKeys] containsObject:kUserName]) {
                tmpUser.userName = userDict[kUserName];
            }
            if ([[userDict allKeys] containsObject:kAge]) {
                tmpUser.age = userDict[kAge];
            }
            if ([[userDict allKeys] containsObject:kHeadImage]) {
                tmpUser.headImage = userDict[kHeadImage];
            }
        }
        
        // 存儲
        [_context save:&error];
        if (error) {
            NSLog(@"%@", error);
        }
    }
}

@end
5. 詳情視圖控制器(相冊部分內(nèi)容需要回顧加深)
//
//  DetailViewController.h
//  01_CoreDataDemo

#import <UIKit/UIKit.h>
#import "User.h"

@interface DetailViewController : UIViewController

@property (nonatomic, strong) User *user;

@end

#import "DetailViewController.h"
#import "MyUtility.h"
#import "DBManager.h"

#define kUserId         (@"userId")
#define kUserName       (@"userName")
#define kAge            (@"age")
#define kHeadImage      (@"headImage")
#define kCountry        (@"country")

@interface DetailViewController () <UINavigationControllerDelegate ,UIImagePickerControllerDelegate>
{
    // 用戶Id
    UITextField *_userIdTextField;
    // 用戶名
    UITextField *_userNameTextField;
    // 年齡
    UITextField *_ageTextField;
    // 圖片
    UIButton *_imageBtn;
}

@end

@implementation DetailViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.view.backgroundColor = [UIColor whiteColor];

    // 用戶名
    UILabel *userIdLabel = [MyUtility createLabelWithFrame:CGRectMake(30, 100, 80, 30) title:@"用戶ID:" font:nil];
    _userIdTextField = [MyUtility createTextField:CGRectMake(130, 100, 200, 30) placeHolder:@"請輸入用戶ID"];
    [self.view addSubview:userIdLabel];
    [self.view addSubview:_userIdTextField];
    
    // 用戶名
    UILabel *userNameLabel = [MyUtility createLabelWithFrame:CGRectMake(30, 150, 80, 30) title:@"用戶名:" font:nil];
    _userNameTextField = [MyUtility createTextField:CGRectMake(130, 150, 200, 30) placeHolder:@"請輸入用戶名"];
    [self.view addSubview:userNameLabel];
    [self.view addSubview:_userNameTextField];
    
    // 年齡
    UILabel *userAgeLabel = [MyUtility createLabelWithFrame:CGRectMake(30, 200, 80, 30) title:@"年齡:" font:nil];
    _ageTextField = [MyUtility createTextField:CGRectMake(130, 200, 200, 30) placeHolder:@"請輸入年齡"];
    [self.view addSubview:userAgeLabel];
    [self.view addSubview:_ageTextField];

    // 頭像
    UILabel *imageLabel = [MyUtility createLabelWithFrame:CGRectMake(30, 280, 80, 30) title:@"頭像" font:nil];
    _imageBtn = [MyUtility createButtonWithFrame:CGRectMake(130, 260, 100, 100) title:nil backgroundImageName:nil target:self action:@selector(clickBtn)];
    _imageBtn.layer.cornerRadius = 8;
    _imageBtn.clipsToBounds = YES;
#warning 邊框
    _imageBtn.layer.borderColor = [UIColor cyanColor].CGColor;
    _imageBtn.layer.borderWidth = 2;
    [self.view addSubview:imageLabel];
    [self.view addSubview:_imageBtn];
    
    // 保存按鈕
    UIBarButtonItem *rightSaveItem = [[UIBarButtonItem alloc] initWithTitle:@"保存" style:UIBarButtonItemStylePlain target:self action:@selector(saveAction)];
    self.navigationItem.rightBarButtonItem = rightSaveItem;
    
    // 如果是修改界面, 顯示傳過來的數(shù)據(jù)
    if (self.user) {
        _userIdTextField.text = self.user.userId.stringValue;
        _userNameTextField.text = self.user.userName;
        _ageTextField.text = self.user.age.stringValue;
        // headImage
        [_imageBtn setBackgroundImage:[UIImage imageWithData:self.user.headImage] forState:UIControlStateNormal];
    }
    
    
}

- (void)saveAction
{
    NSMutableDictionary *userDict = [NSMutableDictionary dictionary];
    
    if (_userIdTextField.text.length > 0) {
        NSNumber *userId = [NSNumber numberWithInt:_userIdTextField.text.intValue];
        [userDict setObject:userId forKey:kUserId];
    }
    if (_userNameTextField.text.length > 0) {
        [userDict setObject:_userNameTextField.text forKey:kUserName];
    }
    if (_ageTextField.text.length > 0) {
        NSNumber *userAge = [NSNumber numberWithInt:_ageTextField.text.intValue];
        [userDict setObject:userAge forKey:kAge];
    }
    if ([_imageBtn backgroundImageForState:UIControlStateNormal]) {
        // 存儲圖片
        UIImage *bgImage = [_imageBtn backgroundImageForState:UIControlStateNormal];
        NSData *data = UIImagePNGRepresentation(bgImage);
        [userDict setObject:data forKey:kHeadImage];
    }

    [userDict setObject:@80 forKey:kCountry];
    
    if (self.user) {
        // 修改
        [[DBManager sharedManager] updateUser:userDict];
    } else {
        // 存儲
        [[DBManager sharedManager] insertUser:userDict];
    }
}

- (void)clickBtn
{
#warning 從相冊選圖片
    UIImagePickerController *ctrl = [[UIImagePickerController alloc] init];
    ctrl.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    ctrl.delegate = self;
    
    [self presentViewController:ctrl animated:YES completion:nil];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - UINavigationControllerDelegate ,UIImagePickerControllerDelegate代理
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    // 獲取圖片
    UIImage *image = info[UIImagePickerControllerOriginalImage];
    
    [_imageBtn setBackgroundImage:image forState:UIControlStateNormal];
    
    [picker dismissViewControllerAnimated:YES completion:nil];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
    [picker dismissViewControllerAnimated:YES completion:nil];
}

@end
6. ViewController.m(在查詢時由于數(shù)據(jù)量可能較大, 因此使用GCD知識; 刪除時方法- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath要注意刪除順序)
//
//  ViewController.m
//  01_CoreDataDemo

#import "ViewController.h"
#import "UserCell.h"
#import "DetailViewController.h"
#import "DBManager.h"

@interface ViewController () <UITableViewDataSource, UITableViewDelegate>

// 數(shù)據(jù)源
@property (nonatomic, strong) NSMutableArray *dataArray;
// 表格
@property (nonatomic, strong) UITableView *tableView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // 創(chuàng)建表格
    [self createTableView];
    
    // 添加按鈕
    UIBarButtonItem *rightItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(gotoAddPage)];
    self.navigationItem.rightBarButtonItem = rightItem;
}

- (void)gotoAddPage
{
    // 跳轉(zhuǎn)界面
    DetailViewController *dCtrl = [[DetailViewController alloc] init];
    [self.navigationController pushViewController:dCtrl animated:YES];
}

- (NSMutableArray *)dataArray
{
    if (!_dataArray) {
        _dataArray = [NSMutableArray array];
    }
    return _dataArray;
}

- (void)createTableView
{
    self.automaticallyAdjustsScrollViewInsets = NO;
    
    _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, self.view.bounds.size.width, self.view.bounds.size.height - 64) style:UITableViewStylePlain];
    _tableView.delegate = self;
    _tableView.dataSource = self;
    [self.view addSubview:_tableView];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)viewWillAppear:(BOOL)animated
{
    // 查詢所有數(shù)據(jù)
    // 查詢數(shù)據(jù)量可能較大, 因此開一個線程來進行查詢
    __weak ViewController *weakSelf = self;
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(globalQueue, ^{
        
        NSArray *array = [[DBManager sharedManager] searchAllUsers];
        weakSelf.dataArray = [NSMutableArray arrayWithArray:array];
        
        // 回到主線程刷新UI
        dispatch_async(dispatch_get_main_queue(), ^{
            [weakSelf.tableView reloadData];
        });
        
    });
}

#pragma mark - UITableView代理
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.dataArray.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellId = @"cellId";
    UserCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
    if (cell == nil) {
        cell = [[[NSBundle mainBundle] loadNibNamed:@"UserCell" owner:nil options:nil] lastObject];
        NSLog(@"%ld", indexPath.row);
    }

    // 顯示數(shù)據(jù)
    User *model = self.dataArray[indexPath.row];
    NSLog(@"%@", model.country);
    [cell config:model];

    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 80;
}

// 刪除
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
#warning 刪除數(shù)據(jù)的順序(從數(shù)據(jù)庫刪除和數(shù)據(jù)源刪除的順序不能調(diào)換)
        // 從數(shù)據(jù)庫刪除
        User *user = self.dataArray[indexPath.row];
        [[DBManager sharedManager] deleteUser:user];
        
        // 數(shù)據(jù)源刪除
        [self.dataArray removeObjectAtIndex:indexPath.row];
        
        // UI刪除
        [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}

// 修改
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    DetailViewController *dCtrl = [[DetailViewController alloc] init];
    dCtrl.user = self.dataArray[indexPath.row];
    
    [self.navigationController pushViewController:dCtrl animated:YES];
}

@end

三. 當(dāng)CoreData數(shù)據(jù)庫升級時我們需要

首先要明白的是升級的含義:

升級的意思是數(shù)據(jù)庫里面的類增加了或者類的屬性添加或修改了
升級是當(dāng)前需要發(fā)布的版本跟AppStore線上版本比較而言的

1. 假設(shè)我們添加一個屬性, 首先我們要建立一個新版本的模型, NSManagedObject Subclass也要重新生成
選中, 點擊Editor -> Add Model Version
更改當(dāng)前的Model Version
2. 修改DBManager.m中的- (void)createManagedContext方法
// 創(chuàng)建上下文對象
- (void)createManagedContext
{
    // 1. 創(chuàng)建描述文件的關(guān)聯(lián)對象
    // 文件的路徑
    …………………………………………………………………………………………  
    
    // 2. 關(guān)聯(lián)數(shù)據(jù)庫文件(SQLite)
    …………………………………………………………………………………………        
    
    /*
     - (NSPersistentStore *)addPersistentStoreWithType:(NSString *)storeType configuration:(NSString *)configuration URL:(NSURL *)storeURL options:(NSDictionary *)options error:(NSError **)error;
     
     方法中的options在CoreData數(shù)據(jù)庫升級的時候使用
     升級的意思是數(shù)據(jù)庫里面的類增加了或者類的屬性添加或修改了
     升級是當(dāng)前需要發(fā)布的版本跟AppStore線上版本比較而言的
     */
    NSDictionary *dict = @{NSMigratePersistentStoresAutomaticallyOption:[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption:[NSNumber numberWithBool:YES]};
    [coor addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:sqliteUrl options:dict error:nil];
    
    // 3. 創(chuàng)建上下文對象, 跟上面的對象關(guān)聯(lián)起來
    …………………………………………………………………………………………  
}
3. 模擬處理country屬性
4. 如果原有的數(shù)據(jù)庫文件內(nèi)有數(shù)據(jù)的話, 需要刪除原來的數(shù)據(jù)庫文件, 否則可能會報錯(可能是數(shù)據(jù)結(jié)構(gòu)問題)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末续徽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子纫版,更是在濱河造成了極大的恐慌客情,老刑警劉巖膀斋,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仰担,死亡現(xiàn)場離奇詭異,居然都是意外死亡赂苗,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門朴沿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赌渣,“玉大人昌犹,你說我怎么就攤上這事祭隔。” “怎么了千贯?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵搔谴,是天一觀的道長桩撮。 經(jīng)常有香客問我店量,道長,這世上最難降的妖魔是什么右钾? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任舀射,我火速辦了婚禮怀伦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘邢羔。我一直安慰自己张抄,他們只是感情好洼怔,可當(dāng)我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布镣隶。 她就那樣靜靜地躺著安岂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪咙边。 梳的紋絲不亂的頭發(fā)上次员,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天淑蔚,我揣著相機與錄音刹衫,去河邊找鬼。 笑死音羞,一個胖子當(dāng)著我的面吹牛仓犬,可吹牛的內(nèi)容都是我干的婶肩。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼险毁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起鲸鹦,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤齐板,失蹤者是張志新(化名)和其女友劉穎葛菇,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體济舆,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡滋觉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年椎侠,在試婚紗的時候發(fā)現(xiàn)自己被綠了肺蔚。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片儡羔。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡汰蜘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出苛坚,到底是詐尸還是另有隱情泼舱,我是刑警寧澤枷莉,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布笤妙,位于F島的核電站噪裕,受9級特大地震影響膳音,放射性物質(zhì)發(fā)生泄漏铃诬。R本人自食惡果不足惜氧急,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一吩坝、第九天 我趴在偏房一處隱蔽的房頂上張望哑蔫。 院中可真熱鬧闸迷,春花似錦、人聲如沸逮走。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽妖谴。三九已至,卻和暖如春嗡载,著一層夾襖步出監(jiān)牢的瞬間洼滚,已是汗流浹背琳轿。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留吧秕,地道東北人迹炼。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓斯入,卻偏偏與公主長得像刻两,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子滋迈,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,033評論 2 355

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