Realm的簡單使用

前言

由于最近項(xiàng)目中在用Realm箱蟆,所以把自己實(shí)踐過程中的一些心得總結(jié)分享一下。

Realm是由Y Combinator孵化的創(chuàng)業(yè)團(tuán)隊(duì)開源出來的一款可以用于iOS(同樣適用于Swift&Objective-C)和Android的跨平臺移動數(shù)據(jù)庫。目前最新版是Realm 2.0.2,支持的平臺包括Java,Objective-C丽旅,Swift,React Native纺棺,Xamarin榄笙。

Realm官網(wǎng)上說了好多優(yōu)點(diǎn),我覺得選用Realm的最吸引人的優(yōu)點(diǎn)就三點(diǎn):

跨平臺:現(xiàn)在很多應(yīng)用都是要兼顧iOS和Android兩個平臺同時開發(fā)祷蝌。如果兩個平臺都能使用相同的數(shù)據(jù)庫茅撞,那就不用考慮內(nèi)部數(shù)據(jù)的架構(gòu)不同,使用Realm提供的API巨朦,可以使數(shù)據(jù)持久化層在兩個平臺上無差異化的轉(zhuǎn)換米丘。

簡單易用:Core Data 和 SQLite 冗余、繁雜的知識和代碼足以嚇退絕大多數(shù)剛?cè)腴T的開發(fā)者糊啡,而換用 Realm拄查,則可以極大地減少學(xué)習(xí)成本,立即學(xué)會本地化存儲的方法棚蓄。毫不吹噓的說堕扶,把官方最新文檔完整看一遍,就完全可以上手開發(fā)了梭依。

可視化:Realm 還提供了一個輕量級的數(shù)據(jù)庫查看工具稍算,在Mac Appstore 可以下載“Realm Browser”這個工具,開發(fā)者可以查看數(shù)據(jù)庫當(dāng)中的內(nèi)容役拴,執(zhí)行簡單的插入和刪除數(shù)據(jù)的操作糊探。畢竟,很多時候河闰,開發(fā)者使用數(shù)據(jù)庫的理由是因?yàn)橐峁┮恍┧^的“知識庫”科平。

Realm Browser

“Realm Browser”這個工具調(diào)試起Realm數(shù)據(jù)庫實(shí)在太好用了,強(qiáng)烈推薦姜性。

[RLMRealmConfiguration defaultConfiguration].fileURL

打印出Realm 數(shù)據(jù)庫地址,然后在Finder中??G跳轉(zhuǎn)到對應(yīng)路徑下,用Realm Browser打開對應(yīng)的.realm文件就可以看到數(shù)據(jù)啦.

如果是使用真機(jī)調(diào)試的話“Xcode->Window->Devices(??2)”,然后找到對應(yīng)的設(shè)備與項(xiàng)目,點(diǎn)擊Download Container匠抗,導(dǎo)出xcappdata文件后,顯示包內(nèi)容,進(jìn)到AppData->Documents,使用Realm Browser打開.realm文件即可.

自2012年起, Realm 就已經(jīng)開始被用于正式的商業(yè)產(chǎn)品中了污抬。經(jīng)過4年的使用,逐步趨于穩(wěn)定。

Realm 安裝

使用 Realm 構(gòu)建應(yīng)用的基本要求:

  1. iOS 7 及其以上版本, macOS 10.9 及其以上版本印机,此外 Realm 支持 tvOS 和 watchOS 的所有版本矢腻。
  2. 需要使用 Xcode 7.3 或者以后的版本。

注意: 這里如果是純的OC項(xiàng)目射赛,就安裝OC的Realm多柑,如果是純的Swift項(xiàng)目,就安裝Swift的Realm楣责。如果是混編項(xiàng)目竣灌,就需要安裝OC的Realm,然后要把 Swift/RLMSupport.swift 文件一同編譯進(jìn)去秆麸。

RLMSupport.swift這個文件為 Objective-C 版本的 Realm 集合類型中引入了 Sequence 一致性初嘹,并且重新暴露了一些不能夠從 Swift 中進(jìn)行原生訪問的 Objective-C 方法,例如可變參數(shù) (variadic arguments)沮趣。更加詳細(xì)的說明見官方文檔屯烦。

