反射 Mirror | Swift 動(dòng)態(tài)性

Mirror是Swift中的反射機(jī)制凄敢,反射就是可以動(dòng)態(tài)的獲取類(lèi)型以及成員信息,同時(shí)也可以在運(yùn)行時(shí)動(dòng)態(tài)的調(diào)用方法和屬性等短蜕。

1. Mirror 簡(jiǎn)介

Mirror是Swift中的反射機(jī)制的實(shí)現(xiàn)癣朗,它的本質(zhì)是一個(gè)結(jié)構(gòu)體。
創(chuàng)建 Mirror 最簡(jiǎn)單的方式就是使用 reflecting 構(gòu)造器:

public init(reflecting subject: Any)

正如你所見(jiàn)捏萍,對(duì)象的類(lèi)型是 Any。這是 Swift 中最通用的類(lèi)型空闲。Swift 中的任何東西至少都是 Any類(lèi)型的令杈。這樣一來(lái) mirror 就可以兼容 struct, class, enum, Tuple, Array, Dictionary, set 等。

下面列舉了 Mirror 可用的屬性 / 方法:

  • let children: Children:對(duì)象的子節(jié)點(diǎn)碴倾。
  • displayStyle: Mirror.DisplayStyle?:對(duì)象的展示類(lèi)型
  • let subjectType: Any.Type:對(duì)象的類(lèi)型
  • func superclassMirror() -> Mirror?:對(duì)象父類(lèi)的 mirror

displayStyle

public enum DisplayStyle {
    case Struct
    case Class
    case Enum
    case Tuple
    case Optional
    case Collection
    case Dictionary
    case Set
}

它會(huì)返回 DisplayStyle enum 的其中一種情況逗噩。如果你想要對(duì)某種不支持的類(lèi)型進(jìn)行反射,你會(huì)得到一個(gè)空的 Optional 值跌榔。
例如:
正如之前我們知道的异雁,反射只要求對(duì)象是 Any 類(lèi)型,而且Swift 標(biāo)準(zhǔn)庫(kù)中還有很多類(lèi)型為 Any 的東西沒(méi)有被列舉在上面的 DisplayStyle enum 中僧须。如果試圖反射它們中間的某一個(gè)又會(huì)發(fā)生什么呢纲刀?比如 closure。

let closure = { (a: Int) -> Int in return a * 2 }
let aMirror = Mirror(reflecting: closure)
print("\(aMirror)----------\(aMirror.displayStyle)")
//Mirror for (Int) -> Int----------nil

children

這會(huì)返回一個(gè)包含了對(duì)象所有的子節(jié)點(diǎn)的 AnyForwardCollection<Child>担平。這些子節(jié)點(diǎn)不單單限于 Array 或者 Dictionary 中的條目示绊。諸如 struct 或者 class 中所有的屬性也是由 AnyForwardCollection<Child> 這個(gè)屬性返回的子節(jié)點(diǎn)。AnyForwardCollection 協(xié)議意味著這是一個(gè)支持遍歷的 Collection 類(lèi)型暂论。

public class Store {
    let storesToDisk: Bool = true
}
public class BookmarkStore: Store {
    let itemCount: Int = 10
}
public struct Bookmark {
     enum Group {
     case Tech
     case News
     }
     private let store = {
           return BookmarkStore()
     }()
     let title: String?
     let url: NSURL
     let keywords: [String]
     let group: Group
}
let aBookmark = Bookmark(title: "Appventure", url: NSURL(string: "appventure.me")!, keywords: ["Swift", "iOS", "OSX"], group: .Tech)
        
let aMirror = Mirror(reflecting: aBookmark)
for case let (label?, value) in aMirror.children {
    print (label, value)
}
//輸出:
//store TestDemo3.ViewController.BookmarkStore
//title Optional("Appventure")
//url appventure.me
//keywords ["Swift", "iOS", "OSX"]
//group Tech

SubjectType

這是對(duì)象的類(lèi)型:

print(aMirror.subjectType)
//輸出 : Bookmark
print(Mirror(reflecting: 5).subjectType)
//輸出 : Int
print(Mirror(reflecting: "test").subjectType)
//輸出 : String
print(Mirror(reflecting: NSNull()).subjectType)
//輸出 : NSNull

SuperclassMirror

這是我們對(duì)象父類(lèi)的 mirror面褐。如果這個(gè)對(duì)象不是一個(gè)類(lèi),它會(huì)是一個(gè)空的 Optional 值取胎。如果對(duì)象的類(lèi)型是基于類(lèi)的展哭,你會(huì)得到一個(gè)新的 Mirror:

// 試試 struct
print(Mirror(reflecting: aBookmark).superclassMirror)
// 輸出: nil
// 試試 class
print(Mirror(reflecting: aBookmark.store).superclassMirror)
// 輸出: Optional(Mirror for Store)
2.反射 Mirror 使用

1.Mirror 轉(zhuǎn)換對(duì)象為字典

  • 定義如下對(duì)象:
    struct Person {
        var name: String = "YDW"
        var isMale: Bool = true
        var birthday: Date = Date()
    }
     
    class Animal: NSObject {
        private var eat: String = "吃"
        var age: Int = 0
        var optionValue: String?
    }
     
    class Cat: Animal {
        var like: [String] = ["mouse", "fish"]
        var master = Person()
    }
  • 遍歷出字典:
   func mapDic(mirror: Mirror) -> [String: Any] {
        var dic: [String: Any] = [:]
        for child in mirror.children {
            // 如果沒(méi)有l(wèi)abel就會(huì)被拋棄
            if let label = child.label {
                let propertyMirror = Mirror(reflecting: child.value)
                   dic[label] = child.value
            }
        }
        // 添加父類(lèi)屬性
        if let superMirror = mirror.superclassMirror {
            let superDic = mapDic(mirror: superMirror)
            for p in superDic {
                dic[p.key] = p.value
            }
        }
        return dic
    }
  • 使用 Mirror 轉(zhuǎn)換對(duì)象并打印結(jié)果, 可以看到可以打印出私有屬性:
// Mirror使用
    let objc  = Cat()
    let  mirror = Mirror(reflecting: objc)
    let mirrorDic = mapDic(mirror: mirror)
    print(mirrorDic)
     
// 打印結(jié)果
["master": TestDemo3.ViewController.Person(name: "YDW", isMale: true, birthday: 2022-07-15 03:51:59 +0000), "eat": "吃", "optionValue": nil, "age": 0, "like": ["mouse", "fish"]]
  • 在實(shí)際運(yùn)用中扼菠,可以將應(yīng)用于元組參數(shù)傳遞(比如網(wǎng)絡(luò)請(qǐng)求傳參摄杂,傳入元組,網(wǎng)絡(luò)請(qǐng)求時(shí)轉(zhuǎn)換為字典)循榆,優(yōu)點(diǎn):外部使用知道具體傳入什么參數(shù)析恢,參數(shù)更改不影響方法錯(cuò)誤。
// 外部參數(shù)定義
    var params = (title: "name", comment: "Mirror")
     
    // 網(wǎng)絡(luò)層統(tǒng)一轉(zhuǎn)換為字典秧饮,進(jìn)行網(wǎng)路請(qǐng)求
    let paramsDic = mapDic(mirror: Mirror(reflecting: params))
    print(paramsDic)
     
    // 打印結(jié)果
    ["title": "name", "comment": "Mirror"]
  • 需要注意是只能傳入基本類(lèi)型映挂,并且元組參數(shù)要命名,如果直接使用(“name”,“Mirror”)則會(huì)變成下面這種情況:
// 外部參數(shù)定義
    var params = ("name","Mirror")
     
    // 網(wǎng)絡(luò)層統(tǒng)一轉(zhuǎn)換為字典盗尸,進(jìn)行網(wǎng)路請(qǐng)求
    let paramsDic = mapDic(mirror: Mirror(reflecting: params))
    print(paramsDic)
    // 打印
    [".1": "Mirror", ".0": "name"]
  1. JSON 解析
  • 定義一個(gè) YDWTeacher 類(lèi):
class YDWTeacher {
    var age = 18
    var name = "YDW"
}
  • 運(yùn)用 Mirror 來(lái)解析柑船,實(shí)現(xiàn)代碼如下:
// JSON解析
    func test(_ obj: Any) -> Any {
        let mirror = Mirror(reflecting: obj)
        // 判斷條件 - 遞歸終止條件
        guard !mirror.children.isEmpty else {
            return obj
        }
        // 字典
        var keyValue: [String: Any] = [:]
        // 遍歷
        for children in mirror.children {
            if let keyName = children.label {
                // 遞歸調(diào)用
                keyValue[keyName] = test(children.value)
            } else {
                print("children.label 為空")
            }
        }
        return keyValue
    }
    
    // 使用
    var t = YDWTeacher()
    print(test(t))
  • 運(yùn)行代碼,打印結(jié)果如下:
["name": "YDW","age": 18]
  • 如果想在工程中大量的使用上述的 JSON 解析泼各,可以將 Mirror JSON 解析抽取成一個(gè)協(xié)議鞍时,然后提供一個(gè)默認(rèn)實(shí)現(xiàn),讓類(lèi)遵守協(xié)議,如下:
// 定義JSON解析協(xié)議
    protocol CustomJSONMap {
        func jsonMap() -> Any
    }
    
    // 提供默認(rèn)實(shí)現(xiàn)
    extension CustomJSONMap{
        func jsonMap() -> Any{
            let mirror = Mirror(reflecting: self)
            // 遞歸終止條件
            guard !mirror.children.isEmpty else {
                return self
            }
            // 字典逆巍,用于存儲(chǔ)json數(shù)據(jù)
            var keyValue: [String: Any] = [:]
            // 遍歷
            for children in mirror.children {
                if let value = children.value as? CustomJSONMap {
                    if let keyName = children.label {
                        // 遞歸
                        keyValue[keyName] = value.jsonMap()
                    } else {
                        print("key是nil")
                    }
                } else {
                    print("當(dāng)前-\(children.value)-沒(méi)有遵守協(xié)議")
                }
            }
            return keyValue
        }
    }
    
    // 讓類(lèi)遵守協(xié)議(注意:類(lèi)中屬性的類(lèi)型也需要遵守協(xié)議及塘,否則無(wú)法解析)
    class YDWTeacher: CustomJSONMap {
        var age = 18
        var name = "YDW"
    }
    
    // 使用
    var t = YDWTeacher()
    print(t.jsonMap())
  • 運(yùn)行,可以發(fā)現(xiàn)并沒(méi)達(dá)到我們預(yù)想的結(jié)果锐极,這是因?yàn)?YDWTeacher 的屬性的類(lèi)型也需要遵守 CustomJSONMap 協(xié)議:
當(dāng)前-18-沒(méi)有遵守協(xié)議
當(dāng)前-YDW-沒(méi)有遵守協(xié)議
  • 修改如下笙僚,這樣就可以達(dá)到我們預(yù)想的結(jié)果:
// Int、String遵守協(xié)議
extension Int: CustomJSONMap{}
extension String: CustomJSONMap{}

// 打印結(jié)果 
["name": "YDW", "age": 18]

3.錯(cuò)誤處理

  • 為了讓封裝的JSON 解析更加完善灵再,除了對(duì)正常返回的處理肋层,還需要對(duì)其中的錯(cuò)誤進(jìn)行處理,在上面的封裝中翎迁,采用的是 print 打印的栋猖,這樣并不規(guī)范,也不好維護(hù)及管理鸳兽。那么如何在 swift 中正確的表達(dá)錯(cuò)誤呢掂铐?
  • Swift 中,提供了 Error 協(xié)議來(lái)標(biāo)識(shí)當(dāng)前應(yīng)用程序發(fā)生錯(cuò)誤的情況揍异,其中 Error 的定義如下:
public protocol Error { }
  • 可以看到:Error 是一個(gè)空協(xié)議全陨,其中沒(méi)有任何實(shí)現(xiàn),這也就意味著可以遵守該協(xié)議衷掷,然后自定義錯(cuò)誤類(lèi)型辱姨,因此不管是 struct、Class戚嗅、enum雨涛,都可以遵循這個(gè) Error 來(lái)表示一個(gè)錯(cuò)誤。
  • 那么上面封裝的 JSON 解析修改錯(cuò)誤處理懦胞,首先定義一個(gè) JSONMapError 錯(cuò)誤枚舉替久,將默認(rèn)實(shí)現(xiàn)的 print 替換成枚舉類(lèi)型:
// 定義錯(cuò)誤類(lèi)型
enum JSONMapError: Error{
    case emptyKey
    case notConformProtocol
}
extension CustomJSONMap {
        func jsonMap() throws -> Any {
            let mirror = Mirror(reflecting: self)
            // 遞歸終止條件
            guard !mirror.children.isEmpty else {
                return self
            }
            // 字典,用于存儲(chǔ)json數(shù)據(jù)
            var keyValue: [String: Any] = [:]
            // 遍歷
            for children in mirror.children {
                if let value = children.value as? CustomJSONMap {
                    if let keyName = children.label {
                        // 遞歸
                        keyValue[keyName] = try value.jsonMap()
                    } else {
                        throw JSONMapError.emptyKey
                    }
                } else {
                    throw JSONMapError.notConformProtocol
                }
            }
            return keyValue
        }
    }
  • 封裝完成躏尉,使用如下:
// 使用時(shí)需要加上try
var t = YDWTeacher()
do{
     _ = try t.jsonMap()
}catch JSONMapError.emptyKey{
     print("???emptyKey????")
}catch JSONMapError.notConformProtocol{
     print("???notConformProtocol?????")
}catch{
}

4.獲取類(lèi)型蚯根,屬性個(gè)數(shù)及其值

  • 定義一個(gè)用戶類(lèi):
class YDWUser {
     var name: String = ""
     var nickName: String?
     var age: Int?
     var emails: [String]?
}
  • 然后創(chuàng)建一個(gè)用戶對(duì)象,并通過(guò)反射獲取這個(gè)對(duì)象的信息:
// 創(chuàng)建一個(gè)User實(shí)例對(duì)象
    let user = YDWUser()
    user.name = "DW"
    user.age = 18
    user.emails = ["12345@qq.com", "56789@qq.com"]
                 
    // 將user對(duì)象進(jìn)行反射
    let hMirror = Mirror(reflecting: user)
                 
    print("對(duì)象類(lèi)型:\(hMirror.subjectType)")
    print("對(duì)象子元素個(gè)數(shù):\(hMirror.children.count)")
                 
    print("--- 對(duì)象子元素的屬性名和屬性值分別如下 ---")
    for case let  (label?, value)  in  hMirror.children {
        print("屬性:\(label)     值:\(value)")
    }
  • 打印如下:
對(duì)象類(lèi)型:YDWUser
對(duì)象子元素個(gè)數(shù):4
--- 對(duì)象子元素的屬性名和屬性值分別如下 ---
屬性:name     值:DW
屬性:nickName     值:nil
屬性:age     值:Optional(18)
屬性:emails     值:Optional(["12345@qq.com", "56789@qq.com"])

5.通過(guò)屬性名(字符串)獲取對(duì)應(yīng)的屬性值胀糜,并對(duì)值做類(lèi)型判斷(包括是否為空)

  • 定義兩個(gè)方法:getValueByKey() 是用來(lái)根據(jù)傳入的屬性名字符串來(lái)獲取對(duì)象中對(duì)應(yīng)的屬性值颅拦,unwrap() 是用來(lái)給可選類(lèi)型拆包的(對(duì)于非可選類(lèi)型則返回原值):
// 根據(jù)屬性名字符串獲取屬性值
    func getValueByKey(obj: AnyObject, key: String) -> Any {
         let hMirror = Mirror (reflecting: obj)
         for case let (label?, value) in hMirror.children {
             if label == key {
                return unwrap(any: value)
             }
         }
         return  NSNull ()
    }
     
    // 將可選類(lèi)型(Optional)拆包
    func unwrap(any: Any ) ->  Any  {
         let mi =  Mirror (reflecting: any)
        if mi.displayStyle! != .optional {
             return any
         }
         
         if mi.children.count == 0 {
            return any
         }
         let  (_, some) = mi.children.first!
         return  some
    }
  • 用上例的 YDWUser 對(duì)象做測(cè)試:
// 創(chuàng)建一個(gè)User實(shí)例對(duì)象
    let user = YDWUser()
    user.name = "DW"
    user.age = 18
    user.emails = ["12345@qq.com", "56789@qq.com"]
     
    // 通過(guò)屬性名字符串獲取對(duì)應(yīng)的值
    let name = getValueByKey(obj: user, key:  "name")
    let nickName = getValueByKey(obj: user, key:  "nickName")
    let age = getValueByKey(obj: user, key:  "age")
    let emails = getValueByKey(obj: user, key:  "emails")
    let tel = getValueByKey(obj: user, key:  "tel")
    print(name, nickName, age, emails, tel)
     
    // 對(duì)于獲取到的值進(jìn)行類(lèi)型判斷
    if name is NSNull {
        print("name這個(gè)屬性不存在")
    } else if (name as? AnyObject) == nil {
        print("name這個(gè)屬性是個(gè)可選類(lèi)型,且為nil")
    } else if name is String {
        print("name這個(gè)屬性String類(lèi)型教藻,其值為:\(name)")
    }
    if tel is NSNull {
        print("tel這個(gè)屬性不存在")
    } else if (tel as? AnyObject) == nil {
        print("tel這個(gè)屬性是個(gè)可選類(lèi)型距帅,且為nil")
    } else if tel is String {
        print("tel這個(gè)屬性String類(lèi)型,其值為:\(tel)")
    }
  • 運(yùn)行程序括堤,打印如下:
DW nil 18 ["12345@qq.com", "56789@qq.com"] <null>
name這個(gè)屬性String類(lèi)型碌秸,其值為:DW
tel這個(gè)屬性不存在
3.Swift動(dòng)態(tài)性
  • 所謂動(dòng)態(tài):就是在運(yùn)行階段才知道自己的類(lèi)是什么
  • 父類(lèi)對(duì)象指向子類(lèi)對(duì)象绍移,是動(dòng)態(tài)特性,因?yàn)樵谶\(yùn)行的時(shí)候讥电,才知道這個(gè)變量真正的類(lèi)型是子類(lèi)
  • 具有方法動(dòng)態(tài)派發(fā)(函數(shù)表派發(fā)登夫,消息派發(fā))
  • 繼承自O(shè)C的類(lèi)Swift類(lèi),具有動(dòng)態(tài)特性
  • dynamic修飾的方法和屬性允趟,具有動(dòng)態(tài)特性
  • Swift中的反射機(jī)制,是動(dòng)態(tài)特性

靜態(tài)派發(fā)
在編譯期的時(shí)候鸦致,編譯器就知道要為某個(gè)方法調(diào)用某種實(shí)現(xiàn)

動(dòng)態(tài)派發(fā)
對(duì)于每個(gè)方法的調(diào)用潮剪,編譯器必須在方法列表中查找執(zhí)行方法的實(shí)現(xiàn),比如在運(yùn)行時(shí)判斷是選擇父類(lèi)的實(shí)現(xiàn)分唾,還是子類(lèi)的實(shí)現(xiàn)抗碰。對(duì)于對(duì)象的內(nèi)存都是在運(yùn)行時(shí)分配的,因此只能在運(yùn)行時(shí)執(zhí)行檢查

編譯型語(yǔ)言的函數(shù)派發(fā)方式

  • 直接派發(fā)(Direct Dispatch)
    編譯后確定了方法的調(diào)用地址(靜態(tài)派發(fā))绽乔,匯編代碼中弧蝇,直接跳到了方法的地址執(zhí)行,生成的匯編指令最少折砸,速度最快
    例如C語(yǔ)言看疗,C++默認(rèn)也是直接派發(fā)
    由于缺乏動(dòng)態(tài)性,無(wú)法實(shí)現(xiàn)多態(tài)
  • 函數(shù)表派發(fā)(Table Dispatch)
    在運(yùn)行時(shí)通過(guò)函數(shù)查找需要執(zhí)行的方法睦授,多一次查表的過(guò)程两芳,速度比直接派發(fā)慢
    C++的虛函數(shù)(Virtual Table),維護(hù)一個(gè)虛函數(shù)表去枷,對(duì)象創(chuàng)建的時(shí)候會(huì)保存虛表的指針怖辆,調(diào)用方之前,會(huì)從對(duì)象中取出虛表地址删顶,根據(jù)編譯時(shí)的方法偏移量從虛表取出方法的地址竖螃,跳到方法的地址執(zhí)行
  • 消息派發(fā)(Message Dispatch)
    objc消息發(fā)送機(jī)制
  • 性能:直接派發(fā) > 函數(shù)表派發(fā) > 消息機(jī)制派發(fā)

直接派發(fā)

  • 全局函數(shù)
  • 使用static聲明的方法
  • 使用final聲明的所有方法,使用final聲明的類(lèi)里面的所有方法
  • 使用private聲明的方法和屬性逗余,會(huì)隱式final聲明
  • 值類(lèi)型的方法特咆,比如structenum中的方法
  • extension中沒(méi)有使用@objc修飾的實(shí)例方法

函數(shù)表派發(fā)

  • 只有引用類(lèi)型才是函數(shù)表派發(fā)
  • 在Swift中,類(lèi)的方法默認(rèn)使用函數(shù)表派發(fā)的方式
  • Swift對(duì)于協(xié)議Protocol默認(rèn)使用的是函數(shù)表派發(fā)猎荠,協(xié)議可以為struct提供多態(tài)的支持
  • Swift的函數(shù)表叫做 witness table(C++叫做virtual table)
    1.每個(gè)子類(lèi)都有自己的表結(jié)構(gòu)
    2.對(duì)于類(lèi)中每個(gè)重寫(xiě)的方法坚弱,都有不同的函數(shù)指針
    3.當(dāng)子類(lèi)添加新方法時(shí),這些方法指針會(huì)添加到函數(shù)表的末尾
    4.在運(yùn)行時(shí)使用此表來(lái)調(diào)用函數(shù)的實(shí)現(xiàn) (函數(shù)表指針 + 函數(shù)偏移 就能找到對(duì)應(yīng)的方法)

