Objective-C 編碼建議

轉(zhuǎn)載自:CocoaChina

Objective-C 是 C 語(yǔ)言的擴(kuò)展,增加了動(dòng)態(tài)類型和面對(duì)對(duì)象的特性。它被設(shè)計(jì)成具有易讀易用的,支持復(fù)雜的面向?qū)ο笤O(shè)計(jì)的編程語(yǔ)言。它是 Mac OS X 以及 iPhone 的主要開發(fā)語(yǔ)言。

Cocoa 是 Mac OS X 上主要的應(yīng)用程序框架之一。它由一組 Objective-C 類組成,為快速開發(fā)出功能齊全的 Mac OS X 應(yīng)用程序提供支持。

而在日常的編程中,我們除了要寫代碼,還需要去閱讀別人的代碼,熟悉過往的業(yè)務(wù)邏輯。不知,你可曾發(fā)過牢騷:這代碼怎么能這么寫呢?有些時(shí)候我們的代碼,也會(huì)被別人去讀,不知你可曾想過,當(dāng)別人讀到你的代碼的時(shí)候會(huì)作何評(píng)價(jià)。誠(chéng)然,“讓代碼能夠工作”是做為開發(fā)者的頭等大事。但是,代碼的可維護(hù)性卻是更加影響深遠(yuǎn)的一件事情。你的代碼既有可能在下一個(gè)版本中被修改,也極有可能被交給另外的同事去修改。畢竟我們寫代碼,不止是在和機(jī)器溝通,而且也是在和人溝通——和其他的程序員溝通。大家都知道“學(xué)好普通話,走遍天下都不怕”,同樣的道理:寫出一手漂亮的代碼,你和誰(shuí)溝通都沒問題。

即使你的原始代碼修改之后,其代碼風(fēng)格和可讀性仍會(huì)影響到可維護(hù)性和可擴(kuò)展性。即使代碼不復(fù)存在,你的風(fēng)格和律條仍存活下來(lái)。

下面我們將圍繞一些基本的準(zhǔn)則展開討論,目的是讓我們寫出一手漂亮的代碼,更好的用代碼與其他同事溝通,也為了提高我們代碼的可維護(hù)性和可修改性,也是為了讓我們自己工作的地方有一個(gè)愉悅的代碼環(huán)境。

(PS:當(dāng)你真的按照這些看似偏執(zhí)的規(guī)則去做的時(shí)候,你就真的能夠發(fā)現(xiàn)“偉大來(lái)自細(xì)節(jié)”,而且會(huì)受益匪淺。保劍鋒自磨礪出,梅花香自苦寒來(lái)。)

總則

1.Don’t repeat your self.

2.代碼自注釋,依靠代碼本身來(lái)表達(dá)你的設(shè)計(jì)意圖,不要依賴注釋。

3.單一指責(zé),無(wú)論是類、函數(shù)、模塊、包盡可能令其指責(zé)純凈且單一。

4.死程序不說謊,不要因?yàn)榉乐笴rash寫奇葩的代碼。程序Crash了,反而更容易查找錯(cuò)誤。

5.借用美國(guó)童子軍軍規(guī):讓營(yíng)地比你來(lái)時(shí)更干凈。

格式

1.任意函數(shù)長(zhǎng)度不得超過50行。

2.任意行代碼不得超過80字符。可以在設(shè)置中設(shè)置超過80個(gè)字符的提醒。

3.在定義函數(shù)的行前留白一行

4.功能相近的代碼要放在一起。

5.使用#pragma來(lái)切分不同功能區(qū)域的代碼。

6.二元運(yùn)算符和參數(shù)之間需要放置一個(gè)空格,一元運(yùn)算符、強(qiáng)制類型轉(zhuǎn)換和參數(shù)之間不放置空格。關(guān)鍵字之后圓括號(hào)之前需要放置一個(gè)空格.

void *ptr = &value + 10 * 3;

NewType a = (NewType)b;

for(int i = 0; i < 10; i++) {

doCoolThings();

}

7.長(zhǎng)的字面值應(yīng)被拆分為多行。

