iOS 屬性 @property 詳細(xì)探究

探究系列已發(fā)布文章列表,有興趣的同學(xué)可以翻閱一下:

第一篇 | iOS 屬性 @property 詳細(xì)探究

第二篇 | iOS 深入理解 Block 使用及原理

第三篇 | iOS 類別 Category 和擴(kuò)展 Extension 及關(guān)聯(lián)對(duì)象詳解

第四篇 | iOS 常用鎖 NSLock ,@synchronized 等的底層實(shí)現(xiàn)詳解

第五篇 | iOS 全面理解 Nullability

------- 正文開(kāi)始 -------

引言

@property 應(yīng)該是面試過(guò)程中被問(wèn)到最多的一個(gè)技術(shù)點(diǎn)溢十,既能考察一個(gè)人的基礎(chǔ)菊霜,又能挖掘一個(gè)人對(duì)技術(shù)細(xì)節(jié)的掌握度屯曹,本文著重全面抄谐,細(xì)致的介紹一下 @property 都有哪些技術(shù)點(diǎn)值得我們關(guān)注摹蘑。

  • 代碼規(guī)范

聲明 @property 時(shí)筹燕,注意關(guān)鍵詞及字符間的空格。

@property (nonatomic, copy) NSString *name;

  • 本質(zhì)

@property 的本質(zhì)其實(shí)是:ivar (實(shí)例變量) + getter + setter 衅鹿;

  • 常用關(guān)鍵詞

// 存取器方法
1. getter=getterName
2. setter=setterName

// 讀寫(xiě)權(quán)限
1. readonly
2. readwrite

// 內(nèi)存管理
1. strong
2. assign
3. copy
4. weak
5. retain
6. unsafe_unretained

// 原子性
1. nonatomic
2. atomic

接下來(lái)逐個(gè)介紹一下撒踪,每個(gè)關(guān)鍵詞的作用:

存取器方法

  1. getter=getterName
  2. setter=setterName:

指定獲取屬性對(duì)象的名字為 getterName,如果你沒(méi)有使用 getter 指定getterName 大渤,系統(tǒng)默認(rèn)直接使用 propertyName 訪問(wèn)即可制妄。通常來(lái)說(shuō),只有所指屬性需要我們指定 isPropertyName 對(duì)應(yīng)的 Bool 值時(shí)泵三,才使用指定 getterName 忍捡,一般直接用 PropertyName 即可。setter=setterName: 則是用來(lái)指定設(shè)置屬性所使用的的 setter 方法切黔,即設(shè)置屬性值時(shí)使用 setterName: 方法砸脊,此處 setterName 是一個(gè)方法名,因此要以":"結(jié)尾纬霞,具體示例如下:

// 指定getter訪問(wèn)名為`isHappy`
@property (nonatomic, assign, getter=isHappy) BOOL happy;

// 使用系統(tǒng)默認(rèn)getter/setter方法
@property (nonatomic, assign) NSInteger age;

// 指定setter方法名為`setNickName:`
@property (nonatomic, copy, setter=setNickName:) NSString *name;

讀寫(xiě)權(quán)限

  1. readwrite
  2. readonly
  • readwrite:表示自動(dòng)生成對(duì)應(yīng)的 gettersetter 方法凌埂,即可讀可寫(xiě)權(quán)限, readwrite是編譯器的默認(rèn)選項(xiàng)诗芜。
  • readonly:表示只生成 getter 瞳抓,不需要生成 setter ,即只可讀伏恐,不可以修改孩哑。

內(nèi)存管理

  1. strong // 強(qiáng)引用,引用計(jì)數(shù)+1
  2. assign // assign是指針賦值翠桦,不對(duì)引用計(jì)數(shù)操作横蜒,對(duì)象銷毀后不會(huì)自動(dòng)置為nil
  3. copy // copy出一個(gè)新對(duì)象胳蛮,引用計(jì)數(shù)為1
  4. weak // 弱引用,不對(duì)引用計(jì)數(shù)操作丛晌,對(duì)象銷毀時(shí)自動(dòng)置為nil
  5. retain // 強(qiáng)引用仅炊,對(duì)象引用計(jì)數(shù)+1
  6. unsafe_unretained // 弱引用,不對(duì)引用計(jì)數(shù)操作澎蛛,對(duì)象銷毀時(shí)不會(huì)自動(dòng)置為nil
  • strong

