Objective c 将方法标记为从不返回nil

Objective c 将方法标记为从不返回nil,objective-c,clang,Objective C,Clang,我正在使用Objective-C开发一个API,这个API有一些虚构的方法的协议: - (NSString *)gimmeString; // Want implementations to never return nil 我非常喜欢提供上下文,所以为此我大量使用了所有东西,包括\uuuu attribute\uuuu((非空))和friends等属性。我要问的是是否有方法提供上下文,并且是否可能为方法实现添加编译时检查,说“当使用clang编译时,此方法从不返回nil” i、 e.我想要一

我正在使用Objective-C开发一个API,这个API有一些虚构的方法的协议:

- (NSString *)gimmeString; // Want implementations to never return nil
我非常喜欢提供上下文,所以为此我大量使用了所有东西,包括
\uuuu attribute\uuuu((非空))
和friends等属性。我要问的是是否有方法提供上下文,并且是否可能为方法实现添加编译时检查,说“当使用clang编译时,此方法从不返回nil”

i、 e.我想要一些类似于:

@protocol MyProtocol
- (NSString *)gimmeString __attribute__((no_I_never_really_really_return_that_weird_nil));
@end

@implementation MyProtocolAdopter
- (NSString *)gimmeString
{
    return nil; // WARNING! You're returning nil, YOU PROMISED!
}
@end
而不仅仅是:

@protocol MyProtocol
// This method should never return nil
- (NSString *)gimmeString;
@end 

@implementation MyProtocolAdopter
- (NSString *)gimmeString
{
    // muvahaha, I lied!
    return nil;
}
@end
我知道不可能在编译时完全确定,但是检测
返回nil或计算结果肯定为
nil
的函数可以

类似于
\uuu属性(objc\u方法\u族(copy))
的想法似乎很奇怪,令人无法接受,但我没有找到比添加注释更好的方法,这让我的API用户陷入了一个更可怕、更不可靠的世界。

-XCode 6.3- 实际上,从XCode 6.3开始,您就可以进行编译时检查

- (nonnull NSString *)gimmeString;

-预XCode 6.3- 经过一些研究,包括深入研究clang和gcc文档,我发现在Objective-C中没有办法实现我想要的

为什么会这样: 我认为这是因为无法在编译时以某种复杂的质量级别来确定这一点。您无法确定该方法在编译时是否总是返回NOTNIL。确定方法
是否可以返回nil是不可靠的,猜测一下,有可能对所有

return %something_which_evaluates_to_nil_at_compile_time%;
并对所有依赖于此的方法发出警告,但是,例如,您不能确保某些
-init
方法不总是返回nil,或者某些web请求在没有提供任何附加上下文的情况下向您发出请求,您将以误判告终

即使是
-dequeueReusableCellWithIdentifier:forIndexPath:
UITableView
中保证始终返回有效单元格,也定义为:

- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier
                           forIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);

我想到的是: 因此,我在Objective-C中提到的是在不进行编译时检查的情况下提供上下文。我加上这样的评论:

@protocol MyProtocol
/**
 *  Creates and returns a string.
 *
 *  @note Implementations should never return nil.
 *
 *  @return A string, guarantied not to be nil.
 */
- (NSString *)gimmeString;
@end
还有一件事可以让它更具可读性,我们可以定义一个空的define并将其附加到声明的末尾,如下所示:

// Marks method to never return nil
#define MD_RETURNS_NONNULL

@protocol MyProtocol
/**
 *  Creates and returns a string.
 *
 *  @note Implementations should never return nil.
 *
 *  @return A string, guarantied not to be nil.
 */
- (NSString *)gimmeString MD_RETURNS_NONNULL;
@end
所以,这句话让你的代码更具可读性,让你的代码用户更快乐,因为他们更容易理解你想强调的内容

敏捷的 最后但并非最不重要的一点是建议转向Swift。在Swift中,这是可能的,并且是内置的,您只需定义返回的方法,而不是可选类型

protocol MyProtocol {
    func gimmeString -> String
}
你可以走了

结论 如果您真的希望在Objective-C中进行这样的检查,那么没有什么神奇之处,您只能在运行时进行检查,同时可以提供上下文,这非常好。但是,哦,等等,还有Swift选项,我们无论如何会在某个时候迁移到它,所以花点时间学习这门伟大的新语言。这是一个很好的例子,Swift的安全功能非常适用


UPD:玩了一点,看起来像这样的东西可以用它来实现(或者只是写一个自定义的叮当扩展)。

不确定你想用赏金来实现什么。你已经有了正确的答案。目标C是动态的,在这种情况下不是类型安全的。Swift的主要设计目标之一就是这个问题。@LeoNatan是的,我认为这也是正确的。只是好奇,是否有一些相关的引擎盖下的书呆子的细节或一些实验性的叮当声分支,它围绕着我想要的东西。