NSArray *theShit = @[

@"Got some long string objects in here.",

[AndSomeModelObjects too],

@"Moar strings."

];

NSDictionary *keyedShit = @{

@"this.key": @"corresponds to this value",

@"otherKey": @"remoteData.payload",

@"some": @"more",

@"JSON": @"keys",

@"and": @"stuff",

};

命名

命名是編程中最基本的技能,我們給變量、函數(shù)、類、包等等命名。給他們以名字,讓他們有意義,既能表示他們到底是做什么的,也能將其與其他變量區(qū)別開來(lái)。而通過,語(yǔ)言的發(fā)展史,我們也能夠看到“方便編程人員理解和使用”一直都是編程語(yǔ)言發(fā)展的動(dòng)力之一,而命名則是其最最核心的環(huán)節(jié)。像人一樣娶一個(gè)好名字至關(guān)重要,“丁當(dāng)”總比“狗蛋”來(lái)的好聽。 為什么要命名?命名代表著抽象,我們使用名字將一些沒必要關(guān)系的細(xì)節(jié)隱去,減少我們自己的記憶成本,也更加方便我們理解。用過C語(yǔ)言的人都知道,一個(gè)變量名最終會(huì)轉(zhuǎn)化成類似于~~~0x11111111~~~之類的地址,相比去理解和記憶這些地址,用一個(gè)更加抽象的變量名來(lái)代表這些地址。無(wú)論從理解還是記憶上都要方便的。

命名一定要“名副其實(shí)”,盡可能使用有意的名稱,而且這個(gè)意義和指稱的變量真實(shí)意義相關(guān)。

盡量不要出現(xiàn)沒有任何意義的命名類似于下述形式的命名:

int a = 1;

int b = 3;

CGPoint point = CGPointMake(a,b);

如果換成下面的形式是不是可讀性強(qiáng)了很多:

int startX = 1;

int startY = 3;

CGPoint startPoint = CGPointMake(startX,startY);

命名首字母大寫,其他命名首字母小寫。并且采用駝峰格式分割單詞。

例如:BWTest

使用能夠讀出來(lái)的名稱

人類長(zhǎng)于記憶和使用單詞。大腦中的相當(dāng)一部分就是用來(lái)容納和處理單詞的。單詞如果能夠讀的出來(lái),則非常方便我們閱讀和理解。

錯(cuò)誤的示例: genymdhms (生成日期,年、月、日、時(shí)、分、秒)

正確的實(shí)例: generationTimeStamp

使用可搜索的名稱

單字母名稱和數(shù)字常量有一個(gè)問題,就是很難在一大篇文字中找出來(lái)。試想一下,你找~~~MAX_CLASSES_PER_STUDENT~~~容易還是找數(shù)字7容易。

文件名

文件名反映出了其實(shí)現(xiàn)了什么類(包括大小寫),你需要遵循所參與醒目的約定。

文件的擴(kuò)展名及其意義如下:

類別的擴(kuò)展名以“被擴(kuò)展的類名+自定義命名部分組成”

例如:NSSstring+Utils.h

縮略詞

雖然方法命名不應(yīng)使用縮略詞,然而有些縮略詞在過去被反復(fù)的使用,所以使用這些縮略詞能更好的的表達(dá)代碼的含義。下表列出了Cocoa可接受的縮略詞。

以下是一些常用的首字母縮略詞:ASCII,PDF,XML,HTML,URL,RTF,HTTP,TIFF,JPG,PNG,GIF,LZW,ROM,RGB,CMYK,MIDI,FTP…

宏定義全部字母大寫,例如:#define BW_DEBUG 1

常量定義,字符串定義以小寫字母 k 開頭,隨后首字母大寫

static NSString* const kBWBarTitle = @"動(dòng)態(tài)";

如果要定義常量使用static const優(yōu)于宏定義,前者會(huì)進(jìn)行類型檢查

因?yàn)镺C沒有命名空間的概念,所以使用前兩個(gè)或者多個(gè)字母來(lái)表示命名空間,例如”NSObject中的NS”,我們也使用自己的命名空間。比如

紅點(diǎn)中使用了VAS:VASAddValueInfo...

錢包中使用了QW:QWApplication....

