最新整理:iOS面試題-面試常問問題(三)

前言:

最近把 iOS 面試中可能會遇到的問題整理了一番, 題目大部分是網上收錄的, 方便自己鞏固復習, 也分享給大家; 希望對大家有所幫助!

  • 對于答案,不一定都合適,歡迎大家積極討論;整理不易,如果您覺得還不錯,麻煩在文末 “點個贊” ,或者留下您的評論“Mark” 一下,謝謝您的支持

目錄合集

iOS面試題-面試常問問題(三)

1. 一個OC對象占用多少內存

  • 系統分配了16個字節給NSObject對象(通過malloc_size函數獲得)
  • 但NSObject對象內部只使用了8個字節的空間(64bit環境下,可以通過class_getInstanceSize函數獲得)

2. 對象的isa指針指向哪里?

  • instance對象的isa指向class對象
  • class對象的isa指向meta-class對象
  • meta-class對象的isa指向基類的meta-class對象

3.OC的類信息存放在哪里?

  • 對象方法、屬性、成員變量、協議信息,存放在class對象中
  • 類方法,存放在meta-class對象中
  • 成員變量的具體值,存放在instance對象

4.iOS用什么方式實現對一個對象的KVO?(KVO的本質是什么?)

  • 利用RuntimeAPI動態生成一個子類,并且讓instance對象的isa指向這個全新的子類
  • 當修改instance對象的屬性時,會調用Foundation的_NSSetXXXValueAndNotify函數
    willChangeValueForKey:
    父類原來的setter
    didChangeValueForKey:
  • 內部會觸發監聽器(Oberser)的監聽方法(observeValueForKeyPath:ofObject:change:context:

5.如何手動觸發KVO?

手動調用willChangeValueForKey:和didChangeValueForKey:

- (void)viewDidLoad {
[super viewDidLoad];

    Person *person = [[Person alloc]init];;
    [p addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    [p willChangeValueForKey:@"name"];
    [p didChangeValueForKey:@"name"];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    NSLog(@"被觀測對象:%@, 被觀測的屬性:%@, 值的改變: %@\n, 攜帶信息:%@", object, keyPath, change, context);
}

6.直接修改成員變量會觸發KVO么?

  • 不會觸發KVO

7.通過KVC修改屬性會觸發KVO么?

  • 會觸發KVO
  • KVC在賦值時候,內部會觸發監聽器(Oberser)的監聽方法(observeValueForKeyPath:ofObject:change:context:) 發送通知

8.KVC的賦值和取值過程是怎樣的?原理是什么?

  • KVC的全稱是Key-Value Coding,俗稱“鍵值編碼”,可以通過一個key來訪問某個屬性
  • 調用 setValue:forKey:
    setKey,_setKey ->找到了則進行賦值,未找到調用 accessInstanceVarlableDirctly 是否允許修改value值,返回YES, 調用_key, _isKey, key, isKey 進行賦值

9.Category的使用場合是什么?

  • 在不修改原有類代碼的情況下,為類添對象方法或者類方法
  • 或者為類關聯新的屬性
  • 分解龐大的類文件

使用場合:

  • 添加實例方法
  • 添加類方法
  • 添加協議
  • 添加屬性
  • 關聯成員變量

10.Category的實現原理

  • Category編譯之后的底層結構是struct category_t,里面存儲著分類的對象方法、類方法、屬性、協議信息
  • 在程序運行的時候,runtime會將Category的數據,合并到類信息中(類對象、元類對象中)

11.Category和Class Extension的區別是什么?

  • Class Extension在編譯的時候,它的數據就已經包含在類信息中
  • Category是在運行時,才會將數據合并到類信息中

12.Category中有load方法嗎?load方法是什么時候調用的?load 方法能繼承嗎?

  • 有load方法
  • load方法在runtime加載類、分類的時候調用
  • load方法可以繼承,但是一般情況下不會主動去調用load方法,都是讓系統自動調用

13. initialize方法如何調用,以及調用時機

  • 當類第一次收到消息的時候會調用類的initialize方法
  • 是通過 runtime 的消息機制 objc_msgSend(obj,@selector()) 進行調用的
  • 優先調用分類的 initialize, 如果沒有分類會調用 子類的,如果子類未實現則調用 父類的

14. load、initialize方法的區別什么?它們在category中的調用的順序?以及出現繼承時他們之間的調用過程?

  • load 是類加載到內存時候調用, 優先父類->子類->分類
  • initialize 是類第一次收到消息時候調用,優先分類->子類->父類
  • 同級別和編譯順序有關系
  • load 方法是在 main 函數之前調用的

15. Category能否添加成員變量?如果可以,如何給Category添加成員變量?

  • 不能直接給Category添加成員變量,但是可以間接實現Category有成員變量的效果
  • Category是發生在運行時,編譯完畢,類的內存布局已經確定,無法添加成員變量(Category的底層數據結構也沒有成員變量的結構)
  • 可以通過 runtime 動態的關聯屬性

16. block的原理是怎樣的?本質是什么?

  • block 本質其實是OC對象
  • block 內部封裝了函數調用以及調用環境

17. __block的作用是什么?有什么使用注意點?

  • 如果需要在 block 內部修改外部的 局部變量的值,就需要使用__block 修飾(全局變量和靜態變量不需要加__block 可以修改)
  • __block 修飾以后,局部變量的數據結構就會發生改變,底層會變成一個結構體的對象,結構內部會聲明 一個 __block修飾變量的成員, 并且將 __block修飾變量的地址保存到堆內存中. 后面如果修改 這個變量的值,可以通過 isa 指針找到這個結構體,進來修改 這個變量的值;
  • 可以在 block 內部修改 變量的值

18. block的屬性修飾詞為什么是copy?使用block有哪些使用注意?

  • block 一旦沒有進行copy操作,就不會在堆上
  • 使用注意:循環引用問題 (外部使用__weak 解決)

19. block在修改NSMutableArray,需不需要添加__block?

  • 如果是操作 NSMutableArray 對象不需要,因為 block 內部拷貝了 NSMutableArray對象的內存地址,實際是通過內存地址操作的
  • 如果 NSMutableArray 對象要重新賦值,就需要加__block

20. Block 內部為什么不能修改局部變量,需要加__block

  • 通過查看Block 源碼,可以發現, block 內部如果單純使用 外部變量, 會在 block 內部創建同樣的一個變量,并且將 外部變量的值引用過來..(只是將外部變量值拷貝到 block 內部), 內部這個變量和外部 實際已經沒關系了
  • 從另一方面分析,block 本質也是一個 函數指針, 外部的變量也是一個局部變量,很有可能 block 在使用這個變量時候,外部變量已經釋放了,會造成錯誤
  • 加了__block 以后, 會將外部變量的內存拷貝到堆中, 內存由 block 去管理.

21. 講一下 OC 的消息機制

  • OC中的方法調用其實都是轉成了objc_msgSend函數的調用,給receiver(方法調用者)發送了一條消息(selector方法名)
  • objc_msgSend底層有3大階段
    • 消息發送(當前類、父類中查找)、
    • 動態方法解析、
    • 消息轉發

22. 消息發送流程

  • 當我們的一個 receiver(實例對象)收到消息的時候, 會通過 isa 指針找到 他的類對象, 然后在類對象方法列表中查找 對應的方法實現,如果 未找到,則會通過 superClass 指針找到其父類的類對象, 找到則返回,未找打則會一級一級往上查到,最終到NSObject 對象, 如果還是未找到就會進行動態方法解析
  • 類方法調用同上,只不過 isa 指針找到元類對象;

23. 動態方法解析機制

當我們發送消息未找到方法實現,就會進入第二步,動態方法解析: 代碼實現如下

//  動態方法綁定- 實例法法調用
+ (BOOL)resolveInstanceMethod:(SEL)sel{
    if (sel == @selector(run)) {
        Method method = class_getInstanceMethod(self, @selector(test));
        class_addMethod(self, sel, method_getImplementation(method), method_getTypeEncoding(method));
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}
// 類方法調用
+(BOOL) resolveClassMethod:(SEL)sel....

24.消息轉發機制流程

未找到動態方法綁定,就會進行消息轉發階段

// 快速消息轉發- 指定消息處理對象
- (id)forwardingTargetForSelector:(SEL)aSelector{
    if (aSelector == @selector(run)) {
        return [Student new];
    }
    return  [super forwardingTargetForSelector:aSelector];
} 

// 標準消息轉發-消息簽名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
    if(aSelector == @selector(run))
    {
        return [NSMethodSignature signatureWithObjCTypes:"v@:"];
    }
    return [super methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
   //內部邏輯自己處理 
}

25. 什么是Runtime?平時項目中有用過么?

  • Objective-C runtime是一個運行時庫,它為Objective-C語言的動態特性提供支持,我們所寫的OC代碼在運行時都轉成了runtime相關的代碼,類轉換成C語言對應的結構體,方法轉化為C語言對應的函數,發消息轉成了C語言對應的函數調用。通過了解runtime以及源碼,可以更加深入的了解OC其特性和原理
  • OC是一門動態性比較強的編程語言,允許很多操作推遲到程序運行時再進行
  • OC的動態性就是由Runtime來支撐和實現的,Runtime是一套C語言的API,封裝了很多動態性相關的函數
  • 平時編寫的OC代碼,底層都是轉換成了Runtime API進行調用

26. runtime具體應用

  • 利用關聯對象(AssociatedObject)給分類添加屬性
  • 遍歷類的所有成員變量(修改textfield的占位文字顏色、字典轉模型、自動歸檔解檔)
  • 交換方法實現(交換系統的方法)
  • 利用消息轉發機制解決方法找不到的異常問題

27. unrecognized selector sent to instance 錯誤

該錯誤是基于OC的消息機制:

  1. 在方法列表中未找到方法實現
  2. 嘗試動態方法解析,也未綁定犯法
  3. 進行消息轉發,也未處理
  4. 最后進行報錯

28. 如果向一個nil對象發消息不會crash的話,那么message sent to deallocated instance的錯誤是怎么回事?

  • 這是因為這個對象已經被釋放了(引用計數為0了),那么這個時候再去調用方法肯定是會Crash的,因為這個時候這個對象就是一個野指針(指向僵尸對象(對象的引用計數為0,指針指向的內存已經不可用)的指針)了,安全的做法是釋放后將對象重新置為nil,使它成為一個空指針

29. 向一個nill對象發送消息會發生什么?

  • OC中向nil發消息,什么都不會方式,程序是不會崩潰的。
  • 因為OC的函數都是通過objc_msgSend進行消息發送來實現的,相對于C和C++來說,對于空指針的操作會引起crash問題,而objc_msgSend會通過判斷self來決定是否發送消息,如果self為nil,那么selector也會為空,直接返回,不會出現問題。視方法返回值,向nil發消息可能會返回nil(返回值為對象),0(返回值為一些基礎數據)或0X0(返回值為id)等。但對于[NSNull null]對象發送消息時,是會crash的,因為NSNull類只有一個null方法

30. 代碼打印結果:

@interface Person : NSObject
@end
@implementation Person
@end

@interface Student : Person
@end
@implementation Student
- (instancetype)init{
    if (self= [super init]) {
        NSLog(@"%@", [self class]);
        NSLog(@"%@", [super class]);
        NSLog(@"%@", [self superclass]);
        NSLog(@"%@", [super superclass]);
    }
}
[self class] 和 [super class] 都是給當前類返送消息,spuer 表示在父類中查找
[self superClass]  和 [super superclass] 也是也當前類發消息,返回父類
第一個打印:
Student / Student/ Person / Person

31. 代碼運行結果?

BOOL res1 = [[NSObject class] isKindOfClass:[NSObject class]];
BOOL res2 = [[NSObject class] isMemberOfClass:[NSObject class]];
BOOL res3 = [[Person class] isKindOfClass:[Person class]];
BOOL res4 = [[Person class] isMemberOfClass:[Person class]];
NSLog(@"%d-%d-%d-%d",res1, res2, res3, res4);

  • isKindOfClass 表示對象是否為當前類或者子類的 類型
  • isMemberOfClass 表示是否為當前類的的類型
  • isMemberOfClass 分為- 對象方法 和+ 類方法2中
    - (bool)isMemberOfClass; 比較的是類對象
    + (bool)isMemberOfClass; 比較的是元類

打印結果: 1 ,0, 0, 0

32. 講講 RunLoop,項目中有用到嗎?

  • runloop運行循環,保證程序一直運行,主線程默認開啟
  • 用于處理線程上的各種事件,定時器等
  • 可以提高程序性能,節約CPU資源,有事情做就做,沒事情做就讓線程休眠
  • 應用范疇:
    定時器,事件響應,手勢識別,界面刷新,以及autoreleasePool 等等

33. runloop內部實現邏輯?

  • 實際上 RunLoop 就是這樣一個函數,其內部是一個 do-while 循環。當你調用 CFRunLoopRun() 時,線程就會一直停留在這個循環里;直到超時或被手動停止,該函數才會返回。

34. runloop和線程的關系?

  • 每條線程都有唯一的一個與之對應的RunLoop對象
  • RunLoop保存在一個全局的Dictionary里,線程作為key,RunLoop作為value
  • 線程剛創建時并沒有RunLoop對象,RunLoop會在第一次獲取它時創建
  • RunLoop會在線程結束時銷毀
  • 主線程的RunLoop已經自動獲取(創建),子線程默認沒有開啟RunLoop

35. timer 與 runloop 的關系?

  • timer 定時器,是基于 runloop 來實現的, runloop 在運行循環當中,監聽到了定制器 就會執行;所以 timer 需要添加到 runloop 中去, 注意子線程的 runloop 默認是不開啟的,如果在子線程執行 timer 需要手動開啟 runloop

36. 程序中添加每3秒響應一次的NSTimer,當拖動tableview時timer可能無法響應要怎么解決?

  • 將 timer 對象添加到 runloop 中,并修改 runloop 的運行 mode
 NSTimer *timer = [NSTimer timerWithTimeInterval:1 repeats:YES block:nil];
 [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

37. runloop的mode作用是什么?

runloop 只能在一種 mode 下運行, 做不同的事情,runloop 會切換到對應的 model 下來執行,默認是 kCFRunLoopDefaultMode 如果視圖滑動再回切換到 UITrackingRunLoopMode,如果需要在多種 mode 下運行則需要手動設置 kCFRunLoopCommonModes;

  1. kCFRunLoopDefaultMode:App的默認Mode,通常主線程是在這個Mode下運行
  2. UITrackingRunLoopMode:界面跟蹤 Mode,用于 ScrollView 追蹤觸摸滑動,保證界面滑動時不受其他 Mode 影響
  3. UIInitializationRunLoopMode: 在剛啟動 App 時第進入的第一個 Mode,啟動完成后就不再使用,會切換到kCFRunLoopDefaultMode
  4. GSEventReceiveRunLoopMode: 接受系統事件的內部 Mode,通常用不到
  5. kCFRunLoopCommonModes: 這是一個占位用的Mode,作為標記kCFRunLoopDefaultMode和UITrackingRunLoopMode用,并不是一種真正的Mode

38. 使用method swizzling要注意什么?

  1. 方式無限循環
  2. 進行版本迭代的時候需要進行一些檢驗,防止系統庫的函數發生了變化

39. 一個系統方法被 多次交換,會有什么影響嗎?以及調用順序?原理

都會執行,后交換的會先調用.

第一次交換   viewwillAppAppear 和 test1 的指向的方法實現地址發生變化
第二次交換   viewwillAppAppear 和 test2 實際上等于是 test2 和 test1 進行了交換,因為 viewwillAppAppear 已經變為了 test1了.

調用 --> viewwillAppAppear
實際調用順序 -->test2--->test1-->viewwillAppAppear
形成一個閉環:viewwillAppAppear 也只會調用一次

40. runloop 主線程監聽卡頓

  • 用戶層面感知的卡頓都是來自處理所有UI的主線程上,包括在主線程上進行的大計算,大量的IO操作,或者比較重的繪制工作。
  • 如何監控主線程呢,首先需要知道的是主線程和其它線程一樣都是靠NSRunLoop來驅動的。可以先看看CFRunLoopRun的大概的邏輯 ,不難發現NSRunLoop調用方法主要就是在kCFRunLoopBeforeSources和kCFRunLoopBeforeWaiting之間,還有kCFRunLoopAfterWaiting之后,也就是如果我們發現這兩個時間內耗時太長,那么就可以判定出此時主線程卡頓.只需要另外再開啟一個線程,實時計算這兩個狀態區域之間的耗時是否到達某個閥值,便能揪出這些性能殺手.
  • 用GCD里的dispatch_semaphore_t開啟一個新線程,設置一個極限值和出現次數的值,然后獲取主線程上在kCFRunLoopBeforeSources到kCFRunLoopBeforeWaiting再到kCFRunLoopAfterWaiting兩個狀態之間的超過了極限值和出現次數的場景,將堆棧dump下來,最后發到服務器做收集,通過堆棧能夠找到對應出問題的那個方法。
- (void)start
{
    if (observer)
        return;

    // // 創建信號
    semaphore = dispatch_semaphore_create(0);

    // 注冊RunLoop狀態觀察
    CFRunLoopObserverContext context = {0,(__bridge void*)self,NULL,NULL};
    observer = CFRunLoopObserverCreate(kCFAllocatorDefault,
                                       kCFRunLoopAllActivities,
                                       YES,
                                       0,
                                       &runLoopObserverCallBack,
                                       &context);
    CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes);

    // 在子線程監控時長
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        while (YES)
        {
            // 假定連續5次超時50ms認為卡頓(當然也包含了單次超時250ms)
            long st = dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 50*NSEC_PER_MSEC));
            // Returns zero on success, or non-zero if the timeout occurred.
            if (st != 0)
            {
                if (!observer)
                {
                    timeoutCount = 0;
                    semaphore = 0;
                    activity = 0;
                    return;
                }

                // kCFRunLoopBeforeSources 即將處理source kCFRunLoopAfterWaiting 剛從睡眠中喚醒
                // RunLoop會一直循環檢測,從線程start到線程end,檢測檢測到事件源(CFRunLoopSourceRef)執行處理函數,首先會產生通知,corefunction向線程添加runloopObservers來監聽事件,并控制NSRunLoop里面線程的執行和休眠,在有事情做的時候使當前NSRunLoop控制的線程工作,沒有事情做讓當前NSRunLoop的控制的線程休眠。

                if (activity == kCFRunLoopBeforeSources || activity == kCFRunLoopAfterWaiting)
                {

                    if (++timeoutCount < 3)
                        continue;

                     NSLog(@"有點兒卡");
                }
            }
            timeoutCount = 0;
        }
    });
}

