Bir URL'den bir UIImage yükleyebilir miyim?


134

Bir görüntü için bir URL var (UIImagePickerController aldım) ama artık bellekte görüntü yok (URL, uygulamanın önceki bir çalıştırmadan kaydedildi). UIImage'ı URL'den tekrar yükleyebilir miyim?

UIImage bir imageWithContentsOfFile olduğunu görüyorum: ama bir URL var. URL'yi okumak için NSData'nın dataWithContentsOfURL: yöntemini kullanabilir miyim?

Edit1


@ Daniel'in cevabına dayanarak aşağıdaki kodu denedim ama çalışmıyor ...

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

Ne zaman koştu konsol gösterir:

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

Çağrı yığınına baktığımda, URLWithString: relativeToURL:, sonra initWithString: relativeToURL:, ardından _CFStringIsLegalURLString, sonra CFStringGetLength, sonra yönlendirme_Crep_0 , sonra yönlendirme , ardından - [NSObject], [NSObject]

NSString'imin (photoURL adresi 0x536fbe0) neden uzunlamasına yanıt vermediğine dair bir fikrin var mı? Neden yanıt vermediğini söylüyor - [NSURL uzunluğu]? Param'in bir NSURL değil, bir NSString olduğunu bilmiyor mu?

EDIT2


Tamam, kodla ilgili tek sorun dizeden URL'ye dönüşümdür. Dizeyi sabit kodluyorsam, her şey iyi çalışıyor. Bu yüzden NSString'imle ilgili bir sorun var ve eğer anlayamıyorsam, sanırım bu farklı bir soru olarak girmeli. Bu satır eklendiğinde (yukarıdaki konsol günlüğünden yolu yapıştırdım), iyi çalışıyor:

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

Görünüşe göre photoURL, NSLog'un ele aldığı göz önüne alındığında, bir NSString değil, zaten bir NSURL gibi görünüyor.
drawnonward

@drawn: Dokümanlardaki bir hata gibi görünüyor. UIImagePickerControllerMediaURL bir NSString olduğunu ancak aslında bir NSURL nesnesi olduğunu söylüyor.
progrmr

DLImageLoader kütüphanesi İNANILMAZ. kaya gibi sağlam, doco yok, bir komut ve her şey mükemmel. Ne bulmak.
Fattie

İkinci (üçüncü?) DLImageLoader. Bu sayfadaki yorumların objektif olup olmadığı konusunda şüpheliydim - ama yine de denedim ve çok güzel çalışıyor. Bir UITableViewCell içinde bir UIImageView var. Tüm yaptığım UIImageView yerine bir DLImageView, daha sonra görüntüyü yüklemek için imageFromUrl: yöntemi denilen oldu ve hepsi işe yarıyor - asenkron yükleme, önbellekleme, vb. Daha kolay olamazdı.
itnAAnti

DLImageLoader iyi bir tanesidir, fantastik kalır Haneke oldukça korunmaz olmaktan biraz düşer rağmen.
Fattie

Yanıtlar:


319

Bunu şu şekilde yapabilirsiniz (senkronize, ancak kompakt):

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

Çok daha iyi bir yaklaşım, etkileşimi korumak için Apple'ın LazyTableImages'ı kullanmaktır.


1
Verilerin PNG (veya JPG) dosya biçiminden UIImage verilerine dönüştürülmesi gerekmez mi? Yoksa UIImage bunu bir şekilde anlıyor mu?
progrmr

2
Sanırım sadece RTFM gerekir, doğru UIImage Sınıf Referans hangi dosya formatlarını destekleyebilir diyor ve imageWithData: bir dosyadan veri olabilir diyor, çalışması gerektiği gibi geliyor.
progrmr

@Daniel: işe yaramadı, sorumu gerçek kodumu ve istisna bilgilerini içerecek şekilde düzenledim. Biraz tuhaf.
progrmr

@Daniel: Ben geçiyordu NSString yerine bir dize sabiti kullanırsanız çalışır. Bu son sorun benim NSString ile yanlış bir şey oldu, çalışan NSURL / NSData / UIImage kodu ile ilgili bir sorun değil. Teşekkürler Daniel!
progrmr

