ios6:WWDC 2012 Session笔记——405 Modern Obj

2022-03-10

本文转自:WWDC 2012 Notes – 405-C

2007 年,-C 在 TIOBE 编程语言排名中仍然排名第 45 位。随着移动互联网的快速发展和iPad等iOS设备的广阔市场前景,-C也迅速崛起并进入市场。开发人员的观点。在最近的TIOBE排名中,-C已经达到了惊人的第4名,可以说已经成为当今世界上非常重要的编程语言。

而 -C 现在主要由 Apple 维护。为了满足开发的需要,苹果一直在完善OC和相应的cocoa库。2.0中引入的block,iOS4引入的block,去年引入的ARC,大部分都是他们开发的。欢迎。主要功能几乎每年都会增加,这不是每种语言都能做到的,更何况这些功能给大家带来了很多便利。

今年的 WWDC 也不例外,OC 和 LLVM 获得了重大改进。本文将简要组织和评论这些改进。

方法顺序

如果您有以下代码:

@interface SongPlayer : NSObject
- (void)playSong:(Song *)song;
@end 
@implementation SongPlayer
- (void)playSong:(Song *)song {
    NSError *error;
    [self startAudio:&error];
    ...
} 
- (void)startAudio:(NSError **)error { ... }
@end

在早期版本中,上述代码会在 [self:&error] 处给出未找到实例方法的警告。因为编译顺序,编译器无法知道-:方法后面有-:,所以给出警告。之前有两种解决方案:要么将-:的实现移到-:之上,要么在类中声明-:(顺便说一句..直接把-:放在.h文件中是完全错误的,因为这种方法不应该)。前者破坏了.m文件的结构,打乱了方法的顺序,给以后的维护带来了麻烦;后者需要编写额外的不必要的代码以使 .m 文件更长。实际上,这两种方法都不是一个好的解决方案。

不用再担心这个问题了,LLVM已经增加了新的特性,现在上面的代码可以直接使用,无需额外处理,避免警告。新的编译器改变了以往顺序编译的行为,改为先扫描方法声明,再编译方法的具体实现。这样,在同一个实现文件中,无论方法写在哪里,编译器都可以在编译方法实现之前知道所有方法的名称,从而避免警告。

枚举改进

从 .4 开始,有一种更好的方式来编写枚举:

typedef enum NSNumberFormatterStyle : NSUInteger {
    NSNumberFormatterNoStyle,
    NSNumberFormatterDecimalStyle,
    NSNumberFormatterCurrencyStyle,
    NSNumberFormatterPercentStyle,
    NSNumberFormatterScientificStyle,
    NSNumberFormatterSpellOutStyle
} NSNumberFormatterStyle;

列出枚举列表时,绑定了枚举类型,相比之前的直接枚举和先枚举再绑定类型,优点是方便编译器给出更准确的警告。个人觉得对于一般的开发者来说并不是特别有用,因为它往往不会涉及到很复杂的枚举,而且之前的枚举声明方式也不会混淆。所以最好使用你习惯的枚举方法。但是,如果你有条件或者还没有形成自己的习惯或者想开始一个新的项目,最好试试这个新方法,因为它比较严格。一些。

属性自动绑定

每个人都喜欢它,这是毫无疑问的。但是在写的时候,一般都要写实例变量和对应的,实在是不爽。Apple 已经做出了一些努力,至少取消了编写实例变量的要求。等号后面的值是强度变量名称。现在苹果更进一步,给我们带来了一个非常好的消息:不要再写了!在 Xcode 4.4 之后,现在会自动生成对应关系。

默认情况下,对于属性 foo,编译器会自动为开发者完成实现文件,就好像你写了 @foo = _foo; . 默认实例变量以下划线开头,后跟属性名称。如果是自己写的,就要以开发者自己的写法为准,比如只写@foo;那么实例变量名是 foo。如果不是,并且您自己实现 -foo 和 -: ,它将不对应于实例变量。而如果只实现了or中的一个,其他的方法会自动帮助生成(即使没有写,当然是另外一种方式)。

对于写了@的实现,所有对应的都不会生效(即使不写,这也是必然的..),可以理解为如果写了,总和必须在运行时确定。

总结一下,新的属性绑定规则如下:

速记