消息派發(fā)

  • dynamic修飾的方法是消息派發(fā)
  • 對(duì)于繼承自NSObject的Swift類(lèi)关摇,消息派發(fā)方式
    注意: @objc修飾方法荒叶,只是把方法暴露給objc,是函數(shù)表派發(fā)
例子
  • 普通的實(shí)例方法,使用函數(shù)表派發(fā)
  • @objc聲明的方法输虱,使用函數(shù)表派發(fā)
  • 對(duì)于重寫(xiě)了OC的方法些楣。使用消息派發(fā)
  • extension中的方法,直接派發(fā)
  • dynamic修飾的方法,使用消息派發(fā)
//舉例說(shuō)明:
class CustomView: UIView {
    /// static修飾:直接派發(fā)
    static func staticMehod() {}
    /// private: 直接派發(fā)
    private func privateMethod() {}
    /// final修飾:直接派發(fā)
    final func finalMethod() {}
    /// 直接派發(fā)
    static func staticMethod() {}
    /// 普通的實(shí)例方法 函數(shù)表派發(fā)
    func commonMethod() {}
    /// @objc修飾 函數(shù)表派發(fā)
    @objc func method1() {}
    /// dynamic修飾: 消息派發(fā)
    @objc dynamic
    func method2() {}
    /// 重寫(xiě)了OC的方法: 消息派發(fā)
    override func layoutSubviews() {
        super.layoutSubviews()
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末愁茁,一起剝皮案震驚了整個(gè)濱河市蚕钦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌鹅很,老刑警劉巖嘶居,帶你破解...
    沈念sama閱讀 206,013評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異促煮,居然都是意外死亡邮屁,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)菠齿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)佑吝,“玉大人,你說(shuō)我怎么就攤上這事绳匀∮蠓蓿” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,370評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵疾棵,是天一觀的道長(zhǎng)戈钢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)陋桂,這世上最難降的妖魔是什么逆趣? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,168評(píng)論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮嗜历,結(jié)果婚禮上宣渗,老公的妹妹穿的比我還像新娘。我一直安慰自己梨州,他們只是感情好痕囱,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著暴匠,像睡著了一般鞍恢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上每窖,一...
    開(kāi)封第一講書(shū)人閱讀 48,954評(píng)論 1 283
  • 那天帮掉,我揣著相機(jī)與錄音,去河邊找鬼窒典。 笑死蟆炊,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瀑志。 我是一名探鬼主播涩搓,決...
    沈念sama閱讀 38,271評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼污秆,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了昧甘?” 一聲冷哼從身側(cè)響起良拼,我...
    開(kāi)封第一講書(shū)人閱讀 36,916評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎充边,沒(méi)想到半個(gè)月后庸推,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,382評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡浇冰,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評(píng)論 2 323
  • 正文 我和宋清朗相戀三年予弧,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片湖饱。...
    茶點(diǎn)故事閱讀 37,989評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖杀捻,靈堂內(nèi)的尸體忽然破棺而出井厌,到底是詐尸還是另有隱情,我是刑警寧澤致讥,帶...
    沈念sama閱讀 33,624評(píng)論 4 322
  • 正文 年R本政府宣布仅仆,位于F島的核電站,受9級(jí)特大地震影響垢袱,放射性物質(zhì)發(fā)生泄漏墓拜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評(píng)論 3 307
  • 文/蒙蒙 一请契、第九天 我趴在偏房一處隱蔽的房頂上張望咳榜。 院中可真熱鬧,春花似錦爽锥、人聲如沸涌韩。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,199評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)臣樱。三九已至,卻和暖如春腮考,著一層夾襖步出監(jiān)牢的瞬間雇毫,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,418評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工踩蔚, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留棚放,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,401評(píng)論 2 352
  • 正文 我出身青樓寂纪,卻偏偏與公主長(zhǎng)得像席吴,于是被迫代替她去往敵國(guó)和親赌结。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評(píng)論 2 345

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