Bisakah saya memuat UIImage dari URL?

134

Saya memiliki URL untuk gambar (mendapatkannya dari UIImagePickerController) tetapi saya tidak lagi memiliki gambar dalam memori (URL disimpan dari menjalankan aplikasi sebelumnya). Bisakah saya memuat ulang UIImage dari URL lagi?

Saya melihat bahwa UIImage memiliki imageWithContentsOfFile: tetapi saya memiliki URL. Bisakah saya menggunakan data NSDataWithContentsOfURL: untuk membaca URL?

EDIT1


berdasarkan jawaban @ Daniel saya mencoba kode berikut tetapi tidak berhasil ...

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

Ketika saya menjalankannya konsol menunjukkan:

-[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'

Melihat tumpukan panggilan, saya memanggil URLWithString, yang memanggil URLWithString: relatifToURL :, lalu initWithString: relatifToURL :, lalu _CFStringIsLegalURLString, lalu CFStringGetLength, lalu meneruskan , _ forward , bukan proyek.

Adakah ide mengapa NSString saya (alamat photoURL 0x536fbe0) tidak menanggapi panjang? Mengapa dikatakan tidak merespons - [Panjang NSURL]? Tidakkah ia tahu bahwa param adalah NSString, bukan NSURL?

EDIT2


OK, satu-satunya masalah dengan kode adalah konversi string ke URL. Jika saya hardcode string, semuanya berjalan dengan baik. Jadi ada yang salah dengan NSString saya dan jika saya tidak bisa mengetahuinya, saya kira itu harus masuk sebagai pertanyaan yang berbeda. Dengan baris ini dimasukkan (saya menempel jalur dari konsol log di atas), itu berfungsi dengan baik:

photoURL = @"file://localhost/Users/gary/Library/Application%20Support/iPhone%20Simulator/3.2/Media/DCIM/100APPLE/IMG_0004.JPG";
program
sumber
Sepertinya photoURL sudah menjadi NSURL, bukan NSString, mengingat NSLog menanganinya.
ditarik
@ditarik: Sepertinya ada kesalahan dalam dokumen. Dikatakan bahwa UIImagePickerControllerMediaURL adalah NSString tetapi sebenarnya objek NSURL.
program
Pustaka DLImageLoader LUAR BIASA. kokoh, tidak ada doko, satu perintah dan semuanya sempurna. Temukan apa.
Fattie
Saya kedua (ketiga?) DLImageLoader. Saya ragu apakah komentar tentang hal ini di halaman ini objektif - tetapi saya tetap mencobanya dan itu bekerja dengan sangat baik. Saya memiliki UIImageView dalam UITableViewCell. Yang saya lakukan adalah mengganti UIImageView dengan DLImageView, lalu memanggil metode imageFromUrl: untuk memuat gambar, dan semuanya berfungsi - pemuatan asinkron, caching, dll. Tidak bisa lebih mudah.
itnAAnti
DLImageLoader tetap fantastis, satu lagi yang bagus adalah Haneke , meskipun sedikit menderita karena tidak terawat.
Fattie

Jawaban:

319

Anda dapat melakukannya dengan cara ini (secara sinkron, tetapi kompak):

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

Pendekatan yang jauh lebih baik adalah dengan menggunakan LazyTableImages Apple untuk menjaga interaktivitas.

Daniel Blezek
sumber
1
Tidakkah data perlu dikonversi dari format file PNG (atau JPG) ke data UIImage? Atau apakah UIImage mengetahui hal itu?
program
2
Tebak saya seharusnya hanya RTFM, ia mengatakan tepat di UIImage Class Reference format file apa yang dapat didukung dan imageWithData: mengatakan itu bisa berupa data dari file, sepertinya itu harus bekerja.
progrmr
@Aniel: tidak berfungsi, saya mengedit pertanyaan saya untuk memasukkan kode aktual dan info pengecualian. Agak aneh.
program
@Aniel: itu berfungsi jika saya menggunakan string konstan bukan NSString saya lewat. Jadi masalah terbaru ini ada yang salah dengan NSString saya, bukan masalah dengan kode NSURL / NSData / UIImage yang berfungsi. Daniel terima kasih!
program
Jika Anda hanya menggunakan satu gambar dan Anda sedang mencari perbaikan cepat, Anda bisa menulis sedikit kode yang menyimpan gambar tunggal.
MrDatabase
27

Anda dapat mencoba SDWebImage , ini menyediakan:

  1. Pemuatan asinkron
  2. Caching untuk penggunaan offline
  3. Tempatkan gambar dudukan untuk ditampilkan saat memuat
  4. Bekerja dengan baik dengan UITableView

Contoh cepat:

    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
Muhammad Hassan Nasr
sumber
2
Saya telah memodifikasi perpustakaan itu sedikit dan mengintegrasikannya dengan UIImage + Ubah Ukuran untuk menambahkan kemampuan Ubah Ukuran / Potong ke dalamnya. Jika Anda memerlukannya, periksa di github.com/toptierlabs/ImageCacheResize
Tony
1
Contoh ini mengisi a UIImageView. SDWebImagejuga memungkinkan Anda mengisi UIImagelangsung menggunakan SDWebImageManager - (void) downloadWithURL:.... Lihat contoh mereka di baca saya.
bendytree
10

Dan versi cepat:

   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)
