URLからUIImageをロードできますか?


134

画像の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:relativeToURL :、次にinitWithString:relativeToURL :、次に_CFStringIsLegalURLString、次にCFStringGetLength、次にforwarding_prep_0、次にForwarding、次に-[NSObject doesNotRecognizeSelector]を呼び出すURLWithStringを呼び出しています。

NSString(photoURLのアドレスが0x536fbe0)が長さに応答しない理由はありますか?-[NSURLの長さ]に応答しないと表示されるのはなぜですか?paramがNSURLではなくNSStringであることを知らないのですか?

EDIT2


OK、コードの唯一の問題は、文字列からURLへの変換です。文字列をハードコーディングすると、他のすべてが正常に機能します。したがって、NSStringに何か問題があり、それを理解できない場合は、別の質問として入力する必要があります。この行を挿入すると(上記のコンソールログのパスを貼り付けました)、正常に動作します。

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

NSLogが処理した場合、photoURLはすでにNSStringではなくNSURLのようです。
描画

@drawn:ドキュメントのエラーのようです。UIImagePickerControllerMediaURLはNSStringですが、実際にはNSURLオブジェクトです。
progrmr 2010年

ライブラリDLImageLoaderは信じられないほどです。堅実、ドコなし、1つのコマンドですべてが完璧です。なんという発見だ。
Fattie

2番目(3番目?)のDLImageLoader。このページのコメントが客観的であるかどうかは疑問でしたが、とにかく試してみたところ、非常にうまく機能しました。UITableViewCell内にUIImageViewがあります。私が行ったのは、UIImageViewをDLImageViewに置き換え、imageFromUrl:メソッドを呼び出して画像をロードすることだけでした。すべてが機能します-非同期のロード、キャッシングなど。簡単にはできませんでした。
itnAAnti 2016年

DLImageLoaderは、別の良いものがあり、幻想のままHanekeそれはかなり保たれていないされてから少し苦しんでいるものの、。
Fattie

回答:


319

次のようにして実行できます(同期的ですが、コンパクトです)。

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

はるかに優れたアプローチは、AppleのLazyTableImagesを使用して対話性を維持することです。


1
データをPNG(またはJPG)ファイル形式からUIImageデータに変換する必要はありませんか?それともUIImageはどういうわけかそれを理解していますか?
progrmr

2
RTFMだけでいいと思います。UIImageClass Referenceで、サポートできるファイル形式とimageWithDataを示しています。これは、ファイルからのデータである可能性があり、動作するように聞こえます。
progrmr

@Daniel:動作しませんでした。質問を編集して、実際のコードと例外情報を含めました。それは少し奇妙です。
progrmr 2010年

@Daniel:渡したNSStringの代わりに文字列定数を使用すると機能します。この最新の問題は、NSString / NSData / UIImageコードの問題ではなく、NSStringの問題でした。ダニエル、ありがとう!
progrmr 2010年

1つの画像のみを使用していて、簡単な修正を探している場合は、1つの画像をキャッシュするコードを少し書くだけです。
MrDatabase

27

あなたはSDWebImageを試すことができます、それは提供します:

  1. 非同期読み込み
  2. オフラインで使用するためのキャッシュ
  3. ロード中に表示されるプレースホルダー画像
  4. UITableViewとうまく連携します

簡単な例:

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

2
このライブラリを少し変更し、UIImage + Resizeと統合して、サイズ変更/切り抜き機能を追加しました。必要な場合は、github.com / toptierlabs / ImageCacheResize
Tony

1
この例では、UIImageViewSDWebImageまた、UIImageを使用して直接データを入力することもできますSDWebImageManager - (void) downloadWithURL:...。彼らの例を読んでください。
bendytree

10

そして迅速なバージョン:

   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)

7

あなたがしている場合は、本当に、絶対にプラスに必ずNSURLは、ファイルのURLであること、すなわち[url isFileURL]、あなたの場合にはtrueを返すことが保証され、その後、あなたは簡単に使用することができます。

[UIImage imageWithContentsOfFile:url.path]

7

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

上で述べたように、最近考慮すべきもう1つの優れたライブラリはHanekeです(残念ながら、それほど軽量ではありません)。


1
SDWebImageはObjective-Cで最も人気のあるライブラリで、KingFisherはSwiftの移植版です。
XY

1
Trueですが、DLImageLoaderの方が優れています!:)
Fattie

5

次のコードを試してください。画像の読み込みを設定できるので、ユーザーはアプリが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"];
            }
        });
    });

2
サードパーティのフレームワークをロードしたり、データロードキューをインスタンス化したりする必要がないため、このソリューションを
選択しました。– BillyRayCyrus

4

こちらでAsyncImageView提供されているものを確認してください。いくつかの優れたサンプルコードであり、「そのまま」使用することもできます。


興味深い例ですが、前の回答で述べたAppleのLazyTableImagesの例と概念はよく似ています。
progrmr

これは似ていますが、AsyncImageViewが実際にはテーブルで機能しないことに注意してください。少なくとも、(必要に応じて)テーブルセルをリサイクルするときは機能しません。
n13

4

AFNetworkingは、プレースホルダーのサポートにより、UIImageViewへの非同期画像の読み込みを提供します。また、一般的にAPIを操作するための非同期ネットワーキングもサポートしています。


3

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];

2

Swift Extensionを使用して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()
    }
}

0

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];
    });
});

置き換えimgUrlあなたによってImageURL
置き換えimgViewあなたのことでUIImageView

別のスレッドで画像を読み込むので、アプリの読み込みが遅くなることはありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.