表示強(qiáng)引用關(guān)系抚垄,即修飾對(duì)象的引用計(jì)數(shù)會(huì)+1,通常用來(lái)修飾對(duì)象類型谋逻,可變集合及可變字符串類型呆馁。當(dāng)對(duì)象引用計(jì)數(shù)為0,即不被任何對(duì)象持有毁兆,且此對(duì)象不再顯示在列表中時(shí)浙滤,對(duì)象就會(huì)從內(nèi)存中釋放。

  • assign

對(duì)象不進(jìn)行 retain 操作荧恍,即不改變對(duì)象引用計(jì)數(shù)瓷叫。通常用來(lái)修飾基本數(shù)據(jù)類型( NSInteger, CGFloat, Bool, NSTimeInterval 等)屯吊,內(nèi)存在棧上由系統(tǒng)自動(dòng)回收送巡。

assign 也可以用來(lái)修飾 NSObject 類型對(duì)象,因?yàn)?assign 不會(huì)改變修飾對(duì)象的引用計(jì)數(shù)盒卸,所以當(dāng)修飾對(duì)象的引用計(jì)數(shù)為0骗爆,對(duì)象銷毀的時(shí)候,對(duì)象指針不會(huì)被自動(dòng)清空蔽介。而此時(shí)對(duì)象指針指向的地址已被銷毀摘投,這時(shí)再訪問(wèn)該屬性會(huì)產(chǎn)生野指針錯(cuò)誤:EXC_BAD_ACCESS,因此 assign 通常用來(lái)修飾基本數(shù)據(jù)類型虹蓄。

  • copy

當(dāng)調(diào)用修飾對(duì)象的 setter 方法時(shí)犀呼,會(huì)建立一個(gè)引用計(jì)數(shù)為 1 的新對(duì)象,即對(duì)象會(huì)在內(nèi)存里拷貝一份副本薇组,兩個(gè)指針指向不同的內(nèi)存地址外臂。一般用于修飾字符串( NSString )和集合類( NSArray , NSDictionary )的不可變變量,Block 也是用 copy 修飾律胀。

針對(duì) copy 宋光,這里又牽涉到了深 copy 和淺 copy 的問(wèn)題,這里做一下簡(jiǎn)單介紹炭菌,后續(xù)會(huì)有文章專門探討這個(gè)問(wèn)題:

淺 copy :是對(duì)指針的 copy 罪佳,指針指向的內(nèi)容是同一個(gè)地址,對(duì)象的引用計(jì)數(shù)+1;

深 copy :是對(duì)內(nèi)容的 copy 黑低,會(huì)開(kāi)辟新的內(nèi)存空間赘艳,將內(nèi)容重新 copy 一份;

  • 非集合對(duì)象的 copy 與 mutableCopy

不可變對(duì)象:copy 操作為淺 copy,mutableCopy 操作為深 copy第练。

可變對(duì)象:copy 操作為深 copy阔馋,mutableCopy 操作也為深 copy。

  • 集合類對(duì)象的 copy 與 mutableCopy

不可變對(duì)象:copy 操作為深 copy 娇掏,mutableCopy 操作為深copy呕寝。

可變對(duì)象:copy 操作為深 copy ,可變對(duì)象的 mutableCopy 也為深 copy 婴梧。

注意:當(dāng)使用 copy 修飾的屬性賦值時(shí)下梢,copy 出來(lái)的是一份不可變對(duì)象。因此當(dāng)對(duì)象是一個(gè)可變對(duì)象時(shí)塞蹭,切記不要使用 copy 進(jìn)行修飾孽江。如果這時(shí)使用 copy 修飾,當(dāng)使用 copy 出來(lái)的對(duì)象調(diào)用可變對(duì)象所特有的方法時(shí)番电,會(huì)因?yàn)檎也坏綄?duì)應(yīng)的方法而 Crash岗屏。

  • weak

表示弱引用關(guān)系,修飾對(duì)象的引用計(jì)數(shù)不會(huì)增加漱办,當(dāng)修飾對(duì)象被銷毀的時(shí)候这刷,對(duì)象指針會(huì)自動(dòng)置為 nil,防止出現(xiàn)野指針娩井。weak 也用來(lái)修飾 delegate 暇屋,避免循環(huán)引用。另外 weak 只能用來(lái)修飾對(duì)象類型洞辣,且是在 ARC 下新引入的修飾詞咐刨,MRC 下相當(dāng)于使用 assign