推薦的安裝方法:

  1. CocoaPods,在項(xiàng)目的Podfile中房铭,添加pod 'Realm'驻龟,在終端運(yùn)行pod install。
  2. Static Framework
  • 下載 Realm 的最新版本并解壓缸匪,將 Realm.framework 從 ios/static/文件夾拖曳到您 Xcode 項(xiàng)目中的文件導(dǎo)航器當(dāng)中翁狐。確保 Copy items if needed 選中然后單擊 Finish;
  • 在 Xcode 文件導(dǎo)航器中選擇您的項(xiàng)目凌蔬,然后選擇您的應(yīng)用目標(biāo)露懒,進(jìn)入到 Build Phases 選項(xiàng)卡中。在 Link Binary with Libraries 中單擊 + 號然后添加libc++.dylib龟梦;

Realm 中的相關(guān)術(shù)語

為了能更好的理解Realm的使用隐锭,先介紹一下涉及到的相關(guān)術(shù)語。

RLMRealm:Realm是框架的核心所在计贰,是我們構(gòu)建數(shù)據(jù)庫的訪問點(diǎn)钦睡,就如同Core Data的管理對象上下文(managed object context)一樣。出于簡單起見躁倒,realm提供了一個默認(rèn)的defaultRealm( )的便利構(gòu)造器方法荞怒。

RLMObject:這是我們自定義的Realm數(shù)據(jù)模型。創(chuàng)建數(shù)據(jù)模型的行為對應(yīng)的就是數(shù)據(jù)庫的結(jié)構(gòu)秧秉。要創(chuàng)建一個數(shù)據(jù)模型褐桌,我們只需要繼承RLMObject,然后設(shè)計(jì)我們想要存儲的屬性即可象迎。

關(guān)系(Relationships):通過簡單地在數(shù)據(jù)模型中聲明一個RLMObject類型的屬性荧嵌,我們就可以創(chuàng)建一個“一對多”的對象關(guān)系呛踊。同樣地,我們還可以創(chuàng)建“多對一”和“多對多”的關(guān)系啦撮。

寫操作事務(wù)(Write Transactions):數(shù)據(jù)庫中的所有操作谭网,比如創(chuàng)建、編輯赃春,或者刪除對象愉择,都必須在事務(wù)中完成≈校“事務(wù)”是指位于write閉包內(nèi)的代碼段锥涕。

查詢(Queries):要在數(shù)據(jù)庫中檢索信息,我們需要用到“檢索”操作狭吼。檢索最簡單的形式是對Realm( )數(shù)據(jù)庫發(fā)送查詢消息层坠。如果需要檢索更復(fù)雜的數(shù)據(jù),那么還可以使用斷言(predicates)搏嗡、復(fù)合查詢以及結(jié)果排序等等操作窿春。

RLMResults:這個類是執(zhí)行任何查詢請求后所返回的類,其中包含了一系列的RLMObject對象采盒。RLMResults和NSArray類似旧乞,我們可以用下標(biāo)語法來對其進(jìn)行訪問,并且還可以決定它們之間的關(guān)系磅氨。不僅如此尺栖,它還擁有許多更強(qiáng)大的功能,包括排序烦租、查找等等操作延赌。

Realm如何使用

由于Realm的API極為友好,一看就懂叉橱,所以這里就按照平時開發(fā)的順序挫以,把需要用到的都梳理一遍。

  1. 創(chuàng)建數(shù)據(jù)庫
  • 一般地,我們使用的為默認(rèn)的Realm數(shù)據(jù)庫,即調(diào)用[RLMRealm defaultRealm]來初始化以及訪問我們的realm變量窃祝。這個方法將會返回一個 RLMRealm對象掐松,并指向您應(yīng)用的 Documents (iOS) 文件夾下的一個名為“default.realm”的文件。

  • 用自己創(chuàng)建的數(shù)據(jù)庫

-(void)creatDataBaseWithName:(NSString *)databaseName {
    NSArray *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [docPath objectAtIndex:0];
    NSString *filePath = [path stringByAppendingPathComponent:databaseName];
    NSLog(@"數(shù)據(jù)庫目錄 = %@",filePath);
    RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
    config.fileURL = [NSURL URLWithString:filePath];
    config.objectClasses = @[MyClass.class, MyOtherClass.class];
    config.readOnly = NO;
    int currentVersion = 1.0;
    config.schemaVersion = currentVersion;
    config.migrationBlock = ^(RLMMigration *migration , uint64_t oldSchemaVersion) {
       // 這里是設(shè)置數(shù)據(jù)遷移的block
        if (oldSchemaVersion < currentVersion) {
        }
    };
    [RLMRealmConfiguration setDefaultConfiguration:config];
}

拓展:

// 查詢指定的 Realm 數(shù)據(jù)庫
RLMRealm *petsRealm = [RLMRealm realmWithPath:@"pets.realm"]; // 獲得一個指定的 Realm 數(shù)據(jù)庫
RLMResults *otherDogs = [Dog allObjectsInRealm:petsRealm]; // 從該 Realm 數(shù)據(jù)庫中粪小,檢索所有狗狗

創(chuàng)建數(shù)據(jù)庫主要設(shè)置RLMRealmConfiguration大磺,設(shè)置數(shù)據(jù)庫名字和存儲地方。把路徑以及數(shù)據(jù)庫名字拼接好字符串探膊,賦值給fileURL即可杠愧。

objectClasses這個屬性是用來控制對哪個類能夠存儲在指定 Realm 數(shù)據(jù)庫中做出限制。例如逞壁,如果有兩個團(tuán)隊(duì)分別負(fù)責(zé)開發(fā)您應(yīng)用中的不同部分流济,并且同時在應(yīng)用內(nèi)部使用了 Realm 數(shù)據(jù)庫锐锣,那么您肯定不希望為它們協(xié)調(diào)進(jìn)行數(shù)據(jù)遷移您可以通過設(shè)置RLMRealmConfiguration的 objectClasses屬性來對類做出限制。objectClasses一般可以不用設(shè)置袭灯。
readOnly是控制是否只讀屬性刺下。

2.建表

  • 創(chuàng)建簡單數(shù)據(jù)模型
#import <Realm/Realm.h>

@interface MJCoutryModel : RLMObject

@property (nonatomic, copy) NSString *countryId;

@property (nonatomic, copy) NSString *country;

@property (nonatomic, copy) NSString *dialCode;

@end

RLM_ARRAY_TYPE(MJCoutryModel)

可以設(shè)置配置

//主鍵
+ (NSString *)primaryKey {
    return @"countryId";
}

////設(shè)置屬性默認(rèn)值
//+ (NSDictionary *)defaultPropertyValues {
//    return @{@"dialCode":@"00" };
//}

//設(shè)置忽略屬性,即不存到realm數(shù)據(jù)庫中
+ (NSArray<NSString *> *)ignoredProperties {
    return @[@"country"];
}

//一般來說,屬性為nil的話realm會拋出異常,但是如果實(shí)現(xiàn)了這個方法的話,就只有countryId為nil會拋出異常,也就是說現(xiàn)在dialCode屬性可以為空了
+ (NSArray *)requiredProperties {
    return @[@"countryId"];
}

//設(shè)置索引,可以加快檢索的速度
+ (NSArray *)indexedProperties {
    return @[@"countryId"];
}
  • 創(chuàng)建嵌套數(shù)據(jù)模型
#import <Realm/Realm.h>
@class Person;
// 狗狗的數(shù)據(jù)模型
@interface Dog : RLMObject
@property NSString *name;
@property Person   *owner;
@end
RLM_ARRAY_TYPE(Dog) // 定義RLMArray<Dog>
// 狗狗主人的數(shù)據(jù)模型
@interface Person : RLMObject
@property NSString      *name;
@property NSDate        *birthdate;
// 通過RLMArray建立關(guān)系
@property RLMArray<Dog> *dogs;
@end
RLM_ARRAY_TYPE(Person) // 定義RLMArray<Person>

注意:RLMObject 官方建議不要加上 Objective-C的property attributes(如nonatomic, atomic, strong, copy, weak 等等)假如設(shè)置了,這些attributes會一直生效直到RLMObject被寫入realm數(shù)據(jù)庫稽荧。

3.增

    Dog *myDog = [[Dog alloc] init];
    myDog.name = @"小花";
    
    Dog *yourDog = [[Dog alloc] init];
    yourDog.name = @"小黑";
    
    Person *me = [[Person alloc] initWithValue:@[@"小明",[NSDate dateWithTimeIntervalSinceNow:1],@[myDog,yourDog]]];
    
    yourDog.owner = me;
    myDog.owner = me;
    
    
    RLMRealm *realm = [RLMRealm defaultRealm];
    [realm beginWriteTransaction];
    [realm addObject:yourDog];
    [realm addObject:myDog];
    [realm addObject:me];
    [realm commitWriteTransaction];

使用Realm進(jìn)行數(shù)據(jù)管理的方式:
方式一:

 RLMRealm *realm = [RLMRealm defaultRealm];

// 開放RLMRealm事務(wù)
[realm beginWriteTransaction];

// 在開放開放/提交事務(wù)之間進(jìn)行數(shù)據(jù)處理

// 提交事務(wù)
[realm commitWriteTransaction];

方式二:

[realm transactionWithBlock:^{

 // 進(jìn)行數(shù)據(jù)處理

}];

