繁体   English   中英

我可以从 URL 加载 UIImage 吗?

[英]Can I load a UIImage from a URL?

我有一个图像的 URL(从 UIImagePickerController 获取),但我的内存中不再有图像(URL 是从应用程序的上一次运行中保存的)。 我可以再次从 URL 重新加载 UIImage 吗?

我看到 UIImage 有一个 imageWithContentsOfFile: 但我有一个 URL。 我可以使用 NSData 的 dataWithContentsOfURL: 来读取 URL 吗?

编辑1


基于@Daniel 的回答,我尝试了以下代码,但它不起作用...

NSLog(@"%s %@", __PRETTY_FUNCTION__, photoURL);     
if (photoURL) {
    NSURL* aURL = [NSURL URLWithString:photoURL];
    NSData* data = [[NSData alloc] initWithContentsOfURL:aURL];
    self.photoImage = [UIImage imageWithData:data];
    [data release];
}

当我运行它时,控制台显示:

-[PhotoBox willMoveToWindow:] file://localhost/Users/gary/Library/Application%20Support/iPhone%20Simulator/3.2/Media/DCIM/100APPLE/IMG_0004.JPG
*** -[NSURL length]: unrecognized selector sent to instance 0x536fbe0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSURL length]: unrecognized selector sent to instance 0x536fbe0'

查看调用堆栈,我正在调用 URLWithString,它调用 URLWithString:relativeToURL:,然后是 initWithString:relativeToURL:,然后是 _CFStringIsLegalURLString,然后是 CFStringGetLength,然后是forwarding_prep_0 ,然后是forwarding ,然后是 -[NSObject doesNotRecognizeSelector]。

任何想法为什么我的 NSString(photoURL 的地址是 0x536fbe0)不响应长度? 为什么它说它不响应 -[NSURL length]? 难道它不知道 param 是一个 NSString,而不是一个 NSURL?

编辑2


好的,代码唯一的问题是字符串到 URL 的转换。 如果我对字符串进行硬编码,则其他一切正常。 所以我的 NSString 有问题,如果我无法弄清楚,我想这应该作为一个不同的问题。 插入这一行(我粘贴了上面控制台日志中的路径),它工作正常:

photoURL = @"file://localhost/Users/gary/Library/Application%20Support/iPhone%20Simulator/3.2/Media/DCIM/100APPLE/IMG_0004.JPG";

你可以这样做(同步,但紧凑):

UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:MyURL]]];

更好的方法是使用 Apple 的 LazyTableImages 来保持交互性。

您可以尝试SDWebImage ,它提供:

  1. 异步加载
  2. 缓存供离线使用
  3. 加载时显示的占位符图像
  4. 与 UITableView 配合使用

快速示例:

    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

和快速版本:

   let url = NSURL.URLWithString("http://live-wallpaper.net/iphone/img/app/i/p/iphone-4s-wallpapers-mobile-backgrounds-dark_2466f886de3472ef1fa968033f1da3e1_raw_1087fae1932cec8837695934b7eb1250_raw.jpg");
    var err: NSError?
    var imageData :NSData = NSData.dataWithContentsOfURL(url,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err)
    var bgImage = UIImage(data:imageData)

获取DLImageLoader并尝试以下代码

   [DLImageLoader loadImageFromURL:imageURL
                          completed:^(NSError *error, NSData *imgData) {
                              imageView.image = [UIImage imageWithData:imgData];
                              [imageView setContentMode:UIViewContentModeCenter];

                          }];

使用 DLImageLoader 的另一个典型的现实世界示例,它可能会帮助某人...

PFObject *aFacebookUser = [self.fbFriends objectAtIndex:thisRow];
NSString *facebookImageURL = [NSString stringWithFormat:
    @"http://graph.facebook.com/%@/picture?type=large",
    [aFacebookUser objectForKey:@"id"] ];

__weak UIImageView *loadMe = self.userSmallAvatarImage;
// ~~note~~ you my, but usually DO NOT, want a weak ref
[DLImageLoader loadImageFromURL:facebookImageURL
   completed:^(NSError *error, NSData *imgData)
    {
    if ( loadMe == nil ) return;

    if (error == nil)
        {
        UIImage *image = [UIImage imageWithData:imgData];
        image = [image ourImageScaler];
        loadMe.image = image;
        }
    else
        {
        // an error when loading the image from the net
        }
    }];