weak的底層實(shí)現(xiàn)原理

weak 的底層實(shí)現(xiàn)是基于 Runtime 底層維護(hù)的 SideTables 的 hash 數(shù)組扬霜,里面存儲(chǔ)的是一個(gè) SideTable 的數(shù)據(jù)結(jié)構(gòu):

struct SideTable {
    spinlock_t slock; // 確保原子性操作的鎖定鸟,雖然名字還叫 spinlock_t ,其實(shí)本質(zhì)已經(jīng)是 mutex_t著瓶,具體可見(jiàn) objc-os 源碼( `using spinlock_t = mutex_tt<LOCKDEBUG>;` )

    RefcountMap refcnts; // 用來(lái)存儲(chǔ)對(duì)象引用計(jì)數(shù)的 hash 表
    
    weak_table_t weak_table // 存儲(chǔ)對(duì)象 weak 引用指針的 hash 表
    //...
};
  • weak 功能實(shí)現(xiàn)核心的數(shù)據(jù)結(jié)構(gòu) weak_table_t:
/**
 * The global weak references table. Stores object ids as keys,
 * and weak_entry_t structs as their values.
 */
struct weak_table_t {
    weak_entry_t *weak_entries; // 存儲(chǔ) weak 對(duì)象信息的 hash 數(shù)組
    size_t    num_entries; // 數(shù)組中元素的個(gè)數(shù)
    uintptr_t mask;        // 計(jì)數(shù)輔助量
    uintptr_t max_hash_displacement; // hash 元素最大偏移值
};
  • weak_entry_t也是一個(gè)hash結(jié)構(gòu):
#define WEAK_INLINE_COUNT 4
#define REFERRERS_OUT_OF_LINE 2

struct weak_entry_t {
    DisguisedPtr<objc_object> referent;
    union {
        // 動(dòng)態(tài)數(shù)組
        struct {
            weak_referrer_t *referrers; // 弱引用該對(duì)象的對(duì)象指針的hash數(shù)組
            uintptr_t        out_of_line_ness : 2;
            uintptr_t        num_refs : PTR_MINUS_2;
            uintptr_t        mask;
            uintptr_t        max_hash_displacement;
        };
        // 定長(zhǎng)數(shù)組联予,最大值為4,蘋(píng)果考慮到一半弱引用的指針個(gè)數(shù)不會(huì)超過(guò)這個(gè)數(shù)蟹但,因此為了提升運(yùn)行效率躯泰,一次分配一整塊的連續(xù)內(nèi)存空間
        struct {
            // out_of_line_ness field is low bits of inline_referrers[1]
            weak_referrer_t  inline_referrers[WEAK_INLINE_COUNT];
        };
    };

    // 判斷當(dāng)前是動(dòng)態(tài)數(shù)組,還是定長(zhǎng)數(shù)組
    bool out_of_line() {
        return (out_of_line_ness == REFERRERS_OUT_OF_LINE);
    }

    weak_entry_t& operator=(const weak_entry_t& other) {
        memcpy(this, &other, sizeof(other));
        return *this;
    }

    weak_entry_t(objc_object *newReferent, objc_object **newReferrer)
        : referent(newReferent)
    {
        inline_referrers[0] = newReferrer;
        for (int i = 1; i < WEAK_INLINE_COUNT; i++) {
            inline_referrers[i] = nil;
        }
    }
};

這里重點(diǎn)說(shuō)一下 weak_entry_t 定長(zhǎng)數(shù)組動(dòng)態(tài)數(shù)組的切換华糖,首先會(huì)將原來(lái)定長(zhǎng)數(shù)組中的內(nèi)容轉(zhuǎn)移到動(dòng)態(tài)數(shù)組中麦向,然后再在動(dòng)態(tài)數(shù)組中插入新的元素。

而對(duì)于動(dòng)態(tài)數(shù)組中元素個(gè)數(shù)大于或等于總空間的 3/4 時(shí)客叉,會(huì)對(duì)動(dòng)態(tài)數(shù)組進(jìn)行總空間 * 2 的擴(kuò)容

    if (entry->num_refs >= TABLE_SIZE(entry) * 3/4) {
        return grow_refs_and_insert(entry, new_referrer);
    }

