我知道,当我们想要创建一个未知值的对象时,我们会使用id.然而,我很好奇,当每个对象都是NSObject的子类时,为什么苹果会 Select 在运行时决定其值的id.所以我们可以用NSObject *delegate而不是id delegate,有人知道为什么吗?谢谢

推荐答案

id删除类型,这相当于说"此对象响应翻译可见的任何 Select 器".当然,当你删除类型时(以及当你打字时),确保你的程序是正确的是your的责任.

如果类型为NSObject,那么如果 Select 器未在NSObject的接口或其采用的协议中声明,编译器会说"NSObject可能不响应selector".在这种情况下,您还可以添加一个类型转换,将其转换为您期望的类型.

对于严格/正确的类型,编译器可以启动并帮助您完成,这很好,因为ObjC是一种非常动态的语言.

id在使用(或构建)集合类型时特别有用.除非定义了新的根类型(不从NSObject继承),否则添加对象不会有问题.如果我们要将其用作基类(NSObject)以外的东西,则从集合中获取值需要类型转换.

Objective-C不支持泛型——例如,您不能声明NSStrings中的NSArray个.在没有保留类型安全性的情况下(a la泛型),可以用NSString填充NSArray,并将其传递到id,以获得更自然的书写风格.

所以,让我们用一些真实的代码来扩展一下.

Example A

NSString * string = [array objectAtIndex:0]; // << trust me (via id)
return [string length];
-or-
return [[array objectAtIndex:0] length]; // << trust me (via id)

Example B

现在假设id不可用,我们修复了所有编译器警告,因为这样做是正确的:

NSString * string  = (NSString*)[array objectAtIndex:0]; // << typecast == trust me
return [string length];
-or-
return [(NSString*)[array objectAtIndex:0] length]; // << typecast == trust me

id不会在运行时决定其值,任何NSObject也不会.ObjC对象不执行隐式提升,它们只是在没有正式提升的情况下投射指针.

与您的示例相关,我实际上将我的委托和参数声明为具有协议的NSObject:

NSObject<MONShapeDelegate>* delegate;

Objective-c相关问答推荐

Objective-C:为什么[对象复制]的两个请求返回相同的结果?

MKMapView 上的 UIPanGestureRecognizer?

等到多个网络请求都执行完毕 - 包括它们的完成块

如何通过仅更改高度而不更改宽度来调整 UILabel 的大小?

如何更改图像中的特定 colored颜色 ?

NSError 和 __autoreleasing

使用 arc4random() 时如何 Select 值的范围

在objective-c中isa是什么意思?

NSTimeZone:localTimeZone 和 systemTimeZone 有什么区别?

Objective C 代码是否有 github markdown 语言标识符?

测试应用程序是否确实从 UILocalNotification 变为活动状态

Objective-C:集合枚举块中的 continue继续?

从我在 iPhone 上的应用程序调用官方 *Settings* 应用程序

UIWebView 不会zoom 内容以适应

具有高质量代码的开源 Objective-C 项目?

何时应该使用 initWithNibName 初始化视图控制器?

如何在 Cocoa 中获取 NSArray 的第一个 x 元素?

ARC时代的财产与ivar

找出用户是否按下了 uinavigationcontroller 中的后退按钮?

info.plist 中的Application Requires iPhone Environment键是什么意思?