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 , 전달 ,-[NSObject does notRecognizeSelector] 를 호출하는 URLWithString을 호출합니다 .

내 NSString (photoURL의 주소는 0x536fbe0)이 길이에 응답하지 않는 이유가 있습니까? -[NSURL 길이]에 응답하지 않는 이유는 무엇입니까? param이 NSURL이 아닌 NSString이라는 것을 모르십니까?

편집 2


코드의 유일한 문제는 문자열을 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

DLImageLoader 라이브러리는 믿을 수 없습니다. 견고하고 도코가 없으며 하나의 명령으로 모든 것이 완벽합니다. 이게 뭐야
Fattie

나는 두 번째 (세 번째?) DLImageLoader입니다. 이 페이지에 대한 의견이 객관적인지 여부에 대해 회의적이었습니다. 그러나 어쨌든 시도해 보았으며 매우 잘 작동합니다. UITableViewCell 내에 UIImageView가 있습니다. UIImageView를 DLImageView로 바꾸고 imageFromUrl : 메소드를 호출하여 이미지를로드하기 만하면 비동기 로딩, 캐싱 등 모든 것이 작동합니다.
itnAAnti

DLImageLoader는 여전히 환상적이며, 또 다른 좋은 하나는 Haneke 입니다.
Fattie

답변:


319

이 방법으로 (동기식이지만 컴팩트하게) 할 수 있습니다.

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

훨씬 더 좋은 방법은 Apple의 LazyTableImage를 사용하여 대화 형 기능을 유지하는 것입니다.


1
데이터를 PNG (또는 JPG) 파일 형식에서 UIImage 데이터로 변환 할 필요가 없습니까? 아니면 UIImage가 어떻게 든 알아낼 수 있습니까?
progrmr

2
RTFM을 사용해야한다고 생각합니다 .UIImage 클래스 참조에서 지원 할 수있는 파일 형식과 imageWithData : 파일의 데이터 일 수 있으며 작동하는 것처럼 들립니다.
progrmr

@Daniel : 작동하지 않았습니다. 실제 코드와 예외 정보를 포함하도록 질문을 편집했습니다. 조금 기괴하다.
progrmr

@Daniel : 전달한 NSString 대신 문자열 상수를 사용하면 작동합니다. 따라서이 최신 문제는 NSString / NSData / UIImage 코드의 문제가 아닌 NSString의 문제입니다. 고마워 다니엘!
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 + 크기 조정과 통합했습니다. 필요한 경우 github.com/toptierlabs/ImageCacheResize
Tony

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]귀하의 경우에 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
        }
    }];

위에서 언급했듯이 요즘 고려해야 할 또 다른 훌륭한 도서관은 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
는 등, 데이터 로딩 큐를 어떤 제 3 자 프레임 워크를로드하거나 인스턴스화 필요로하지 않았기 때문에 나는이 솔루션을 선호
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(소스 코드 here ) :

관련 컴퓨팅 속성 생성 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.