每次動(dòng)態(tài)數(shù)組擴(kuò)容诵竭,都會(huì)將原先數(shù)組中的內(nèi)容重新插入到新的數(shù)組中话告。

當(dāng)對(duì)象的引用計(jì)數(shù)為 0 時(shí),底層會(huì)調(diào)用 _objc_rootDealloc 方法對(duì)對(duì)象進(jìn)行釋放卵慰,而在 _objc_rootDealloc 方法里面會(huì)調(diào)用 rootDealloc 方法沙郭,如果對(duì)象有被 weak 引用,則會(huì)進(jìn)入 object_dispose , 之后會(huì)在 objc_destructInstance 函數(shù)里面調(diào)用 obj->clearDeallocating(); 根據(jù)對(duì)象地址獲取所有 weak 指針地址數(shù)組裳朋,遍歷數(shù)組找到對(duì)應(yīng)的值病线,將其值為 nil ,然后將 entryweak 表中移除鲤嫡,最后從引用計(jì)數(shù)表中刪除以廢棄對(duì)象的地址為鍵值的記錄送挑。

備注: 此處省略了 weak 底層實(shí)現(xiàn)的很多細(xì)節(jié),具體詳細(xì)實(shí)現(xiàn)暖眼,后續(xù)會(huì)單獨(dú)發(fā)文介紹惕耕。

  • retain 是在 MRC 下常用的修飾詞:

ARC 下已不再使用 retain ,而是使用 strong 代替诫肠。retainstrong 類似司澎,用來(lái)修飾對(duì)象類型,強(qiáng)引用對(duì)象栋豫,其修飾對(duì)象的引用計(jì)數(shù)會(huì) +1挤安,不會(huì)對(duì)對(duì)象分配新的內(nèi)存空間。

  • unsafe_unretained 同 weak 類似:

unsafe_unretained 不會(huì)對(duì)對(duì)象的引用計(jì)數(shù) +1笼才,只能用來(lái)修飾對(duì)象類型漱受,修飾的對(duì)象在被銷毀時(shí)络凿,其指針不會(huì)自動(dòng)清空骡送,指向的仍然是已銷毀的對(duì)象,這時(shí)再調(diào)用該指針會(huì)產(chǎn)生野指針 :EXC_BAD_ACCESS 錯(cuò)誤絮记。


原子性

atomic 原子性:系統(tǒng)會(huì)自動(dòng)給生成的 getter/setter 方法進(jìn)行加鎖操作摔踱;

nonatomic 非原子性:系統(tǒng)不會(huì)給自動(dòng)生成的 getter/setter 方法進(jìn)行加鎖操作;

設(shè)置屬性函數(shù) reallySetProperty(...) 的原子性非原子性實(shí)現(xiàn)如下:

    if (!atomic) {
        oldValue = *slot;
        *slot = newValue;
    } else {
        spinlock_t& slotlock = PropertyLocks[slot];
        slotlock.lock();
        oldValue = *slot;
        *slot = newValue;        
        slotlock.unlock();
    }

獲取屬性函數(shù) objc_getProperty(...) 的內(nèi)部實(shí)現(xiàn)如下:

    if (offset == 0) {
        return object_getClass(self);
    }

    // Retain release world
    id *slot = (id*) ((char*)self + offset);
    if (!atomic) return *slot;
        
    // Atomic retain release world
    spinlock_t& slotlock = PropertyLocks[slot];
    slotlock.lock();
    id value = objc_retain(*slot);
    slotlock.unlock();
    
    // for performance, we (safely) issue the autorelease OUTSIDE of the spinlock.
    return objc_autoreleaseReturnValue(value);

由此可見(jiàn)怨愤,對(duì)屬性對(duì)象的加鎖操作僅限于對(duì)象的 getter/setter 操作派敷,如果是 getter/setter 以外的操作,該加鎖并沒(méi)有意義撰洗。因此 atomic 的原子性篮愉,僅能保障對(duì)象的 getter/setter 的線程安全,并不能保障多線程下對(duì)對(duì)象的其他操作安全差导。如一個(gè)線程在 getter/setter 操作试躏,另一個(gè)線程進(jìn)行 release 操作,可能會(huì)導(dǎo)致 crash设褐。此種場(chǎng)景的線程安全颠蕴,還需要由開(kāi)發(fā)者自己進(jìn)行處理泣刹。