41. _objc_msgForward 函數是做什么的?直接 調用它將會發生什么?

  • _objc_msgForward 是 IMP 類型,用于消息轉發的:當向一個對象發送一條消息,但 它并沒有實現的時候,_objc_msgForward 會嘗試做消息轉發
  • 直接調用_objc_msgForward 是非常危險的事,這是把雙刃刀,如果用不好會直接 導致程序 Crash,但是如果用得好,能做很多非常酷的事
  • JSPatch 就是直接調用_objc_msgForward 來實現其核心功能的

42. 如何打印一個類中的所有實例變量

OC的類實際上是一個objc_class類型的結構體,包含了實例變量列表: (objc_ivar_list),可以通過 runtime 函數來獲取這個列表:
OBJC_EXPORT Ivar _Nonnull * _Nullable class_copyIvarList(Class _Nullable cls, unsigned int * _Nullable outCount)

例子:

Student *stu = [[Student alloc]init];
stu.stu_name = @"alex";
stu.stu_age = 10;

unsigned int count = 0;
Ivar *list = class_copyIvarList([stu class], &count);
NSMutableDictionary * dict = [NSMutableDictionary dictionary];
for (int i = 0; i< count; i++){
    id iVarName = [NSString stringWithUTF8String:ivar_getName(list[i])];
    dict[iVarName] = [stu valueForKey:iVarName];
}

NSLog(@"%@",dict);

43. 如何使用 rumtime 動態添加一個類

runtime 很強大.可以動態的創建一個全新的類或對象

// 添加一個繼承NSObject的類 類名是MyClass
Class MyClass = objc_allocateClassPair([NSObject class], "MyClass", 0);
// 增加實例變量
class_addIvar(MyClass, "_age", sizeof(NSString *), 0, "@");
//注冊這個類到runtime系統中就可以使用他了
objc_registerClassPair(MyClass);
//生成了一個實例化對象
id myobj = [[MyClass alloc] init];
//給剛剛添加的變量賦值
[myobj setValue:@30 forKey:@"age"];
// 打印
NSLog(@"age= %@",[myobj valueForKey:@"age"]);

收錄 | 原文地址


結語

再次說一聲,對于答案,不一定都合適,歡迎大家積極討論;整理不易,如果您覺得還不錯,麻煩在文末 “點個贊” ,或者留下您的評論“Mark” 一下,謝謝您的支持


推薦文集

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,885評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,312評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,993評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,667評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,410評論 6 411
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,778評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,775評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,955評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,521評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,266評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,468評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,998評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,696評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,095評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,385評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,193評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,431評論 2 378

推薦閱讀更多精彩內容