1.Nullability

添加了一些新的关键字.

关键字 作用描述
nonnull / __nonnull / _Nonnull 不可为空
nullable / __nullable / _Nullable 可以为空 nullable更多的作用在于程序员之间的沟通交流(提醒同事某个属性可能是nil)
null_unspecified 不确定是否可以为空(极少情况)
null_resettable set方法可以为nil,get方法不可返回nil,
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END 二者之间的所有属性都是 __nonnull

举例

@property (nonnull, copy, nonatomic) NSString *title;
@property (nullable, copy, nonatomic) NSString *authur;
@property (null_unspecified, copy, nonatomic) NSString *name;
@property (null_resettable, copy, nonatomic) NSString *age;
@property (nonatomic, strong, nullable) NSArray *names;
@property (nonatomic, strong) NSArray * __nullable ages;
// 错误写法
//@property (nonatomic, assign, nullable) int age;

// 在调用方法传nil的时候会有警告。
- (void)setValue:(NSNumber * _Nonnull )number{   
}
- (void)setValue:(NSNumber * __nonnull )number{   
}
- (void)setValue:(nonnull NSNumber * )number{   
}

// NS_ASSUME_NONNULL_BEGIN  NS_ASSUME_NONNULL_END  之间的所有属性都是  __nonnull
NS_ASSUME_NONNULL_BEGIN
@interface ViewController ()
@property (nonatomic, strong) NSArray *a1;
@property (nonatomic, strong) NSArray *a2;
@property (nonatomic, strong) NSArray *a3;
@property (nonatomic, strong) NSArray *a4;
@property (nonatomic, strong) NSArray *a5;
@end
NS_ASSUME_NONNULL_END

2.泛型

用法

// 声明了这样一个数组后,就好比我告诉了编译器,这个数组中的数据类型都是NSString *类型的,如果我这个数组中元素的方法,会有提示了.
NSMutableArray<NSString *> *array = [[NSMutableArray alloc] init];
// 在我们向这个数组中追加元素的时候,编译器将元素的类型提示了出来,并且将FromArray方法中需要的元素类型也提示了出来。
// 同样如果我们向这个数组中追加类型不匹配的元素,会有警告。

自定泛型

// 这个Type其实只是一个类型标识符,它具体怎么写并不重要,只是系统中都约定使用了Type.
@interface Bag<Type> : NSObject

@property (strong, nonatomic) Type typeObj;
@property (nonatomic, strong, nonnull) NSMutableArray<Type> *array;
@property (nonatomic, strong, nonnull) NSMutableArray<UIView *> *viewArray;
@property (strong, nonatomic) NSMutableDictionary<NSString *, NSNumber *> *dict;

- (void)add:(nonnull Type)object;
- (Type)get:(int)index;

@end

协变性与逆变性

Bag<NSString *> *bagt1;
Bag<NSMutableString *> *bagt2;

bagt1 = bagt2; // 这里如果我们这样写,强行转换,会报警告,就有了逆变和协变这个概念
关键字 作用描述
__covariant 子类型指针可以向父类型指针转换
__contravariant 父类型指针可以向子类型转换

我们将自定义的类做如下修改,就不会出现警告了

@interface Bag<__covariant Type> : NSObject
  
@property (strong, nonatomic) Type typeObj;
@property (nonatomic, strong, nonnull) NSMutableArray<Type> *array;
@property (nonatomic, strong, nonnull) NSMutableArray<UIView *> *viewArray;
@property (strong, nonatomic) NSMutableDictionary<NSString *, NSNumber *> *dict;

- (void)add:(nonnull Type)object;
- (Type)get:(int)index;

@end

3._kindof

关键字 作用描述
__kindof 告诉编译器,这里可以返回Type类型的子类指针
- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIButton *btn;
    Bag *bag = [[Bag alloc] init];
    [bag.viewArray addObject:btn];
    
    // 这里会有警告,说类型不对
    UIButton *button = [bag.viewArray firstObject];
}

以前需要强转,现在只需要这样,加上__kindof警告就没了

@property (nonatomic, strong, nonnull) NSMutableArray<__kindof UIView *> *viewArray;