【问题标题】:Why NULL needs typecasting with blocks?为什么 NULL 需要使用块进行类型转换?
【发布时间】:2014-09-01 05:50:00
【问题描述】:

看到这个场景:

@property (nonatomic,copy) UIImage * (^bgImageBlock)(void);

bgImageBlock块变量的定义:

objDrawing.bgImageBlock = ^(){
         return (UIImage *)NULL;
    };

bgImageBlock 具有返回类型 UIImage,如果我像这样传递 NULL:

objDrawing.bgImageBlock = ^(){
         return NULL;
    };

会给出编译时错误:Incompitable block pointer type assigning to UIImage.

而如果我采用简单的 UIImage 变量并将其分配为 NULL,那绝对没问题。那么为什么在 Blocks 的情况下它不能接受没有类型转换的 NULL 。 ?

【问题讨论】:

  • 您应该向 Apple 提交错误报告。使用“Incompitable”一词的错误消息是不可接受的。
  • @gnasher729 是的,我正在考虑这样做......无论如何,谢谢。

标签: ios objective-c xcode uiimage objective-c-blocks


【解决方案1】:

如果您没有明确告知,编译器会根据您返回的对象类型推断块返回类型。所以,在这种情况下:

objDrawing.bgImageBlock = ^(){
     return NULL;
};

...我假设它看到了NULL 并推断您的块的返回类型是void *,即NULL 的类型。这与您的属性类型不匹配,因此编译器会抱怨。 (请注意,错误与“块指针类型”有关;它是块属性的声明与您尝试存储在其中的块之间的不匹配。)

如果你明确告诉它你的类型,你应该可以使用你的简单 NULL 返回:

objDrawing.bgImageBlock = ^UIImage*(){
     return NULL;
};

从返回类型推断出的块类型记录在in the Clang documentation

返回类型是可选的,是从返回语句中推断出来的。如果 return 语句返回一个值,它们都必须返回一个相同类型的值。如果没有返回值,则推断的 Block 类型为 void;否则为返回语句值的类型。

2013 WWDC session“Objective 的进步- C”。 (参见标题为“返回类型推断”的部分)。

【讨论】:

  • 所以没有声明返回类型,它默认为 void。这意味着简单的return; 应该没问题,对吧?否则,如果您声明返回为id,您可以使用return nil;,这将是更传统的Objective-C,但仍然允许返回一个对象,对吧?
【解决方案2】:

您的块需要UIImage* 类型。然而,NULL 是一个指针,它只是无法识别它指向UIImage* 类型的任何地方(不管它什么都不是)。 Bam,错误。

但是,您现在正在投射一个指针。它在运行时实际上并没有做任何事情。 它只是修改被指向的类型,然后影响对结果值的后续操作。但是实际的指针值将通过强制转换保持不变。

虽然实际的指针保持不变(尽管如此,指向的值是空的),但它现在指向一个 type 块预计将返回。一切都很好。 :)

【讨论】:

    【解决方案3】:

    NULL 的类型为void *,因此推断该块具有返回类型void *,并且非Objective-C-object 指针类型(如void *)与Objective-C-不兼容对象指针类型(如UIImage *)。相反,您应该使用nil,它也是一个空指针,但类型为id,它与所有Objective-C-object 指针类型兼容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-20
      • 1970-01-01
      • 2021-05-08
      相关资源
      最近更新 更多