Чи можу я завантажити URL-адресу UII з URL-адреси?


134

У мене є URL-адреса для зображення (отримано його від UIImagePickerController), але я більше не маю цього зображення в пам'яті (URL-адресу було збережено з попереднього запуску програми). Чи можу я знову завантажити UIImage з URL-адреси?

Я бачу, що UIImage має зображенняWithContentsOfFile: але у мене є URL. Чи можу я використовувати дані NSDataWithContentsOfURL: для читання URL-адреси?

EDIT1


на основі відповіді @ Даніеля я спробував наступний код, але він не працює ...

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: RelaToURL:, потім initWithString: RelaToURL:, потім _CFStringIsLegalURLString, потім CFStringGetLength, потім переадресація_преп_0 , потім переадресація , потім - [NSObco,

Будь-які ідеї, чому мій NSString (адреса photoURL 0x536fbe0) не відповідає довжині? Чому він каже, що не відповідає - [довжина NSURL]? Хіба не знає, що парам - це NSString, а не NSURL?

EDIT2


Гаразд, єдина проблема з кодом - це перетворення рядка в URL. Якщо я жорстко кодую рядок, все інше працює добре. Так що з моїм NSString щось не так, і якщо я не можу цього розібратися, я думаю, це повинно виникнути як інше питання. З цим вставленим рядком (я вставив шлях із журналу консолі вище), він працює добре:

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

Здається, що photoURL - це вже NSURL, а не NSString, враховуючи, що NSLog цим керував.
розіграш

@drawn: Схоже на помилку в документах. Це говорить про те, що UIImagePickerControllerMediaURL - це NSString, але насправді це об’єкт NSURL.
progrmr

Бібліотека DLImageLoader НЕВЕРЕЗНА. рок-солід, без доко, одна команда і все ідеально. Яка знахідка.
Fattie

I другий (третій?) DLImageLoader. Я скептично ставився до того, чи були коментарі щодо цього на цій сторінці об’єктивними - але я все-таки спробував це, і це працює дуже добре. У мене є UIImageView в UITableViewCell. Все, що я зробив, було замінити UIImageView на DLImageView, потім зателефонував метод imageFromUrl: для завантаження зображення, і все це просто працює - асинхронне завантаження, кешування тощо. Не може бути простіше.
itnAAnti

DLImageLoader залишається фантастичним, ще одним хорошим є Ханеке , хоча це трохи страждає від того, що він не дуже підтримується.
Фетті

Відповіді:


319

Ви можете це зробити так (синхронно, але компактно):

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

Набагато кращий підхід полягає у використанні Apple LazyTableImages для збереження інтерактивності.


1
Чи не потрібно перетворювати дані з формату файлів PNG (або JPG) у дані UIImage? Або UIImage зрозуміє це якось?
progrmr

2
Зрозуміло, я повинен просто RTFM, він прямо говорить у довідці про клас UIImage, які формати файлів він може підтримувати та imageWithData: каже, що це можуть бути дані з файлу, схоже, що це має працювати.
progrmr

@Daniel: не вийшло, я змінив своє запитання, щоб включити власний код та інформацію про виключення. Це трохи химерно.
progrmr

@Daniel: це спрацьовує, якщо я використовую константу рядка замість NSString, в який я проходив. Отже, ця остання проблема була з моїм NSString щось не так, а не з кодом NSURL / NSData / UIImage, який працює. Дякую Даніелю!
progrmr

Якщо ви використовуєте лише одне зображення і шукаєте швидке виправлення, ви можете просто написати трохи коду, який кеширує одне зображення.
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, щоб додати до неї можливості Resize / Crop. Якщо вам потрібно це перевірити на веб-
Тоні,

1
Цей приклад заповнює а UIImageView. SDWebImageтакож дозволяє заповнити 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]гарантовано повертає істину в вашому випадку, то ви можете просто використовувати:

[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
SDWebImage - найпопулярніша бібліотека в Objective-C, а KingFisher - порт Swift.
XY

1
Щоправда, але 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 з підтримкою заповнювачів. Він також підтримує мережу async для роботи з 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 до 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.

Він завантажить зображення в іншу нитку, тому це не сповільнить завантаження програми.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.