xib相關(十九) —— UINib之Nib文件(四)

版本記錄

版本號 時間
V1.0 2018.05.04

前言

iOS中的視圖加載可以有兩種方式,一種是通過xib加載,另外一種就是通過純代碼加載。它們各有優點和好處,xib比較直觀簡單,代碼比較靈活但是看著很多很亂,上一家公司主要風格就是用純代碼,這一家用的就是xib用的比較多。這幾篇我們就詳細的介紹一個xib相關知識。感興趣的可以看上面寫的幾篇。
1. xib相關(一) —— 基本知識(一)
2. xib相關(二) —— 文件沖突問題(一)
3. xib相關(三) —— xib右側標簽介紹(一)
4. xib相關(四) —— 連線問題(一)
5. xib相關(五) —— 利用layout進行約束之界面(一)
6. xib相關(六) —— 利用layout進行約束之說明和注意事項(二)
7. xib相關(七) —— Storyboard中的segue (一)
8. xib相關(八) —— Size Classes(一)
9. xib相關(九) —— 幾個IB修飾符(一)
10. xib相關(十) —— xib的國際化(一)
11. xib相關(十一) —— xib的高冷用法之修改視圖的圓角半徑、邊框寬度和顏色(一)
12. xib相關(十二) —— UIStackView之基本介紹(一)
13. xib相關(十三) —— UIStackView之枚舉UIStackViewDistribution使用(二)
14. xib相關(十四) —— UIStackView之UIStackViewAlignment使用(三)
15. xib相關(十五) —— UIStackView之工程實踐(四)
16. xib相關(十六) —— UINib之基本介紹(一)
17. xib相關(十七) —— UINib之Introduction(二)
18. xib相關(十八) —— UINib之Nib文件(三)

回顧

上一篇主要講述了UINib之Nib文件,這一篇繼續講述Nib文件。


Managing the Lifetimes of Objects from Nib Files - 管理從Nib文件加載的對象的生命周期

每次您要求NSBundle或NSNib類加載nib文件時,底層代碼都會在該文件中創建對象的新副本并將它們返回給您。 (nib加載代碼不會從之前的加載嘗試中回收nib文件對象)。您需要確保您只需要維護新的對象圖,并在完成時將其忽略。 您通常需要對頂級對象的強引用以確保它們不會被釋放; 您不需要強烈參考圖表中較低的對象,因為它們是由父類擁有的,您應該盡量減少創建強引用的風險。

從實際角度來看,iOS和OS X應該將outlet定義為已聲明的屬性。 除了從文件所有者到應用程序強大的nib文件中的頂級對象(或者在iOS中,故事板場景),outlet通常應該用weak。 因此,您創建的outlet通常應該weak,因為:

  • 例如,您為視圖控制器的視圖或窗口控制器的窗口的子視圖創建的outlet是在不隱式表示所有權的對象之間的任意引用。

  • 強大的outlet通常由框架類指定(例如,UIViewController的視圖outlet或NSWindowController的窗口outlet)。

@property (weak) IBOutlet MyView *viewContainerSubview;
@property (strong) IBOutlet MyOtherClass *topLevelObject;

注意:在OS X中,并非所有類都支持弱引用 - 請參閱Transitioning to ARC Release Notes。 如果你不能指定weak,你應該使用assign:

@property (assign) IBOutlet NSTextView *textView;

Outlets一般被認為是定義類的private,除非有公開property的理由,否則將屬性聲明隱藏為類擴展。 例如:

// MyClass.h
 
@interface MyClass : MySuperclass
@end
 
// MyClass.m
 
@interface MyClass ()
@property (weak) IBOutlet MyView *viewContainerSubview;
@property (strong) IBOutlet MyOtherClass *topLevelObject;
@end

這些模式擴展到從容器視圖到其子視圖的引用,您必須考慮對象圖的內部一致性。 例如,對于table view cell,特定子視圖的outlet通常應該為weak。 如果table view包含圖像視圖和文本視圖,那么只要它們是table view cell的子視圖,它們就保持有效。

Outlet應被視為擁有參考對象時,outlet應更改為strong:

  • 正如前面所指出的,這個是File's Owner 的情況- 通常認為nib文件中的頂級對象由文件的所有者擁有。

  • 您可能在某些情況下需要來自nib文件的對象存在于其原始容器之外。 例如,您可能有一個可從臨時視圖層次暫時移除的outlet視圖,因此必須單獨維護。

