当前位置: 首页 > 科技观察

Objective-C的现代语法和新特性

时间:2023-03-13 18:00:27 科技观察

Swift确实是一门非常强大的语言,各种特性使用起来非常简单强大,但是目前感觉成熟度不够,所以商业上使用OCprojects是一个相对健壮的行为。看看WWDC2015的Swift和Objective-CInteroperabilitysession,视频前半部分主要讲解swift和OC的交互规则,后半部分介绍OC的新语言特性。这些功能由Apple开发。正如工作人员在WWDC上所说,代码的可读性大大提高,所以把这个特性从swift引入OC,个人感觉也为后续迁移到swift提供了支持。最重要的是,这些特性在iOSSDK中是完全采用并兼容低版本的,所以这些特性可以在目前的工作中引入。文章前半部分记录了之前OC的一些现代语法,后面讲解了WWDC2015引入的新特性。建议详细观看WWDC2015视频。instancetype可以参考我之前总结的一篇博客,关于id、NSObject*、id、instancetype的区别:http://blog.csdn.net/colorapp/article/details/45317347Properties有很多使用方法属性而不是实例变量优点:自动合成的getter和setter。使用@property声明的属性可以自动生成getter和setter方法。更好地声明一组方法的意图。比为属性声明一组方法更清晰的代码。表示有关行为的附加信息的属性关键字。Property使用一些其他关键字来表达实例变量不能表达的信息,如assign、weak、atomic等。property方法有非常简洁的命名约定。getter方法的名字就是属性的名字,setter方法的名字就是在属性名前加一个set前缀(驼峰式)。getter的名称也可以通过getter关键字指定。声明属性时,请记住以下不能是属性:init方法复制方法、mutableCopy方法类工厂方法初始化操作并返回BOOL结果方法显式更改内部状态的方法作为getterEnumration的副作用Marcos使用NS_ENUM定义枚举和NS_OPTIONS来定义选项。这两个宏通过显式指示枚举和选项的类型和大小来改进Xcode中的代码完成。对象初始化可能与swift兼容。OC新增了designatedinitializer初始化方法和convenienceinitializers初始化方法:designatedinitializer:负责调用父类的初始化方法,初始化自己的实例变量。便利构造器:非指定构造器称为指定构造器。这些初始化器的内部实现一般会调用另一个初始化器。但是,在一系列链式调用之后,将调用一个指定的初始化方法来执行初始化行为。实现一个designatedinitializer方法很简单,通过NS_DESIGNATED_INITIALIZER宏就可以实现,但是在使用designatedinitializer的时候,会有一些限制性的规则,和swift中的这些规则很相似。详情请参考:https://developer.apple.com/library/ios/releasenotes/ObjectiveC/ModernizationObjC/AdoptingModernObjective-C/AdoptingModernObjective-C.htmlWWDC2015NullabilityNullability用于指示Objective-C/C指针是否可以是零。很明显,使用这个特性可以清楚的表达API的意图,同时可以提高编译器的静态检查,一点点可以提高这些API在swift中的易用性。如果您使用Xcode7,您可能已经注意到此功能已在iOSSDK中大量采用。下面的屏幕截图说明了可空性的用法。OC是怎么引入这个特性,让低版本的iOS支持的呢?Apple称之为AuditedRegions,也就是下面两个宏NS_ASSUME_NONNULL_BEGIN…NS_ASSUME_NONNULL_END之间的区域。AuditedRegions对指针做了一些默认假设。单级指针被认为是非空的,而NSError**指针在每个指针级别都被认为是可空的。所以我们只需要在AuditedRegions中指定那些nullable或null_unspecified的场景。在C指针中使用Nullability时,与OC不同的是,使用的可空性限定符需要在前面加上双下划线,并且可空性限定符必须写在指针之后。比如下面的:LightweightGenerics,轻量级的泛型,会提高代码的可读性,让API更加清晰。另一方面,编译器可以帮我们做一些类型检查,发现一些潜在的错误,达到TypeSafety的效果。日常主要使用的是两个集合类,NSArray和NSDictionary。详细用法请参考官方SDK中的用法。同时,我们也可以在自己的代码中,在自定义的类、类别、扩展等中使用这个轻量级的泛型。自定义类中的使用语法:Category/Extension使用语法:WWDC也强调LightweightGenerics是向前兼容的,不会改变OC的runtime,不会对生成的代码产生任何影响。__kindof在OC中,我们会在代码中大量使用id特性。这个特性会带来很多方便的特性,但是它有一个缺陷,我们经常需要进行强制类型转换。Xcode7中有一个新特性,__kindof,“Kindof”类型表示“某种X”,用__kind修饰的变量表示某个类或该类的子类。当我们将本类或子类的其他变量赋值给这个变量时,编译器会默认帮我们进行类型转换和类型检查,这样我们就不需要写一些强制类型转换等代码了。最简单的例子就是在UITableView的应用中,cellForRowAtIndexPath:返回的变量使用了这个修饰之后,我们就不需要再写强制类型转换了,比如CustomCell*cell=[tableviewcellForRowAtIndexPath:indexPath];同时,我们可以结合Kindof类型和轻量级泛型,比如官方的特性:看了上面关于id类型的新特性,你会发现在平时的开发中,真的需要那么多id吗?大多数情况下,我们可以使用更精确的类型表示,这样可以避免一些类型安全等问题,也可以让代码更清晰。我们来看看官方替换id的场景:在返回“self”的方法中,使用instancetype代替id大部分Collections可以变成TypedCollections而不是id__kindofX*来表示“X的某个子类”而不是再次使用id可以reduce类型强制等代码,id表示任何符合SomeProtocol的类型。那么应该在什么情况下使用id呢?仅当您确定要表示“任何类型的对象”时才使用id,否则,请尝试使用其他语法而不是id。参考资料https://developer.apple.com/library/ios/releasenotes/ObjectiveC/ModernizationObjC/AdoptingModernObjective-C/AdoptingModernObjective-C.htmlhttps://developer.apple.com/videos/play/wwdc2015-401/http://blog.sunnyxx.com/2015/06/12/objc-new-features-in-2015/