Ios &引用;缺少“块类型说明符”;重构代码后出现编译错误,但在重构前确认

Ios &引用;缺少“块类型说明符”;重构代码后出现编译错误,但在重构前确认,ios,objective-c,objective-c-blocks,Ios,Objective C,Objective C Blocks,我有一些代码可以下载图像并在块中分配它。代码目前运行正常,但我想将其重构为一个单独的方法,但重构后我会出现编译错误 这是编译并运行成功分配下载映像的原始代码: - (void) someMethod { … MyObject* object = [[MyObject alloc] init]; [self.objects addObject: object]; NSString* graphRequest = [NSString stringWithFormat:@"%

我有一些代码可以下载图像并在块中分配它。代码目前运行正常,但我想将其重构为一个单独的方法,但重构后我会出现编译错误

这是编译并运行成功分配下载映像的原始代码:

- (void) someMethod
{
   …
   MyObject* object = [[MyObject alloc] init];
   [self.objects addObject: object];

   NSString* graphRequest = [NSString stringWithFormat:@"%@%@%@",  @"https://graph.facebook.com/",
                              fbid,
                              @"/picture?type=square"];
    FBRequest *fbRequest = [FBRequest requestForGraphPath: graphRequest];
    [fbRequest startWithCompletionHandler:
     ^(FBRequestConnection *connection, id result, NSError *theError)
     {
         NSDictionary<FBGraphObject> *dict = (NSDictionary<FBGraphObject> *) result;
         if (dict)
         {
             NSString* urlAsString = [dict objectForKey:@"id"];
             if ([urlAsString length] > 0)
             {
                 NSURL *url = [NSURL URLWithString: urlAsString];
                 NSData *data = [NSData dataWithContentsOfURL:url];
                 object.image = [UIImage imageWithData:data];
             }
         }
     }];
}
-(void)someMethod
{
…
MyObject*object=[[MyObject alloc]init];
[self.objects addObject:object];
NSString*graphRequest=[NSString stringWithFormat:@“%@%@%@”,@”https://graph.facebook.com/",
fbid,
@“/picture?type=square”];
FBRequest*FBRequest=[FBRequestRequestForGraphPath:graphRequest];
[fbRequest startWithCompletionHandler:
^(FBRequestConnection*连接,id结果,N错误*theError)
{
NSDictionary*dict=(NSDictionary*)结果;
if(dict)
{
NSString*urlAsString=[dict objectForKey:@“id”];
如果([urlAsString长度]>0)
{
NSURL*url=[NSURL URLWithString:URLAString];
NSData*data=[NSData dataWithContentsOfURL:url];
object.image=[UIImage imageWithData:data];
}
}
}];
}
如果我将其重构为以下内容,则会出现编译错误

- (void) someMethod
{
   …
   MyObject* object = [[MyObject alloc] init];
   [self.objects addObject: object];
   [self fetchFbImage: object.image forFbid:fbid];
}


- (void) fetchFbImage:(UIImage*) targetImage forFbid:(NSString*) fbid
{
    NSString* graphRequest = [NSString stringWithFormat:@"%@%@%@",  @"https://graph.facebook.com/",
                              fbid,
                              @"/picture?type=square"];
    FBRequest *fbRequest = [FBRequest requestForGraphPath: graphRequest];
    [fbRequest startWithCompletionHandler:
     ^(FBRequestConnection *connection, id result, NSError *theError)
     {
         NSDictionary<FBGraphObject> *dict = (NSDictionary<FBGraphObject> *) result;
         if (dict)
         {
             NSString* urlAsString = [dict objectForKey:@"id"];
             if ([urlAsString length] > 0)
             {
                 NSURL *url = [NSURL URLWithString: urlAsString];
                 NSData *data = [NSData dataWithContentsOfURL:url];
                 targetImage = [UIImage imageWithData:data];
             }
         }
     }];
}
-(void)someMethod
{
…
MyObject*object=[[MyObject alloc]init];
[self.objects addObject:object];
[self-fetchFbImage:object.image forFbid:fbid];
}
-(void)fetchFbImage:(UIImage*)targetImage forFbid:(NSString*)fbid
{
NSString*graphRequest=[NSString stringWithFormat:@“%@%@%@”,@”https://graph.facebook.com/",
fbid,
@“/picture?type=square”];
FBRequest*FBRequest=[FBRequestRequestForGraphPath:graphRequest];
[fbRequest startWithCompletionHandler:
^(FBRequestConnection*连接,id结果,N错误*theError)
{
NSDictionary*dict=(NSDictionary*)结果;
if(dict)
{
NSString*urlAsString=[dict objectForKey:@“id”];
如果([urlAsString长度]>0)
{
NSURL*url=[NSURL URLWithString:URLAString];
NSData*data=[NSData dataWithContentsOfURL:url];
targetImage=[UIImage imageWithData:data];
}
}
}];
}
编译错误是分配到targetImage的行“变量不可分配(缺少块类型说明符)”

我应该在哪里添加块类型说明符?为什么在重构之后而不是重构之前会出现问题

感谢您的第一种方法(无需重构),您可以将图像设置为object,因为您对对象有引用,所以您做到了

object.image = [UIImage imageWithData:data];
但是在重构之后,您不能以您正在做的方式设置图像,您还应该发送对象

- (void) someMethod
{
   …
   MyObject* object = [[MyObject alloc] init];
   [self.objects addObject: object];
   [self fetchFbImageForObj:object forFbid:fbid];
}


- (void) fetchFbImageForObject:(MyObject*)object forFbid:(NSString*) fbid
{
    NSString* graphRequest = [NSString stringWithFormat:@"%@%@%@",  @"https://graph.facebook.com/",
                              fbid,
                              @"/picture?type=square"];
    FBRequest *fbRequest = [FBRequest requestForGraphPath: graphRequest];
    [fbRequest startWithCompletionHandler:
     ^(FBRequestConnection *connection, id result, NSError *theError)
     {
         NSDictionary<FBGraphObject> *dict = (NSDictionary<FBGraphObject> *) result;
         if (dict)
         {
             NSString* urlAsString = [dict objectForKey:@"id"];
             if ([urlAsString length] > 0)
             {
                 NSURL *url = [NSURL URLWithString: urlAsString];
                 NSData *data = [NSData dataWithContentsOfURL:url];
                 object.image = [UIImage imageWithData:data];
             }
         }
     }];
}
-(void)someMethod
{
…
MyObject*object=[[MyObject alloc]init];
[self.objects addObject:object];
[自取fbimageforobj:objectforfbid:fbid];
}
-(void)fetchFbImageForObject:(MyObject*)对象forFbid:(NSString*)fbid
{
NSString*graphRequest=[NSString stringWithFormat:@“%@%@%@”,@”https://graph.facebook.com/",
fbid,
@“/picture?type=square”];
FBRequest*FBRequest=[FBRequestRequestForGraphPath:graphRequest];
[fbRequest startWithCompletionHandler:
^(FBRequestConnection*连接,id结果,N错误*theError)
{
NSDictionary*dict=(NSDictionary*)结果;
if(dict)
{
NSString*urlAsString=[dict objectForKey:@“id”];
如果([urlAsString长度]>0)
{
NSURL*url=[NSURL URLWithString:URLAString];
NSData*data=[NSData dataWithContentsOfURL:url];
object.image=[UIImage imageWithData:data];
}
}
}];
}

试试看。如果有任何错误或什么,请在下面评论。

您似乎对Objective-C中的参数是如何工作的感到困惑

在原始代码中,您有:

MyObject* object = [[MyObject alloc] init];
它将
对象
声明为方法的局部变量。然后在块内写入:

object.image = [UIImage imageWithData:data];
targetImage = [UIImage imageWithData:data];
因此,块引用局部变量
object
,并且(由于声明中没有
\uu block
属性),块获取变量内容的常量副本。这很好,因为您没有更改
object
中的内容,该对象是对
MyObject
实例的引用,而是在该实例上调用一个方法,该方法会更改该实例的内部状态。[*]

现在让我们看看您的重构。您删除了
someMethod
的代码块,并将其放置在新方法
fetchFbImage
中。在
someMethod
中调用
fetchFbImage

[self fetchFbImage:object.image forFbid:fbid];
这会将
object.image
的当前值传递给方法,而不会以可在
fetchFbImage
中指定的方式传递属性。参数
targetImage
的类型是
UIImage*
-对
UIImage
的引用-它不是“类型为
UIImage*
的属性”-不能有此类类型的参数,属性不能仅传递其值或对具有属性的对象的引用

调用方法时,每个参数实际上是一个局部变量,初始化为传递的参数值,因此上述方法调用有效地执行:

UIImage *targetImage = object.image;
其中,
targetImage
fetchFbImage
范围内的局部变量,
object
somethod
范围内的局部变量

现在,在您编写的
fetchFbImage
内的块中
- (void) fetchFbImage:(MyObject *)targetObject forFbid:(NSString *)fbid
{
   ...
   targetObject.image = [UIImage imageWithData:data];
   ...
}

...

[self fetchFbImage:object forFbid:fbid];
typedef void (^ImageConsumer)(NSImage *image);
- (void) fetchFbImageForFbid:(NSString *)fbid completionHandler:(ImageConsumer)handler
handler([UIImage imageWithData:data]);
[self fetchFbImageForFbid:fbid
        completionHandler:^(NSImage *image) { object.image = image; }
];