您希望被子類化的類(特別是抽象類)公開地公開這些子類(例如UIViewController的view outlet)。 如果期望該類的使用者需要與該屬性互動,那么outlet也可能會暴露出來; 例如一個table view cell可能會暴露子視圖。 在后一種情況下,可能適宜將公開只讀的outlet重新定義為一個讀寫,例如:

// MyClass.h
 
@interface MyClass : UITableViewCell
@property (weak, readonly) MyType *outletName;
@end

// MyClass.m
 
@interface MyClass ()
@property (weak, readwrite) IBOutlet MyType *outletName;
@end

1. Top-level Objects in OS X May Need Special Handling - OSX中的頂層對象需要特殊處理

由于歷史原因,在OS X中,nib文件中的頂級對象是使用額外引用計數創建的。 Application Kit提供了一些有助于確保nib對象正確釋放的功能:

  • NSWindow對象(包括面板)具有isReleasedWhenClosed屬性,該屬性如果設置為YES,則指示窗口在關閉時自行釋放(并因此在視圖層次結構中釋放所有依賴對象)。在nib文件中,您可以通過Xcode檢查器的“屬性”窗格中的Release when closed復選框來設置此選項。

  • 如果nib文件的File’s OwnerNSWindowController對象(基于文檔的應用程序中的文檔nib中的默認值 - 回想起NSDocument管理NSWindowController的實例)或NSViewController對象,它會自動處理其管理的窗口。

