`
啸笑天
  • 浏览: 3466268 次
  • 性别: Icon_minigender_1
  • 来自: China
社区版块
存档分类
最新评论

Nullability and Objective-C

 
阅读更多

https://developer.apple.com/swift/blog/?id=25

 

http://www.cocoachina.com/ios/20150601/11989.html

 

http://blog.csdn.net/zhangao0086/article/details/44409913

 

http://blog.sunnyxx.com/tags/iOS9/

 http://blog.csdn.net/colorapp/article/details/49391209

 

Nullability

 
Nullability特性用来指明 Objective-C/C 指针是否可以为nil。显然,使用这个特性更能清晰表达API的意图,同时可以提升编译器的static checking,还有一点就可以提高这些API在swift中的可用性。如果使用Xcode 7的话,可能注意到在iOS SDK中这个特性已经被大量采用了。下面这种截图说明了Nullability的用法。


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

总的来说,可空特性标示符有三种,可以用双下划线(用在任何指针类型),或者没有下划线的(用在Objective-C属性,方法结果类型或者方法参数类型)。

Type qualifier spelling
Objective-C property/method spelling
Swift view
Meaning 
__nonnull  nonnull  Non-optional, 如: UINib 该值永远不会为nil(有一种例外是可能参数传递时传入的消息为空)
__nullable  nullable  Optional, 如:UITableViewCell? 该值可能为nil 
__null_unspecified null_unspecified  隐式解封可选类型如, NSDate! 不确定该值是否为空(很少见) 
  • ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
 
OC是如何引入这个特性,并且又让低版本的iOS支持的呢?Apple称之为 Audited Regions,也就是下面这两个宏之间的区域,NS_ASSUME_NONNULL_BEGIN … NS_ASSUME_NONNULL_END。
Audited Regions对其中的指针做了一些默认的假设,Single-level指针被认为是nonnull的,NSError**指针被认为在各个指针level上面都是nullable的。所以我们在Audited Regions内只需要指明那些 nullable 或者 null_unspecified的场景。
NS_ASSUME_NONNULL_BEGIN
@interface AAPLList : NSObject <NSCoding, NSCopying>
//---
- (nullable AAPLListItem *)itemWithName:(NSString *)name;
- (NSInteger)indexOfItem:(AAPLListItem *)item;

@property (copy, nullable) NSString *name;
@property (copy, readonly) NSArray *allItems;
//---
@end
NS_ASSUME_NONNULL_END

// --------------

self.list.name = nil;   // okay

AAPLListItem *matchingItem = [self.list itemWithName:nil];  // warning
 在C指针中使用 Nullability 的话,与OC中不同的地方在于,使用的nullability qualifier需要在前面添加双下划线,并且要将nullability qualifier写在指针后面。例如下面:


 

为了安全起见,这个规则也有一些例外情况:

  • typedef定义的类型不会继承nullability特性—它们会轻松地根据上下文选择nullable或non-nullable,所以,就算是在审查区域内,typedef定义的类型也不会被当作nonnull
  • id *这样更复杂的指针类型必须被显式地注解,比如,你要指定一个nonnull的指针为一个nullable的对象引用,那么需要使用__nullable id * __nonnull
  • NSError **这些特殊的、通过方法参数返回错误对象的类型,将总是被当作是一个nullable的指针指向一个nullable的指针:__nullable NSError ** __nullable

你可以通过Error Handling Programming Guide了解更多详细内容。

兼容性

你的Objective-C框架现有的代码写对了吗?是否能安全的改变它们的类型? Yes, it is.

  • 现有的、被编译过的代码还能继续使用你的框架,也就是说ABI没有变化(编译器不会报错),这也意味着现有的代码不会在运行时捕获到nil的不正确传值。
  • 用新的Swift编译器编译现有的源码,并在使用你的框架的时候,可能会因为一些不安全的行为在编译时得到额外的警告。
  • nonnull不影响优化,尤其是你还可以在运行时检查标记为nonnull的参数是否为nil,这可能需要必要的向后兼容。

 

 

Lightweight Generics

这个轻量级泛型,一方面会提高代码可读性,让API变得更加清晰。另外一方面,还能使编译器会帮助我们做一些类型检查,找到一些潜在的错误,达到 Type Safety的效果。
 
日常主要的用法是针对两个集合类的,NSArray与NSDictionary,详细用法可以参考官方SDK中的使用。同时,我们也可以在我们自己的代码来使用这个轻量级泛型,在自定义类,category,extension等等。
Lightweight Generics 个纯编译器的语法支持(llvm 7.0),和 Nullability 一样,没有借助任何 objc runtime 的升级,也就是说,这个新语法在 Xcode 7 上可以使用且完全向下兼容(更低的 iOS 版本)

 

NSArray<NSString *> *strings = @[@"sun", @"yuan"];
NSDictionary<NSString *, NSNumber *> *mapping = @{@"a": @1, @"b": @2};

 

 自定义类中的使用语法:



 
Category / Extension的使用语法:


 

 

 

__kindof

在OC中,我们的代码中会大量使用id这个特性,这个特性用起来会带来很多很方便的特性,但是它有个缺陷,我们经常需要进行强制类型转换。Xcode 7中有个新特性,__kindof,“Kindof” types express “some kind of X”,用__kind修饰的变量表示是某个类或者这个类的子类。

__kindof 这修饰符还是很实用的,解决了一个长期以来的小痛点,拿原来的 UITableView 的这个方法来说:

- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier;

使用时前面基本会使用 UITableViewCell 子类型的指针来接收返回值,所以这个 API 为了让开发者不必每次都蛋疼的写显式强转,把返回值定义成了 id 类型,而这个 API 实际上的意思是返回一个 UITableViewCell 或 UITableViewCell 子类的实例,于是新的 __kindof 关键字解决了这个问题:

- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;

既明确表明了返回值,又让使用者不必写强转。再举个带泛型的例子,将Kindof types和lightweight generics结合在一起,UIView 的 subviews 属性被修改成了:

@property (nonatomic, readonly, copy) NSArray<__kindof UIView *> *subviews;

这样,写下面的代码时就没有任何警告了:

UIButton *button = view.subviews.lastObject;

 

协变性和逆变性

当类支持泛型后,它们的 Type 发生了变化,比如下面三个对象看上去都是 Stack,但实际上属于三个 Type:

1
2
3
Stack *stack; // Stack *
Stack<NSString *> *stringStack; // Stack<NSString *>
Stack<NSMutableString *> *mutableStringStack; // Stack<NSMutableString *>

当其中两种类型做类型转化时,编译器需要知道哪些转化是允许的,哪些是禁止的,比如,默认情况下:



 

我们可以看到,不指定泛型类型的 Stack 可以和任意泛型类型转化,但指定了泛型类型后,两个不同类型间是不可以强转的,假如你希望主动控制转化关系,就需要使用泛型的协变性逆变性修饰符了:

__covariant - 协变性,子类型可以强转到父类型(里氏替换原则)
__contravariant - 逆变性,父类型可以强转到子类型(WTF?)

协变:

1
@interface Stack<__covariant ObjectType> : NSObject

效果:



 

逆变:

1
@interface Stack<__contravariant ObjectType> : NSObject

效果:



 

协变是非常好理解的,像 NSArray 的泛型就用了协变的修饰符,而逆变我还没有想到有什么实际的使用场景。 

 

 

关于id类型

 
看了上面这些新特性之后,你会发现在平时开发中,你真的还需要那么多id吗?大多数情况下,我们都可以使用一个更加精确的类型表示,这样能避免一些例如 type safety的问题,同时也能让代码更加清晰。下面看一下官方指明的替代id的情景:
  • 在返回 “self” 的方法中,使用instancetype来代替id
  • 大多数 Collections 都可以变成 Typed Collections 来代替id
  • __kindof X * 来表示 “some subclass of X”,而不再使用id,可以减少类型强制转换之类的代码
  • id<SomeProtocol> 表示conforms to SomeProtocol的任意类型
 
那什么情况下使用id呢?只有那些你确认要表示”an object of any type”的时候再使用id,否则,尽量使用其他语法代替id。
 
 
 

 

  • 大小: 62.4 KB
  • 大小: 51.1 KB
  • 大小: 120.9 KB
  • 大小: 82.4 KB
  • 大小: 176.2 KB
  • 大小: 99.8 KB
  • 大小: 176.2 KB
  • 大小: 97.7 KB
分享到:
评论
4 楼 啸笑天 2016-04-26  
http://www.csdn.net/article/2015-02-10/2823901-apple-releases-xcode-6-3-beta-and-swift-update/1   Xcode 6.3 Beta发布,Swift 1.2带来哪些新变化?
3 楼 啸笑天 2016-04-26  
为空性修饰符 中的 四种修饰符

nonnull 不为空
nullable 可以为空
null_unspecified 不确定是否为空
null_resettable setter 可以为空, getter 不为空


http://www.jianshu.com/p/0aca839891fe
2 楼 啸笑天 2016-04-26  
Difference between nullable, __nullable and _Nullable in Objective-C
http://stackoverflow.com/questions/32452889/difference-between-nullable-nullable-and-nullable-in-objective-c
1 楼 啸笑天 2015-11-04  
Object Initialization
可能是为了兼容swift,OC中添加了 designated initializer 初始化方法和 convenience initializers 初始化方法:
designated initializer : 负责调用superclass的初始化方法以及初始化自己的实例变量的初始化方法
convenience initializers : 非designated initializer都被称为designated initializer。这些initializer内部实现一般都是调用另外一个initializer,然而最终一系列链式调用之后,最终都会调用某一个designated initializer 方法来进行初始化行为。

实现一个designated initializer方法很简单,通过NS_DESIGNATED_INITIALIZER宏即可实现,但是使用designated initializer的时候,会有一些限制规则,跟swift中的这些规则非常类似。详情可以参考:https://developer.apple.com/library/ios/releasenotes/ObjectiveC/ModernizationObjC/AdoptingModernObjective-C/AdoptingModernObjective-C.html

相关推荐

    Objective-C基础教程(入门教程).pdf

    Objective-C是一种广泛用于苹果平台应用程序开发的编程语言,它是C语言的一个超集,并加入了Smalltalk风格的消息传递机制。本篇教程主要面向初学者,介绍了Objective-C的基础知识点和一些核心概念。 1. Objective-C...

    Objective-c语言学习-快速入门完整版完整版

    Objective-C是在C语言基础上扩展的,引入了Smalltalk的面向对象特性,如消息传递机制,使得代码更加灵活和可扩展。 "第二讲 数据类型、运算符和表达式"深入讲解了基本的数据类型,包括整型、浮点型、字符型等,以及...

    Using Swift with Cocoa and Objective-C (Swift 4) EN.epub

    Using Swift with Cocoa and Objective-C (Swift 4) EN.epub 去除 DRM

    Using Swift With Cocoa and Objective-C中文版

    Using Swift With Cocoa and Objective-C中文版,OC和Swift混合使用

    windows 下搭建 Objective-C 开发环境

    ### 在Windows下搭建Objective-C开发环境 随着移动应用开发的普及,越来越多的开发者开始尝试不同的编程语言和技术栈。尽管Objective-C主要与Apple的平台(如iOS和macOS)相关联,但有时候,出于某些原因(比如团队...

    Objective-C Runtime测试代码

    Objective-C语言的许多决策可以在编译和运行时执行。只要有可能,它是动态的。这意味着Objective-C语言不仅需要一个编译器,还需要一个运行时系统来执行编译的代码。Runtime系统是一种用于Objective-C语言的操作系统...

    Objective-C高级编程 iOS与OS X多线程和内存管理_Objective-C_ios_

    《Objective-C高级编程:iOS与OS X多线程和内存管理》是一本深入探讨Apple平台开发中的关键技术的书籍。本书主要围绕Objective-C语言在iOS和OS X操作系统上的应用,特别是针对多线程和内存管理这两个核心主题进行...

    Using-Swift-with-Cocoa-and-Objective-C(4.1)

    "Using Swift with Cocoa and Objective-C(4.1)"是Apple官方发布的文档,旨在帮助开发者理解如何在同一个项目中有效地结合使用Swift和Objective-C。这份文档详细介绍了两者之间的差异、互操作性、以及混合编译过程中...

    Objective-C语言入门教程&深入浅出,理论实践相结合.pdf

    Objective-C语言入门教程&深入浅出,理论实践相结合 Objective-C语言入门教程&深入浅出,理论实践相结合 Objective-C语言入门教程&深入浅出,理论实践相结合 Objective-C语言入门教程&深入浅出,理论实践相结合 ...

    Objective-C编程全解最新版.pdf.zip

    1. **Objective-C基础**:Objective-C是在C语言基础上扩展的,因此,理解C语言的基本语法是必要的。Objective-C添加了消息传递机制、类和协议等面向对象特性。 2. **消息传递**:Objective-C中的对象通过发送消息来...

    C语言主要知识点巩固(学习Objective-C 的前提)

    C语言是计算机编程的基础,它是Objective-C的重要基石。在学习Objective-C之前,深入理解C语言的知识点至关重要。C语言以其高效、简洁和灵活性被广泛应用于系统编程、嵌入式开发、游戏引擎等领域。本资料主要涵盖了...

    Objective-C语言教程

    希望这个简单的Objective-C语言教程能够为你提供一个入门的起点。Objective-C是一种面向对象的编程语言,广泛应用于Mac OS和iOS开发。通过学习Objective-C的基本语法、类和对象、控制流程和方法等内容,你将能够编写...

    Objective-C与Objective-C++的混用代码示例

    Objective-C是基于C语言的,主要用于构建iOS和macOS应用程序,而Objective-C++则是Objective-C的一个扩展,它引入了C++的特性,使得开发者可以同时利用Objective-C的动态特性和C++的面向对象编程能力。 ### ...

    Objective-C程序设计 第6版 pdf

    1. **Objective-C基础**:Objective-C是在C语言基础上扩展的,因此它包含了C的所有特性。书中会讲解基本的数据类型、控制结构、函数和指针等基础知识,同时介绍Objective-C特有的动态类型和消息传递机制。 2. **...

    《Objective-C基础教程》中文版(含源代码)

    《Objective-C基础教程》是一本面向初学者的编程书籍,主要涵盖了Objective-C语言的基本概念、语法和编程实践,尤其适合那些想要踏入iOS应用开发领域的学习者。Objective-C是Apple公司开发的面向对象的编程语言,它...

    Objective-C2.0程序设计第二版中文版及代码

    1. **Objective-C基础**:Objective-C是在C语言基础上扩展的,添加了面向对象特性。它的基础包括类、对象、消息传递等概念。类定义了对象的属性和行为,对象则是类的实例。消息传递是Objective-C的核心,通过`...

    Objective-C的语法与Cocoa框架.pdf

    Objective-C语法的基石是C语言的语法结构,这意味着所有的C语言代码都可以在Objective-C中直接使用。但是,Objective-C在C的基础上新增了消息传递机制,这是它与C语言的一个重要区别。在Objective-C中,方法调用是...

    Objective-C程序设计(第4版)(全球最畅销Objective-C编程书籍)

    《Objective-C 程序设计(第4版)》作者假设读者没有面向对象程序语言或者C语言(Objective-C基础)编程经验,因此,初学者和有经验的程序员都可以使用这本《Objective-C 程序设计(第4版)》学习Objective-C。...

    用Objective-C语言实现了各种设计模式,收集各种例子,方便大家学习和普及设计模式 .zip

    用Objective-C语言实现了各种设计模式,收集各种例子,方便大家学习和普及设计模式。.zip用Objective-C语言实现了各种设计模式,收集各种例子,方便大家学习和普及设计模式。.zip用Objective-C语言实现了各种设计...

Global site tag (gtag.js) - Google Analytics