Objective c 块完成后只返回

Objective c 块完成后只返回,objective-c,objective-c-blocks,Objective C,Objective C Blocks,我想知道,为了使下面的代码正常工作,应该使用什么样的解决方案 - (CGFloat)getRowImageHeight { CGFloat defaultHeight = 300.f; __block CGFloat height = defaultHeight; [self configureImageTVCell:self.itemImageTVCell block:^(UIImage *image, BOOL

我想知道,为了使下面的代码正常工作,应该使用什么样的解决方案

- (CGFloat)getRowImageHeight
{
    CGFloat defaultHeight   = 300.f;
    __block CGFloat height  = defaultHeight;

    [self configureImageTVCell:self.itemImageTVCell
                         block:^(UIImage *image, BOOL succeeded) {
                             if( succeeded )
                                 height     = image.size.height;
                         }];

    return height;
}

我希望在返回高度之前先完成该区块,因为我想从区块完成获得最新高度

我尝试了一些解决方案,使用调度信号量\u t,但它会导致模拟器实际挂起的地方出现死锁

dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

[self configureImageTVCell:self.itemImageTVCell
                         block:^(UIImage *image, BOOL succeeded) {
                             if( succeeded )
                                 height     = image.size.height;

                             dispatch_semaphore_signal(semaphore);
                         }];

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);

这方面的想法已经没有了,确实需要帮助。

基本上,你想要做的是不可能的。一方面,您有一个方法,需要立即从中返回一个值:

- (CGFloat)getRowImageHeight
{
    // ... do some stuff ...
    return height;
}

另一方面,在该代码的中间(“做一些东西”),您正在执行异步操作:

[self configureImageTVCell:self.itemImageTVCell
                     block:^(UIImage *image, BOOL succeeded) {
                         // THIS IS ASYNCHRONOUS
                         if( succeeded )
                             height     = image.size.height;
                     }];
这意味着,根据定义,块中的代码将在未来某个未知时间运行。同时,您的外部方法
getRowImageHeight
早已完成并返回其值

这就是异步代码执行的本质

您需要重新构建整个方法,以便它与异步代码配合使用


当然,你还没有透露你真正想做什么,所以我不能告诉你如何重新构建它。但让我们先假设您正试图用从Internet下载的图像填充表视图的单元格。这是一个公认的问题,到处都有答案,包括许多关于堆栈溢出的好解释。因此,您可以阅读这些答案。

好方法如下:

- (void)getRowImageHeightWithCompletionBlock:(void(^)(CGFloat height))completion {
    CGFloat defaultHeight = 300.f;
    [self configureImageTVCell:self.itemImageTVCell block:^(UIImage *image, BOOL succeeded) {
        if(succeeded && completion) {
            completion(image.size.height);
        }
    }];
}

我试图做的事情是在视图加载时,我在图像出现在视图上之前预加载它。然后让image block返回图像高度,我想将高度返回到

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
但上面的答案似乎告诉我,这种方法是不可能的。因此,我尝试使用delegate,将高度返回到主视图,并在单元格级别成功获取图像后,使用下面的代码更新单元格高度

- (void)reloadItemImageTVCellHeight:(CGFloat)height
{
    if( !self.hasUpdatedImageCellHeight ){
        self.hasUpdatedImageCellHeight   = YES;
        self.itemImageCellHeight        = height;
        [self.mTableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:ROW_IMAGE inSection:0]]
                         withRowAnimation:UITableViewRowAnimationNone];
    }
}
在viewDidLoad中,我将self.hasUpdatedImageCellHeight设置为NO,并将self.itemImageCellHeight设置为300.fself.hasUpdatedImageCellHeight用于控制代理是否已返回任何值,如果YES,则我将其更新为YES,以防止代理代码再次调用


这是我的方法,但如果有一种方法可以在完全加载表视图之前以本机方式知道图像高度,那么它仍然是最好的。

“我希望块在返回高度之前首先完成”您的预期是错误的。你现在明白为什么了吗?不要试图用信号量来破坏异步代码的执行。异步是无法逃避的。接受它:)我喜欢你详细的解释,我最喜欢的解释是:“马蒂,你没有从第四维度思考……”(马蒂)