如果File’s Owner不是NSWindowControllerNSViewController的實例,那么您需要自己減少頂級對象的引用計數。您必須將對頂級對象的引用轉換為Core Foundation類型并使用CFRelease。 (如果您不想讓所有頂層對象具有outlets ,則可以使用NSNib類的instantiateNibWithOwner:topLevelObjects:方法來獲取一個包含nib文件頂級對象的數組。


Action Methods - Action方法

一般來說,action方法(請參閱OS X中的Target-Action或iOS中的Target-Action)是通常由nib文件中的另一個對象調用的方法。 Action方法使用類型限定符IBAction(代替void返回類型)將所聲明的方法標記為一個操作,以便Xcode知道它。

@interface MyClass

- (IBAction)myActionMethod:(id)sender;

@end

您可以選擇將action方法視為你的類所私有,因此不會在public @interface中聲明它們。 (因為Xcode解析實現文件,所以不需要在頭文件中聲明它們。)

/ MyClass.h
 
@interface MyClass
@end
 
// MyClass.m
 
@implementation MyClass
- (IBAction)myActionMethod:(id)sender {
    // Implementation.
}
@end

您通常不應以編程方式調用操作方法。 如果您的類需要執行與操作方法相關的工作,那么您應該將實現考慮到不同的方法中,然后由操作方法調用該方法。

// MyClass.h
 
@interface MyClass
@end
 
// MyClass.m
 
@interface MyClass (PrivateMethods)
- (void)doSomething;
- (void)doWorkThatRequiresMeToDoSomething;
@end
 
@implementation MyClass
- (IBAction)myActionMethod:(id)sender {
    [self doSomething];
}
 
- (void)doSomething {
    // Implementation.
}
 
- (void)doWorkThatRequiresMeToDoSomething {
    // Pre-processing.
    [self doSomething];
    // Post-processing.
}

@end

Built-In Support For Nib Files - Nib文件的內在支持

AppKit和UIKit框架都提供了一定數量的自動化行為來加載和管理應用程序中的nib文件。 這兩個框架都提供了加載應用程序的主要nib文件的基礎結構。 另外,AppKit框架還支持通過NSDocument和NSWindowController類加載其他的nib文件。 以下各節介紹了對nib文件的內置支持,如何利用它以及如何在自己的應用程序中修改該支持。

1. The Application Loads the Main Nib File - 程序加載主Nib文件

大多數用于應用程序的Xcode項目模板都預先配置了一個主要的nib文件。 你所要做的就是在nib文件中修改這個默認的nib文件并構建你的應用程序。 在啟動時,應用程序的默認配置數據告訴應用程序對象在哪里找到這個nib文件,以便它可以加載它。 在基于AppKit和UIKit的應用程序中,此配置數據位于應用程序的Info.plist文件中。 首次加載應用程序時,默認的應用程序啟動代碼將在Info.plist文件中查找NSMainNibFile項。 如果發現它,它會在應用程序包中查找一個nib文件,該文件的名稱(帶或不帶文件擴展名)與該鍵的值匹配并加載它。

2. Each View Controller Manages its Own Nib File - 每一個View Controller管理自己的Nib文件

UIViewController(iOS)NSViewController(OS X)類支持自動加載關聯的nib文件。 如果您在創建視圖控制器時指定了一個nib文件,那么當您嘗試訪問視圖控制器的視圖時,該nib文件會自動加載。 視圖控制器和nib文件對象之間的任何連接都會自動創建,并且在iOS中,UIViewController對象在視圖最終加載并顯示在屏幕上時也會收到其他通知。 為了更好地管理內存,UIViewController類還處理在內存不足情況下卸載其nib文件(如適用)。

有關如何使用UIViewController類以及如何配置它的更多信息,請參閱View Controller Programming Guide for iOS

3. Document and Window Controllers Load Their Associated Nib File - 文檔和窗口控制器管理它們關聯的Nib文件

在AppKit框架中,NSDocument類使用默認的窗口控制器來加載包含文檔窗口的nib文件。 NSDocumentwindowNibName方法是一種方便的方法,您可以使用它來指定包含相應文檔窗口的nib文件。在創建新文檔時,文檔對象將您指定的nib文件名傳遞給默認的窗口控制器對象,該對象將加載并管理nib文件的內容。如果您使用Xcode提供的標準模板,您唯一需要做的就是將文檔窗口的內容添加到nib文件中。

NSWindowController類還提供了加載nib文件的自動支持。如果以編程方式創建自定義窗口控制器,則可以選擇使用NSWindow對象或nib文件的名稱對它們進行初始化。如果選擇后一個選項,則NSWindowController類會在客戶端第一次嘗試訪問該窗口時自動加載指定的nib文件。之后,窗口控制器將窗口保持在內存中;即使窗口的Release when closed屬性設置,它也不會從nib文件重新加載它。

重要提示:使用NSWindowControllerNSDocument自動加載窗口時,正確配置nib文件非常重要。 這兩個類都包含一個窗口,您必須連接到您希望他們管理的窗口。 如果您沒有將此outlet連接到窗口對象,則會加載nib文件,但文檔或窗口控制器不會顯示該窗口。 有關Cocoa文檔體系結構的更多信息,請參閱Document-Based App Programming Guide for Mac


Loading Nib Files Programmatically - 以編程方式加載Nib文件

OS X和iOS都提供了將nib文件加載到應用程序的便利方法。 AppKit和UIKit框架都在NSBundle類中定義了支持加載nib文件的附加方法。 另外,AppKit框架還提供了NSNib類,它提供了與NSBundle類似的nib加載行為,但提供了一些在特定情況下可能有用的額外優點。

在規劃應用程序時,請確保您打算手動加載的任何nib文件都以簡化加載過程的方式進行配置。 為文件所有者選擇合適的對象并保持較小的nib文件可以大大提高其易用性和內存效率。 有關配置nib文件的更多提示,請參閱Nib File Design Guidelines

1. Loading Nib Files Using NSBundle - 使用NSBundle加載Nib文件

AppKit和UIKit框架定義了NSBundle類的其他方法(使用Objective-C類別)來支持加載nib文件資源。 與兩種方法的語法一樣,使用這些方法的語義在兩個平臺之間也是不同的。 在AppKit中,通常有更多的訪問包的選項,所以相應有更多的方法來從這些包中加載nib文件。 在UIKit中,應用程序只能從其主包中加載nib文件,因此需要更少的選項。 兩種平臺上可用的方法如下:

無論何時加載nib文件,都應該指定一個對象作為該nib文件的文件所有者。文件所有者的角色是一個重要的角色。它是運行代碼和即將在內存中創建的新對象之間的主要接口。所有的nib加載方法提供了一種方法來指定文件的所有者,直接或作為選項字典中的參數。

AppKit和UIKit框架處理nib加載的方式之間的語義差異之一就是頂級nib對象返回到應用程序的方式。在AppKit框架中,您必須使用loadNibFile:externalNameTable:withZone:方法之一顯式請求它們。在UIKit中,loadNibNamed:owner:options:方法直接返回這些對象的數組。在這兩種情況下避免擔心頂級對象的最簡單方法是將它們存儲在File's Owner對象的outlet中(請參閱 Managing the Lifetimes of Objects from Nib Files)。

Listing 1-1顯示了如何在基于AppKit的應用程序中使用NSBundle類加載nib文件的簡單示例。只要loadNibNamed:owner:方法返回,您就可以開始使用任何引用nib文件對象的outlet。換句話說,整個Nib加載過程發生在該單個調用的范圍內。 AppKit框架中的nib加載方法返回一個布爾值,以指示加載操作是否成功。

Listing 1-1  Loading a nib file from the current bundle

- (BOOL)loadMyNibFile
{
    // The myNib file must be in the bundle that defines self's class.
    if (![NSBundle loadNibNamed:@"myNib" owner:self])
    {
        NSLog(@"Warning! Could not load myNib file.\n");
        return NO;
    }
    return YES;
}

Listing 1-2顯示了如何在基于UIKit的應用程序中加載nib文件的示例。 在這種情況下,該方法檢查返回的數組以查看nib對象是否已成功加載。 (每個nib文件應該至少有一個表示nib文件內容的頂級對象。)本示例顯示了nib文件不包含文件所有者對象以外的占位符對象的簡單情況。 有關如何指定其他占位符對象的示例,請參閱Replacing Proxy Objects at Load Time

Listing 1-2  Loading a nib in an iPhone application

- (BOOL)loadMyNibFile
{
    NSArray*    topLevelObjs = nil;
 
    topLevelObjs = [[NSBundle mainBundle] loadNibNamed:@"myNib" owner:self options:nil];
    if (topLevelObjs == nil)
    {
        NSLog(@"Error! Could not load myNib file.\n");
        return NO;
    }
    return YES;
}

注意:如果您正在為iOS開發Universal應用程序,則可以使用特定于設備的命名約定自動為基礎設備加載正確的nib文件。 有關如何命名nib文件的更多信息,請參閱iOS Supports Device-Specific Resources

2.Getting a Nib File’s Top-Level Objects - 獲取Nib文件的頂級對象

獲取nib文件頂級對象的最簡單方法是在文件所有者對象中定義outlet以及用于訪問這些對象的setter方法(或更好的屬性)。 這種方法可確保頂級對象由你的對象引用,并且始終有對它們的引用。

Listing 1-3顯示了簡化的Cocoa類的接口和實現,該類使用outlet保留nib文件唯一的頂級對象。 在這種情況下,nib文件中唯一的頂級對象是NSWindow對象。 由于Cocoa中的頂級對象的初始保留計數為1,因此會包含額外的釋放消息。 這很好,因為在進行調用release時,該屬性已被保留在窗口中。 您不希望在iPhone應用程序中以這種方式釋放頂級對象

Listing 1-3  Using outlets to get the top-level objects

// Class interface.
@interface MyController : NSObject
- (void)loadMyWindow;
@end
 
// Private class extension.
@interface MyController ()
@property (strong) IBOutlet NSWindow *window;
@end
 
 
// Class implementation
@implementation MyController
 
- (void)loadMyWindow {
    [NSBundle loadNibNamed:@"myNib" owner:self];
 
    // The window starts off with a retain count of 1
    // and is then retained by the property, so add an extra release.
    NSWindow *window = self.window;
    CFRelease(__bridge window);
}
@end

如果您不想使用outlet存儲對您的nib文件頂級對象的引用,則必須在代碼中手動檢索這些對象。 獲取頂級對象的技術因目標平臺而異。 在OS X中,您必須明確詢問對象,而在iOS中它們會自動返回給您。

Listing 1-4顯示了在OS X中獲取nib文件的頂級對象的過程。該方法將一個可變數組放入nameTable字典中,并將其與NSNibTopLevelObjects關聯。 nib加載代碼查找此數組對象,如果存在,則將頂級對象放入其中。 由于每個對象在添加到數組之前以保留計數1開始,因此單單釋放數組并不足以釋放數組中的對象。 因此,此方法會向每個對象發送一條釋放消息,以確保該數組是唯一持有對它們的引用的實體。

Listing 1-4  Getting the top-level objects from a nib file at runtime

- (NSArray*)loadMyNibFile
{
    NSBundle*            aBundle = [NSBundle mainBundle];
    NSMutableArray*      topLevelObjs = [NSMutableArray array];
    NSDictionary*        nameTable = [NSDictionary dictionaryWithObjectsAndKeys:
                                            self, NSNibOwner,
                                            topLevelObjs, NSNibTopLevelObjects,
                                            nil];
 
    if (![aBundle loadNibFile:@"myNib" externalNameTable:nameTable withZone:nil])
    {
        NSLog(@"Warning! Could not load myNib file.\n");
        return nil;
    }
 
    // Release the objects so that they are just owned by the array.
    [topLevelObjs makeObjectsPerformSelector:@selector(release)];
    return topLevelObjs;
}

在iPhone應用程序中獲取頂級對象要簡單得多,如Listing 1-2所示。 在UIKit框架中,NSBundleloadNibNamed:owner:options:方法自動返回一個包含頂級對象的數組。 另外,在返回數組時,調整對象的保留計數,以便不需要為每個對象發送額外的釋放消息。 返回的數組是對象的唯一所有者。

3. Loading Nib Files Using UINib and NSNib - 使用UINib和NSNib加載Nib文件

UINib(iOS)和NSNib(OS X)類在您想要創建nib文件內容的多個副本的情況下提供更好的性能。正常的nib加載過程涉及從磁盤讀取nib文件,然后實例化其包含的對象。但是,使用UINib和NSNib類時,只需從磁盤讀取一次nib文件,并將內容存儲在內存中。由于它們在內存中,創建連續的對象集花費的時間更少,因為它不需要訪問磁盤。

使用UINib和NSNib類始終是一個兩步過程。首先,創建類的一個實例,并用nib文件的位置信息初始化它。其次,您將實例化nib文件的內容以將對象加載到內存中。每次您實例化nib文件時,都會指定一個不同的文件所有者對象并接收一組新的頂級對象。

Listing 1-5顯示了一種在OS X中使用NSNib類加載nib文件內容的方法。instantiateNibWithOwner:topLevelObjects:方法返回給您的數組已自動釋放。如果你打算在一段時間內使用該數組,你應該復制它。

Listing 1-5  Loading a nib file using NSNib

- (NSArray*)loadMyNibFile
{
    NSNib*      aNib = [[NSNib alloc] initWithNibNamed:@"MyPanel" bundle:nil];
    NSArray*    topLevelObjs = nil;
 
    if (![aNib instantiateNibWithOwner:self topLevelObjects:&topLevelObjs])
    {
        NSLog(@"Warning! Could not load nib file.\n");
        return nil;
    }
    // Release the raw nib data.
    [aNib release];
 
    // Release the top-level objects so that they are just owned by the array.
    [topLevelObjs makeObjectsPerformSelector:@selector(release)];
 
    // Do not autorelease topLevelObjs.
    return topLevelObjs;
}

4. Replacing Proxy Objects at Load Time - 在加載時替換代理對象

在iOS中,可以創建包含File’s Owner之外的占位符對象的nib文件。 代理對象表示創建在nib文件外的對象,但它們與nib文件的內容有一些連接。 代理通常用于在iPhone應用程序中支持導航控制器。 在使用導航控制器時,通常將文件所有者對象連接到某個通用對象,如應用程序代理。 代理對象因此代表已經加載到內存中的導航控制器對象層次結構的部分,因為它們是以編程方式創建的或從不同的nib文件加載的。

注意:OS X nib文件不支持自定義占位符對象(文件所有者除外)。

添加到nib文件的每個占位符對象都必須具有唯一的名稱。要為對象指定名稱,請在Xcode中選擇對象并打開檢查器窗口。檢查器的“屬性”窗格包含一個Name字段,您可以使用該字段指定占位符對象的名稱。您指定的名稱應該描述對象的行為或類型,但實際上它可以是任何您想要的。

當準備加載包含占位符對象的nib文件時,當您調用loadNibNamed:owner:options:方法時,您必須為任何代理指定替換對象。此方法的options參數接受附加信息的字典。您可以使用此字典來傳遞有關占位符對象的信息。字典必須包含UINibExternalObjects鍵,其值是包含每個占位符替換的名稱和對象的另一個字典。

Listing 1-6顯示了手動加載應用程序的主要nib文件的applicationDidFinishLaunching:方法的示例代碼。由于應用程序的代理對象是由UIApplicationMain函數創建的,因此此方法在主nib文件中使用占位符(名稱為“AppDelegate”)來表示該對象。代理字典存儲占位符對象信息和選項字典包裝該字典。

Listing 1-6  Replacing placeholder objects in a nib file

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
    NSArray*    topLevelObjs = nil;
    NSDictionary*    proxies = [NSDictionary dictionaryWithObject:self forKey:@"AppDelegate"];
    NSDictionary*    options = [NSDictionary dictionaryWithObject:proxies forKey:UINibExternalObjects];
 
    topLevelObjs = [[NSBundle mainBundle] loadNibNamed:@"Main" owner:self options:options];
    if ([topLevelObjs count] == 0)
    {
        NSLog(@"Warning! Could not load myNib file.\n");
        return;
    }
 
    // Show window
    [window makeKeyAndVisible];
}