注釋

讓代碼自注釋,不要依賴注釋來(lái)解釋自己的設(shè)計(jì)或者編碼意圖。除了特殊情況外,代碼中不要有多余的注釋。

函數(shù)

函數(shù)長(zhǎng)度不要超過50行,小函數(shù)要比大函數(shù)可閱讀性和可復(fù)用性強(qiáng)。

零元函數(shù)最好,一元函數(shù)也不錯(cuò),二元函數(shù)擔(dān)心了,三元函數(shù)有風(fēng)險(xiǎn),高于三元需重構(gòu)。函數(shù)的參數(shù)越多,引起其變化的因素就越多。越不利于以后的修改。

不知道當(dāng)你看到如下形式的函數(shù)的時(shí)候,是什么想法:

- (void)RequestGetLocation:(int)lat lon:(int)lon alt:(int)alt isMars:(BOOL)yn bJiejingSOSO:(BOOL)bJiejingSOSO;

盡量少的寫有副作用的函數(shù)

盡量不要出現(xiàn)火車鏈?zhǔn)降拿绻梢员M量使用過程變量替代。

反例例如:

_needLogoutAccount = [[[[BWAppSetting GetInstance] appSetting] valueForKey:NeedLogoutAccounts] retain];

考慮如果改成下述模樣,是不是可讀性一下子提高了很多:

BWAppSetting* shareSetting = [BWAppSetting GetInstance];

BWLockDictionary* defaultSettings = [shareSetting appSetting];

_needLogoutAccount = [[defaultSettings valueForKeyPath:NeedLogoutAccounts] retain];

調(diào)用時(shí)所有參數(shù)應(yīng)該在同一行

[myObject doFooWith:arg1 name:arg2 error:arg3];

或者每行一個(gè)參數(shù),以冒號(hào)對(duì)齊:

[myObject doFooWith:arg1

name:arg2

error:arg3];

對(duì)于參數(shù)過多的函數(shù),盡量使用后面一種對(duì)其方式。

不要使用下面的縮進(jìn)風(fēng)格:

[myObject doFooWith:arg1 name:arg2// some lines with >1 arg

error:arg3];

[myObject doFooWith:arg1

name:arg2 error:arg3];

[myObject doFooWith:arg1

name:arg2// aligning keywords instead of colons

error:arg3];

如果對(duì)傳入?yún)?shù)進(jìn)行數(shù)據(jù)保護(hù)盡量不要用~~~if(!objc)~~~,使用斷言來(lái)處理。

- (void) sendArgs:(NSDictionary*)args {

NSAssert(args, @"args is nil");

.....

}

方法參數(shù)名前一般使用的前綴包括“the”、“an”、“new”。

示例:

- (void) setTitle: (NSString *) aTitle;

- (void) setName: (NSString *) newName;

- (id) keyForOption: (CDCOption *) anOption

- (NSArray *) emailsForMailbox: (CDCMailbox *) theMailbox;

- (CDCEmail *) emailForRecipients: (NSArray *) theRecipients;

Block相關(guān)

在block中使用到self變量的時(shí)候,一定要先weak再strong.

__weaktypeof(self) weakSelf = self;

[self doABlockOperation:^{

__strongtypeof(weakSelf) strongSelf = weakSelf;

if(strongSelf) {

...

}

}];

控制結(jié)構(gòu)

順序結(jié)構(gòu)

分支結(jié)構(gòu)

if-else結(jié)構(gòu)超過四層的時(shí)候,要考慮重構(gòu)。多層的ifelse結(jié)構(gòu)極其難維護(hù)。

當(dāng)需要滿足一定條件時(shí)才執(zhí)行某項(xiàng)操作時(shí),最左邊緣應(yīng)該是愉快路徑代碼。不要將愉快路徑代碼內(nèi)嵌到if語(yǔ)句中。多個(gè)return是正常合理的。

良好的風(fēng)格:

- (void) someMethod {

if(![someOther boolValue]) {

return;

}

//Do something important

}

反面教材:

- (void) someMethod {

if([someOther boolValue]) {

//Do something important

}

所有的邏輯塊必須使用花括號(hào)包圍,即使條件體只需編寫一行代碼也必須使用花括號(hào)。

良好的風(fēng)格:

if(!error) {

returnsuccess;

}

反面教材:

if(!error)

returnsuccess;

...

if(!error)returnsuccess;

循環(huán)結(jié)構(gòu)

遍歷可變?nèi)萜髦埃枰獜?fù)制該容器,遍歷該容器的Copy.

//typeof(self.cells) is NSMutableArray

NSArray* cellArrays = [self.cells copy];

for(UITableViewCell* cellincellArrays) {

...

}

盡量不要使用異常,尤其是不要將異常做為業(yè)務(wù)邏輯的一部分,在異常中嘗試進(jìn)行災(zāi)難恢復(fù)。

類與對(duì)象

明確指定構(gòu)造函數(shù)

注釋并且明確指定你的類的構(gòu)造函數(shù)。

對(duì)于需要繼承你的類的人來(lái)說,明確指定構(gòu)造函數(shù)十分重要。這樣他們就可以只重寫一個(gè)構(gòu)造函數(shù)(可能是幾個(gè))來(lái)保證他們的子類的構(gòu)造函數(shù)會(huì)被調(diào)用。這也有助于將來(lái)別人調(diào)試你的類時(shí),理解初始化代碼的工作流程。 ###重載指定構(gòu)造函數(shù)

當(dāng)你寫子類的時(shí)候,如果需要 init… 方法,記得重載父類的指定構(gòu)造函數(shù)。

如果你沒有重載父類的指定構(gòu)造函數(shù),你的構(gòu)造函數(shù)有時(shí)可能不會(huì)被調(diào)用,這會(huì)導(dǎo)致非常隱秘而且難以解決的 bug。

重載 NSObject的方法

如果重載了 NSObject 類的方法,強(qiáng)烈建議把它們放在 @implementation 內(nèi)的起始處,這也是常見的操作方法。

通常適用(但不局限)于init…,copyWithZone:,以及dealloc方法。所有init…方法應(yīng)該放在一起,copyWithZone: 緊隨其后,最后才是dealloc 方法

初始化

不要在 init 方法中,將成員變量初始化為 0 或者 nil;毫無(wú)必要。

現(xiàn)代的 Ojbective-C 代碼通過調(diào)用 alloc 和 init 方法來(lái)創(chuàng)建并 retain 一個(gè)對(duì)象。由于類方法 new 很少使用,這使得有關(guān)內(nèi)存分配的代碼審查更困難。

保持init函數(shù)簡(jiǎn)潔,不要讓init函數(shù)成為千行的大函數(shù),當(dāng)超過50行的時(shí)候,適當(dāng)考慮分拆一下。

良好的風(fēng)格實(shí)例:

- (void) commonInit

{

_rightAppendImageView = [UIImageViewnew];

[self.contentView addSubview:_rightAppendImageView];

}

- (instancetype) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

{

self = [superinitWithStyle:style reuseIdentifier:reuseIdentifier];

if(!self) {

returnself;

}

[self commonInit];

returnself;

}

UIView的子類初始化的時(shí)候,不要進(jìn)行任何布局操作。布局操作在LayoutSubViews里面做。

UIView的子類布局必須在layoutSubViews里面進(jìn)行,需要布局的時(shí)候調(diào)用~~~setNeedLayout~~~來(lái)告訴系統(tǒng),需要重新布局該View,不要直接調(diào)用~~~layoutSubViews~~~

保持公共 API 簡(jiǎn)單

"保持類簡(jiǎn)單;避免 “廚房水槽(kitchen-sink)” 式的 API。如果一個(gè)函數(shù)壓根沒必要公開,就不要這么做。用私有類別保證公共頭文件整潔。"

與 C++ 不同,Objective-C 沒有方法來(lái)區(qū)分公共的方法和私有的方法 – 所有的方法都是公共的(譯者注:這取決于 Objective-C 運(yùn)行時(shí)的方法調(diào)用的消息機(jī)制)。因此,除非客戶端的代碼期望使用某個(gè)方法,不要把這個(gè)方法放進(jìn)公共 API 中。盡可能的避免了你你不希望被調(diào)用的方法卻被調(diào)用到。這包括重載父類的方法。對(duì)于內(nèi)部實(shí)現(xiàn)所需要的方法,在實(shí)現(xiàn)的文件中定義一個(gè)類別,而不是把它們放進(jìn)公有的頭文件中。

