iOS代碼規范

iOS代碼規范

一、前言

本規范基于Google Objective-C Style Guide和百度Objective-C規范和實際開發情況,對其中的說明性語句及非ARC部分進行了刪減。
每項規范前面的[強制]代表該規范需要強制執行,[建議]代表推薦執行但不強制。

本文章里面的代碼格式大部分內容可以通過插件自動格式化,詳見ClangFormat-Xcode插件使用。

二、縮進與格式

1、縮進符

  • [強制] 只用空格,用4個空格表示一個縮進。

2、每行的長度

  • [強制] 應盡量控制每行代碼的長度在120個字符以內。

3、逗號分隔項

  • [強制] 用逗號分隔多項時,每個逗號后使用1個空格進行分隔。

4、左大括號位置

  • [強制] 左大括號 { 不單獨占據一行,放置在上一行的末尾,可以在 { 前增加一個空格。

5、聲明與定義

  • [強制] -,+ 與返回類型之間必須有一個空格,在參數列表中,除了參數之間不要有任何間距。

示例

- (void)doSomethingWithString:(NSString *)theString { 
    ...
} 
  • [強制] * 號前面必須要加空格,增加可讀性。

  • [建議] 如果有參數太多無法放在同一行內, 最好每個參數各自一行。如果采用多行,每個參數建議按照 : 進行對齊。

示例

- (void)doSomethingWith:(GTMFoo *)theFoo 
                   rect:(NSRect)theRect                
               interval:(float)theInterval { 
    ...
} 
  • [建議] 當第一個關鍵詞比其他的短時,可以縮進之后的行至少4個空格,同樣按 : 進行對齊。

示例

- (void)short:(GTMFoo *)theFoo 
      longKeyword:(NSRect)theRect     
evenLongerKeyword:(float)theInterval                 
            error:(NSError **)theError { 
     ...
} 

6、方法調用

  • [建議] 方法調用的格式須要與定義時的格式一致。當有多種格式化的樣式可供選擇的時候,按照慣例,采用在給定的源文件中使用過的那個方式。
  • [建議] 所有的參數都應該在同一行。

示例

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

或者每個參數一行,并按 : 對齊。

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

不建議采用以下風格:

 [myObject doFooWith:arg1 name:arg2 //這行寫了兩個參數
               error:arg3];  
[myObject doFooWith:arg1                
                 name:arg2 error:arg3]; 

就像聲明和定義一樣,當第一個關鍵詞比其他的短時,可以縮進之后的行至少4個空格,同樣按 : 進行對齊:

[myObj short:arg1          
    longKeyword:arg2    
  evenLongerKeyword:arg3                
          error:arg4]; 

7、@public、@protected與@private

  • [強制] 訪問修飾符 @public, @private,@protected必須縮進2個空格。

8、異常

  • [建議] 在單獨一行時,使用 @ 標簽格式化 exceptions, @ 標簽和左大括號 { 間加一個空格,在 @catch 和 對象捕獲聲明之間也一樣。建議遵循下面的格式:
@try {     
    foo(); 
} @catch (NSException *ex) {     
    bar(ex); 
} @finally {     
    baz(); 
}

9、協議

  • [強制] 在類型標識符和封裝在尖括號中的 Protocols 名稱之間要有空格。
@interface MyProtocoledClass : NSObject <NSWindowDelegate> {    
    @private      id <MyFancyDelegate> delegate_; 
} 
(void)setDelegate:(id <MyFancyDelegate>)aDelegate; 
@end 

解釋:這些適用于類的聲明、實例變量和方法的聲明。

10、Blocks

  • [強制] 塊內的代碼應縮進4個空格。
  • [建議] 因為具體block長度的不同,可以有以下幾種風格:
    (1)如果block一行就能放下,就不需要換行。
    (2)如果必須要換行,那么 } 需要和block所在行的第一個字符對齊。
    (3)block中的代碼塊應該縮進4個空格。
    (4)如果block很大,比如超過20行,建議單獨拿出來賦給一個本地變量
    (5)如果block沒有參數,那字符 ^{ 之間就不應有空格。如果有參數,字符 ^{ 之間同樣沒有空格,但是字符 ) { 之間需要有一個空格。
    (6)包含內聯block的函數調用可以在縮進4個空格的基礎上左對齊,尤其是調用中包含多個內聯block。

示例


//整個block放在一行的 
[operation setCompletionBlock:^{ [self onOperationDone]; }];

//多行時縮進四個空格,{要和block所在行的第一個字符對齊
[operation setCompletionBlock:^{

    [self.delegate newDataAvailable];
}]; 

//在C函數中使用block時遵循和Objective-C同樣的對齊和縮進原則
dispatch_async(fileIOQueue_, ^{

    NSString *path = [self sessionFilePath];     
    if (path) {       // ...     
    } 
});

// 方法參數與block聲明能放到一行時。注意比較^(SessionWindow *window) {和上面的^{。 
[[SessionService sharedService]  loadWindowWithCompletionBlock:^(SessionWindow *window) {
         
    if (window) {          
    [self windowDidLoad:window];        
    } else {           
        [self errorLoadingWindow];        
    }     
}]; 

//方法參數與block聲明不能放到一行時。 
[[SessionService sharedService]     
    loadWindowWithCompletionBlock:^(SessionWindow *window) {  
           
        if (window) {              
        [self windowDidLoad:window];             
        } else {               
        [self errorLoadingWindow];             
        }         
    }];  

// 較長的Block可聲明為變量。 
void (^largeBlock)(void) = ^{
     // ... 
}; 
[operationQueue_ addOperationWithBlock:largeBlock]; 

 // 一次調用中包含多個內聯block。 
[myObject doSomethingWith:arg1
    firstBlock:^(Foo *a) { // ...
    }
    secondBlock:^(Bar *b){
            // ...
    }];

11、Container Literals

  • [強制] 使用容器(數組和字典)常量,如果其內容被分為多行,應該縮進4個空格。
  • [建議] 如果內容單行就能放下,在左大括號之后和右大括號之前各添加一個空格。
NSArray *array = @[ [foo description], @"Another String", [bar description] ];
NSDictionary *dict = @{ 
    NSForegroundColorAttributeName : [NSColor redColor] 
};
  • [建議] 如果內容跨越多行,將左括號和聲明放在同一行,之后換行的內容縮進4個空格,并將右括號單獨放在新的一行里和聲明行對齊。
NSArray *array = @[     
    @"This",     
    @"is",    
    @"an",     
    @"array" 
]; 
NSDictionary *dictionary = @{
    NSFontAttributeName : [NSFont fontWithName:@"Helvetica-Bold" size:12],
    NSForegroundColorAttributeName : fontColor
};

三、命名與規范

在撰寫純粹的Objective-C代碼時,推薦使用駝峰命名法。

1、文件名

文件名應該反映其中包含的類實現的名稱,按照項目中的約定且大小寫相關。

  • [強制] 實現Category的文件名需包含類名,如 NSString+Utils.h 或 NSTextView+Autocomplete.h。

2、Objective-C++

在一個源碼文件中, Objective-C++ 遵循你實現的函數/方法的風格。
為了最小化在混合開發Cocoa/Objective-C和C++時由命名風格造成的沖突,遵循正在實現方法的風格。如果正在實現的方法是在@implementation 塊中, 使用Objective-C的命名規范。如果正在實現的方法是在C++的class中,則采用C++的命名規范。

class CrossPlatformAPI {
  public:
    ... int DoSomethingPlatformSpecific(); // 每個平臺的實現都不一樣

  private:
    int an_instance_var_;
};

// 文件 mac_implementation.mm
#include "cross_platform_header.h" //

// 典型的Objective-C class, 使用Objective-C命名規范。
@interface MyDelegate :

    NSObject {
  @private
    int _instanceVar;
    CrossPlatformAPI *_backEndObject;
}
- (void)respondToSomething:(id)something;
@end

@implementation MyDelegate

- (void)respondToSomething:(id)something {

    //從Cocoa橋接到C++的后端
    _instanceVar = _backEndObject->DoSomethingPlatformSpecific();
    NSString *tempString = [NSString stringWithFormat:@"%d", _instanceVar];
    NSLog(@"%@", tempString);
}
@end

// C++ class平臺相關的實現, 使用C++命名規范
int CrossPlatformAPI::DoSomethingPlatformSpecific() {

    NSString *temp_string = [NSString stringWithFormat:@"%d", an_instance_var_];
    NSLog(@"%@", temp_string);
    return [temp_string intValue];
}

3、類名

  • [強制] 類名(包括Category、Protocol名和Block名)以大寫字母開始,通過大小寫而不是下劃線分隔。
  • [建議] 在設計可跨越多個應用之間共享的代碼時,推薦使用前綴,(例如,GTMSendMessage)。還有很多外部依賴庫的大型應用中設計的類最好也使用前綴。
  • [建議] 若使用前綴,則前綴縮寫要大于2個字符。
  • [建議] Protocal和Block名稱如果和類相關建議加類名前綴。

示例


@protocol AdvertisingViewDelegate <NSObject>

- (void)didSelectImageAtIndex:(NSInteger)index;

@end

@interface AdvertisingView : UIView

@property (weak, nonatomic) id <AdvertisingViewDelegate> delegate;

@end

4、Category名

  • [強制] 類別(Category)名中需要加入被擴展的類名。

比如我們要給NSString類加一個解析的功能,我們創建一個category,命名為GTMStringParsingAdditions,并且放在名為NSString+Parsing.h的文件中。

  • [強制] 類名與左括號中間需要有一個空格。

示例

//擴展一個framework類:
@interface NSString (GTMStringParsingAdditions)
- (NSString *)foobarString;
@end

//使方法和屬性私有化
@interface FoobarViewController ()
@property(nonatomic, retain) NSView *dongleView;
- (void)performLayout;
@end

5、Objective-C 方法名

  • [強制] 方法名應該以小寫字母開頭,混合大小寫。每個命名參數也應該以小寫字母開頭。
  • [建議] 方法名稱應該盡可能讀起來像句子,意味著你應該選擇能夠搭配方法名的參數名。(比如:convertPoint:fromRect:或replaceCharactersInRange:withString:)。
  • [建議] getter類型的方法不加get前綴。

示例

- (id)getDelegate;  // 應避免的 
- (id)delegate;     // 推薦的
  • [建議] 在所有參數前面添加關鍵字。

示例

- (void)sendAction:(SEL)aSelector toObject:(id)anObject forAllCells:(BOOL)flag;  // 推薦的 
- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag;      // 錯誤的 
  • [建議] 確保參數前面的關鍵字可以正確描述參數。

示例

-  (id)viewWithTag:(NSInteger)aTag;  // 推薦的 
- (id)taggedView:(int)aTag;          // 錯誤的
  • [強制] 當需要基于已有的一個方法創建新方法時,請將新的關鍵字添加到原有方法后面。

示例

- (id)initWithFrame:(CGRect)frameRect;  // 原有方法 
- (id)initWithFrame:(NSRect)frameRect
               mode:(int)aMode
          cellClass:(Class)factoryId
       numberOfRows:(int)rowsHigh
    numberOfColumns:(int)colsWide;     // 新方法
  • [建議] 盡量不要使用“and” 描述參數。

示例

// 推薦的
(int)runModalForDirectory:(NSString *)path file:(NSString *) name types:(NSArray *)fileTypes;   
//錯誤的      
(int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes;

6、變量名

  • [強制] 變量名以小寫字母開頭,混合大小寫以區分單詞。

6.1、普通變量名

  • [建議] 不要使用匈牙利命名法,比如不要使用變量的靜態類型(int 或 pointer)。盡量寫具有描述意義的名稱。比如不要使用下面的變量全名:
int w;
int nerr;
int nCompConns;
tix = [[NSMutableArray alloc] init];
obj = [someObject object];
p = [network port];

建議使用如下的變量命名:

int numErrors;
int numCompletedConnections;
tickets = [[NSMutableArray alloc] init];
userInfo = [someObject object];
port = [network port];

6.2、類成員變量

  • [建議] 類成員變量的命名是在普通變量的名字前,添加一個下劃線做前綴,比如_usernameTextField。

6.3、常量

  • [強制] 常量名(宏,本地常變量等)首字母應該以小寫的k開頭,然后使用混合大小寫區分單詞,枚舉值前面需要以枚舉名為前綴,前面加E。

示例

const int kNumberOfFiles = 12;
NSString *const kUserKey = @"kUserKey";
enum EDisPlayTinge { 
    EDisplayTingeGreen = 1 E
    DisplayTingeBlue = 2 
};

6.4、靜態變量

  • [強制]靜態變量應該以s或者以shared開頭使用混合大小寫命名。

示例

static MyClass *sharedInstance = nil;
static MyClass *sMyClassInstance = nil;

7、圖片命名

  • [強制]命名規則為「模塊+類型+一級屬性+二級屬性」。

示例

「tabbar_btn_red_n.png」  //tabbar 導航欄,btn 按鈕,n normal 狀態
  • [強制]圖片應該為PNG文件,且需要放入images.scassets中。
  • [強制]圖片必須包含@2x圖,如果只有@3x圖需要使用插件轉換為@2x圖片。
  • [建議]images.scassets應該安照模塊進行分組,方便查找。

四、注釋

1、文件注釋

  • [建議] 創建文件時會生成默認的注釋。如果看了文件名還不懂該文件是干什么,可以有選擇的在一個文件開頭寫一段關于內容的描述。

2、聲明部分的注釋

  • [建議] 每個接口,類別,協議的聲明都應該有個伴隨的注釋,來描述它的作用以及它如何融入整體環境。注釋遵循apple doc風格,以/*開始,/結束。
  • [強制] 聲明部分的注釋如果以“//”開頭,且與代碼同一行,在 “//” 前加空格。

示例

/** 
  * <#Description#>
  * @param nibNameOrNil <#nibNameOrNil description#>
  * @param nibBundleOrNil <#nibBundleOrNil description#>
  * @return <#return value description#>
*/
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
@property(copy) NSString *host;   //network host
  • [建議] 公共接口的每個方法,都應該有注釋來解釋它的作用、參數、返回值以及其它影響。

3、實現部分的注釋

  • [強制] 實現部分的注釋如果以“//”開頭,且與代碼同一行,在 “//“ 前加空格。

五、Cocoa 和 Objective-C 特性

1、重載指定構造函數

  • [強制] 當寫子類的時候,如果需要init方法,必須重載父類的指定構造函數。

2、重載 NSObject 的方法

  • [建議] 如果重載了NSObject類的方法,建議把它們放在@implementation內的前邊,這也是慣例。 通常適用(但不局限)于 init...,copyWithZone:,以及dealloc方法。所有init...應放在一起,后面跟著其他NSObject的方法。

3、初始化

  • [建議] 不要在 init 方法中,將成員變量初始化為 0或 nil。如果一個對象可被復用,狀態需要全部重置,這時可引入 reset方法。
  • [強制] 局部變量不會被編譯器初始化,所有局部變量使用前必須初始化。

4、避免調用+ new

  • [強制] 不要調用NSObject的類方法new,也不要在子類中重載它。使用alloc和init方法創建并初始化對象。

5、保持公共 API 簡單

  • [建議] 保持公共API簡單,避免“包含一切式“的API。

示例

#import "GTMFoo.h"
@interface GTMFoo (PrivateDelegateHandling)
- (NSString *)doSomethingWithDelegate;
// Declare private method
@end

@implementation GTMFoo (PrivateDelegateHandling)
- (NSString *)doSomethingWithDelegate {
    // Implement this method
}
@end
  • [強制] 可以使用私有Category保證公共頭文件整潔。

示例

@interface GTMFoo () { 
    ...
} 

6、#import與#include

-[強制] 使用#import來引用Objective-C/Objective-C++頭文件,使用#include引用C/C++頭文件。

7、使用根框架

  • [強制] 包含根框架,而非單獨的文件。

示例

#import <Foundation/Foundation.h>     // good 
#import <Foundation/NSArray.h>        // avoid

8、在init和dealloc中避免使用存取方法

  • [建議] 在init和dealloc方法執行的過程中,子類可能會處在一個不穩定狀態,所以這些方法中應避免調用存取方法,應在這些方法中直接對成員變量進行賦值或釋放操作。

示例

- (instancetype)init {
    self = [super init];
    if (self) {
        _bar = [[NSMutableString alloc] init]; // good
    }
    return self;
}

- (void)dealloc {
    [_bar release];
    // good
    [super dealloc];
}

- (instancetype)init {
    self = [super init];
    if (self) {
        self.bar = [NSMutableString string];   // avoid
    }
    return self;
}

- (void)dealloc {
    self.bar = nil;   // avoid
    [super dealloc];
}

9、按照聲明順序銷毀實例變量

  • [建議] dealloc中對象被釋放的順序應該與他們在@interface中聲明的順序一致,這有助于代碼檢查。

10、setter中對NSString進行copy

  • [建議] 接受NSString作為參數的setter,應該copy它所接受的字符串。

示例

- (void)setFoo:(NSString *)aFoo {

    [_foo autorelease];
    _foo = [aFoo copy];
} 

11、避免拋出異常

  • [建議] 不要@throw Objective-C 異常,但要注意從第三方的調用或者系統調用捕捉異常。如果確實使用了異常,請注釋期望什么方法拋出異常。

12、BOOL的使用

  • [強制] 不要直接將 BOOL 值與 YES 、NO進行比較。
  • [建議] 對 BOOL 使用邏輯運算符(&&, || 和 !)是合法的,返回值也可以安全地轉換成 BOOL。

示例

- (BOOL)isBold {
    return [self fontTraits] & NSFontBoldTrait;
}

- (BOOL)isValid {
    return [self stringValue];
}

- (BOOL)isBold {
    return ([self fontTraits] & NSFontBoldTrait) ? YES : NO;
}

- (BOOL)isValid {
    return [self stringValue] != nil;
}

- (BOOL)isEnabled {
    return [self isValid] && [self isBold];
}

同樣,不要直接比較 YES/NO 和 BOOL 變量。

BOOL great = [foo isGreat]; if (great == YES) {   // ...be great! } 
BOOL great = [foo isGreat]; if (great) {   // ...be great! } 

13、屬性

  • [建議] 屬性所關聯的實例變量的命名必須遵守以下劃線作為前綴的規則。屬性的名字應該與成員變量去掉下劃線后綴的名字一模一樣。@property后面緊跟括號,不留空格。

示例

@interface MyClass : NSObject
@property(copy, nonatomic) NSString *name;
@end

@implementation MyClass
// No code required for auto-synthesis, else use: //
@synthesize name = _name;
@end

14、沒有實例變量的接口

  • [強制] 沒有聲明任何實例變量的接口,應省略空大括號。

示例

@interface MyClass : NSObject // Does a lot of stuff 
- (void)fooBarBam; 
@end
 
@interface MyClass : NSObject { } // Does a lot of stuff 
- (void)fooBarBam; 
@end

15、自動synthesize實例變量

  • [建議] 優先考慮使用自動 synthesize 實例變量。

示例


@interface Foo : NSObject <Thingy>
// A guy walks into a bar.
@property(nonatomic, copy) NSString *bar;
@end

// Implementation file
@interface Foo ()
@property(nonatomic, retain) NSArray *baz;
@end

@implementation Foo
@synthesize widgetName = _widgetName;
@end

16、數據格式

-[強制]suggest:
NSDictionary *userDic =
@{@"login_phone": theApp.user.phone? theApp.user.phone : @"",
@"timestamp" : timestamp,
@"version" : kAppstore_Version,
@"encoding" : @"utf-8",
@"client_type": @"1",
@"app_code" : VKNetContext.app_ProCode,
@"push_id" : theApp.apnsToken ? theApp.apnsToken : @""};

avoid:
NSNumber *timestamp = [NSNumber numberWithInt:[[NSDate date] timeIntervalSince1970]];
NSDictionary *userDic = @{@"login_phone": theApp.user.phone? theApp.user.phone : @"",@"timestamp" : timestamp,@"version": kAppstore_Version,@"encoding" : @"utf-8",@"client_type": @"1",@"app_code" : VKNetContext.app_ProCode,@"push_id" : theApp.apnsToken ? theApp.apnsToken : @""};

六、性能調優

這里只列一些需要注意的點,具體原理參見iOS應用性能調優的25個建議和技巧

入門級(這是些你一定會經常用在你app開發中的建議)

    1. 用ARC管理內存
    1. 在正確的地方使用reuseIdentifier
    1. 盡可能使Views不透明
    1. 避免龐大的XIB
    1. 不要block主線程
    1. 在Image Views中調整圖片大小
    1. 選擇正確的Collection
    1. 打開gzip壓縮

中級(這些是你可能在一些相對復雜情況下可能用到的)

    1. 重用和延遲加載Views
    1. Cache, Cache, 還是Cache!
    1. 權衡渲染方法
    1. 處理內存警告
    1. 重用大開銷的對象
    1. 使用Sprite Sheets
    1. 避免反復處理數據
    1. 選擇正確的數據格式
    1. 正確地設定Background Images
    1. 減少使用Web特性
    1. 設定Shadow Path
    1. 優化你的Table View
    1. 選擇正確的數據存儲選項

進階級(這些建議只應該在你確信他們可以解決問題和得心應手的情況下采用)

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

推薦閱讀更多精彩內容

  • iOS編程規范0規范 0.1前言 為??高產品代碼質量,指導廣大軟件開發人員編寫出簡潔、可維護、可靠、可 測試、高效...
    iOS行者閱讀 4,471評論 21 35
  • 概要 Objective-C是一門面向對象的動態編程語言,主要用于編寫iOS和Mac應用程序。關于Objectiv...
    DreamMmMmM閱讀 1,184評論 0 7
  • 點擊查看簡書原文 一. 格式化代碼 1. 指針“*”號的位置 2. 空格 VS tabs ? 只允許使用空格,將編...
    漂泊海上的大土豆閱讀 1,851評論 0 8
  • 作為萬物之靈,人應該是唯一可以感受到脆弱的生物。 我們從小受的教育,都是告誡大家要堅強,泰山崩于前而...
    Jenny_Yuan閱讀 270評論 1 1
  • 慈母手中線, 游子身上衣。臨行密密縫, 意恐遲遲歸。誰言寸草心, 報得三春暉。 清明過后,又開始離家上班,心中卻時...
    可可熊Q閱讀 296評論 1 4