在 swift 语言中,经过 ! 和 ? 能够将对象声明成 Optional,用于标记这个对象能够有一个指定值,或 者为nil。在 OC 中,之前是没有这样的功能的,所以咱们在开发中会常常遇到由于某个方法应该返回实例而返回了空致使的崩溃的问题。Nullability 的主要用武之地,就是在这里,它能够起到提示开发者作是否为空的判断的提示。这一特性在 Xcode6.3 中就已经支持,但在 Xcode7 中又作了一些写法上的小改动。swift
Xcode7 中,系统的框架中已经支持了 Nullability,以下所示,这是 NSArray 中的两个属性,其中 nullable 关键字说明了这里可能返回空的值。数组
若是仅仅是在返回值中给开发者一些提示,可能以为应用并不大,对开发者最大的帮助是这一特性能够用于方法的参数中,这样咱们在调用方法时起到的提示做用,将是很是重要的,越是多人合做的项目,做用也越大。例如如下方法中,咱们在调用函数时,若是传入了空值,编译器会给咱们警告。框架
属性声明中:ide
方法(函数)参数中:函数
iOS9 的 SDK 中已经彻底兼容使用了这些特性,而且 nonnull 的使用会比 nullable 普遍的多,系统提供了这样一对宏,咱们在这对宏之间定义的变量都会加上 nonnull 的修饰符,只有咱们特殊声明 nullable 的才须要手动写。atom
#define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin") #define NS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
#import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN @interface NSData (FormData) - (void)q_setHttpHeaderFieldWithRequest:(NSMutableURLRequest *)request fileBoundary:(nullable NSString *)fileBoundary; @end NS_ASSUME_NONNULL_END
Xcode 7 对系统中经常使用的一系列 容器类型 都增长了泛型支持,有了泛型就能够告诉开发人员容器类中装的对象是什么类型的。假如向泛型容器中加入不符合要求类型的对象,编译器会报警告。仅仅是警告,没什么实质的卵用。spa
1.正常的状况下,数组中存放的是 id对象, 若是取出某个对象,想使用点语法访问它的属性,必须先进行强转..net
2.若是咱们使用泛型的话,能够限制里面的内容,若是传入的不是Person类型的对象,就会有警告指针
给集合类型添加一个泛型的约定。(声明了这样一个数组后,就比如告诉了编译器,这个数组中的数据类型都是 NSString 类型的,你强行加入别的也是拦不住的,只是个防君子,不防小人的玩意)code
1.加入一个字符串到数组中,没有任务问题!
2.加入一个NSNumber到数组中,编译器就报警告⚠️
3.点语法,取出数组中的元素后,直接能够用点语法访问
若是不是泛型数组,没法用点语法直接访问,须要先强制类型转换
Xcode7中系统的类,会带有 ObjectType
这个单词,它是一个类型通配符,具体怎么写并不重要,也能够写成xxx,只是系统中都约定使用了 ObjectType
,你也能够在本身的类中按本身的喜爱来命名。 ObjectType
是传入类型的 占位符,它只能在 @interface 上定义(类声明、类扩展、Category),这个类型在 @interface 和 @end 区间的做用域有效,能够把它做为入参、出参、甚至内部 NSArray 属性的泛型类型,应该说一切都是符合预期的。:
建立一个类,继承于NSObject,取名叫MyArray:
.m中就不能用 <Type> 了哦
在ViewDidLoad方法中 写以下代码
能够看到当咱们设置泛型为<Person *>的时候,编译器就会提示 Person *
设置为<NSString *> 时,编译器就会提示 NSString *
当类支持泛型后,它们的 Type 发生了变化,好比下面三个对象看上去都是 Stack,但实际上属于三个 Type:
不指定泛型类型的 Stack 能够 和 任意泛型类型转化,但指定了泛型类型后,两个不一样
类型间是不能够强转的,否则编译器会报警告⚠️ 。
假如你但愿主动控制转化关系,就须要使用泛型的协变性和逆变性修饰符了:
__covariant
- 协变性,子类型能够强转到父类型
__contravariant
- 逆变性,父类型能够强转到子类型
协变:
效果:NSMutableString 是 NSString 的子类
逆变:
效果:NSString 是 NSMutableString 的父类
解决了一个长期以来的小痛点,拿原来的 UITableView 的这个方法来讲:
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier;
使用时前面基本会使用 UITableViewCell 子类型的指针来接收返回值,因此这个 API 为了让开发者没必要每次都蛋疼的写显式强转,把返回值定义成了 id 类型,而这个 API 实际上的意思是返回一个 UITableViewCell 或 UITableViewCell子类 的实例,因而新的 __kindof 关键字解决了这个问题:
- (__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier;
既明确代表了返回值,又让使用者没必要写强转。
再举个带泛型的例子,UIView 的 subviews 属性被修改为了:
@property (nonatomic, readonly, copy) NSArray<__kindof UIView *> *subviews;
这样,写下面的代码时就没有任何警告了:(否则你要先强转成UIButton才会没有警告)
UIButton *button = view.subviews.lastObject;