这是一个从ALAssetsLibrary加载图像的静态函数。
它在IOS4.X上运行良好,但在IOS5上,它将停在该行: “[albumReadLock lockWhenCondition:WDASSETURL_ALLFINISHED];”
如何在IOS4.x和iOS5上使用NSConditionLock?
// loads the data for the default representation from the ALAssetLibrary
+ (UIImage *) loadImageFromLibrary:(NSURL *)assetURL {
static NSConditionLock* albumReadLock;
static UIImage *realImage;
// this method *cannot* be called on the main thread as ALAssetLibrary needs to run some code on the main thread and this will deadlock your app if you block the main thread...
// don't ignore this assert!!
NSAssert(![NSThread isMainThread], @"can't be called on the main thread due to ALAssetLibrary limitations");
// sets up a condition lock with "pending reads"
albumReadLock = [[NSConditionLock alloc] initWithCondition:WDASSETURL_PENDINGREADS];
// the result block
ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset) {
ALAssetRepresentation *rep = [myasset defaultRepresentation];
//NSNumber *orientation = [myasset valueForProperty:ALAssetPropertyOrientation];
CGImageRef iref = [rep fullResolutionImage];
NSNumber *orientation = [myasset valueForProperty:ALAssetPropertyOrientation];
UIImage *image = [UIImage imageWithCGImage:iref scale:1.0 orientation:[orientation intValue]];
realImage = [image retain];
// notifies the lock that "all tasks are finished"
[albumReadLock lock];
[albumReadLock unlockWithCondition:WDASSETURL_ALLFINISHED];
};
ALAssetsLibraryAccessFailureBlock failureblock = ^(NSError *myerror)
{
//NSLog(@"NOT GOT ASSET");
//NSLog(@"Error '%@' getting asset from library", [myerror localizedDescription]);
// important: notifies lock that "all tasks finished" (even though they failed)
[albumReadLock lock];
[albumReadLock unlockWithCondition:WDASSETURL_ALLFINISHED];
};
// schedules the asset read
ALAssetsLibrary* assetslibrary = [[[ALAssetsLibrary alloc] init] autorelease];
[assetslibrary assetForURL:assetURL
resultBlock:resultblock
failureBlock:failureblock];
// non-busy wait for the asset read to finish (specifically until the condition is "all finished")
[albumReadLock lockWhenCondition:WDASSETURL_ALLFINISHED];
[albumReadLock unlock];
// cleanup
[albumReadLock release];
albumReadLock = nil;
// returns the image data, or nil if it failed
return realImage;
}
答案 0 :(得分:2)
使用dispatch_semaphore_t代替NSConditionLock
答案 1 :(得分:2)
迟到的答案但我找到了问题的解决方案。检查以下代码,我已经更改了导致崩溃的以下代码行的位置。
ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
albumReadLock = [[NSConditionLock alloc] initWithCondition:0];
// non-busy wait for the asset read to finish (specifically until the condition is "all finished")
[albumReadLock lockWhenCondition:1];
[albumReadLock unlock];
============================== 以下是所有代码 ====== ===============================
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
if(info)
{
// Don't pay any attention if somehow someone picked something besides an image.
if([[info objectForKey:UIImagePickerControllerMediaType] isEqualToString:(NSString *)kUTTypeImage]){
// UIImageView *imageView1=[[UIImageView alloc]init]; // = (UIImageView *)self.view;
// Hand on to the asset URL for the picked photo..
self.imageURL = [info objectForKey:UIImagePickerControllerReferenceURL];
// To get an asset library reference we need an instance of the asset library.
static NSConditionLock* albumReadLock;
// sets up a condition lock with "pending reads"
ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
albumReadLock = [[NSConditionLock alloc] initWithCondition:0];
// non-busy wait for the asset read to finish (specifically until the condition is "all finished")
[albumReadLock lockWhenCondition:1];
[albumReadLock unlock];
NSString *osVersion = [[UIDevice currentDevice] systemVersion];
NSString *versionWithoutRotation = @"5.0";
BOOL noRotationNeeded = ([versionWithoutRotation compare:osVersion options:NSNumericSearch]
!= NSOrderedDescending);
// The assetForURL: method of the assets library needs a block for success and
// one for failure. The resultsBlock is used for the success case.
ALAssetsLibraryAssetForURLResultBlock resultsBlock = ^(ALAsset *asset)
{
ALAssetRepresentation *representation = [asset defaultRepresentation];
CGImageRef image = [representation fullScreenImage];
if(noRotationNeeded)
{
// Create a UIImage from the full screen image. The full screen image
// is already scaled and oriented properly.
imageView.image = [UIImage imageWithCGImage:image];
}
else
{
// prior to iOS 5.0, the screen image needed to be rotated so
// make sure that the UIImage we create from the CG image has the appropriate
// orientation, based on the EXIF data from the image.
ALAssetOrientation orientation = [representation orientation];
imageView.image = [UIImage imageWithCGImage:image scale:1.0
orientation:(UIImageOrientation)orientation];
}
[albumReadLock lock];
[albumReadLock unlockWithCondition:1];
[picker dismissModalViewControllerAnimated:YES];
};
ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError *error)
{
NSLog(@"FAILED! due to error in domain %@ with error code %d", error.domain, error.code);
// This sample will abort since a shipping product MUST do something besides logging a
// message. A real app needs to inform the user appropriately.
[albumReadLock lock];
[albumReadLock unlockWithCondition:1];
[picker dismissModalViewControllerAnimated:YES];
abort();
};
// Get the asset for the asset URL to create a screen image.
[assetsLibrary assetForURL:self.imageURL resultBlock:resultsBlock failureBlock:failureBlock];
// Release the assets library now that we are done with it.
[assetsLibrary release];
}
}
}