Yalnızca bir resim kullanıyorsanız ve hızlı bir düzeltme arıyorsanız, tek resmi önbelleğe alan biraz kod yazabilirsiniz.
MrDatabase

27

SDWebImage'ı deneyebilirsiniz, şunları sağlar:

  1. Eşzamansız yükleme
  2. Çevrimdışı kullanım için önbellekleme
  3. Yükleme sırasında görünecek tutucu resmi yerleştirin
  4. UITableView ile iyi çalışır

Hızlı örnek:

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

2
Bu kütüphaneyi biraz değiştirdim ve Resize / Crop yeteneklerini eklemek için UIImage + Resize ile entegre ettim. Eğer buna ihtiyacınız varsa github.com/toptierlabs/ImageCacheResize
Tony

1
Bu örnekte a UIImageView. SDWebImageayrıca UIImagedoğrudan kullanarak doldurmanıza olanak tanır SDWebImageManager - (void) downloadWithURL:.... Beni oku örneklerini inceleyin.
bendytree

10

Ve hızlı sürüm:

   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

Eğer ediyorsanız gerçekten , kesinlikle olumlu emin NSURL bir dosya url olduğunu, yani [url isFileURL]sizin durumunuzda gerçek dönmek garantilidir, o zaman basitçe kullanabilirsiniz:

[UIImage imageWithContentsOfFile:url.path]

7

olsun DLImageLoader ve kodu folowing deneyin

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

                          }];

Birisine yardımcı olabilecek DLImageLoader'ı kullanmanın başka bir gerçek dünya örneği ...

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

Yukarıda bahsettiğim gibi, bu günlerde dikkate alınması gereken bir başka büyük kütüphane Haneke (ne yazık ki hafif değil).


1
SDWebImage, Objective-C'deki en popüler kütüphane ve KingFisher Swift portudur.
XY

1
Doğru, ancak DLImageLoader daha iyi! :)
Fattie

5

Bu kodu deneyin, onunla yükleme resmi ayarlayabilirsiniz, böylece kullanıcılar uygulamanızın url'den bir resim yüklediğini bilir:

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
Bu çözümü, herhangi bir üçüncü taraf çerçevesinin yüklenmesini veya veri yükleme kuyruklarının vb.
Başlatılmasını

4

BuradaAsyncImageView sağlanan göz atın . Bazı iyi örnek kodlar ve sizin için "kutunun dışında" kullanılabilir.


İlginç bir örnek olarak, Apple'ın önceki yanıtta bahsedilen LazyTableImages örneğine çok benzer.
progrmr

Buna benzer, ancak AsyncImageView'ın gerçekten tablolarda çalışmadığına dikkat edin, en azından tablo hücrelerini geri dönüştürdüğünüzde değil (gerektiği gibi).
n13

4

AFNetworking , yer tutucu desteği ile bir UIImageView'e eşzamansız görüntü yüklemesi sağlar. Ayrıca genel olarak API'lerle çalışmak için zaman uyumsuz ağ oluşturmayı da destekler.


3

Bu ayarları iOS 9'dan etkinleştirdiğinizden emin olun:

Uygulama Taşıma Güvenlik Ayarları içinde Info.plist o indirme resmi izin ve ayarlayın, böylece URL'den Yükleme resmini sağlamak için.

resim açıklamasını buraya girin

Ve şu kodu yazın:

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

2

Bir Swift kullanarak yolu Uzatma için UIImageView(kaynak kodu burada ):

Associated için Hesaplanmış Özellik Oluşturma 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()
            })
        }
    }

Özel Başlatıcı ve Ayarlayıcı

    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

Resmi Url ile yüklemenin en iyi ve kolay yolu şu Kod'dur:

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

Değiştir imgUrlsenin tarafından ImageURL
yerine imgViewİSS'niz tarafından UIImageView.

Görüntüyü başka bir iş parçacığına yükler, bu nedenle Uygulama yükünüzü yavaşlatmaz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.