正如我在上面提到的,最近要考虑的另一个很棒的库是Haneke (不幸的是,它没有那么轻量级)。

如果你真的,绝对是积极肯定的NSURL是一个文件的URL,即[url isFileURL]是保证你的情况返回true,那么你可以简单地使用:

[UIImage imageWithContentsOfFile:url.path]

试试这个代码,你可以用它设置加载图片,这样用户就知道你的应用正在从 url 加载图片:

UIImageView *yourImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"loading.png"]];
    [yourImageView setContentMode:UIViewContentModeScaleAspectFit];

    //Request image data from the URL:
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://yourdomain.com/yourimg.png"]];

        dispatch_async(dispatch_get_main_queue(), ^{
            if (imgData)
            {
                //Load the data into an UIImage:
                UIImage *image = [UIImage imageWithData:imgData];

                //Check if your image loaded successfully:
                if (image)
                {
                    yourImageView.image = image;
                }
                else
                {
                    //Failed to load the data into an UIImage:
                    yourImageView.image = [UIImage imageNamed:@"no-data-image.png"];
                }
            }
            else
            {
                //Failed to get the image data:
                yourImageView.image = [UIImage imageNamed:@"no-data-image.png"];
            }
        });
    });

AFNetworking提供异步图像加载到具有占位符支持的 UIImageView。 它还支持异步网络以使用一般的 API。

查看此处提供的AsyncImageView 一些很好的示例代码,甚至可能对您来说“开箱即用”。

确保从 iOS 9 启用此设置:

Info.plist 中的应用传输安全设置,以确保从 URL 加载图像,以便它允许下载图像并进行设置。

在此处输入图片说明

并写下这段代码:

NSURL *url = [[NSURL alloc]initWithString:@"http://feelgrafix.com/data/images/images-1.jpg"];
NSData *data =[NSData dataWithContentsOfURL:url];
quickViewImage.image = [UIImage imageWithData:data];

使用 Swift 扩展UIImageView (源代码在这里):

为关联的UIActivityIndicatorView创建计算属性

import Foundation
import UIKit
import ObjectiveC

private var activityIndicatorAssociationKey: UInt8 = 0

extension UIImageView {
    //Associated Object as Computed Property
    var activityIndicator: UIActivityIndicatorView! {
        get {
            return objc_getAssociatedObject(self, &activityIndicatorAssociationKey) as? UIActivityIndicatorView
        }
        set(newValue) {
            objc_setAssociatedObject(self, &activityIndicatorAssociationKey, newValue, UInt(OBJC_ASSOCIATION_RETAIN))
        }
    }

    private func ensureActivityIndicatorIsAnimating() {
        if (self.activityIndicator == nil) {
            self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
            self.activityIndicator.hidesWhenStopped = true
            let size = self.frame.size;
            self.activityIndicator.center = CGPoint(x: size.width/2, y: size.height/2);
            NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
                self.addSubview(self.activityIndicator)
                self.activityIndicator.startAnimating()
            })
        }
    }

自定义初始化器和设置器

    convenience init(URL: NSURL, errorImage: UIImage? = nil) {
        self.init()
        self.setImageFromURL(URL)
    }

    func setImageFromURL(URL: NSURL, errorImage: UIImage? = nil) {
        self.ensureActivityIndicatorIsAnimating()
        let downloadTask = NSURLSession.sharedSession().dataTaskWithURL(URL) {(data, response, error) in
            if (error == nil) {
                NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
                    self.activityIndicator.stopAnimating()
                    self.image = UIImage(data: data)
                })
            }
            else {
                self.image = errorImage
            }
        }
        downloadTask.resume()
    }
}

通过 Url 加载图像的最佳和简单方法是通过以下代码:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSData *data =[NSData dataWithContentsOfURL:[NSURL URLWithString:imgUrl]];

    dispatch_async(dispatch_get_main_queue(), ^{
        imgView.image= [UIImage imageWithData:data];
    });
});

更换imgUrlImageURL
imgView替换为您的UIImageView

它将在另一个线程中加载图像,因此它不会减慢您的应用程序加载速度。

本地 URL 非常简单,只需使用这个:

UIImage(contentsOfFile: url.path)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM