iOS-XL公司面試題

目錄
  • 對象引用計數(shù)放哪里区宇?
  • MVVM和MVC的區(qū)別
  • UIButton防止多次點擊
  • 如何監(jiān)聽弱網(wǎng)
  • 卡頓檢測
  • NSCache轨蛤,NSDictionary朝氓,NSArray的區(qū)別
  • SDWebImage里面用了哪種緩存策略缸逃?
  • self + weakSelf + strongSelf ?
一 對象引用計數(shù)放哪里少辣?

我們先看看 struct objc_class 的結(jié)構(gòu)

image.png

再看看 isa結(jié)構(gòu)

  • 在arm64架構(gòu)之前耕突,isa就是一個普通的指針笤成,存儲著Class、Meta-Class對象的內(nèi)存地址
  • 從arm64架構(gòu)開始眷茁,對isa進行了優(yōu)化炕泳,變成了一個共用體(union)結(jié)構(gòu),還使用位域來存儲更多的信息
image.png
  • isa結(jié)構(gòu)體
/** isa_t 結(jié)構(gòu)體 */
union isa_t {
    Class cls;
    uintptr_t bits;
    struct {
        uintptr_t nonpointer        : 1;
        uintptr_t has_assoc         : 1;
        uintptr_t has_cxx_dtor      : 1;
        uintptr_t shiftcls          : 33;
        uintptr_t magic             : 6;
        uintptr_t weakly_referenced : 1;
        uintptr_t deallocating      : 1;
        uintptr_t has_sidetable_rc  : 1;
        uintptr_t extra_rc          : 19;
    };
};
  • extra_rc:表示該對象的引用計數(shù)值蔼卡,實際上是引用計數(shù)值減 1喊崖,例如,如果對象的引用計數(shù)為 10雇逞,那么 extra_rc 為 9荤懂。如果引用計數(shù)大于 10,則需要使用到下面的 has_sidetable_rc塘砸。

  • has_sidetable_rc:當對象引用計數(shù)大于 10 時节仿,則has_sidetable_rc 的值為 1,那么引用計數(shù)會存儲在一個叫 SideTable 的類的屬性中掉蔬,這是一個散列表廊宪。

對象引用計數(shù)就存放在extra_rc

相關參考

iOS-底層原理(13)-runtime之isa詳解
iOS-底層原理(14)isa-Class的結(jié)構(gòu)詳解

二 MVVM和MVC的區(qū)別
2.1 MVC
MVC.png

MVC的弊端

  • 厚重的View Controller

    • M:模型model的對象通常非常的簡單。根據(jù)Apple的文檔女轿,model應包括數(shù)據(jù)和操作數(shù)據(jù)的業(yè)務邏輯箭启。而在實踐中,model層往往非常薄蛉迹,不管怎樣傅寡,model層的業(yè)務邏輯不應被拖入到controller。

    • V:視圖view通常是UIKit控件(component,這里根據(jù)習慣譯為控件)或者編碼定義的UIKit控件的集合荐操。View的如何構(gòu)建(PS:IB或者手寫界面)何必讓Controller知曉芜抒,同時View不應該直接引用model(PS:現(xiàn)實中,你懂的M衅簟)钝腺,并且僅僅通過IBAction事件引用controller扼睬。業(yè)務邏輯很明顯不歸入view蜗细,視圖本身沒有任何業(yè)務送丰。

    • C:控制器controller。Controller是app的“膠水代碼”:協(xié)調(diào)模型和視圖之間的所有交互疗绣∵胙牵控制器負責管理他們所擁有的視圖的視圖層次結(jié)構(gòu),還要響應視圖的loading持痰、appearing、disappearing等等祟蚀,同時往往也會充滿我們不愿暴露的model的模型邏輯以及不愿暴露給視圖的業(yè)務邏輯工窍。網(wǎng)絡數(shù)據(jù)的請求及后續(xù)處理,本地數(shù)據(jù)庫操作前酿,以及一些帶有工具性質(zhì)輔助方法都加大了Massive View Controller的產(chǎn)生患雏。

  • 遺失(無處安放)的網(wǎng)絡邏輯
    蘋果使用的MVC的定義是這么說的:所有的對象都可以被歸類為一個model,一個view罢维,或是一個controller淹仑。

你可能試著把它放在Model對象里,但是也會很棘手肺孵,因為網(wǎng)絡調(diào)用應該使用異步匀借,這樣如果一個網(wǎng)絡請求比持有它的model生命周期更長,事情將變的復雜平窘。顯然View里面做網(wǎng)絡請求那就更格格不入了吓肋,因此只剩下Controller了。若這樣瑰艘,這又加劇了Massive View Controller的問題是鬼。若不這樣,何處才是網(wǎng)絡邏輯的家呢紫新?

  • 較差的可測試性

由于View Controller混合了視圖處理邏輯和業(yè)務邏輯均蜜,分離這些成分的單元測試成了一個艱巨的任務。

2.2 MVVM

一種可以很好地解決Massive View Controller問題的辦法就是將 Controller 中的展示邏輯抽取出來芒率,放置到一個專門的地方囤耳,而這個地方就是 viewModel 。MVVM衍生于MVC,是對 MVC 的一種演進紫皇,它促進了 UI 代碼與業(yè)務邏輯的分離慰安。它正式規(guī)范了視圖和控制器緊耦合的性質(zhì),并引入新的組件聪铺。他們之間的結(jié)構(gòu)關系如下:

MVVM.png
2.2.1 MVVM 的基本概念
  • MVVM 中化焕,viewview controller正式聯(lián)系在一起,我們把它們視為一個組件
  • viewview controller 都不能直接引用model铃剔,而是引用視圖模型(viewModel
  • viewModel 是一個放置用戶輸入驗證邏輯撒桨,視圖顯示邏輯,發(fā)起網(wǎng)絡請求和其他代碼的地方
  • 使用MVVM會輕微的增加代碼量键兜,但總體上減少了代碼的復雜性
2.2.2 MVVM 的注意事項
  • view 引用viewModel 凤类,但反過來不行(即不要在viewModel中引入#import UIKit.h,任何視圖本身的引用都不應該放在viewModel中)(PS:基本要求普气,必須滿足
  • viewModel 引用model谜疤,但反過來不行* MVVM 的使用建議
  • MVVM 可以兼容你當下使用的MVC架構(gòu)。
  • MVVM 增加你的應用的可測試性现诀。
  • MVVM 配合一個綁定機制效果最好(PS:ReactiveCocoa你值得擁有)夷磕。
  • viewController 盡量不涉及業(yè)務邏輯,讓 viewModel 去做這些事情仔沿。
  • viewController 只是一個中間人坐桩,接收 view 的事件、調(diào)用 viewModel 的方法封锉、響應 viewModel 的變化绵跷。
  • viewModel 絕對不能包含視圖 view(UIKit.h),不然就跟 view 產(chǎn)生了耦合成福,不方便復用和測試碾局。
  • viewModel之間可以有依賴。
  • viewModel避免過于臃腫闷叉,否則重蹈Controller的覆轍擦俐,變得難以維護。
2.2.3 MVVM 的優(yōu)勢
  • 低耦合:View 可以獨立于Model變化和修改握侧,一個 viewModel 可以綁定到不同的 View
  • 可重用性:可以把一些視圖邏輯放在一個 viewModel里面蚯瞧,讓很多 view 重用這段視圖邏輯
  • 獨立開發(fā):開發(fā)人員可以專注于業(yè)務邏輯和數(shù)據(jù)的開發(fā) viewModel,設計人員可以專注于頁面設計
  • 可測試:通常界面是比較難于測試的品擎,而 MVVM 模式可以針對 viewModel來進行測試
2.2.4 MVVM 的弊端
  • 數(shù)據(jù)綁定使得Bug 很難被調(diào)試埋合。你看到界面異常了,有可能是你 View 的代碼有 Bug萄传,也可能是 Model 的代碼有問題甚颂。數(shù)據(jù)綁定使得一個位置的 Bug 被快速傳遞到別的位置蜜猾,要定位原始出問題的地方就變得不那么容易了。
  • 對于過大的項目振诬,數(shù)據(jù)綁定和數(shù)據(jù)轉(zhuǎn)化需要花費更多的內(nèi)存(成本)蹭睡。主要成本在于:
  • 數(shù)組內(nèi)容的轉(zhuǎn)化成本較高:數(shù)組里面每項都要轉(zhuǎn)化成Item對象,如果Item對象中還有類似數(shù)組赶么,就很頭疼肩豁。
  • 轉(zhuǎn)化之后的數(shù)據(jù)在大部分情況是不能直接被展示的,為了能夠被展示辫呻,還需要第二次轉(zhuǎn)化清钥。
  • 只有在API返回的數(shù)據(jù)高度標準化時,這些對象原型(Item)的可復用程度才高放闺,否則容易出現(xiàn)類型爆炸祟昭,提高維護成本。
  • 調(diào)試時通過對象原型查看數(shù)據(jù)內(nèi)容不如直接通過NSDictionary/NSArray直觀怖侦。
  • 同一API的數(shù)據(jù)被不同View展示時篡悟,難以控制數(shù)據(jù)轉(zhuǎn)化的代碼,它們有可能會散落在任何需要的地方匾寝。
2.3 總結(jié)
  • MVC的設計模式也并非是病入膏肓恰力,無藥可救的架構(gòu),最起碼目前MVC設計模式仍舊是iOS開發(fā)的主流框架旗吁,存在即合理。針對文章所述的弊端停局,我們依舊有許多可行的方法去避免和解決很钓,從而打造一個輕量級的ViewController

  • MVVMMVC的升級版董栽,完全兼容當前的MVC架構(gòu)码倦,MVVM雖然促進了UI 代碼與業(yè)務邏輯的分離,一定程度上減輕了ViewController的臃腫度锭碳,但是ViewViewModel之間的數(shù)據(jù)綁定使得 MVVM變得復雜和難用了袁稽,如果我們不能更好的駕馭兩者之間的數(shù)據(jù)綁定,同樣會造成Controller 代碼過于復雜擒抛,代碼邏輯不易維護的問題推汽。

  • 一個輕量級的ViewController是基于MVCMVVM模式進行代碼職責的分離而打造的。MVC和MVVM有優(yōu)點也有缺點歧沪,但缺點在他們所帶來的好處面前時不值一提的歹撒。他們的低耦合性,封裝性诊胞,可測試性暖夭,可維護性和多人協(xié)作便利大大提高了開法效率。

  • 同時,我們需要保持的是一個擁抱變化的心迈着,以及理性分析的態(tài)度竭望。在新技術的面前,不盲從裕菠,也不守舊咬清,一切的決策都應該建立在認真分析的基礎上,這樣才能應對技術的變化糕韧。

相關參考
iOS 關于MVC和MVVM設計模式的那些事

三 UIButton防止多次點擊
3.1 設置enabled或userInteractionEnabled屬性

通過UIButtonenabled屬性和userInteractionEnabled屬性控制按鈕是否可點擊枫振。此方案在邏輯上比較清晰、易懂萤彩,但具體代碼書寫分散粪滤,常常涉及多個地方。

- (void)tapBtn:(UIButton *)btn {
    NSLog(@"按鈕點擊...");
    btn.enabled = NO;
    
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        btn.enabled = YES;
    });
}
3.2 借助cancelPreviousPerformRequestsWithTarget:selector:object實現(xiàn)

通過 NSObject 的兩個方法
實現(xiàn)步驟如下:

  • 1 創(chuàng)建一個UIButton的分類雀扶,使用runtime增加public屬性cs_eventIntervalprivate屬性cs_eventInvalid杖小。
  • 2 在+load方法中使用runtimeUIButton-sendAction:to:forEvent:方法與自定義的cs_sendAction:to:forEvent:方法進行交換
  • 3 使用cs_eventInterval作為控制cs_eventInvalid的計時因子,用cs_eventInvalid控制UIButtonevent事件是否有效愚墓。
// 此方法會在連續(xù)點擊按鈕時取消之前的點擊事件予权,從而只執(zhí)行最后一次點擊事件
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(nullable id)anArgument;
// 多長時間后做某件事情
- (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
/** 方法一 */
- (void)tapBtn:(UIButton *)btn {
    NSLog(@"按鈕點擊了...");
    // 此方法會在連續(xù)點擊按鈕時取消之前的點擊事件,從而只執(zhí)行最后一次點擊事件
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(buttonClickedAction:) object:btn];
    // 多長時間后做某件事情
    [self performSelector:@selector(buttonClickedAction:) withObject:btn afterDelay:2.0];
}

- (void)buttonClickedAction:(UIButton *)btn {
    NSLog(@"真正開始執(zhí)行業(yè)務 - 比如網(wǎng)絡請求...");
}
3.3 通過runtime交換方法實現(xiàn)
@interface UIButton (Extension)

/** 時間間隔 */
@property(nonatomic, assign)NSTimeInterval cs_eventInterval;

@end
#import "UIButton+Extension.h"
#import <objc/runtime.h>

static char *const kEventIntervalKey = "kEventIntervalKey"; // 時間間隔
static char *const kEventInvalidKey = "kEventInvalidKey";   // 是否失效

@interface UIButton()

/** 是否失效 - 即不可以點擊 */
@property(nonatomic, assign)BOOL cs_eventInvalid;

@end

@implementation UIButton (Extension)

+ (void)load {
    // 交換方法
    Method clickMethod = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
    Method cs_clickMethod = class_getInstanceMethod(self, @selector(cs_sendAction:to:forEvent:));
    method_exchangeImplementations(clickMethod, cs_clickMethod);
}

#pragma mark - click

- (void)cs_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
    if (!self.cs_eventInvalid) {
        self.cs_eventInvalid = YES;
        [self cs_sendAction:action to:target forEvent:event];
        [self performSelector:@selector(setCs_eventInvalid:) withObject:@(NO) afterDelay:self.cs_eventInterval];
    }
}

#pragma mark - set | get

- (NSTimeInterval)cs_eventInterval {
    return [objc_getAssociatedObject(self, kEventIntervalKey) doubleValue];
}

- (void)setCs_eventInterval:(NSTimeInterval)cs_eventInterval {
    objc_setAssociatedObject(self, kEventIntervalKey, @(cs_eventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (BOOL)cs_eventInvalid {
    return [objc_getAssociatedObject(self, kEventInvalidKey) boolValue];
}

- (void)setCs_eventInvalid:(BOOL)cs_eventInvalid {
    objc_setAssociatedObject(self, kEventInvalidKey, @(cs_eventInvalid), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

推薦參考 iOS-UIButton防止重復點擊(三種辦法)

四 如何監(jiān)聽弱網(wǎng)

查閱了一些資料浪册,暫時還沒有編碼實現(xiàn)扫腺,后期會更新

參考文章
iOS下的實際網(wǎng)絡連接狀態(tài)檢測
[前端測試] 弱網(wǎng)測試方法整理

五 卡頓檢測

參考以下文章

質(zhì)量監(jiān)控-卡頓檢測

簡單監(jiān)測iOS卡頓的demo

六 NSCache,NSDictionary村象,NSArray的區(qū)別
6.1 NSArray

NSArray作為一個存儲對象的有序集合笆环,可能是被使用最多的集合類。

性能特征
在數(shù)組的開頭和結(jié)尾插入/刪除元素通常是一個O(1)操作厚者,而隨機的插入/刪除通常是 O(N)的躁劣。

有用的方法
NSArray的大多數(shù)方法使用isEqual:來檢查對象間的關系(例如containsObject:)。有一個特別的方法

indexOfObjectIdenticalTo:

用來檢查指針相等库菲,如果你確保在同一個集合中搜索账忘,那么這個方法可以很大的提升搜索速度。

更多相關資料參考

6.2 NSDictionary

一個字典存儲任意的對象鍵值對熙宇。 由于歷史原因鳖擒,初始化方法使用相反的對象到值的方法,

[NSDictionary dictionaryWithObjectsAndKeys:object, key, nil]

而新的快捷語法則從key開始

@{key : value, ...}

NSDictionary中的鍵是被拷貝的并且需要是恒定的烫止。如果在一個鍵在被用于在字典中放入一個值后被改變败去,那么這個值可能就會變得無法獲取了。一個有趣的細節(jié)烈拒,在NSDictionary中鍵是被拷貝的圆裕,而在使用一個toll-free橋接的CFDictionary時卻只被retain广鳍。CoreFoundation類沒有通用對象的拷貝方法,因此這時拷貝是不可能的(*)吓妆。這只適用于使用CFDictionarySetValue()的時候赊时。如果通過setObject:forKey使用toll-free橋接的CFDictionary,蘋果增加了額外處理邏輯來使鍵被拷貝行拢。反過來這個結(jié)論則不成立 — 轉(zhuǎn)換為CFDictionary的NSDictionary對象祖秒,對其使用CFDictionarySetValue()方法會調(diào)用回setObject:forKey并拷貝鍵。

6.3 NSCache

NSCache是一個非常奇怪的集合舟奠。在iOS 4/Snow Leopard中加入竭缝,默認為可變并且線程安全的。這使它很適合緩存那些創(chuàng)建起來代價高昂的對象沼瘫。它自動對內(nèi)存警告做出反應并基于可設置的成本清理自己抬纸。與NSDictionary相比,鍵是被retain而不是被拷貝的耿戚。

NSCache的回收方法是不確定的湿故,在文檔中也沒有說明。向里面放一些類似圖片那樣比被回收更快填滿內(nèi)存的大對象不是個好主意膜蛔。(這是在PSPDFKit中很多跟內(nèi)存有關的crash的原因坛猪,在使用自定義的基于LRU的鏈表的緩存代碼之前,我們起初使用NSCache存儲事先渲染的圖片皂股。)

NSCache可以設置撐自動回收實現(xiàn)了NSDiscardableContent協(xié)議的對象墅茉。實現(xiàn)該屬性的一個比較流行的類是同時間加入的NSPurgeableData,但是在OS X 10.9之前呜呐,是非線程安全的(沒有信息表明這是否也影響到iOS或者是否在iOS 7中被修復了)躁锁。

NSCache性能

那么NSCache如何承受NSMutableDictionary的考驗?加入的線程安全必然會帶來一些消耗。

6.4 iOS 構(gòu)建緩存時選 NSCache 而非NSDictionary
  • 當系統(tǒng)資源將要耗盡時卵史,NSCache可以自動刪減緩存。如果采用普通的字典搜立,那么就要自己編寫掛鉤以躯,在系統(tǒng)通知時手動刪減緩存,NSCache會先行刪減 時間最久為被使用的對象

  • NSCache 并不會拷貝鍵啄踊,而是會保留它忧设。此行為用NSDictionary也可以實現(xiàn),但是需要編寫比較復雜的代碼颠通。NSCache對象不拷貝鍵的原因在于址晕,很多時候鍵都是不支持拷貝操作的對象來充當?shù)摹R虼薔SCache對象不會自動拷貝鍵顿锰,所以在鍵不支持拷貝操作的情況下谨垃,該類比字典用起來更方便

  • NScache是線程安全的启搂,NSDictionary不是。在開發(fā)者自己不編寫加鎖代碼的前提下刘陶,多個線程可以同時訪問NSCache胳赌。對緩存來說,線程安全通常是很重要的匙隔,因為開發(fā)者可能在某個線程中讀取數(shù)據(jù)疑苫,此時如果發(fā)現(xiàn)緩存里找不著指定的鍵,那么就要下載該鍵對應的數(shù)據(jù)了

相關資料參考
iOS7: 漫談基礎集合類(NSArray,NSSet,NSOrderedSet,NSDictionary,NSMapTable,NSHashTable, NSPointerArray, NSIndexSet,NSCache, NSFastEnumeration)

七 SDWebImage里面用了哪種緩存策略纷责?

使用了NSCache做緩存策略捍掺,具體的參考下面的文章,寫的挺詳細的

推薦參考文章

iOS緩存 NSCache詳解及SDWebImage緩存策略源碼分析

八 self + weakSelf + strongSelf ?
__weak __typeof(self)weakSelf = self;    //1

[self.context performBlock:^{      
    [weakSelf doSomething];          //2
     __strong __typeof(weakSelf)strongSelf = weakSelf;  //3
    [strongSelf doAnotherSomething];        
}];
  • 解釋說明
1.使用__weak __typeof是在編譯的時候,另外創(chuàng)建一個局部變量weak對象來操作self再膳,引用計數(shù)不變挺勿。
block 會將這個局部變量捕獲為自己的屬性,
訪問這個屬性饵史,從而達到訪問 self 的效果满钟,因為他們的內(nèi)存地址都是一樣的。

2.因為weakSelf和self是兩個變量,doSomething有可能就直接對self自身引用計數(shù)減到0了.
  所以在[weakSelf doSomething]的時候,你很難控制這里self是否就會被釋放了.weakSelf只能看著.

3.__strong __typeof在編譯的時候,實際是對weakSelf的強引用.
  指針連帶關系self的引用計數(shù)會增加.但是你這個是在block里面,生命周期也只在當前block的作用域.
  所以,當這個block結(jié)束, strongSelf隨之也就被釋放了.不會影響block外部的self的生命周期.

總結(jié)

  • 在 Block 內(nèi)如果需要訪問 self 的方法胳喷、變量湃番,建議使用 weakSelf。
  • 如果在 Block 內(nèi)需要多次 訪問 self吭露,則需要使用 strongSelf吠撮。

推薦參考文章
iOS-Block 中 為何使用 weakSelf 和 strongSelf

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市讲竿,隨后出現(xiàn)的幾起案子泥兰,更是在濱河造成了極大的恐慌,老刑警劉巖题禀,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鞋诗,死亡現(xiàn)場離奇詭異,居然都是意外死亡迈嘹,警方通過查閱死者的電腦和手機削彬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來秀仲,“玉大人融痛,你說我怎么就攤上這事∩窠” “怎么了雁刷?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長保礼。 經(jīng)常有香客問我沛励,道長责语,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任侯勉,我火速辦了婚禮鹦筹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘址貌。我一直安慰自己铐拐,他們只是感情好,可當我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布练对。 她就那樣靜靜地躺著遍蟋,像睡著了一般。 火紅的嫁衣襯著肌膚如雪螟凭。 梳的紋絲不亂的頭發(fā)上虚青,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天,我揣著相機與錄音螺男,去河邊找鬼棒厘。 笑死,一個胖子當著我的面吹牛下隧,可吹牛的內(nèi)容都是我干的奢人。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼淆院,長吁一口氣:“原來是場噩夢啊……” “哼何乎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起土辩,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤支救,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后拷淘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體各墨,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年启涯,在試婚紗的時候發(fā)現(xiàn)自己被綠了贬堵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡逝嚎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出详恼,到底是詐尸還是另有隱情补君,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布昧互,位于F島的核電站挽铁,受9級特大地震影響伟桅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叽掘,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一楣铁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧更扁,春花似錦盖腕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至膛薛,卻和暖如春听隐,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背哄啄。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工雅任, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人咨跌。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓沪么,卻偏偏與公主長得像,于是被迫代替她去往敵國和親虑润。 傳聞我的和親對象是個殘疾皇子成玫,可洞房花燭夜當晚...
    茶點故事閱讀 43,452評論 2 348