【问题标题】:asset imageURL passed as string to another class资产 imageURL 作为字符串传递给另一个类
【发布时间】:2014-10-03 18:59:05
【问题描述】:

这是我拥有的应用程序的简化版本,它从 iPhone/iPad 图像库中获取图像 url,将该 URL 的字符串存储在 core-data 中,然后在另一个控制器中显示它。我认为正确的 URl 存储在核心数据中,但稍后检索时不显示。

为了尝试排除故障,我有一个应用程序,它从 iPhone/iPad 图像库中获取图片并将其显示在屏幕上。然后我按下一个按钮来切换到第二个视图控制器并再次显示它。它不会出现在第二个视图控制器上。我在第一个场景中使用我在第二个控制器中使用的相同方法显示它,只是为了表明该方法可以提供正确的 URL。我将 URL 作为控制器之间的字符串传递,以模拟存储在核心数据中的 URL,因此将其作为 NSURL 传递不是此示例的选项。

首先查看 controller.h 和 .m 文件

//
//  patViewController.h
//  pictureAssetTest
//
//  Created by Chip Cox on 8/10/14.
//  Copyright (c) 2014 Home. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "CCExtras.h"
#import <AssetsLibrary/AssetsLibrary.h>

@interface patViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate>

@end



//
//  patViewController.m
//  pictureAssetTest
//
//  Created by Chip Cox on 8/10/14.
//  Copyright (c) 2014 Home. All rights reserved.
//

#import "patViewController.h"
#import "patSecondVC.h"

@interface patViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageControl;
@property (nonatomic,strong) NSURL *imageURL;
@end

@implementation patViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)selectPictureFromLibrary:(UIButton *)sender
{
    [self startPhotoLibraryFromViewController:self usingDelegate:self];

}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
    [self dismissViewControllerAnimated:YES completion:nil];
}

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    [self dismissViewControllerAnimated:YES completion:nil];
    self.imageURL=[info objectForKey:UIImagePickerControllerReferenceURL];
    CCLog(@"Image =%@",[info objectForKey:UIImagePickerControllerReferenceURL]);

    [self displayImageFromURL:self.imageURL];
}

- (void) displayImageFromURL:(NSURL*)urlIn
{
    ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];

    switch(status){
        case ALAuthorizationStatusDenied: {
            CCLog(@"not authorized");
            break;
        }
        case ALAuthorizationStatusRestricted: {
            CCLog(@"Restricted");
            break;
        }
        case ALAuthorizationStatusNotDetermined: {
            CCLog(@"Undetermined");
            break;
        }
        case ALAuthorizationStatusAuthorized: {
            CCLog(@"Authorized");
            CCLog(@"urlIn=%@",urlIn.pathComponents);
            ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
            __block UIImage *returnValue = nil;
            [library assetForURL:urlIn resultBlock:^(ALAsset *asset) {
                returnValue = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullResolutionImage]];
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self.imageControl setImage:returnValue];
                    [self.imageControl setNeedsDisplay];
                });
            } failureBlock:^(NSError *error) {
                NSLog(@"error : %@", error);
            }];
            break;
        }
        default: {
            CCLog(@"Unknown hit default");
            break;
        }
    }
}

- (BOOL) startPhotoLibraryFromViewController: (UIViewController*) controller
                               usingDelegate: (id <UIImagePickerControllerDelegate,
                                               UINavigationControllerDelegate>) delegate {

    UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
    cameraUI.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

    // Displays a control that allows the user to choose picture or
    // movie capture, if both are available:
    cameraUI.mediaTypes =
    [UIImagePickerController availableMediaTypesForSourceType:
    UIImagePickerControllerSourceTypePhotoLibrary];

    // Hides the controls for moving & scaling pictures, or for
    // trimming movies. To instead show the controls, use YES.
    cameraUI.allowsEditing = NO;

    cameraUI.delegate = delegate;

    [controller presentViewController:cameraUI animated:YES completion:nil];
    return YES;
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([segue.destinationViewController isKindOfClass:[patSecondVC class]]) {
        CCLog(@"Preparing for segue to %@",segue.destinationViewController);
        patSecondVC *dvc=segue.destinationViewController;
        dvc.transferURL=self.imageURL.absoluteString;
    } else {
        CCLog(@"Preparing to segue to unknown destination view controller %@",segue.destinationViewController);
    }
}

@end

以下代码是第二个视图控制器的.h和.m文件。

//
//  patSecondVC.h
//  pictureAssetTest
//
//  Created by Chip Cox on 8/10/14.
//  Copyright (c) 2014 Home. All rights reserved.
//

#import <UIKit/UIKit.h>
#import <AssetsLibrary/AssetsLibrary.h>
#import "CCExtras.h"

@interface patSecondVC : UIViewController
@property (nonatomic,strong) NSString *transferURL;
@end



//
//  patSecondVC.m
//  pictureAssetTest
//
//  Created by Chip Cox on 8/10/14.
//  Copyright (c) 2014 Home. All rights reserved.
//

#import "patSecondVC.h"

@interface patSecondVC ()
@property (weak, nonatomic) IBOutlet UIImageView *imageControl;

@end

@implementation patSecondVC

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    CCLog(@"photo url=%@",self.transferURL);
    [self displayImageFromURL:[NSURL fileURLWithPath:self.transferURL]];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void) displayImageFromURL:(NSURL*)urlIn
{
    ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];

    switch(status){
        case ALAuthorizationStatusDenied: {
            CCLog(@"not authorized");
            break;
        }
        case ALAuthorizationStatusRestricted: {
            CCLog(@"Restricted");
            break;
        }
        case ALAuthorizationStatusNotDetermined: {
            CCLog(@"Undetermined");
            break;
        }
        case ALAuthorizationStatusAuthorized: {
            CCLog(@"Authorized");
            CCLog(@"urlIn=%@",urlIn.pathComponents);
            ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
            __block UIImage *returnValue = nil;
            [library assetForURL:urlIn resultBlock:^(ALAsset *asset) {
                returnValue = [UIImage imageWithCGImage:[[asset defaultRepresentation] fullResolutionImage]];
                dispatch_async(dispatch_get_main_queue(), ^{
                    [self.imageControl setImage:returnValue];
                    [self.imageControl setNeedsDisplay];
                });
            } failureBlock:^(NSError *error) {
                NSLog(@"error : %@", error);
            }];
            break;
        }
        default: {
            CCLog(@"Unknown hit default");
            break;
        }

    }

}
@end

谢谢

添加日志输出

2014-08-11 17:05:37.194 pictureAssetTest[2544:60b] <-[patViewController imagePickerController:didFinishPickingMediaWithInfo:] - 45> Image =assets-library://asset/asset.PNG?id=5E208B2D-65CC-4F46-8F22-DD2E8006AF1B&ext=PNG
2014-08-11 17:05:37.195 pictureAssetTest[2544:60b] <-[patViewController displayImageFromURL:] - 68> Authorized
2014-08-11 17:05:37.196 pictureAssetTest[2544:60b] <-[patViewController displayImageFromURL:] - 69> urlIn=(
    "/",
    "asset.PNG"
)
2014-08-11 17:05:39.149 pictureAssetTest[2544:60b] <-[patViewController prepareForSegue:sender:] - 116> Preparing for segue to <patSecondVC: 0xa49c610>
2014-08-11 17:05:39.150 pictureAssetTest[2544:60b] <-[patSecondVC viewDidLoad] - 31> photo url=assets-library://asset/asset.PNG?id=5E208B2D-65CC-4F46-8F22-DD2E8006AF1B&ext=PNG
2014-08-11 17:05:39.151 pictureAssetTest[2544:60b] <-[patSecondVC displayImageFromURL:] - 59> Authorized
2014-08-11 17:05:39.151 pictureAssetTest[2544:60b] <-[patSecondVC displayImageFromURL:] - 60> urlIn=(
    "/",
    "assets-library:",
    asset,
    "asset.PNG?id=5E208B2D-65CC-4F46-8F22-DD2E8006AF1B&ext=PNG"
)

【问题讨论】:

  • 在 prepareForSegue 中,dvc.transferURL 是否有机会为零?你在 CCLog(@"photo url=%@",self.transferURL); 的输出中看到了什么在第二个控制器中?
  • 按要求添加了日志输出。不,这不是零。在为 segue 做准备时,我尝试使用参考 url 进行设置,在这种情况下,我得到 /asset.PNG 输出,以及示例中显示的绝对路径。两种方式的结果相同。
  • 在第二个 VC 中,您可以进行更改以仅在主线程上调用其尚未在主线程上的调用吗? UIImageView *imageControl IBOutlet 是否连接在情节提要中?你能确认这一行不是零:[self.imageControl setImage:returnValue];也尝试在这一行设置捆绑包中的图像
  • 我猜你想在第二个场景中检查 self.imageControl。我在那里显示了它的描述并得到了 2014-08-11 17:44:22.947 pictureAssetTest[2842:60b] <__35- displayimagefromurl:> self.imageControl=> 所以它不是零。我承认我对目标 C 很陌生。我知道我可以使用 [NSThread isMainThread] 来确定我是否在主线程中。我只是不知道如何在代码中使用它,请指教。
  • 您可以为此设置本地图像吗?而不是来自 url .. 类似 [self.imageControl setImage:[UIImage imageNamed:@"localimage.png"]];

标签: ios objective-c image url alassetslibrary


【解决方案1】:

在第二个vc中将调用改为

[self displayImageFromURL:[NSURL URLWithString:self.transferURL]];

这应该可以解决它!

【讨论】:

  • 但是 imageURL 是一个 NSURL 而不是 NSString。我无法在 coredata 中存储 NSURL。正确的?所以我必须将 NSURL 转换为字符串,然后在目标视图控制器中转换回 NSURL。
  • 得到一个转储 NSInvalidArgumentException',原因:'-[NSURL 长度]:在上面的调用中,无法识别的选择器发送到实例 0xa2b1df0'。这是否需要是一个 c'string 而不是传递给 URLWithString 的 NSString?网址是 assets-library://asset/asset.JPG?id=13A3DD08-3410-4181-8A20-621A53ABBF59&ext=JPG
  • 哪里崩溃了?
  • 知道了,我仍然需要使用 NSURL 而不是 NSURL.absolutePath 来加载 transferURL。我把它改回来,它工作。谢谢
猜你喜欢
  • 1970-01-01
  • 2012-04-21
  • 1970-01-01
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
  • 2018-12-13
  • 2021-11-17
  • 2015-10-10
相关资源
最近更新 更多