iOS应用开发最佳实践系列一:编写高质量的Objective-C代码

摘要:
每行代码不应超过100个字符。三元运算符仅用于赋值和参数。异常仅用于指示程序员错误。如果委托只有几个方法,例如只提交和取消,建议使用块来编写动作响应代码。如果为获取其他信息而调用对象,则使用代理。代理更倾向于过程,而块更倾向于结果。当需要实现多个协议时,将每个协议名称拆分为单独的行。

      本文由海水的味道编译整理,转载请注明译者和出处,请勿用于商业用途!

点标记语法

属性和幂等方法(多次调用和一次调用返回的结果相同)使用点标记语法访问,其他的情况使用方括号标记语法。

良好的风格:

view.backgroundColor = [UIColor orangeColor];

[UIApplication sharedApplication].delegate;

不良的风格:

[view setBackgroundColor:[UIColor orangeColor]];

UIApplication.sharedApplication.delegate;

间距

二元运算符和参数之间需要放置一个空格,一元运算符强制类型转换和参数之间不放置空格。关键字之后圆括号之前需要放置一个空格。

void *ptr = &value + 10 * 3;

NewType a =(NewType)b;

 

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

    doCoolThings();

}

数组和字典类型的字面值的方括号两边各放置一个空格。

NSArray *theShit = @[ @1, @2, @3 ];

字典字面值的键和冒号之间没有空格,冒号和值之间有一个空格。

NSDictionary *keyedShit = @{ GHDidCreateStyleGuide: @YES };

C函数声明中,左括号的前面不保留空格,并且函数名应该像类一样带有命名空间标识。

良好的风格:

void RNCwesomeFunction(BOOL hasSomeArgs);

长的字面值应被拆分为多行。

良好的风格:

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",

};

每一行代码使用4个空格缩进。不使用tab缩进。下图是在Xcode的Preferences进行缩进设置的截图。

 iOS应用开发最佳实践系列一:编写高质量的Objective-C代码第1张

iOS应用开发最佳实践系列一:编写高质量的Objective-C代码第2张 

方法签名以及其他关键字(if/else/switch/while等)后面跟随的左花括号总是和语句出现于同一行,而右花括号独占一行。

良好的风格:

if (user.isHappy) {

//Do something

}

else {

//Do something else

}

如果一个方法内有多个功能区域,可以使用空行分隔功能区域。

每一行代码不要超过100个字符。

每一个方法之前都有一个99字符宽的注释行,注释行相对于使用空行更能提高代码的辨识度,当一行代码很长的时候,注释行也起到了越界检测的作用。注释行:

///////////////////////////////////////////////////////////////////////////////////////////////////

条件语句

当需要满足一定条件时才执行某项操作时,最左边缘应该是愉快路径代码。不要将愉快路径代码内嵌到if语句中。多个return是正常合理的。

良好的风格做法:

- (void)someMethod {

  if (![someOther boolValue]) {

    return;

  }

  //Do something important

}

不良的风格:

- (void)someMethod {

  if ([someOther boolValue]) {

    //Do something important

  }

}

        所有的逻辑块必须使用花括号包围,即使条件体只需编写一行代码也必须使用花括号。

良好的风格做法:

if (!error) {

    return success;

}

不良的风格:

if (!error)

    return success;

或:

if (!error) return success;

三元运算符

长的三元运算符应使用圆括号括起来。三元运算符仅用于赋值和做参数。

Blah *a = (stuff == thing ? foo : bar);

合并的nil三元运算符应该尽量避免。

不良的风格:

Blah *b = thingThatCouldBeNil ?: defaultValue;

多分支条件应该使用if语句或重构为实例变量。

良好的风格:

result = a > b ? x : y;

不良的风格:

result = a > b ? x = c > d ? c : d : y;

异常和错误处理

不要在流控制语句中使用异常(NSException)。

异常仅用于表明程序员的错误。

为了表明一个错误,使用NSError *

当一个方法通过引用返回一个错误参数,应该检测返回值的状态,而不是错误参数的状态。

良好的风格:

NSError *error;

if (![self trySomethingWithError:&error]) {

    // Handle Error

}

不良的风格:

NSError *error;

[self trySomethingWithError:&error];

if (error) {

    // Handle Error

}

在方法执行成功的情况下赋值非Null值给错误参数,会使路径跳转到假条件分支(随后程序奔溃)。