拓展知識(shí)

  • Category 中添加屬性 @property

Category 中添加 @property,只會(huì)生成 setter/getter 方法的聲明犀被,并不會(huì)有具體的代碼實(shí)現(xiàn)椅您。這是因?yàn)?Category 在運(yùn)行期對(duì)象的內(nèi)存布局已經(jīng)確定,此時(shí)如果添加實(shí)例變量就會(huì)破壞對(duì)象的內(nèi)存布局寡键,這將會(huì)是災(zāi)難性的掀泳。因此 Category 無(wú)法添加實(shí)例變量。

那如何給 Category 實(shí)現(xiàn)類似實(shí)例變量功能呢西轩?簡(jiǎn)單列舉兩種方式开伏,此處暫時(shí)不做具體詳解,后續(xù)會(huì)有文章單獨(dú)介紹:

  1. 使用臨時(shí)全局變量代替成員變量遭商,并在屬性的 setter/getter 函數(shù)中進(jìn)行存取值操作固灵;
  2. 通過(guò) Runtime 添加關(guān)聯(lián)對(duì)象實(shí)現(xiàn)成員變量,并在屬性的 setter/getter 函數(shù)中進(jìn)行存取值操作劫流,其關(guān)鍵調(diào)用有兩個(gè):
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy) // 設(shè)置關(guān)聯(lián)對(duì)象值調(diào)用

objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key) // 獲取關(guān)聯(lián)對(duì)象值調(diào)用
  • Protocol 中添加屬性 @property

protocol 中添加屬性 @property巫玻,其實(shí)就是聲明該屬性的 setter/getter 方法,在實(shí)現(xiàn)該 protocol 時(shí)祠汇,并沒(méi)有生成對(duì)應(yīng)的成員變量仍秤,此時(shí)有動(dòng)態(tài)實(shí)現(xiàn)和自動(dòng)實(shí)現(xiàn)兩種方式:

  1. 動(dòng)態(tài)實(shí)現(xiàn),需要在實(shí)現(xiàn)類中添加 protocol 中聲明屬性對(duì)應(yīng)的 setter/getter 方法可很,并聲明一個(gè)私有成員變量用來(lái)進(jìn)行存取操作诗力。備注: 實(shí)現(xiàn)類如果沒(méi)有實(shí)現(xiàn)對(duì)應(yīng)的 setter/getter 方法,在調(diào)用 protocol 屬性的 setter/getter 方法時(shí)會(huì)因?yàn)榉椒ㄕ也坏蕉?Crash我抠;
  2. 自動(dòng)實(shí)現(xiàn)苇本,可以通過(guò) @synthesize propertyName; 告訴編譯器自動(dòng)添加對(duì)應(yīng)的 setter/getter 方法,并生成對(duì)應(yīng)的成員變量菜拓;
  • @synthesize 作用

@synthesize 的作用是告訴編譯器瓣窄,自動(dòng)創(chuàng)建屬性的 setter/getter 方法,同時(shí)生成成員變量纳鼎,并且可以給屬性指定別名俺夕。如:

@synthesize name = nickName;

  • @dynamic 作用

@dynamic 作用是告訴編譯器,無(wú)需自動(dòng)創(chuàng)建屬性的 setter/getter 方法贱鄙,這個(gè)時(shí)候就需要我們手動(dòng)實(shí)現(xiàn)相應(yīng)的 setter/getter劝贸,否則,在使用到相應(yīng)屬性的 setter/getter 方法時(shí)逗宁,會(huì)因找不到方法而 Crash映九。

  • null 相關(guān)的一些關(guān)鍵詞
  1. nullable : 可以為空
  2. nonnull : 不可以為空
  3. null_unspecified : 未知類型
  4. null_resettable : get不能為空,set可以為空
  5. __nullable : 可以為 Null 或 nil
  6. __nonnull : 不可以為空
  • Swift下的 unowned 與 weak 區(qū)別:
  1. Swift下 weak 的使用同 Objective-C 下 weak 的使用相同疙剑。
  2. unowned 無(wú)主引用標(biāo)記對(duì)象氯迂,即使它的原引用已經(jīng)被釋放践叠,它仍然會(huì)保持對(duì)已釋放對(duì)象的引用,它不是 Optional 嚼蚀,也不會(huì)被置為 nil 禁灼。當(dāng)我們?cè)噲D訪問(wèn)這樣的 unowned 引用時(shí),程序會(huì)發(fā)生錯(cuò)誤轿曙。而 weak 在引用的對(duì)象被釋放后弄捕,標(biāo)記為 weak 的對(duì)象將會(huì)自動(dòng)置為 nil

Define a capture in a closure as an unowned reference when the closure and the instance it captures will always refer to each other, and will always be deallocated at the same time.

Conversely, define a capture as a weak reference when the captured reference may become nil at some point in the future. Weak references are always of an optional type, and automatically become nil when the instance they reference is deallocated. This enables you to check for their existence within the closure’s body.

NOTE:

If the captured reference will never become nil, it should always be captured as an unowned reference, rather than a weak reference.

根據(jù)蘋(píng)果官方文檔的建議导帝,如果捕獲的引用永遠(yuǎn)不會(huì)變?yōu)?nil 守谓,我們應(yīng)該使用 unowned,否則應(yīng)該使用 weak 您单。


總結(jié)

@property 延展相關(guān)的技術(shù)點(diǎn)有很多斋荞,如:copy 相關(guān)的 NSCopying 協(xié)議,weak 底層詳細(xì)的實(shí)現(xiàn)原理虐秦,如何保障對(duì)象的多線程安全平酿。還有很多技術(shù)點(diǎn)跟 RuntimeRunloop 有關(guān)悦陋,后續(xù)文章會(huì)陸續(xù)介紹蜈彼。

知識(shí)點(diǎn)完整說(shuō)下來(lái)就是一整套系統(tǒng)的協(xié)同運(yùn)轉(zhuǎn),各個(gè)環(huán)節(jié)緊密相扣俺驶,最終才成為我們現(xiàn)在看到的樣子幸逆。本文及以后的文章都會(huì)盡可能的收縮一下單篇文章探討的范圍,以期能夠讓話題更加緊密暮现。


參考資料:

The Objective-C Programming Language


關(guān)于技術(shù)組

iOS 技術(shù)組主要用來(lái)學(xué)習(xí)还绘、分享日常開(kāi)發(fā)中使用到的技術(shù),一起保持學(xué)習(xí)送矩,保持進(jìn)步蚕甥。文章倉(cāng)庫(kù)在這里:https://github.com/minhechen/iOSTechTeam
微信公眾號(hào):iOS技術(shù)組哪替,歡迎聯(lián)系交流栋荸,感謝閱讀。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末凭舶,一起剝皮案震驚了整個(gè)濱河市晌块,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌帅霜,老刑警劉巖匆背,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異身冀,居然都是意外死亡钝尸,警方通過(guò)查閱死者的電腦和手機(jī)括享,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)珍促,“玉大人铃辖,你說(shuō)我怎么就攤上這事≈硇穑” “怎么了娇斩?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)穴翩。 經(jīng)常有香客問(wèn)我犬第,道長(zhǎng),這世上最難降的妖魔是什么芒帕? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任歉嗓,我火速辦了婚禮,結(jié)果婚禮上背蟆,老公的妹妹穿的比我還像新娘遥椿。我一直安慰自己,他們只是感情好淆储,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布冠场。 她就那樣靜靜地躺著,像睡著了一般本砰。 火紅的嫁衣襯著肌膚如雪碴裙。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,541評(píng)論 1 305
  • 那天点额,我揣著相機(jī)與錄音舔株,去河邊找鬼。 笑死还棱,一個(gè)胖子當(dāng)著我的面吹牛载慈,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播珍手,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼办铡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了琳要?” 一聲冷哼從身側(cè)響起寡具,我...
    開(kāi)封第一講書(shū)人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎稚补,沒(méi)想到半個(gè)月后童叠,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡课幕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年厦坛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了五垮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡杜秸,死狀恐怖拼余,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情亩歹,我是刑警寧澤匙监,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布,位于F島的核電站小作,受9級(jí)特大地震影響亭姥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜顾稀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一达罗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧静秆,春花似錦粮揉、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至殊橙,卻和暖如春辐宾,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背膨蛮。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工叠纹, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人敞葛。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓誉察,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親惹谐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子持偏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355

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