4.刪

清空所有數(shù)據(jù)

   
    RLMRealm *realm = [RLMRealm defaultRealm];
    RLMResults<Person *> *personResults = [Person allObjects];
    if (personResults.count > 0) {
        [realm beginWriteTransaction];
        [realm deleteObjects:personResults];
        [realm commitWriteTransaction];
    }
    
    RLMResults<Dog *> *dogResults = [Dog allObjects];
        [realm beginWriteTransaction];
        [realm deleteAllObjects];
        [realm commitWriteTransaction];

清空某條數(shù)據(jù)

   
    RLMRealm *realm = [RLMRealm defaultRealm];
    RLMResults<MJCoutryModel *> *walletResults = [MJCoutryModel allObjects];
    MJCoutryModel *wallet1 = [walletResults firstObject];

    [realm beginWriteTransaction];
    [realm deleteObject:wallet1];
    [realm commitWriteTransaction];

5.查
數(shù)據(jù)庫查詢

// 查詢默認(rèn)的 Realm 數(shù)據(jù)庫
RLMResults *dogs = [Dog allObjects]; // 從默認(rèn)的 Realm 數(shù)據(jù)庫中,檢索所有狗狗

如果有需要,也可以查詢指定的數(shù)據(jù)庫

// 查詢指定的 Realm 數(shù)據(jù)庫
RLMRealm *petsRealm = [RLMRealm realmWithPath:@"pets.realm"]; // 獲得一個指定的 Realm 數(shù)據(jù)庫
RLMResults *otherDogs = [Dog allObjectsInRealm:petsRealm]; // 從該 Realm 數(shù)據(jù)庫中工腋,檢索所有狗狗

條件查詢
1.使用斷言字符串查詢:

RLMResults *tanDogs = [Dog objectsWhere:@"color = '棕黃色' AND name BEGINSWITH '大'" ascending:YES];

2.使用 NSPredicate 查詢

NSPredicate *pred = [NSPredicate predicateWithFormat:@"color = %@ AND name BEGINSWITH %@",
                                                 @"棕黃色", @"大"];
RLMResults *tanDogs = [Dog objectsWithPredicate:pred];

3.鏈?zhǔn)讲樵?br> 如果我們想獲得獲得棕黃色狗狗的查詢結(jié)果姨丈,并且在這個查詢結(jié)果的基礎(chǔ)上再獲得名字以“大”開頭的棕黃色狗狗。

RLMResults *tanDogs = [Dog objectsWhere:@"color = '棕黃色'"];
RLMResults *tanDogsWithBNames = [tanDogs objectsWhere:@"name BEGINSWITH '大'"];

6.改

  • 當(dāng)沒有主鍵的情況下擅腰,需要先查詢蟋恬,再修改數(shù)據(jù)。
   // 先查詢
    RLMRealm *realm = [RLMRealm defaultRealm];
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"dialCode = %@ AND country BEGINSWITH %@",@"123", @"中國"];
    RLMResults<MJCoutryModel *> *walletResults = [MJCoutryModel objectsWithPredicate:pred];
   // 再修改
    for (int i = 0; i < walletResults.count; i++) {
        MJCoutryModel *wallet = walletResults[i];
        [realm beginWriteTransaction];
        wallet.country = @"托馬斯品欽";
        [realm commitWriteTransaction];
    }
  • 當(dāng)有主鍵的情況下趁冈,有以下幾個非常好用的API
    RLMRealm *realm = [RLMRealm defaultRealm];
    
    MJCoutryModel *country = [[MJCoutryModel alloc] init];
    country.countryId = @"21";
    country.country = @"ee21";
    country.dialCode = @"22";
    
    [realm beginWriteTransaction];
    // 方法一
    [MJCoutryModel createOrUpdateInRealm:realm withValue:country];
    // 方法二
    [realm addOrUpdateObject:country];
    
    [realm commitWriteTransaction];

addOrUpdateObject: 會去先查找有沒有傳入的Car相同的主鍵歼争,如果有,就更新該條數(shù)據(jù)渗勘。這里需要注意沐绒,addOrUpdateObject這個方法不是增量更新,所有的值都必須有旺坠,如果有哪幾個值是null乔遮,那么就會覆蓋原來已經(jīng)有的值,這樣就會出現(xiàn)數(shù)據(jù)丟失的問題取刃。

createOrUpdateInRealm:withValue:這個方法是增量更新的蹋肮,后面?zhèn)饕粋€字典,使用這個方法的前提是有主鍵璧疗。方法會先去主鍵里面找有沒有字典里面?zhèn)魅氲闹麈I的記錄坯辩,如果有,就只更新字典里面的子集崩侠。如果沒有漆魔,就新建一條記錄。

