首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >目标C中可空、__nullable和_Nullable的区别

目标C中可空、__nullable和_Nullable的区别
EN

Stack Overflow用户
提问于 2015-09-08 08:29:55
回答 3查看 47.8K关注 0票数 172

在Xcode 6.3中引入了新的注释,以更好地表达Objective中API的意图(当然,确保更好的Swift支持)。当然,这些注释是nonnullnullablenull_unspecified

但是,在Xcode 7中,出现了许多警告,例如:

指针缺少可空类型说明符(_Nonnull、_Nullable或_Null_unspecified)。

除此之外,苹果还使用另一种类型的空值说明符,标记它们的C代码(来源):

CFArrayRef 非空CFArrayCreate(
CFAllocatorRef 可空分配器,const __nonnull 可空值,CFIndex numValues,const CFArrayCallBacks *可空callBacks);

因此,总而言之,我们现在有以下3种不同的可空注释:

  • nonnullnullablenull_unspecified
  • _Nonnull_Nullable_Null_unspecified
  • __nonnull__nullable__null_unspecified

即使我知道使用哪个注释的原因和位置,我还是对应该使用哪种类型的注释、在哪里使用以及为什么使用感到有点困惑。这就是我能收集到的:

  • 对于属性,我应该使用nonnullnullablenull_unspecified
  • 对于方法参数,我应该使用nonnullnullablenull_unspecified
  • 对于C方法,我应该使用__nonnull__nullable__null_unspecified
  • 对于其他情况,例如双指针,我应该使用_Nonnull_Nullable_Null_unspecified

但我仍然不明白为什么我们有这么多注释,基本上都是这样做的。

所以我的问题是:

这些注释之间的确切区别是什么,如何正确地放置它们,以及为什么?

EN

回答 3

Stack Overflow用户

发布于 2015-11-23 04:14:37

来自Swift博客

这个特性最初是在Xcode 6.3中以关键字__nullable和__nonnull发布的。由于与第三方库的潜在冲突,我们在Xcode 7中将它们更改为您在这里看到的_Nullable和_Nonnull。但是,为了与Xcode 6.3兼容,我们预定义了宏__nullable和__nonnull,以扩展到新的名称。

票数 30
EN

Stack Overflow用户

发布于 2016-01-07 20:20:15

来自clang文档

空(类型)限定符表示给定指针类型的值是否为空。

大多数时间您将使用nonnull nullable**.**

下面是所有可用的说明符。来自这篇文章

  • null_unspecified: 这是默认的.它连接到Swift隐式-非包装可选.
  • nonnull:这个值不会是零。它连接到Swift定期引用。
  • nullable:值可以是零。它连接到Swift的可选选项。
  • null_resettable:读取时该值永远不能为零,但可以将其设置为零以重置它。仅适用于属性。

无论您在属性或函数/变量的上下文中使用它们,上述符号都是不同的:

文章的作者还提供了一个很好的例子:

代码语言:javascript
运行
复制
// property style
@property (nonatomic, strong, null_resettable) NSString *name;

// pointer style
+ (NSArray<NSView *> * _Nullable)interestingObjectsForKey:(NSString * _Nonnull)key;

// these two are equivalent!
@property (nonatomic, strong, nullable) NSString *identifier1;
@property (nonatomic, strong) NSString * _Nullable identifier2;
票数 30
EN

Stack Overflow用户

发布于 2015-11-18 14:03:19

非常方便

代码语言:javascript
运行
复制
NS_ASSUME_NONNULL_BEGIN 

并以

代码语言:javascript
运行
复制
NS_ASSUME_NONNULL_END 

这将取消对代码级‘null makes’:-)的需求,因为假定everything是非空的(或者nonnull_nonnull__nonnull)是有意义的,除非另有说明。

不幸的是,也有例外.

  • typedef不被认为是__nonnull (注意,nonnull似乎不起作用,不得不用它丑陋的同父异母兄弟)
  • id *需要一个明确的无效证明,但是哇罪恶税( _Nullable id * _Nonnull <-猜猜这意味着什么.)
  • 总是假定NSError **是可空的。

因此,除了异常的例外和导致相同功能的不一致关键字之外,方法可能是使用丑陋的版本__nonnull / __nullable / __null_unspecified,并在编者抱怨时交换.?也许这就是它们存在于苹果头上的原因?

有趣的是,有东西把它写进了我的代码..。我讨厌在代码中强调(旧式苹果C++风格的家伙),所以我确信我没有输入这些,但它们出现了(几个例子中的一个例子):

代码语言:javascript
运行
复制
typedef void ( ^ DidReceiveChallengeBlock ) ( NSURLSessionAuthChallengeDisposition disposition,
                                          NSURLCredential * __nullable credential );

更有趣的是,它插入__nullable的地方是错误的.(eek@!)

我真的希望我可以只使用非下划线版本,但显然编译器不会使用它,因为它被标记为错误:

代码语言:javascript
运行
复制
typedef void ( ^ DidReceiveChallengeBlock ) ( NSURLSessionAuthChallengeDisposition disposition,
                                          NSURLCredential * nonnull  credential );
票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32452889

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档