有關loadNibNamed:owner:options:方法的選項字典的更多信息,請參閱NSBundle UIKit Additions Reference

5. Accessing the Contents of a Nib File - 訪問Nib文件的內容

成功加載nib文件后,其內容即可供您立即使用。 如果您將文件所有者中的outlet配置為指向nib文件對象,則現在可以使用這些outlet。 如果您沒有使用任何outlet插座配置文件所有者,則應確保以某種方式獲取對頂級對象的引用,以便稍后可以釋放它們。

由于在加載nib文件時,outlet會填充真實對象,因此隨后可以像使用編程創建的其他對象那樣使用outlet。 例如,如果您有一個指向窗口的outlet,您可以向該窗口發送一個makeKeyAndOrderFront:消息以在用戶的屏幕上顯示該窗口。 當您完成在nib文件中使用對象時,必須像其他任何對象一樣釋放它們。

重要提示:您負責釋放當您完成這些對象時加載的所有nib文件的頂層對象。 不這樣做是許多應用程序內存泄漏的原因。 釋放頂層對象后,最好通過將指向nib文件中的對象的outlet設置為nil來清除所有outlet。 您應該清除與所有nib文件對象關聯的outlet,而不僅僅是頂層對象。


Connecting Menu Items Across Nib Files - 連接Nib文件中的菜單項