pengguna3763002
sumber
7

Jika Anda benar-benar , benar-benar positif yakin bahwa NSURL adalah url file yaitu [url isFileURL]dijamin untuk kembali benar dalam kasus Anda, maka Anda dapat menggunakan:

[UIImage imageWithContentsOfFile:url.path]
Dhiraj Gupta
sumber
7

dapatkan DLImageLoader dan coba kode berikut

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

                          }];

Contoh dunia nyata tipikal lainnya menggunakan DLImageLoader, yang dapat membantu seseorang ...

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

Seperti yang saya sebutkan di atas perpustakaan besar lain untuk mempertimbangkan hari ini adalah Haneke (sayangnya itu tidak ringan).

Muruganandham K
sumber
1
SDWebImage adalah perpustakaan paling populer di Objective-C dan KingFisher adalah port Swift.
XY
1
Benar, tetapi DLImageLoader lebih baik! :)
Fattie
5

Coba kode ini, Anda dapat mengatur memuat gambar dengan itu, sehingga pengguna tahu bahwa aplikasi Anda memuat gambar dari 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"];
            }
        });
    });
Jouhar
sumber
2
Saya lebih suka solusi ini karena tidak memerlukan pemuatan kerangka kerja pihak ke-3 atau instantiasi antrian pemuatan data, dll.
BillyRayCyrus
4

Lihat yang AsyncImageViewdisediakan di sini . Beberapa kode contoh yang baik, dan bahkan dapat digunakan langsung "di luar kotak" untuk Anda.

marcc
sumber
Contoh menarik, konsepnya sangat mirip dengan contoh LazyTableImages Apple yang disebutkan dalam jawaban sebelumnya.
program
Ini serupa tetapi berhati-hatilah karena AsyncImageView benar-benar tidak berfungsi dalam tabel, setidaknya tidak ketika Anda mendaur ulang sel tabel (seperti yang seharusnya).
n13
4

AFNetworking menyediakan pemuatan gambar async ke dalam UIImageView dengan dukungan placeholder. Ini juga mendukung jaringan async untuk bekerja dengan API secara umum.

pauliephonic
sumber
3

Pastikan untuk mengaktifkan pengaturan ini dari iOS 9:

Pengaturan Keamanan Transport Aplikasi di Info.plist untuk memastikan memuat gambar dari URL sehingga memungkinkan unduhan gambar dan mengaturnya.

masukkan deskripsi gambar di sini

Dan tulis kode ini:

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

Cara menggunakan Swift Extension to UIImageView(kode sumber di sini ):

Membuat Properti Terhitung untuk Associated 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()
            })
        }
    }

Initializer dan Setter Kustom

    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()
    }
}
fpg1503
sumber
0

Cara terbaik dan mudah untuk memuat Gambar melalui Url adalah dengan Kode ini:

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

Ganti imgUrldengan Anda ImageURL
Ganti imgViewdengan Anda UIImageView.

Itu akan memuat gambar di utas lain, jadi itu tidak akan memperlambat beban aplikasi Anda.

jalmatari
sumber