gpt4 book ai didi

objective-c - Objective-C c block 中的代码未按预期执行

转载 作者:搜寻专家 更新时间:2023-10-30 20:01:05 25 4
gpt4 key购买 nike

我正在尝试使用此处的奇妙代码从 iOS 相机胶卷中的图像中读取 EXIF 数据:

http://blog.codecropper.com/2011/05/getting-metadata-from-images-on-ios/

不幸的是,在第一次尝试读取数据时,返回的是 nil ...但随后的每次尝试都正常。

博客的作者知道这一点并提出了解决方案,但我根本不明白!我是“ block ”的新手,即使我已经阅读过,我还是不明白:http://thirdcog.eu/pwcblocks/

谁能帮我翻译一下?

这是用于读取数据的代码:

NSMutableDictionary *imageMetadata = nil;
NSURL *assetURL = [info objectForKey:UIImagePickerControllerReferenceURL];

ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library assetForURL:assetURL
resultBlock:^(ALAsset *asset) {
NSDictionary *metadata = asset.defaultRepresentation.metadata;
imageMetadata = [[NSMutableDictionary alloc] initWithDictionary:metadata];
[self addEntriesFromDictionary:metadata];
}
failureBlock:^(NSError *error) {
}];
[library autorelease];

它可以很方便地放入 init 方法中并像这样调用:

NSMutableDictionary *metadata = [[NSMutableDictionary alloc] initWithInfoFromImagePicker:info];

作者对第一次尝试问题的描述是:

One caveat on using this: because it uses blocks, there’s no guarantee that your imageMetadata dictionary will be populated when this code runs. In some testing I’ve done it sometimes runs the code inside the block even before the [library autorelease] is executed. But the first time you run this, the code inside the block will only run on another cycle of the apps main loop. So, if you need to use this info right away, it’s better to schedule a method on the run queue for later with:

[self performSelectorOnMainThread:SELECTOR withObject:SOME_OBJECT waitUntilDone:NO];

.. 我就是被困在了这条线上!我不知道该怎么办?

非常感谢任何帮助!

最佳答案

问题是 block 中的代码被异步调用(这就是 block 可以用于的原因,即使这不是它们唯一的典型用法)。

您可能会认为它是另一种方式来执行通常使用委托(delegate)完成的操作,即在数据可用时异步获知。

对于您的代码,ALAssetsLibrary 将发出请求以获取和解码您请求的 Assets URL 的 EXIF 元数据,但代码将继续(在 block 之后,没有立即执行的 block ),因此转到下一行(在您的情况下为 [library release])。

稍后,一旦 ALAssetsLibrary 最终检索到 Assets 信息和您请求的 ALAsset,它最终将触发您在 block 中设置的代码 (很像当您使用委托(delegate)时,委托(delegate)方法稍后在数据可用时调用)


这就解释了为什么“ block ”中的代码会异步执行,然后可能会在[库发布]之前或之后执行,到时候你会命中 [library release] 行(或您在 assetForURL 调用之后放置的任何代码), block 中的代码可能没有时间执行。

解决方案是不使用 performSelector,但最好将更新界面或处理 EXIF 数据所需的一切代码放在 block 本身中。

例如,您可以直接在此处放置代码来更新您的界面(如 [self.tableView reloadData] 如果您在 tableview 中显示 EXIF 数据),或者触发 NSNotification 以通知您的其余代码已使用 addEntriesFromDictionary 添加了新的 EXIF 数据并需要显示,等等)

关于objective-c - Objective-C c block 中的代码未按预期执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7492936/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com