代理

除了继承一个类或实现一个协议,否则在头文件中仅使用类声明@class指令,不用#import导入类头文件。

如果一个delegate只有几个方法,比如只是提交和取消,推荐使用block编写动作响应代码。

使用block还是delegate编写回调代码遵循以下几点:(详见参考链接[8]

Ø   如果对象存在多个不同事件,则应该使用代理模式编写各事件的处理代码

Ø   如果对象是单例,应该使用block,而不是代理。

Ø   如果对象是为了其他的信息而进行回调,则使用代理。

Ø   代理更多的是面向于过程,而block则更多的面向于结果。

由于代理方法的声明一般都很长,所以必须将代理对象和其他的协议对象放在实例变量定义的下面,否则实例变量定义的对齐方式将会被打乱掉。

当需要实现多个协议的时候,将每一个协议名拆分到单独的行。

良好的风格:

@interface CustomModelViewController : TTViewController <

  TTModelDelegate,

  TTURLRequestDelegate

> {

方法

一个方法的命名首先描述返回什么,接着是什么情况下被返回。方法签名中冒号的前面描述传入参数的类型。以下类方法和实例方法命名的格式语法:

[object/class thing+condition];

[object/class thing+input:input];

[object/class thing+identifer:input];

Cocoa命名举例:

realPath    = [path     stringByExpandingTildeInPath];

fullString  = [string   stringByAppendingString:@"Extra Text"];

object      = [array    objectAtIndex:3];

// 类方法

newString   = [NSString stringWithFormat:@"%f",1.5];

newArray    = [NSArray  arrayWithObject:newString];

良好的自定义方法命名风格:

recipients  = [email    recipientsSortedByLastName];

newEmail    = [CDCEmail emailWithSubjectLine:@"Extra Text"];

emails      = [mailbox  messagesReceivedAfterDate:yesterdayDate];

当需要获取对象值的另一种类型的时候,方法命名的格式语法如下:

[object adjective+thing];

[object adjective+thing+condition];

[object adjective+thing+input:input];

良好的自定义方法命名风格:

capitalized = [name    capitalizedString];

rate        = [number  floatValue];

newString   = [string  decomposedStringWithCanonicalMapping];

subarray    = [array   subarrayWithRange:segment];

方法签名尽量做到含义明确。

不良的风格:

-sortInfo  // 是返回排序结果还是给info做排序

-refreshTimer  // 返回一个用于刷新的定时器还是刷新定时器

-update  // 更新什么,如何更新

良好的风格:

-currentSortInfo      // "current" 清楚地修饰了名词SortInfo

-refreshDefaultTimer  // refresh是一个动词。

-updateMenuItemTitle  // 一个正在发生的动作

方法类型修饰符+/-后要放置一个空格,各参数名之间也要放置一个空格。

良好的风格:

- (void)setExampleText:(NSString *)text image:(UIImage *)image;

如果方法的命名特别长,将方法名拆分成多行。

良好的风格:

color = [NSColor colorWithCalibratedHue: 0.10

                               saturation: 0.82

                              brightness: 0.89

                                    alpha: 1.00];

不要将私有的实例变量和方法声明在头文件中,应将私有变量和方法声明在实现文件的类扩展内。

不良的风格:

//MyViewController.h文件

@interface MyViewController : UIViewController<

 UITalbeViewDataSource,

 UITableViewDelegate> {

 @private:

  UITableView *_myTableView;  // 私有实例变量

}

// 内部使用的属性

@property (nonatomic,strong) NSNumber *variableUsedInternally;

- (void)sortName;  // 只用于内部使用的方法

@end

良好的风格:

//MyViewController.m文件使用类扩展

@interface MyViewController()<

 UITalbeViewDataSource,

 UITableViewDelegate> {

  UITableView *_myTableView;

// 外部需要访问的实例变量声明为属性,不需要外部访问的声明为实例变量

  NSNumber * variableUsedInternally;

}

// Xcode4.3开始,可以不写方法的前置声明,Interface BuilderStoryboard仍然可以找到方法的定义

@end

构造函数通常应该返回实例类型而不是id类型

参数

方法参数名前一般使用的前缀包括“the”、“an”、“new”。

良好的风格:

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

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

- (id)         keyForOption:       (CDCOption *)  anOption

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

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

变量

变量的命令应尽量做到自描述。除了在for()循环语句中,单字母的变量应该避免使用(如i,j,k等)。一般循环语句的当前对象的命名前缀包括“one”、“a/an”。对于简单的单个对象使用“item”命名。

良好的风格:

for (i = 0; i < count; i++) {

    oneObject = [allObjects objectAtIndex: i];

    NSLog (@"oneObject: %@", oneObject);

}

      

NSEnumerator *e = [allObjects objectEnumerator];

id item;

while (item= [e nextObject])

      NSLog (@"item: %@", item);

指针变量的星号指示符应该紧靠变量,比如NSString *text,而不是NSString* textNSString * text

尽量的使用属性而非实例变量。除了在初始化方法(initinitWithCoder:等)、dealloc方法以及自定义settergetter方法中访问属性合成的实例变量,其他的情况使用属性进行访问。

良好的风格:

@interface RNCSection: NSObject

@property (nonatomic) NSString *headline;

@end

不良的风格:

@interface RNCSection : NSObject {

    NSString *headline;

}

当你使用@synthesize指令时,编译器会自动为你创建一个下划线_开头的的实例变量,所以不需要同时声明实例变量和属性。

不良的风格:

@interface RNCSection : NSObject {

    NSString *headline;

}

@property (nonatomic) NSString *headline;

@end

良好的风格:

@interface RNCSection: NSObject

@property (nonatomic) NSString *headline;

@end

不要使用@synthesize除非是编译器需要。注意在@protoco协议中的@optional可选属性必须被显式地使用@synthesize指令合成属性。

缩略词

虽然方法命名不应使用缩略词,然而有些缩略词在过去被反复的使用,所以使用这些缩略词能更好的的表达代码的含义。下表列出了Cocoa可接受的缩略词。

缩略词

含义和备注

alloc

分配,拨出

alt

轮流,交替

app

应用程序。比如NSApp表示全局程序对象。

calc

计算

dealloc

销毁、析构

func

函数

horiz

水平的

info

信息

init

初始化

max

最大的

min

最小的

msg

消息

nib

Interface Builder文档

pboard

黏贴板(仅对常量)

rect

矩形

temp

临时、暂时

vert

垂直的

以下是一些常用的首字母缩略词

ASCII

PDF

XML

HTML

URL

RTF

HTTP

TIFF

JPG

PNG

GIF

LZW

ROM

RGB

CMYK

MIDI

FTP

命名

方法和变量的命令应该尽可能做到自描述。

良好的风格:

UIButton *settingsButton;

不良的风格:

UIButton *setBut;

对于NSStringNSArrayNSNumberBOOL类型,变量的命名一般不需要表明其类型。

良好的风格:

NSString       *accountName;

NSMutableArray *mailboxes;

NSArray        *defaultHeaders;

BOOL             userInputWasUpdated;

不良的风格:

NSString        *accountNameString;

NSMutableArray *mailboxArray;

NSArray        *defaultHeadersArray;

BOOL             userInputWasUpdatedBOOL;

如果变量不是以上基本常用类型,则变量的命名就应该反映出自身的类型。但有时仅需要某些类的一个实例的情况下,那么只需要基于类名进行命名。

NSImage               *previewPaneImage

NSProgressIndicator  *uploadIndicator

NSFontManager        *fontManager;       // 基于类名命名

大部分情况下,NSArrayNSSet类型的变量只需要使用单词复数形式(比如mailboxes),不必在命名中包含“mutable”。如果复数变量不是NSArrayNSSet类型,则需要指定其类型。

良好的风格:

NSDictionary * keyedAccountNames;

NSDictionary * messageDictionary;

NSIndexSet   * selectedMailboxesIndexSet;

由于Objective-C不支持名字空间,为了防止出现命名空间的冲突,在类名和常类型变量名前添加一个由三个大写的字母组成的前缀(如RNC),对于Core Data实体名则可以忽略此规则。如果你子类化了标准的Cocoa类,将前缀和父类名合并是一个很好的做法。如继承UITableView的类可命名为RNCTableView

常类型变量名的书写风格采用驼峰式大小写(第一个单词的首字母小写,其余单词的第一个字母大写。如firstName而不是first_namefirstname。),并使用关联的类名作为其命名前缀,

推荐的做法:

static const NSTimeInterval RNCArticleViewControllerNavigationFadeAnimationDuration = 0.3;

不推荐的做法:

static const NSTimeInterval fadetime = 1.7;

下划线

使用属性的时候,实例变量应该使用self.进行访问和设值。局部变量的命令不要包含下划线。实例变量的命名必须使用下划线_作为前缀,这样可以缩小Xcode自动完成的选项取值范围。

注释

在需要的时候,注释可对代码做必要的解释。更新代码时一定要更新注释,防止对代码造成误解。

使用javadoc风格的文档注释语法。注释的第一行是对注释API的总结,随后的注释行是对代码更多细节的解释。

良好的风格:

/**

 * The maximum size of a download that is allowed.

 *

 * If a response reports a content length greater than the max * will be cancelled. This is helpful for preventing excessive memory usage.

 * Setting this to zero will allow all downloads regardless of size.

 *

 * @default 150000 bytes

 */

@property (nonatomic) NSUInteger maxContentLength;

initdealloc

dealloc方法应该被放置在实现方法的顶部,直接在@synthesize@dynamic语句之后。init方法应该被放置在dealloc方法的下面。

init方法的结构看上去应该像这样:

- (instancetype)init {

    self = [super init]; // or call the designated initalizer

    if (!self) {

        return nil;

    }

      // Custom initialization

    return self;

}

字面值

对于NSStringNSDictionaryNSArrayNSNumber类,当需要创建这些类的不可变实例时,应该使用这些类的字面值表示形式。使用字面值表示的时候nil不需要传入NSArrayNSDictionary中作为字面值。这种语法兼容老的iOS版本,因此可以在iOS5或者更老的版本中使用它。

良好的风格:

NSArray *names = @[@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul"];

NSDictionary *productManagers = @{@"iPhone" : @"Kate", @"iPad" : @"Kamal", @"Mobile Web" : @"Bill"};

NSNumber *shouldUseLiterals = @YES;

NSNumber *buildingZIPCode = @10018;

不良的风格:

NSArray *names = [NSArray arrayWithObjects:@"Brian", @"Matt", @"Chris", @"Alex", @"Steve", @"Paul", nil];

NSDictionary *productManagers = [NSDictionary dictionaryWithObjectsAndKeys: @"Kate", @"iPhone", @"Kamal", @"iPad", @"Bill", @"Mobile Web", nil];

NSNumber *shouldUseLiterals = [NSNumber numberWithBool:YES];

NSNumber *buildingZIPCode = [NSNumber numberWithInteger:10018];

如非必要,避免使用特定类型的数字(相较于使用5.3f,应使用5.3)。

CGRect函数

相较于使用结构体辅助函数(如CGRectMake()函数),优先使用C99结构体初始化语法。

  CGRect rect = {.origin.x = 3.0, .origin.y = 12.0, .size.width = 15.0, .size.height = 80.0 };

当访问CGRect结构体的xywidthheight成员时,应使用CGGeometry函数,不直接访问结构体成员。苹果对CGGeometry函数的介绍:

All functions described in this reference that take CGRect data structures as inputs implicitly standardize those rectangles before calculating their results. For this reason, your applications should avoid directly reading and writing the data stored in the CGRect data structure. Instead, use the functions described here to manipulate rectangles and to retrieve their characteristics.

良好的风格:

CGRect frame = self.view.frame;

CGFloat x = CGRectGetMinX(frame);

CGFloat y = CGRectGetMinY(frame);

CGFloat width = CGRectGetWidth(frame);

CGFloat height = CGRectGetHeight(frame);

不良的风格:

CGRect frame = self.view.frame;

CGFloat x = frame.origin.x;

CGFloat y = frame.origin.y;

CGFloat width = frame.size.width;

CGFloat height = frame.size.height;

常量

 优先使用常类型变量,而不是内嵌的字符串字面值或数字,因为常类型变量能很容易的复用常用的变量值(如π),同时可以快速地修改值而无需查找替换。常类型变量应该声明为static类型,不要使用#define,除非常类型变量被作为宏使用。

良好的风格:

static NSString * const RNCAboutViewControllerCompanyName = @"The New York Times Company";

static const CGFloat RNCImageThumbnailHeight = 50.0;

不良的风格:

#define CompanyName @"The New York Times Company"

#define thumbnailHeight 2

枚举类型

当使用enum关键字时,推荐使用苹果最新引入的固定基础类型语法,因为这将获得强类型检查与代码完成功能。SDK现在包含了一个固定基础类型的宏——NS_ENUM()。

NS_ENUM是在iOS6中开始引入的,为了支持之前的iOS版本,使用简单的内联方法:

#ifndef NS_ENUM

#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type

#endif

良好的风格:

typedef NS_ENUM(NSInteger, RNCAdRequestState) {

    RNCAdRequestStateInactive,

    RNCAdRequestStateLoading

};

私有属性

私有属性应该被声明在实现文件的类扩展中(即匿名的category)。不要将私有属性声明在命名的category(如RNCPrivateprivate),除非是扩展其他类。

良好的风格:

@interface NYTAdvertisement ()

 

@property (nonatomic, strong) GADBannerView *googleAdView;

@property (nonatomic, strong) ADBannerView *iAdView;

@property (nonatomic, strong) UIWebView *adXWebView;

 

@end

图片的命名

图片的命名应该保持一致,以图片的用途描述作为图片文件名。文件名的命名使用驼峰式大小写风格,文件名后可跟随一个自定义的类名或者是自定义的属性名(如果有属性名)、也可以再跟上颜色描述以及/或者位置、图片的最终状态。

良好的风格:

RefreshBarButtonItem / RefreshBarButtonItem@2x RefreshBarButtonItemSelected / RefreshBarButtonItemSelected@2x

ArticleNavigationBarWhite / ArticleNavigationBarWhite@2x ArticleNavigationBarBlackSelected / ArticleNavigationBarBlackSelected@2x.

被用作相似用途的图片应该使用一个图片文件夹进行分开管理。

布尔类型

因为nil被解析为了NO,所以和nil作比较没有任何的必要。不要将变量和YES直接比较,因为YES被定义为1BOOL类型是8位的unsigned int,即BOOL的值不仅仅是10

良好的风格:

if (!someObject) {

}

不良的风格:

if (someObject == nil) {

}

对于一个BOOL值:两种最佳实践:

if (isAwesome)

if (![someObject boolValue])

不良的风格:

if ([someObject boolValue] == NO)

if (isAwesome == YES) // Never do this.

如果一个BOOL类型的属性名是一个形容词,忽略属性名的“is”前缀是允许的,但需要为访问器指定约定的方法名,比如:

@property (assign, getter=isEditable) BOOL editable;

单例

应该使用线程安全的模式创建共享的单例实例。

+ (instancetype)sharedInstance {

   static id sharedInstance = nil;

 

   static dispatch_once_t onceToken;

   dispatch_once(&onceToken, ^{

      sharedInstance = [[self alloc] init];

   });

 

   return sharedInstance;

}

   单例的另一种做法,利用+initialize方法。(JSONModel源码43行:http://t.cn/8F7uBF4):

static JSONAPI* sharedInstance = nil;

+ (void)initialize {

    static dispatch_once_t once;

    dispatch_once(&once, ^{

        sharedInstance = [[JSONAPI alloc] init];

    });

}

附录

Xcode主题

大部分的开发者都使用Xcode默认的字体颜色主题,其实好的主题不仅能提高源代码的辨识度,同时也增添了编码的乐趣。以下是二款Xcode字体颜色主题链接:

 https://github.com/vinhnx/Ciapre-Xcode-theme

https://github.com/tursunovic/xcode-themes

代码片段

熟练使用代码片段库可以提高编码的速度。Xcode4中,打开一个项目并让右侧编辑区可视,然后点击右侧底部面板的第四个{}图标,打开代码片段库,你可以将常用的代码拖入其中。以下是一个最新的开源代码片段库链接:

https://github.com/mattt/Xcode-Snippets

code snippet library新建如下代码,设定一个类似vci(view controller initialize含义)自动提示快捷键。当开始编写ViewControllerView时,键入vci,将相应的代码填入对应的位置。

#pragma mark - init Method

填入init,initWithFrame等方法

#pragma mark- View Life Cycle

填入viewdidload,viewdidappear等方法

#pragma mark- Override Parent Methods

填入updateViewConstraints,updateConstraint, prepareForSegue等方法

#pragma mark- SubViews Configuration

填入configureSubViewsconfigureTableView等方法,这里的方法在init方法或view life cycle被调用

#pragma mark- Actions

填入-(IBAction)action:(id)sender[self addtarget:self action:@selector(action:)]动作指向的方法

#pragma mark- Public Methods

填入在.h外暴露的方法

#pragma mark- Private Methods

填入.m文件内部调用的方法

#pragma mark- DelegateDataSource, Callback Method

填入tableviewscrollview等代理方法

#pragma mark- Getter Setter

填入对@property初始化的方法

#pragma mark- Helper Method

填入一些帮助方法,如果使用扩展实现帮助方法不合适,则将帮助方法填在这里

#pragma mark Temporary Area

填入一些你需要删除,或者不确定后面需不需要用,或者写一写备注之类的,类似代码回收站含义


参考链接

[1] NYTimes Objective-C Style Guidehttps://github.com/NYTimes/objective-c-style-guide

[2] Coding Guidelines for Cocoahttps://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/APIAbbreviations.html

[3] iOS-view-frame-builderhttps://github.com/rsobik/ios-view-frame-builder/commit/0fa2d81762bc21619b1503d34b7d67160f4678f8

[4] Cocoa Style for Objective-C: Part Ihttp://cocoadevcentral.com/articles/000082.php

[5] Cocoa Style for Objective-C: Part IIhttp://cocoadevcentral.com/articles/000083.php

[6] objective-c-conventionsIhttps://github.com/github/objective-c-conventions

[7] The official raywenderlich.com Objective-C style guide.https://github.com/raywenderlich/objective-c-style-guide#cgrect-functions

[8] Blocks or Delegationhttp://stablekernel.com/blog/blocks-or-delegation/

文档修订历史

时间

备注

2015-10-18

添加code-snippet示例

2014-01-16

完善代理、条件语句、单例

2013-09-07

编写高质量的Objective-C代码

如果喜欢此文,记得点击文章下方的推荐,以让更多的人有所收获。

文章中如有错误或不当之处望不吝指出,谢谢!

我的邮箱和微博: xdreamarshal@gmail.com, http://weibo.com/xdream86

本文的pdf下载地址

免责声明:文章转载自《iOS应用开发最佳实践系列一:编写高质量的Objective-C代码》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇TFS源代码管理各类文件的文件头标志[转]下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

c语言运算符

1.运算符概述 运算符是一种编译器执行特定的数学或逻辑操作的符号。C语言提供了以下类型的运算符: 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符 条件运算符 其他运算符 2.算术运算符 算术运算符分为单目运算符和双目运算符,单目运算符表示只需要一个操作数,双目运算符需要两个操作数。 2.1 双目算术运算符 1)+ :加法,把两个操作数相加...

Java 8:掌握 Lambda 表达式

本文将介绍 Java 8 新增的 Lambda 表达式,包括 Lambda 表达式的常见用法以及方法引用的用法,并对 Lambda 表达式的原理进行分析,最后对 Lambda 表达式的优缺点进行一个总结。 ​ 1. 概述 Java 8 引入的 Lambda 表达式的主要作用就是简化部分匿名内部类的写法。 能够使用 Lambda 表达式的一个重要依据是必须...

C# 设置DateTime类型的变量值等于Null

做一个项目时,有个日期字段客户可输入可不输入值,直接把DateTime=Null时会出错,提示错误:无法将 NULL 转换成"System.DateTime",因为它是一种值类型   在网上查看下相关资料后,找到处理办法: Nullable<DateTime> now = DateTime.Now; Nullable<DateTime&g...

iOS网络NSURLSession使用详解

一、整体介绍 NSURLSession在2013年随着iOS7的发布一起面世,苹果对它的定位是作为NSURLConnection的替代者,然后逐步将NSURLConnection退出历史舞台。现在使用最广泛的第三方网络框架:AFNetworking、SDWebImage等等都使用了NSURLSession。作为iOS开发人员,应该紧随苹果的步伐,不断的学...

ES6中的export以及import的使用多样性

模块功能主要由两个命令构成:export和import。export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。 一、export导出模块使用部分的几种方式 一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。下面是一个 JS 文件,里...

java 基本理论知识点

http://www.cnblogs.com/hellokitty1/p/4491808.html 1、main方法是怎么写的        public static void main(String [] args){}//最习惯的      public static void main(String  args[]){}      static p...