數(shù)據(jù)遷移

當(dāng)您使用任意一個數(shù)據(jù)庫時啦膜,您隨時都可能打算修改您的數(shù)據(jù)模型有送。通過設(shè)置 RLMRealmConfiguration.schemaVersion 以及RLMRealmConfiguration.migrationBlock 可以定義一個遷移操作以及與之關(guān)聯(lián)的架構(gòu)版本。 遷移閉包將會提供提供相應(yīng)的邏輯操作僧家,以讓數(shù)據(jù)模型從之前的架構(gòu)轉(zhuǎn)換到新的架構(gòu)中來雀摘。 每當(dāng)通過配置創(chuàng)建完一個 RLMRealm 之后,遷移閉包將會在遷移需要的時候八拱,將給定的架構(gòu)版本應(yīng)用到更新 RLMRealm 操作中阵赠。
如下所示是最簡單的數(shù)據(jù)遷移的必需流程:

// 在 [AppDelegate didFinishLaunchingWithOptions:] 中進(jìn)行配置

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.schemaVersion = 2;
config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion)
{
    // enumerateObjects:block: 遍歷了存儲在 Realm 文件中的每一個“Person”對象
    [migration enumerateObjects:MJCoutryModel.className block:^(RLMObject *oldObject, RLMObject *newObject) {
        // 只有當(dāng) Realm 數(shù)據(jù)庫的架構(gòu)版本為 0 的時候涯塔,才添加 “fullName” 屬性
        if (oldSchemaVersion < 1) {
            newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@", oldObject[@"firstName"], oldObject[@"lastName"]];
        }
        // 只有當(dāng) Realm 數(shù)據(jù)庫的架構(gòu)版本為 0 或者 1 的時候,才添加“email”屬性
        if (oldSchemaVersion < 2) {
            newObject[@"email"] = @"";
        }
       // 替換屬性名
       if (oldSchemaVersion < 3) { // 重命名操作應(yīng)該在調(diào)用 `enumerateObjects:` 之外完成 
            [migration renamePropertyForClass:Person.className oldName:@"yearsSinceBirth" newName:@"age"]; }
    }];
};
[RLMRealmConfiguration setDefaultConfiguration:config];
// 現(xiàn)在我們已經(jīng)成功更新了架構(gòu)版本并且提供了遷移閉包清蚀,打開舊有的 Realm 數(shù)據(jù)庫會自動執(zhí)行此數(shù)據(jù)遷移匕荸,然后成功進(jìn)行訪問
[RLMRealm defaultRealm];

參考鏈接

Realm官網(wǎng)
Realm官方文檔
Realm GitHub
參考博客一
參考博客二

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市枷邪,隨后出現(xiàn)的幾起案子榛搔,更是在濱河造成了極大的恐慌,老刑警劉巖东揣,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件践惑,死亡現(xiàn)場離奇詭異,居然都是意外死亡嘶卧,警方通過查閱死者的電腦和手機(jī)尔觉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來芥吟,“玉大人侦铜,你說我怎么就攤上這事≈油遥” “怎么了钉稍?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長携添。 經(jīng)常有香客問我嫁盲,道長,這世上最難降的妖魔是什么烈掠? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任羞秤,我火速辦了婚禮,結(jié)果婚禮上左敌,老公的妹妹穿的比我還像新娘瘾蛋。我一直安慰自己,他們只是感情好矫限,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布哺哼。 她就那樣靜靜地躺著,像睡著了一般叼风。 火紅的嫁衣襯著肌膚如雪取董。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天无宿,我揣著相機(jī)與錄音茵汰,去河邊找鬼。 笑死孽鸡,一個胖子當(dāng)著我的面吹牛蹂午,可吹牛的內(nèi)容都是我干的栏豺。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼豆胸,長吁一口氣:“原來是場噩夢啊……” “哼奥洼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起晚胡,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤灵奖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后估盘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體桑寨,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年忿檩,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爆阶。...
    茶點(diǎn)故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡燥透,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出辨图,到底是詐尸還是另有隱情班套,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布故河,位于F島的核電站吱韭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏鱼的。R本人自食惡果不足惜理盆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凑阶。 院中可真熱鬧猿规,春花似錦、人聲如沸宙橱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春烟零,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背姓言。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工莽龟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人猬仁。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓帝璧,卻偏偏與公主長得像先誉,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子的烁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評論 2 348

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