如何在IOS5上使用NSConditionLock

时间:2011-11-26 03:46:00

标签: iphone objective-c ios5

这是一个从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;
}

2 个答案:

答案 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];
    }
}
 }