-C 的语法一直被认为是繁琐的,而且大多数消息都是用很长的函数名发送的。这实际上是一把双刃剑。从好的方面来说,它使代码相当容易阅读,因为几乎所有方法都用全英文描述,并且如果遵循命名约定,参数类型和方法角色就很清楚了。楚,但不利的一面是,它使更多不必要的键盘敲击,降低了开发效率。Apple 意识到了这一点,并在新的 LLVM 中引入了一系列列规则来简化 OC。简化后,以降低部分可读性为代价,开发时间稍快,可以说更符合当前开发周期短的需求。简化的 OC 代码的出现更接近 Perl 或这样一种快速开发语言。至于实际使用与否,还是另当别论。至少我个人不喜欢一些缩写。。可能是因为看到缩写的代码还没有形成直觉,所以需要一段时间才能知道它是什么……

所有 […:] 方法都可以缩写:

嗯…方便多了~以前最烦的是数字必须封装在Array中…现在可以直接将@开头的数字连接起来,可以简化为很多。

一些方法已被简化:

可以理解为@符号代表一个NS对象(和@符号一样),然后后面跟很多其他语言中常见的方括号[]来代表一个数组。事实上,当我们使用速记时,编译器会自动将其翻译成我们常用的代码。例如,对于@[ a, b, c ],实际编译的代码是

// compiler generates: 
id objects[] = { a, b, c };
NSUInteger count = sizeof(objects)/ sizeof(id);
array = [NSArray arrayWithObjects:objects count:count];

需要注意的是,如果a,b,c中有nil,生成的时候会抛出异常,而不是像[:a,b,c,nil]这样形成不完整的。事实上,这是一个很好的特性,避免了难以发现的 bug 的存在。

由于数组被简化,字典没有运行,它仍然非常类似于 Perl、Ruby 和预期的写法:

与数组类似,在编写 @{ 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 = [NSDictionary dictionaryWithObjects:objects forKeys:keys count:count];

版本和静态版本

上面生成的版本是不可变的,如果你想要一个可变的版本,你可以给它发送一个 – 消息来生成一个可变的副本。例如

NSMutableArray *mutablePlanets = [@[
                                  @"Mercury", @"Venus",
                                  @"Earth", @"Mars",
                                  @"Jupiter", @"Saturn",
                                  @"Uranus", @"Neptune" ]
                                  mutableCopy];

另外,对于标记为的数组(没有字典。。哈希和排序是在编译时进行的,cocoa框架的key不是常量),不能使用简写来赋值(其实原来传统的文笔不好)。解决方法是在类方法+(void)中赋值,例如:

static NSArray *thePlanets;
+ (void)initialize {
    if (self == [MyClass class]) {
        thePlanets = @[ @"Mercury", @"Venus", @"Earth", @"Mars", @"Jupiter", @"Saturn", @"Uranus", @"Neptune" ];
    }
}

下标

事实上,使用这些速记的主要目的之一是您可以使用下标来访问元素:

很方便,但必须注意方括号[]也用于字典,而不是想象中的大括号{}。估计是想避免和代码块的大括号冲突……简写的实际工作原理真的只是简单对应方法的简写,没有意外。

但是还是有惊喜的。就是使用类似的一套方法,我们自己的类都可以做到,也可以使用下标来访问。为了实现这一点,我们需要实现以下方法,

对于类似数组的结构:

- (elementType)objectAtIndexedSubscript:(indexType)idx; 
- (void)setObject:(elementType)object atIndexedSubscript:(indexType)idx;

对于类似字典的结构:

- (elementType)objectForKeyedSubscript:(keyType)key; 
- (void)setObject:(elementType)object forKeyedSubscript:(keyType)key;

固定桥

也许 ARC 最令人困惑和最容易出错的方面是桥接的概念。由于历史原因,CF对象和对象转换之间一直存在着一些微妙的关系,而在引入ARC之后,这些关系变得复杂了:主要是明确CF或者应该负责内存管理(关于ARC 和有关更详细的解释,请参阅我之前编写的介绍性 ARC 教程)。

在 0.4 之后,之前区分谁实际拥有对象的工作可能会变得模糊。加和到代码块区间,前面的桥接转换可以简单的写成CF和NS之间的强制转换,不需要额外的关键字。谁来照顾这段记忆?留给系统处理吧~

-C 确实是一种正在高速变化的语言。一方面,它的动态特性和闲聊的烙印并没有消失,另一方面,它正在积极接近各种简单语言的语法。各种自动化有点令人不安,但事实证明它们运行良好,确实为开发人员节省了时间。努力尽快迎接新的变化吧~

分类:

技术要点:

相关文章:

© 版权声明
THE END
喜欢就支持一下吧
点赞90赞赏 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容