问题描述
在我的应用程序中,我通过选择器打开相机,拍完照片后,我想通过以下方法将资产库安全。调用writeImageToSavedPhotosAlbum后,该方法会冻结。
In my app I open the camera by a picker and after the photo has been taken I'd like to safe it by the following method the assets library. The method freezes after the call of the writeImageToSavedPhotosAlbum.
如果没有信号量,方法可以正常工作。但是我错过了收到assetURL。
Without the semaphores the methods work perfectly. But than I miss to receive the assetURL.
+ (NSURL*)safeImageToAssetsLibrary:(UIImage *)image metadata:(NSDictionary *)metadata
{
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
__block NSURL *retAssestURL = nil;
dispatch_semaphore_t semaWaitingForSafeImage = dispatch_semaphore_create(0);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// safe the image to the assests library
NSLog(@"Safe image to asssets library...");
dispatch_async(queue, ^{
[library writeImageToSavedPhotosAlbum:image.CGImage metadata:metadata completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
NSLog(@"Image could not be safed to the assets library: %@", error);
retAssestURL = nil;
}
else {
NSLog( @"Image safed successfully to assetURL: %@", assetURL);
retAssestURL = assetURL;
}
dispatch_semaphore_signal(semaWaitingForSafeImage);
}];
});
dispatch_semaphore_wait(semaWaitingForSafeImage, DISPATCH_TIME_FOREVER);
return retAssestURL;
}
这是我调用 safeImageToAssetsLibrary 方法:
And this is method where I call the safeImageToAssetsLibrary
method:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissViewControllerAnimated:YES completion:NULL];
// get chosen image and add thumbnail to collection view
NSURL *imageUrl = info[UIImagePickerControllerReferenceURL];
UIImage *chosenImage = info[UIImagePickerControllerOriginalImage];
// safe image to photo library if the camera has been used
if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
imageUrl = [BaseImageHandler safeImageToAssetsLibrary:chosenImage metadata:info[UIImagePickerControllerMediaMetadata]];
}
// UPDATE View and Core Data here...
}
推荐答案
不等待。永远不要做你正在做的事。您无法理解异步的含义。这意味着当你完成块中的时,你会被回叫。所以 是你执行下一步的地方。
Do not wait. Never, never do what you are doing. You are failing to understand what "asynchronous" is about. It means that you are called back when it's all over in the completion block. So that is where you perform the next step.
不要尝试从获取该值的方法中返回一个值一个异步完成块。
所以,在这里,在 writeImageToSavedPhotosAlbum:
的完成块, 是您收到 retAssestURL
的地方。因此,如果还有一个步骤,现在做,那里,在完成块中 。这可能涉及调用另一种方法或任何你喜欢的方法,但关键是,事情现在将以正确的顺序发生。
So, here, in writeImageToSavedPhotosAlbum:
's completion block, that is where you receive retAssestURL
. So if there is a further step, now do it, there, in the completion block. This could involve calling another method or whatever you like, but the point is, things will now happen in the correct order.
最重要的是,不要使用信号量(或其他技巧)试图将异步转变为同步。异步事物是异步的,原因很简单。 使用框架,不要战斗它。 (实际上,你在这里使用信号量所做的不仅仅是对抗框架,而是随意吐痰。)
And above all, Do NOT use semaphores (or other trickery) to try to turn asynchronous into synchronous. Asynchronous things are asynchronous for a reason. Use the framework, don't fight it. (Actually, what you are doing with semaphores here is not just fighting the framework but spitting in its eye.)
这篇关于等待信号量完成writeImageToSavedPhotosAlbum的块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!