基于Xcode4.4(不完全独有)。
1. 成员方法无需前置声明
之前,我们调用一个定义在后面(未声明)的成员方法,比如[self callSomeMethod],会得到警告说没有找到该函数。
通常,这种情况下,为了消除这个警告,我们会很郁闷地(为了代码整洁)跑到前面声明下,使用旧版本Xcode往往还要临时写一个匿名扩展(新版本Xcode自动生成);或者(无所谓地)直接把后面的函数定义放到前面。
现在,编译器会先扫描@implementation内的方法,如果存在函数定义,则不出现该警告。
让程序员心情更好,提高生产力有木有!
2. 枚举类型改进
这点对我这种开发者意义不大,不过也更清晰了。
我个人习惯用如下风格定义枚举类型:
清晰地知道起始值和边界值,方便做安全检查。
不过我不清楚枚举值的边界能有多大,当然,一般开发活动中不会有什么问题。
现在,我们可以清楚地知道枚举值的范围,且跨平台:
1
2
3
4
5
6
|
typedef
enum
_someEnumType :
NSUInteger
{
kOriginalType = 0,
kYellowType,
kRedType,
kTotalTypeCount
} SomeEnumType;
|
如果没有听错的话,这个特性是从C++ 11引进的。
3. 自动合成属性
在之前的Xcode版本,我们在.h文件里声明属性@property后,还需要在.m文件中合成@synthesize,很是麻烦。
现在,我们只需要声明@property name即可,Xcode会自动合成@synthesize name = _name。
这完全符合基本编码风格!所以不需要管其它细节了,照常使用就行。
4. 新增语法特性
通过神奇的@符号,直接简化语法,变身脚本语言!LOL
以前字符串可以这么写:NSString *str = @"Hello";。
现在NSNumber这么写:
1
2
3
4
|
NSNumber
*number = @
'H'
;
number =
@1
.2;
number =
@YES
;
number = @(60 * 60 * 24);
|
最后一句是表达式封装特性,@( expression ),比如NSString *name = @([self getMyName]);。
数组可以这么写:
1
2
3
|
NSArray
*array = @[@
"1"
, @
"2"
];
NSString
*str = array[0];
NSMutable
*mutableArray = [@[@
"1"
] mutableCopy];
|
字典可以这么写:
1
2
|
NSDictionary
*dict = @{@
"name"
: @
"Jason"
, @
"password"
: @
"Hello,world"
};
NSString
*name = dict[@
"name"
];
|
上述写法多简洁啊!让coder从冗长的语法中脱离出来。
【 更新 :上面有两行代码(下标取值),我没测试就想当然自己添加上去了,编译不过请见 SO 】
编译器为我们做了些事情(代码片段摘自WWDC 2012 Session 405):
1
2
3
4
5
6
7
8
9
|
// when you write this:
dict = @{ k1 : o1, k2 : o2, k3 : o3 };
// compiler generates:
id
objects[] = { o1, o2, o3 };
id
keys[] = { k1, k2, k3 };
NSUInteger
count =
sizeof
(objects) /
sizeof
(
id
);
dict = [
NSDictionarydictionaryWithObjects
:objects
forKeys:keys
count:count];
|
我们也可以在自定义对象中添加如下方法来支持下标取值特性:
1
2
3
4
5
6
|
- (
id
)objectAtIndexedSubscript:(
NSUInteger
)idx {
return
container[idx];
}
- (
void
)setObject:(
id
)obj atIndexedSubscript:(
NSUInteger
)idx {
container[idx] = obj;
}
|
不过,这种语法仍然不支持常量容器。关于compile-time c*****tant,这里有一份讨论。
对此,我们可以采用类方法initialize(代码片段摘自WWDC 2012 Session 405):
1
2
3
4
5
6
7
8
9
10
11
|
@implementation
MyClass
static
NSArray
*thePlanets;
+ (
void
)initialize {
if
(
self
== [MyClass
class
]) {
thePlanets = @[
@
"Mercury"
, @
"Venus"
, @
"Earth"
,
@
"Mars"
, @
"Jupiter"
, @
"Saturn"
,
@
"Uranus"
, @
"Neptune"
];
}
}
|
关于initialize类方法,这里有一份讨论,这里有一份说明,包括为何要判断self类型——因为子类没有实现该方法的话,子类收到消息会转发给父类。
为什么放在initialize类方法中就可以呢?
而字典是没有常量一说的,即不存在常量字典。
为什么?
5. End
更详细请看: http://clang.llvm.org/docs/ObjectiveCLiterals.html