OS X應用程序菜單欄中的項目通常需要與許多不同的對象進行交互,包括應用程序的文檔和窗口。問題是許多這些對象不能(或不應該)從主要的nib文件直接訪問。主nib文件的文件所有者始終設置為NSApplication類的實例。盡管您可能能夠在主nib文件中實例化一些自定義對象,但這樣做實際上并不必要。對于文檔對象,直接連接到特定的文檔對象是不可能的,因為文檔對象的數量可以動態改變,甚至可以為零。

大多數菜單項將action消息發送到以下其中一項:

  • 始終處理命令的固定對象
  • 動態對象,如文檔或窗口

消息傳遞固定對象是一個相對直接的過程,通常通過應用程序委托來處理。應用程序委托對象在運行應用程序時協助NSApplication對象,并且是在主要nib文件中屬于的少數幾個對象之一。如果菜單項引用了應用程序級別的命令,則可以直接在應用程序委托中實現該命令,或者僅讓委托將消息轉發到應用程序中其他位置的相應對象。

如果您有一個菜單項作用于最前面窗口的內容,則需要將該菜單項鏈接到First Responder占位符對象。如果與菜單項關聯的action方法特定于您的某個對象(并且未由Cocoa定義),則必須在創建連接之前將該操作添加到First Responder。

創建連接后,您需要在自定義類中實現操作方法。該對象還應實現validateMenuItem:validateMenuItem:方法以在適當的時間啟用菜單項。有關響應者鏈如何處理命令的更多信息,請參閱Cocoa Event Handling Guide

后記

本篇主要講述了UINib之Nib文件,感興趣的給個贊或者關注~~~

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

推薦閱讀更多精彩內容