马上就要出iOS10了,但是还是有好多小伙伴不知道iOS9的新特性,这怎么能行呢,今天就要给不知道小伙伴讲一讲。
1.关键字
nullable:表示可以为空
书写规范
@property(nonatomic,strong,nullable)UIImageView * image;
@property(nonatomic,strong)UIImageView * _Nullable image;
nonnull:表示不可以为空
书写规范
@property(nonatomic,strong,nonnull)UIImageView * image;
@property(nonatomic,strong)UIImageView * _Nonnull image;
方法中的使用和属于一样
-(void)test:(nullable NSString*)str
{
}
注意nullable,nonnull只能修饰对象,不能修饰基本数据类型
但是有一个问题,随便点开一个控件的头文件,你发现有些属性和方法使用nullable,但是没发现有哪个方法和属性使用nonnull的啊,这是怎么回事
大家看这里
NS_ASSUME_NONNULL_BEGIN
NS_ASSUME_NONNULL_END
有这样一对宏表达的意思是:NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END之间的对象属性和方法在默认情况下都是nonnull的**
null_resettable
表示get方法不行为空,set方法可以为空
例如
@property(nonatomic,strong,null_resettable)UIImageView * image;
get方法:
set方法:
如果使用null_resettable的话,必须重写get或者set方法来处理设置的值为空的情况,原因上面说了,get方法不能为空。
但是你会发现当你用点语法时
_Null_unspecified的意思是不确定是否为空
因为你用点语法是赋值还是取值是不确定的
2.泛型:限制类型
泛型的使用场景一:集合中(数组,字典,NSSet)
书写规范
@property(nonatomic,strong)NSMutableArray <UIButton *>*array;
表示数组里只能放UIButton对象
泛型的好处
- 提高开发规范,减少程序员的交流成本
- 从集合中取出的对象可以直接使用点语法
泛型的使用场景二:自定义泛型
现在有一个人的类,人有一个狗的属性,狗呢有不同的品种,当创建一个人类的时候给人类的狗属性赋值,因为狗的类型不确定,这时候怎么办呢?
DogOne,DogTwo,DogThree都继承于Dog
person.h定义一个属性
<ObjectType> 只表示声明泛型
//<ObjectType>只是在声明泛型
@interface person<ObjectType> : NSObject
@property(nonatomic,strong)ObjectType dog;
@end
person <DogOne*>*p1=[person new];
p1.dog=[DogOne new];
person <DogTwo*>*p2=[person new];
p2.dog=[DogTwo new];
在定义person时,确定想要的泛型
这时候看下图,dog属性的类型就确定了
如果在定义person时没有确定泛型,那么默认类型就为id
协变(__covariant)和逆变 (__contravariant)
协变(__covariant):用于泛型数据强转类型,可以向上强转,子类可以转成父类
person <Dog*>*p1=[person new];
p1.dog=[Dog new];
person <DogTwo*>*p2=[person new];
p2.dog=[DogTwo new];
p1=p2;
此时这样赋值会有警告
如果在声明泛型的时候加上__covariant
@interface person<__covariant ObjectType> : NSObject
@property(nonatomic,strong)ObjectType dog;
@end
这样就没有警告了
如果理解了协变(__covariant),那么逆变 (__contravariant)也就很容易了
逆变 (__contravariant):用于泛型数据强转类型,可以向下强转,父类可以转成子类
@interface person<__contravariant ObjectType> : NSObject
@property(nonatomic,strong)ObjectType dog;
@end
这样父类既可以赋值给子类了
person <Dog*>*p1=[person new];
p1.dog=[Dog new];
person <DogTwo*>*p2=[person new];
p2.dog=[DogTwo new];
p2=p1;
3.__kindof:表示当前类或它的子类
Dog类是DogOne类的父类,我就拿它们俩举例子
父类有这样一个类方法
@interface Dog : NSObject
+(instancetype)dog;
@end
当DogTwo调用父类的dog方法时返回的类型是instancetype
我们不知道返回的是什么
如果在这么写
@interface person<__contravariant ObjectType> : NSObject
+ (__kindof Dog*)dog;
@end
如果感觉这篇文章对您有所帮助,顺手点个喜欢,谢谢啦