// GTMFoo.m

#import "GTMFoo.h"

@interface GTMFoo (PrivateDelegateHandling)

- (NSString *)doSomethingWithDelegate;// Declare private method

@end

@implementation GTMFoo(PrivateDelegateHandling)

...

- (NSString *)doSomethingWithDelegate {

// Implement this method

}

...

@end

在OC2.0以后,你可以在實(shí)現(xiàn)文件中使用,類擴(kuò)展來(lái)生命你的私有類別:

@interface GMFoo () { ... }

每個(gè)文件中只創(chuàng)建或者實(shí)現(xiàn)一個(gè)類。同一個(gè)文件中不要存在多個(gè)類。

Protocol單獨(dú)用一個(gè)文件來(lái)創(chuàng)建。盡量不要與相關(guān)類混在一個(gè)文件中。

類的私有變量以”_“開頭。

創(chuàng)建私有變量,份兩種情況。 第一種情況子類需要繼承的,在頭文件中定義:

// BWTest.h

@interface BWTest : NSObject

{

NSString* _name;

}

第二種情況,不需要子類繼承的,在實(shí)現(xiàn)文件中以Category的方式定義:

// BWTest.m @interface BWTest () { NSString* _name; }

@implementation BWTest

...

@end

公有變量在一般使用屬性的方法定義 @property (….) …

使用委托模式,設(shè)置delegate的時(shí)候,在ARC下使用 weak ;在MRC下使用 retain ,并且在dealloc中將其指針置空。

外部引用對(duì)象,外部不會(huì)發(fā)生set操作的對(duì)象,比如在創(chuàng)建界面元素的時(shí)候,使用readonly屬性。

@interface BWView : UIView

@property (nonatomic, strong, readonly) UIView* backgoundView;

@end

@implementation BWView

@end

在類定義中使用到自己定義的類的時(shí)候,盡量不要在頭文件中引入自己定義的類的同文件,使用 @class 替換。在實(shí)現(xiàn)文件中引入相應(yīng)頭文件。

例如:

//BWTest.h @class BWDataCenter; @interface BWTest : NSObject @property (nonatomic, strong) BWDataCenter* dataCenter; @end

//BWTest.m

import “BWDataCenter.h”

@implementation BWTest @end

如果一個(gè)類只是DTO(data transfer object),只是作為數(shù)據(jù)傳輸使用,可以不用引入使用的自定義的類的頭文件,只是用 @class ,表明相應(yīng)的自定義的類型。

對(duì)于DTO類型的對(duì)象,在給其成員變量設(shè)置值的時(shí)候可以考慮使用KVC,實(shí)現(xiàn)下述函數(shù):

- (void) setValue:(id)value forKey:(NSString *)key

{

if([key isEqualToString:kRedDotAppInfoPath]) {

....

}elseif...

....

}

- (id) valueForKey:(NSString *)key {

....

}

點(diǎn)標(biāo)記語(yǔ)法

屬性和冪等方法(多次調(diào)用和一次調(diào)用返回的結(jié)果相同)使用點(diǎn)標(biāo)記語(yǔ)法訪問,其他的情況使用方括號(hào)標(biāo)記語(yǔ)法。 良好的風(fēng)格:

view.backgroundColor = [UIColor orangeColor];

[UIApplication sharedApplication].delegate;

反面實(shí)例:

[view setBackgroundColor:[UIColor orangeColor]];

UIApplication.sharedApplication.delegate;

Cocoa相關(guān)

每個(gè)NSObject都有其生命周期,要在其生命周期的合適的時(shí)機(jī)做合適的事情。

例如:在初始化的時(shí)候,進(jìn)行變量初始化,在銷毀的時(shí)候,銷毀變量等等。

盡量不要在界面布局的寫任何死數(shù)字

錯(cuò)誤的示范:

CGFloat delta = SYSTEM_VERSION >= 7.0 ? 0.0f : -14.0f;

newFrame = CGRectMake(245 + delta,

(self.frame.size.height - tipNewSize.height)/2,

tipNewSize.width,

tipNewSize.height);

dotFrame = CGRectMake(258.0 + delta, (self.frame.size.height - tipDotSize.height)/2,

tipDotSize.width,

tipDotSize.height);

iconFrame = CGRectMake(245 + delta,

(self.frame.size.height - tipIconSize.height)/2,

tipIconSize.width,

tipIconSize.height);

numFrame = CGRectMake(245+delta, (self.frame.size.height - tipNumSize.height)/2, tipNumSize.width, tipNumSize.height);

正確的示范:

CGFloat cellHeight = CGRectGetHeight(self.frame);

CGFloat cellWidth = CGRectGetWidth(self.frame);

CGRect numFrame = CGRectZero;

numFrame.size = CGSizeMake(cellWidth,cellHeight);

...

布局時(shí)盡量使用相對(duì)布局,比如使用子View在父View中的相對(duì)位置。

在使用UITableView和UITableViewCell的時(shí)候一定要考慮到cell被復(fù)用的情況,在合適的時(shí)機(jī)對(duì)重用的cell進(jìn)行清除操作。

為UITableViewCell功能或者子View的時(shí)候有限考慮子類化。盡量不要使用在delegate中為Cell添加View。子類化,利于Cell重用和對(duì)cell內(nèi)新添加的子View的布局。

良好的風(fēng)格示例:

@interface BWSettingCell : UITableViewCell

@property (nonatomic, strong, readonly) UIImageView* rightAppendImageView;

@end

@implementation BWSettingCell

- (instancetype) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

{

self = [superinitWithStyle:style reuseIdentifier:reuseIdentifier];

if(!self) {

returnself;

}

_rightAppendImageView = [UIImageViewnew];

[self.contentView addSubview:_rightAppendImageView];

returnself;

}

- (void) layoutSubviews

{

[superlayoutSubviews];

CGSize rightImageSize = _rightAppendImageView.image.size;

_rightAppendImageView.frame = CGRectMake(CGRectGetWidth(self.frame) - rightImageSize.width,

(CGRectGetHeight(self.frame) - rightImageSize.height) /2,

rightImageSize.width,

rightImageSize.height);

}

@end

反面教材:

- (UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

static NSString* const settingCellIdentify = @"settingCellIdentify";

UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:settingCellIdentify];

if(!cell) {

cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:settingCellIdentify];

}

static int kSettingCellSubViewTag = 90001;

//非常錯(cuò)誤的地方,盡量不要這樣寫

[cell.contentView removeAllSubviews];

UIImageView* rightAppendingView = [UIImageViewnew];

rightAppendingView.image = nil;

rightAppendingView.frame = CGRectMake(230, 8, 30, 30);

[cell.contentView addSubview:rightAppendingView];

returncell;

}

設(shè)計(jì)模式相關(guān)

使用設(shè)計(jì)模式的最基本原則,除非你明確知道自己要做件什么事情,而且知道使用特定設(shè)計(jì)模式帶來(lái)的影響,否則不要刻意的使用設(shè)計(jì)模式。

單例模式

創(chuàng)建一個(gè)單例模式可以使用dispatch_once

+ (instancetype)defaultManager

{

if(!_defaultManager) {

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

_defaultManager = [[FlappyEggManager alloc] init];

});

}

return_defaultManager;

}

觀察者模式

如果只是單純的傳遞數(shù)據(jù),不要使用觀察者模式,容易導(dǎo)致邏輯鏈斷裂。

參考資料

1.《Clean Code

2.《編寫可閱讀代碼的藝術(shù)

3.《Google Objective-C Style Guide

4.《Introduction to Coding Guidelines for Cocoa

5.《iOS應(yīng)用開發(fā)最佳實(shí)踐系列一:編寫高質(zhì)量的Objective-C代碼

想要閱讀更多內(nèi)容,歡迎關(guān)注微信公共賬號(hào)IOS_Tips。

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

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