MTLDevice 类需要 id<>

J.D*_*Doe 0 objective-c ios metal

我对 Objective-c 很陌生,所以请耐心等待,我仍在尝试理解可以在目标 c 中放置属性和类变量的众多位置。

我是一名经验丰富的 Metal 开发人员,但我几乎没有用 Objective-c 做过任何事情。

我正在尝试创建一个 MetalCore 类,该类将保存 MTLDevice、MTLCommandQueue 并促进应用程序核心管道等的创建。

因此,我定义了以下内容

@property (readonly, nonatomic, assign) MTLDevice* devicePtr;
Run Code Online (Sandbox Code Playgroud)

然而,在我的课堂上,Unknown type name MTLDevice; did you mean...即使我得到了错误#import <Metal/Metal.h>,这里发生了什么?

我查看了堆栈溢出并找到了人们定义这样的函数的示例

- (<MTLDevice> *)device;
Run Code Online (Sandbox Code Playgroud)

或者

- (instancetype)initWithDevice:(id<MTLDevice>) device;
Run Code Online (Sandbox Code Playgroud)

整个 id 和 <> 是怎么回事?在什么情况下可以省略 id 部分?

我觉得特别奇怪的是,虽然大多数 Metal 类型似乎都需要 id,但有些类似的MTLRenderPipelineDescriptor不需要它,实际上只在该Type*模式下工作。这是为什么,我如何从文档中确定需要什么?

war*_*enm 6

在 Objective-C 中,id基本上意味着“任何对象类型”。如果要确保对象符合协议(例如MTLDevice),请id在说明其类型后在尖括号中指定协议:id<MTLDevice>表示“符合MTLDevice协议的类型”。

与具体类(例如MTLRenderPipelineDescriptor)不同,您不使用*after id,因此您不会写入id<MTLDevice> *(除非您使用指向设备的指针,这并不常见)。MTLDevice *没有意义,因为MTLDevice不是具体类型。<MTLDevice>本身就是无稽之谈,并且是语法错误,就像<MTLDevice> *.

来自 Swift,您可能习惯于将协议和具体类型混为一谈,因为 Swift 没有在“符合协议的某种类型”和“某种具体类型”之间进行语法区分。要判断某事是否是协议,请查阅文档;它会明确指出什么时候是协议。在金属,所有的“描述”的类型是具体的(如MTLRenderPipelineDescriptor),而大多数其他对象类型都被抽象背后的协议(MTLDeviceMTLCommandQueueMTLLibraryMTLFunctionMTLTextureMTLRenderPipelineStateMTLCommandBuffer,等)