Swift의 URL에서 이미지로드 / 다운로드


412

내 응용 프로그램의 URL에서 이미지를로드하고 싶습니다. 먼저 Objective-C로 시도했지만 Swift에서는 컴파일 오류가 발생했습니다.

'imageWithData'를 사용할 수 없습니다 : 객체 생성 사용 'UIImage (data :)'

내 기능 :

@IBOutlet var imageView : UIImageView

override func viewDidLoad() {
    super.viewDidLoad()

    var url:NSURL = NSURL.URLWithString("http://myURL/ios8.png")
    var data:NSData = NSData.dataWithContentsOfURL(url, options: nil, error: nil)

    imageView.image = UIImage.imageWithData(data)// Error here
}

Objective-C에서 :

- (void)viewDidLoad {
    [super viewDidLoad];

    NSURL *url = [NSURL URLWithString:(@"http://myURL/ios8.png")];
    NSData *data = [NSData dataWithContentsOfURL:url];

    _imageView.image = [UIImage imageWithData: data];
    _labelURL.text = @"http://www.quentinroussat.fr/assets/img/iOS%20icon's%20Style/ios8.png";
 }

누군가 imageWithData:Swift와 작동하지 않는 이유를 설명 하고 문제를 어떻게 해결할 수 있습니까 ?


3
이것을 시도imageURL.image = UIImage(data: myDataVar)
aleclarson

완벽하게 작동했습니다! 감사합니다. 그러나이 방법이 Swift가 아닌 Objective C에서 작동하는 이유는 없습니다 ... Strange
QuentR

Cocoa 클래스에 문제가있을 때 CMD + 클래스 이름을 클릭하면 클래스의 Swift 인터페이스를 볼 수 있습니다!
aleclarson

3
if url = NSURL (string : "imageurl") {if let data = NSData (contentsOfURL : url) {imageView.image = UIImage (data : data)}}
Hardik Bar

2
@Leo Dabus이 질문은 Swift 2에만 국한된 것이 아닙니다. 해당 태그 추가를 중단하십시오.
Mick MacCallum

답변:


769

Xcode 8 이상 • Swift 3 이상

동 기적으로 :

if let filePath = Bundle.main.path(forResource: "imageName", ofType: "jpg"), let image = UIImage(contentsOfFile: filePath) {
    imageView.contentMode = .scaleAspectFit
    imageView.image = image
}

비동기 적으로 :

URL에서 이미지 데이터를 가져 오기 위해 완료 핸들러로 메소드를 작성하십시오.

func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
    URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
}

이미지 다운로드 방법 생성 (작업 시작)

func downloadImage(from url: URL) {
    print("Download Started")
    getData(from: url) { data, response, error in
        guard let data = data, error == nil else { return }
        print(response?.suggestedFilename ?? url.lastPathComponent)
        print("Download Finished")
        DispatchQueue.main.async() { [weak self] in
            self?.imageView.image = UIImage(data: data)
        }
    }
}

용법:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    print("Begin of code")
    let url = URL(string: "https://cdn.arstechnica.net/wp-content/uploads/2018/06/macOS-Mojave-Dynamic-Wallpaper-transition.jpg")! 
    downloadImage(from: url)
    print("End of code. The image will continue downloading in the background and it will be loaded when it ends.")
}

연장 :

extension UIImageView {
    func downloaded(from url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {  // for swift 4.2 syntax just use ===> mode: UIView.ContentMode
        contentMode = mode
        URLSession.shared.dataTask(with: url) { data, response, error in
            guard
                let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
                let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
                let data = data, error == nil,
                let image = UIImage(data: data)
                else { return }
            DispatchQueue.main.async() { [weak self] in
                self?.image = image
            }
        }.resume()
    }
    func downloaded(from link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {  // for swift 4.2 syntax just use ===> mode: UIView.ContentMode
        guard let url = URL(string: link) else { return }
        downloaded(from: url, contentMode: mode)
    }
}

용법:

imageView.downloaded(from: "https://cdn.arstechnica.net/wp-content/uploads/2018/06/macOS-Mojave-Dynamic-Wallpaper-transition.jpg")

13
여기서 단지 참고로, 관련 개체를 설정해야합니다. 그렇지 않으면 이미지를 서로로드 할 수 있습니다. 예를 들어 UITableView셀에 이미지가 표시되고 대기열에서 제외 된 셀이 반환되면 이미지가 업데이트됩니다. 프로세스 # 1이 프로세스 # 2보다 시간이 오래 걸리면 프로세스 # 2는 이미지를 표시하고 나중에 해당 이미지가 사용자에게 더 이상 유효하지 않더라도 프로세스 # 1에 의해 업데이트됩니다.
Paul Peelen

1
이것은 내 문제를 해결했습니다. 테이블보기에서 URL이있는 이미지를로드하려고하면 스크롤보기가 위 또는 아래로 스크롤 할 때 실제로 응답하지 않습니다. UIImageView Extension을 사용하여 문제를 해결했습니다. 감사.
JengGe Chao

1
@LeoDabus 감사합니다. SO에 대한 많은 질문에 답변 해 주셔서 감사합니다! 당신은 스위프트와 iOS의 교수와 같습니다. :)
Crashalot

2
@ LeoDabus는 downloadTaskWithURL 대신 dataTaskWithURL을 어떻게 사용 했습니까?
Crashalot

3
첫 번째 파일을 메모리로 다운로드하고 두 번째 파일을 파일로 다운로드
Leo Dabus

349

(Swift 4 업데이트) 원래 질문에 직접 대답하기 위해 게시 된 Objective-C 스 니펫과 동일한 기능을 제공합니다.

let url = URL(string: image.url)
let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
imageView.image = UIImage(data: data!)

기권:

Data(contentsOf:)메소드는 코드가 실행되는 동일한 스레드에서 URL의 컨텐츠를 동 기적 으로 다운로드 하므로 애플리케이션의 기본 스레드에서이를 호출 하지 마십시오 .

UI를 차단하지 않고 동일한 코드를 비동기식으로 실행하는 쉬운 방법은 GCD를 사용하는 것입니다.

let url = URL(string: image.url)

DispatchQueue.global().async {
    let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
    DispatchQueue.main.async {
        imageView.image = UIImage(data: data!)
    }
}

즉, 실제 응용 프로그램에서 최상의 사용자 경험을 원하고 동일한 이미지를 여러 번 다운로드하지 않으려면 다운로드뿐만 아니라 캐시해야 할 수도 있습니다. 이미 매우 매끄럽고 사용하기 쉬운 라이브러리가 많이 있습니다. 개인적으로 Kingfisher를 추천합니다 :

import Kingfisher

let url = URL(string: "url_of_your_image")
// this downloads the image asynchronously if it's not cached yet
imageView.kf.setImage(with: url) 

그리고 그게 다야


12
"쉽게"는 주관적이며 초보 코더는 원치 않는 동작을 예상하지 않지만 그대로 복사 / 붙여 넣기합니다. 아마도 답변을 업데이트 할 수 있습니까?
Orlin Georgiev

13
나는 여전히 동의하지 않습니다. 일부 답변은 간단하게 유지해야하며 여기에 오는 많은 사람들이 작은 코드 스 니펫을 복사하여 붙여 넣기를 좋아합니다. 방금 원래 질문에서 objective-C 코드를 Swift로 번역했는데 그 외에도 모든 것이 보너스입니다. 그런데 이런 종류의 보너스 정보를 제공하는 동일한 질문에 대한 답변이 이미 있습니다. 정보를 복제하는 것은 의미가 없습니다.
Lucas Eduardo

1
@User image.url는 하드 코딩 된이든 아니든 모든 문자열 URL로 대체합니다.
Lucas Eduardo

1
@IanWarburton 물론 원하는대로 사용할 수 있습니다 :). 1)이 답변은 objective-C에서 동일한 접근 방식을 사용하고 있던 원래의 질문을 바탕으로 한 것이므로, "번역"을 신속하게 도와주었습니다. 2)이 접근법을 제거하고 URLSession.dataTask여기에 많은 다른 답변이 이미 수행 방법을 보여주기 때문에 합리적이지 않습니다 . 다른 옵션을 열어 두는 것이 좋습니다.
Lucas Eduardo

2
답변에 명시된 바와 같이 제안 된 프레임 워크 인 Kingfisher는 모든 무거운 작업을 수행합니다. 제안 해 주셔서 감사합니다!
Kilmazing

68

이미지를 비동기식 으로로드 하려면 빠른 코드 에이 작은 확장을 추가하십시오.

extension UIImageView {
    public func imageFromUrl(urlString: String) {
        if let url = NSURL(string: urlString) {
            let request = NSURLRequest(URL: url)
            NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {
                (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in
                if let imageData = data as NSData? {
                    self.image = UIImage(data: imageData)
                }
            }
        }
    }
}

그리고 이런 식으로 사용하십시오 :

myImageView.imageFromUrl("https://robohash.org/123.png")

1
그것은 나타나지 않고 GCD가 필요하기 때문에 생각합니다. 어떻게 새로 고치나요?
jo3birdtalk

@ jo3birdtalk 그것은 GCD의 문제가 아닙니다. 바인딩을 확인하십시오.
skywinder

6
NSURLConnection은 iOS 9 등에서 더 이상 사용되지 않습니다. NSURLSession intead를 사용하십시오.
muhasturk

2
sendAsynchronousRequest는 iOS 9에서 사용되지 않습니다
Crashalot

고맙습니다 skywinder, 배열에서 이미지를 다운로드하는 데이 방법을 사용하고 있습니다. 사용자가 cancel버튼 을 누르면 다운로드가 중지 되고 싶습니다 . 이 방법을 사용하여 어떻게이 작업을 수행 할 수 있는지 알고 있습니까? 취소 기능을 추가해야합니다.
ZAFAR007

44

스위프트 2.2 || Xcode 7.3

나는 놀라운 결과를 얻었다 !! 와 AlamofireImage의 빠른 라이브러리

다음과 같은 여러 기능을 제공합니다.

  • 비동기 적으로 다운로드
  • 앱에 메모리 경고가 발생하면 이미지 캐시 자동 제거
  • 이미지 URL 캐싱
  • 이미지 캐싱
  • 중복 다운로드 방지

앱을 구현하기가 매우 쉽습니다.

1 단계 포드 설치


알라모 파이어 3.3.x

포드 'Alamofire'

AlamofireImage 2.4.x

포드 'AlamofireImage'

2 단계 가져 오기 및 사용

import Alamofire
import AlamofireImage

let downloadURL = NSURL(string: "http://cdn.sstatic.net/Sites/stackoverflow/company/Img/photos/big/6.jpg?v=f4b7c5fee820")!
imageView.af_setImageWithURL(downloadURL)

그게 다야 !! 그것은 모든 것을 돌볼 것입니다


iDevelopers의 삶 을 편하게 해준 Alamofire 녀석들 에게 큰 감사를드립니다 .)


8
스위프트 3 : foregroundImage.af_setImage (withURL : URL로 downloadURL)
thejuki

28

Xcode 8스위프트 3

Leo Dabus의 답변은 대단합니다! 방금 올인원 기능 솔루션을 제공하고 싶었습니다.

let url = URL(string: 
    "http://www.apple.com/euro/ios/ios8/a/generic/images/og.png")

let task = URLSession.shared.dataTask(with: url!) { data, response, error in
    guard let data = data, error == nil else { return }

    DispatchQueue.main.async() {    // execute on main thread
        self.imageView.image = UIImage(data: data)
    }
}

task.resume()

3
Mark, 아마도 거기에 "비동기"를 의미했을 것입니다
Fattie

16

질문에 가장 적합한 답변의 코드를 UIImageView를 확장하는 재사용 가능한 단일 클래스로 래핑하여 스토리 보드에서 비동기 로딩 UIImageView를 직접 사용하거나 코드에서 만들 수 있습니다.

여기 내 수업이 있습니다.

import Foundation
import UIKit

class UIImageViewAsync :UIImageView
{

    override init()
    {
        super.init(frame: CGRect())
    }

    override init(frame:CGRect)
    {
        super.init(frame:frame)
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    func getDataFromUrl(url:String, completion: ((data: NSData?) -> Void)) {
        NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: url)!) { (data, response, error) in
            completion(data: NSData(data: data))
        }.resume()
    }

    func downloadImage(url:String){
        getDataFromUrl(url) { data in
            dispatch_async(dispatch_get_main_queue()) {
                self.contentMode = UIViewContentMode.ScaleAspectFill
                self.image = UIImage(data: data!)
            }
        }
    }
}

사용 방법은 다음과 같습니다.

imageView.downloadImage("http://www.image-server.com/myImage.jpg")

2
재정의 된 사람들이 정말로 필요합니까? 어쨌든 init가 상속되지 않습니까? 우리가 여기서 슈퍼를 호출하기 위해 여기를 재정의하는 것처럼 보입니다.
NYC 기술 엔지니어 3

16

스위프트 4 : :

이미지를로드하는 동안 로더가 표시됩니다. 이미지를 일시적으로 저장 하는 NSCache 를 사용할 수 있습니다

let imageCache = NSCache<NSString, UIImage>()
extension UIImageView {
    func loadImageUsingCache(withUrl urlString : String) {
        let url = URL(string: urlString)
        if url == nil {return}
        self.image = nil

        // check cached image
        if let cachedImage = imageCache.object(forKey: urlString as NSString)  {
            self.image = cachedImage
            return
        }

        let activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView.init(activityIndicatorStyle: .gray)
        addSubview(activityIndicator)
        activityIndicator.startAnimating()
        activityIndicator.center = self.center

        // if not, download image from url
        URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
            if error != nil {
                print(error!)
                return
            }

            DispatchQueue.main.async {
                if let image = UIImage(data: data!) {
                    imageCache.setObject(image, forKey: urlString as NSString)
                    self.image = image
                    activityIndicator.removeFromSuperview()
                }
            }

        }).resume()
    }
}

용법:-

truckImageView.loadImageUsingCache(withUrl: currentTruck.logoString)

1
효과가있다. 오류 발생시 activityIndicator 제거를 복사하십시오.
djdance

1
내 프로젝트에 매우 유용합니다.
partikles

13
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)

5
fatal error: unexpectedly found nil while unwrapping an Optional value
사용자

비동기 적으로 무언가를 작성할 수 있습니까?
Jed Grant

@JedGrant dispatch_async를 사용하여 다른 스레드와 콜백에 들어갈 수 있습니다
Matej

NSData를 "!"로 풀어야했습니다. (끝에!를 참고하십시오) var imageData : NSData = NSData (contentsOfURL : url, 옵션 : NSDataReadingOptions.DataReadingMappedIfSafe, 오류 : & err)!
botbot

13

참고 : swift-2.0 Xcode7.0 beta2의 경우

extension UIImageView {
    public func imageFromUrl(urlString: String) {
        if let url = NSURL(string: urlString) {
            let request = NSURLRequest(URL: url)
            NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {
            (response: NSURLResponse?, data: NSData?, error: NSError?) -> Void in
                self.image = UIImage(data: data!)
            }
        }
    }
}

5
NSURLConnection이 폐기되었습니다. NSURLSession을 사용해야합니다. 그것은 스위프트 2.0 엑스 코드 (7) 더 나은 때 코드의
BilalReffas

10

오류 처리 기능이있는 신속한 3

let url = URL(string: arr[indexPath.row] as! String)
if url != nil {
    DispatchQueue.global().async {
        let data = try? Data(contentsOf: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check / try-catch
        DispatchQueue.main.async {
            if data != nil {
                cell.imgView.image = UIImage(data:data!)
            }else{
                cell.imgView.image = UIImage(named: "default.png")
            }
        }
    }
}

확장

extension UIImageView {

    func setCustomImage(_ imgURLString: String?) {
        guard let imageURLString = imgURLString else {
            self.image = UIImage(named: "default.png")
            return
        }
        DispatchQueue.global().async { [weak self] in
            let data = try? Data(contentsOf: URL(string: imageURLString)!)
            DispatchQueue.main.async {
                self?.image = data != nil ? UIImage(data: data!) : UIImage(named: "default.png")
            }
        }
    }
}

확장 사용법

myImageView. setCustomImage("url")

캐시 지원

let imageCache = NSCache<NSString, UIImage>()

extension UIImageView {

    func loadImageUsingCacheWithURLString(_ URLString: String, placeHolder: UIImage?) {

        self.image = nil
        if let cachedImage = imageCache.object(forKey: NSString(string: URLString)) {
            self.image = cachedImage
            return
        }

        if let url = URL(string: URLString) {
            URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in

                //print("RESPONSE FROM API: \(response)")
                if error != nil {
                    print("ERROR LOADING IMAGES FROM URL: \(String(describing: error))")
                    DispatchQueue.main.async { [weak self] in
                        self?.image = placeHolder
                    }
                    return
                }
                DispatchQueue.main.async { [weak self] in
                    if let data = data {
                        if let downloadedImage = UIImage(data: data) {
                            imageCache.setObject(downloadedImage, forKey: NSString(string: URLString))
                            self?.image = downloadedImage
                        }
                    }
                }
            }).resume()
        }
    }
}

9

스위프트 4 : NSCache를 사용하고 항상 메인 스레드에서 실행되는 작은 이미지 (예 : 썸네일)를위한 간단한 로더

class ImageLoader {

  private static let cache = NSCache<NSString, NSData>()

  class func image(for url: URL, completionHandler: @escaping(_ image: UIImage?) -> ()) {

    DispatchQueue.global(qos: DispatchQoS.QoSClass.background).async {

      if let data = self.cache.object(forKey: url.absoluteString as NSString) {
        DispatchQueue.main.async { completionHandler(UIImage(data: data as Data)) }
        return
      }

      guard let data = NSData(contentsOf: url) else {
        DispatchQueue.main.async { completionHandler(nil) }
        return
      }

      self.cache.setObject(data, forKey: url.absoluteString as NSString)
      DispatchQueue.main.async { completionHandler(UIImage(data: data as Data)) }
    }
  }

}

용법:

ImageLoader.image(for: imageURL) { image in
  self.imageView.image = image
}

구조체와 함께 싱글 톤을 사용하는 이유는 무엇입니까? 이렇게하면 클래스가 변경되지 않아 NSCache에 문제가 발생할 수 있습니다.
XcodeNOOB

이것을 지적 해 주셔서 감사합니다 class. 방금 변경했습니다 .
fethica

1
private let cache에서 오류가 발생하여 정적로 변경하여 작동했습니다! 감사합니다
Hammad Tariq

7

당신은하고 싶을 것입니다 :

UIImage(data: data)

Swift에서는 대부분의 Objective C 팩토리 메소드를 일반 생성자로 대체했습니다.

보다:

https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-XID_26


2
기술적으로 매핑되었으며 교체되지 않았습니다. 자신 만의 메소드 +(instancetype)[MyThing thingWithOtherThing:]를 작성하면 MyThing(otherThing: ...)Swift에서도 호출 할 수 있습니다.
Brian Nickel

7

오류 처리 및 사용자 정의 요청 헤더가있는 스위프트 2

UIImageView에 확장을 추가하기 만하면됩니다.

extension UIImageView {
    public func imageFromUrl(urlString: String) {
        if let url = NSURL(string: urlString) {
            let request = NSMutableURLRequest(URL: url)
            request.setValue("<YOUR_HEADER_VALUE>", forHTTPHeaderField: "<YOUR_HEADER_KEY>")
            NSURLSession.sharedSession().dataTaskWithRequest(request) {
                (data, response, error) in
                guard let data = data where error == nil else{
                    NSLog("Image download error: \(error)")
                    return
                }

                if let httpResponse = response as? NSHTTPURLResponse{
                    if httpResponse.statusCode > 400 {
                        let errorMsg = NSString(data: data, encoding: NSUTF8StringEncoding)
                        NSLog("Image download error, statusCode: \(httpResponse.statusCode), error: \(errorMsg!)")
                        return
                    }
                }

            dispatch_async(dispatch_get_main_queue(), {
                NSLog("Image download success")
                self.image = UIImage(data: data)
            })
            }.resume()
        }
    }
}

그런 다음 새로운 기능 imageFromUrl(urlString: String)을 사용하여 이미지를 다운로드하십시오.

용법:

imageView.imageFromUrl("https://i.imgur.com/ONaprQV.png")

스위프트 3 에서이 오류가 계속 발생합니다. 뭐가 문제 야 ? 이 줄에서 "" "URLSession.shared.dataTask (with : url) {" "" "" "" " '(with : URL, (Data ?, URLResponse ?, Error?) 유형의 인수 목록으로'dataTask '를 호출 할 수 없습니다. )-> 무효) '
Aymen BRomdhane

7

스위프트 4

이 방법은 웹 사이트에서 이미지를 비동기 적으로 다운로드하여 캐시합니다.

    func getImageFromWeb(_ urlString: String, closure: @escaping (UIImage?) -> ()) {
        guard let url = URL(string: urlString) else {
return closure(nil)
        }
        let task = URLSession(configuration: .default).dataTask(with: url) { (data, response, error) in
            guard error == nil else {
                print("error: \(String(describing: error))")
                return closure(nil)
            }
            guard response != nil else {
                print("no response")
                return closure(nil)
            }
            guard data != nil else {
                print("no data")
                return closure(nil)
            }
            DispatchQueue.main.async {
                closure(UIImage(data: data!))
            }
        }; task.resume()
    }

사용:

    getImageFromWeb("http://www.apple.com/euro/ios/ios8/a/generic/images/og.png") { (image) in
        if let image = image {
            let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
            imageView.image = image
            self.view.addSubview(imageView)
        } // if you use an Else statement, it will be in background
    }

캐싱은 어떻습니까? 그리고 얼마나 오래?
Ramis

영구적으로 저장된 것 같습니다. 이상하게도 Library> Caches 폴더에 저장됩니다. 시뮬레이터에서 실행할 때 print (NSHomeDirectory ())를 사용하여 컴퓨터에서이 위치에 도달하십시오.
바비

5

스위프트 2.0 :

1)

if let url = NSURL(string: "http://etc...") {
    if let data = NSData(contentsOfURL: url) {
        imageURL.image = UIImage(data: data)
    }        
}

또는

imageURL.image =
    NSURL(string: "http:// image name...")
    .flatMap { NSData(contentsOfURL: $0) }
    .flatMap { UIImage(data: $0) }

2)이 방법을 VC 또는 확장에 추가하십시오.

func load_image(urlString:String)
{   let imgURL: NSURL = NSURL(string: urlString)!
    let request: NSURLRequest = NSURLRequest(URL: imgURL)

    NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) { (response: NSURLResponse?, data: NSData?, error: NSError?) in

        if error == nil {
            self.image_element.image = UIImage(data: data)
        }
    }
}

사용법 :

self.load_image(" url strig here")

sendAsynchronousRequest는 iOS 9에서 더 이상 사용되지 않습니다
Crashalot

5

Kingfisher는 URL에 이미지를로드하기위한 최고의 라이브러리 중 하나입니다.

Github URL- https: //github.com/onevcat/Kingfisher

// If you want to use Activity Indicator.
imageview_pic.kf.indicatorType = .activity
imageview_pic.kf.setImage(with: URL(string: "Give your url string"))

// If you want to use custom placeholder image.
imageview_pic.kf.setImage(with: URL(string: "Give your url string"), placeholder: UIImage(named: "placeholder image name"), options: nil, progressBlock: nil, completionHandler: nil)

5

다음은 URL에서 이미지를로드 / 다운로드하는 작업 코드입니다. NSCache가 자동으로 다운로드되고 플레이스 홀더 이미지가 다운로드되기 전에 표시되고 실제 이미지로드 (Swift 4 Code).

func NKPlaceholderImage(image:UIImage?, imageView:UIImageView?,imgUrl:String,compate:@escaping (UIImage?) -> Void){

    if image != nil && imageView != nil {
        imageView!.image = image!
    }

    var urlcatch = imgUrl.replacingOccurrences(of: "/", with: "#")
    let documentpath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
    urlcatch = documentpath + "/" + "\(urlcatch)"

    let image = UIImage(contentsOfFile:urlcatch)
    if image != nil && imageView != nil
    {
        imageView!.image = image!
        compate(image)

    }else{

        if let url = URL(string: imgUrl){

            DispatchQueue.global(qos: .background).async {
                () -> Void in
                let imgdata = NSData(contentsOf: url)
                DispatchQueue.main.async {
                    () -> Void in
                    imgdata?.write(toFile: urlcatch, atomically: true)
                    let image = UIImage(contentsOfFile:urlcatch)
                    compate(image)
                    if image != nil  {
                        if imageView != nil  {
                            imageView!.image = image!
                        }
                    }
                }
            }
        }
    }
}

다음과 같이 사용하십시오 :

// Here imgPicture = your imageView
// UIImage(named: "placeholder") is Display image brfore download and load actual image. 

NKPlaceholderImage(image: UIImage(named: "placeholder"), imageView: imgPicture, imgUrl: "Put Here your server image Url Sting") { (image) in }

1
나와 함께 일한 유일한 사람. 내 문제는 내가 음악 플레이어를 구현하고 있었고 전화가 닫히고 처리기가 UIImage 유형을 취할 때 알림에로드 할 이미지를 원했기 때문에이 방법을 사용해야했습니다.
JhonnyTawk

4

안전하고 Swift 2.0 및 X-Code 7.1에서 작동하는 이미지를 얻는 방법 :

static func imageForImageURLString(imageURLString: String, completion: (image: UIImage?, success: Bool) -> Void) {
    guard let url = NSURL(string: imageURLString),
        let data = NSData(contentsOfURL: url),
        let image = UIImage(data: data)
        else { 
            completion(image: nil, success: false); 
            return 
       }

    completion(image: image, success: true)
}

그런 다음이 방법을 다음과 같이 호출하십시오.

imageForImageURLString(imageString) { (image, success) -> Void in
        if success {
            guard let image = image 
                 else { return } // Error handling here 
            // You now have the image. 
         } else {
            // Error handling here.
        }
    }

이미지로보기를 업데이트하는 경우 "성공 {"후에이를 사용해야합니다.

    dispatch_async(dispatch_get_main_queue()) { () -> Void in
         guard let image = image 
              else { return } // Error handling here 
         // You now have the image. Use the image to update the view or anything UI related here
         // Reload the view, so the image appears
    }

UI에서 이미지를 사용하는 경우이 마지막 부분이 필요한 이유는 네트워크 호출에 시간이 걸리기 때문입니다. 위와 같이 dispatch_async를 호출하지 않고 이미지를 사용하여 UI를 업데이트하려고 시도하면 컴퓨터는 이미지를 가져 오는 동안 이미지를 찾고 이미지가없는 것을 발견하고 이미지가없는 것처럼 계속 진행합니다. 녹이다. dispatch_async 완료 클로저 안에 코드를 넣으면 컴퓨터에 "이 이미지를 가져와 완료되면이 코드를 완성하십시오"라고 말합니다. 그렇게하면 코드가 호출 될 때 이미지가 생겨서 잘 작동합니다.


4

매우 간단한 구현을 찾고 있다면. (이것은 스위프트 2에서 나를 위해 일했습니다)

 let imageURL = NSURL(string: "https://farm2.staticflickr.com/1591/26078338233_d1466b7da2_m.jpg")
 let imagedData = NSData(contentsOfURL: imageURL!)!
 imageView?.image = UIImage(data: imagedData)

이미지 만있는 사용자 정의 셀로 테이블 뷰 내에 구현했습니다.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{

        let cell = tableView.dequeueReusableCellWithIdentifier("theCell", forIndexPath: indexPath) as! customTableViewCell

        let imageURL = NSURL(string: "https://farm2.staticflickr.com/1591/26078338233_d1466b7da2_m.jpg")

        let imagedData = NSData(contentsOfURL: imageURL!)!

        cell.imageView?.image = UIImage(data: imagedData)

        return cell

    }

메인 스레드에서 다운로드 및 압축이 발생하기 때문에 당신이 맞습니다. 백그라운드 스레드에서이 두 단계를 비동기식으로 수행하는 것이 이상적입니다. dispatch_async 글로벌 큐를 사용 중일 수 있습니다
Naishta

예, 백그라운드 스레드를 사용하여 다운로드 속도를 최적화 할 수 있으며 필요한 경우이 대신 논리를 변경할 수 있습니다. sdWebImage 또는 기타 프레임 워크를 사용할 수 있습니다.
Gourav Joshi

2

Kingfisher 라이브러리를 사용하여 이미지를 비동기 적으로 다운로드하는 것이 좋습니다. Kingfisher를 사용하는 가장 좋은 부분은 기본적으로 이미지 URL을 id로 사용하여 다운로드 한 모든 이미지를 캐시하는 것입니다. 다음에 특정 URl로 이미지 다운로드를 요청하면 캐시에서 이미지를로드합니다.

용법:

newsImage.kf.setImage(with: imageUrl!, placeholder: nil, options: nil, progressBlock: nil, completionHandler: { (image, error, cacheType, imageUrl) in
                if error == nil{
                    self.activityIndicator.stopAnimating()
                }else if error != nil{
                    self.activityIndicator.stopAnimating()
                }
            })

2

포드 SDWebImage를 사용 하여 동일한 결과를 얻을 수 있습니다 . 사용하기 쉽습니다. SDWebImage에서 문서를 얻을 수 있습니다.

다음은 샘플 코드입니다

self.yourImage.sd_setImage(with: NSURL(string: StrUrl as String ) as URL!, placeholderImage: placeholderImage, options: SDWebImageOptions(rawValue: 0), completed: { (image, error, cacheType, imageURL) in
                if( error != nil)
                {
                    print("Error while displaying image" , (error?.localizedDescription)! as String)
                }
            })

2

스위프트 5

extension UIImageView {
    func load(url: URL) {
        DispatchQueue.global().async { [weak self] in
            if let data = try? Data(contentsOf: url) {
                if let image = UIImage(data: data) {
                    DispatchQueue.main.async {
                        self?.image = image
                    }
                }
            }
        }
    }
}

사용하기 위해

override func awakeFromNib() {
    super.awakeFromNib()
    imgView.load(url: "<imageURLHere>")
}

1

누락 된 유일한 것은입니다!

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!)

답변이 늦어서 죄송합니다. 어떤 오류가 발생했는지 더 정확하게 말씀해 주시겠습니까?
Simon Jensen

1

이미지를 파일로 다운로드하는 Swift 2.x 응답 (이미지를 메모리에 저장하는 Leo Dabus의 응답과 반대) Leo Dabus의 답변과 Rob의 답변에 따라 NSURLSession에서 데이터 가져 오기 DownloadTaskWithRequest from completion handler :

    // Set download vars
    let downloadURL = NSURL() // URL to download from
    let localFilename = "foobar.png" // Filename for storing locally 

    // Create download request
    let task = NSURLSession.sharedSession().downloadTaskWithURL(downloadURL) { location, response, error in
        guard location != nil && error == nil else {
            print("Error downloading message: \(error)")
            return
        }

        // If here, no errors so save message to permanent location
        let fileManager = NSFileManager.defaultManager()
        do {
            let documents = try fileManager.URLForDirectory(.DocumentDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)
            let fileURL = documents.URLByAppendingPathComponent(localFilename)
            try fileManager.moveItemAtURL(location!, toURL: fileURL)
            self.doFileDownloaded(fileURL, localFilename: localFilename)
            print("Downloaded message @ \(localFilename)")
        } catch {
            print("Error downloading message: \(error)")
        }
    }

    // Start download
    print("Starting download @ \(downloadURL)")
    task.resume()


// Helper function called after file successfully downloaded
private func doFileDownloaded(fileURL: NSURL, localFilename: String) {

    // Do stuff with downloaded image

}

1

Swift 4.1 이미지 URL을 전달하는 함수를 작성했습니다. 이미지가 생성 된 후 캐시 키를 완성 블록으로 설정하십시오.

   class NetworkManager: NSObject {

  private var imageQueue = OperationQueue()
  private var imageCache = NSCache<AnyObject, AnyObject>()

  func downloadImageWithUrl(imageUrl: String, cacheKey: String, completionBlock: @escaping (_ image: UIImage?)-> Void) {

    let downloadedImage = imageCache.object(forKey: cacheKey as AnyObject)
    if let  _ = downloadedImage as? UIImage {
      completionBlock(downloadedImage as? UIImage)
    } else {
      let blockOperation = BlockOperation()
      blockOperation.addExecutionBlock({
        let url = URL(string: imageUrl)
        do {
          let data = try Data(contentsOf: url!)
          let newImage = UIImage(data: data)
          if newImage != nil {
            self.imageCache.setObject(newImage!, forKey: cacheKey as AnyObject)
            self.runOnMainThread {
              completionBlock(newImage)
            }
          } else {
            completionBlock(nil)
          }
        } catch {
          completionBlock(nil)
        }
      })
      self.imageQueue.addOperation(blockOperation)
      blockOperation.completionBlock = {
        print("Image downloaded \(cacheKey)")
      }
    }
  }
}
extension NetworkManager {
  fileprivate func runOnMainThread(block:@escaping ()->Void) {
    if Thread.isMainThread {
      block()
    } else {
      let mainQueue = OperationQueue.main
      mainQueue.addOperation({
        block()
      })
    }
  }
}

1
class func downloadImageFromUrl(with urlStr: String, andCompletionHandler:@escaping (_ result:Bool) -> Void) {
        guard let url = URL(string: urlStr) else {
            andCompletionHandler(false)
            return
        }
        DispatchQueue.global(qos: .background).async {
            URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) -> Void in
                if error == nil {
                    let httpURLResponse = response as? HTTPURLResponse
                    Utils.print( "status code ID : \(String(describing: httpURLResponse?.statusCode))")
                    if httpURLResponse?.statusCode == 200 {
                        if let data = data {
                            if let image = UIImage(data: data) {
                                ImageCaching.sharedInterface().setImage(image, withID: url.absoluteString as NSString)
                                DispatchQueue.main.async {
                                    andCompletionHandler(true)
                                }
                            }else {
                                andCompletionHandler(false)
                            }
                        }else {
                            andCompletionHandler(false)
                        }
                    }else {
                        andCompletionHandler(false)
                    }
                }else {
                    andCompletionHandler(false)
                }
            }).resume()
        }
    }

Utils.swift클래스를 classname.methodname사용하여 간단하게 액세스 할 수있는 메소드를 호출하기 위해 클래스 에서 간단한 클래스 함수를 만들었으며 이미지는 ImageCaching.swift클래스를 사용하여 NSCache에 저장됩니다.

Utils.downloadImageFromUrl(with: URL, andCompletionHandler: { (isDownloaded) in
                            if isDownloaded {
                                if  let image = ImageCaching.sharedInterface().getImage(URL as NSString) {
                                    self.btnTeam.setBackgroundImage(image, for: .normal)
                                }
                            }else {
                                DispatchQueue.main.async {
                                    self.btnTeam.setBackgroundImage(#imageLiteral(resourceName: "com"), for: .normal)
                                }
                            }
                        })

행복한 코딩. 건배:)


1

스위프트 4.2와 AlamofireImage

라이브러리 사용에 문제가없는 경우의 도움을 받아 라이브러리를 사용할 수 있습니다 AlamofireImage. 내 샘플은 Github 에서 가져온 것입니다.

자리 표시 자 이미지 예 :

let imageView = UIImageView(frame: frame)
let url = URL(string: "https://httpbin.org/image/png")!
let placeholderImage = UIImage(named: "placeholder")!
imageView.af_setImage(withURL: url, placeholderImage: placeholderImage)

이미지 작업을위한 편리한 기능과 확장 기능이 많이 있습니다. 캐싱에서 크기 조정 및 크기 조정 또는 이미지에 필터 적용까지. 앱에서 이미지가 중요한 경우이 프레임 워크를 사용하고 시간을 절약하는 것이 좋습니다.


0

Ascyimageview를 사용하면 imageview에 imageurl을 쉽게로드 할 수 있습니다.

image1Url : URL = URL (문자열 : "(imageurl)"을 문자열로)로 지정하십시오! imageview.imageURL = image1Url


0

서버에서 이미지 로딩 :-

func downloadImage(from url: URL , success:@escaping((_ image:UIImage)->()),failure:@escaping ((_ msg:String)->())){
    print("Download Started")
    getData(from: url) { data, response, error in
        guard let data = data, error == nil else {
            failure("Image cant download from G+ or fb server")
            return
        }

        print(response?.suggestedFilename ?? url.lastPathComponent)
        print("Download Finished")
        DispatchQueue.main.async() {
             if let _img = UIImage(data: data){
                  success(_img)
            }
        }
    }
}
func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
    URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
}

사용법 :-

  if let url = URL(string: "http://www.apple.com/euro/ios/ios8/a/generic/images/og.png") {
                        self.downloadImage(from:url , success: { (image) in
                            print(image)

                        }, failure: { (failureReason) in
                            print(failureReason)
                        })
                    }

0

경량 라이브러리 에서 성능을 향상 UITableView시키거나 UICollectionView경량 라이브러리를 사용하려면 스마트 지연 로딩 URL 비동기식에서 이미지를로드하려는 경우이 지연 로딩 방법을 사용할 수 있습니다

iOS 에서 UICollectionView또는 UITableView사용 NSOperation하고 NSOperationQueueiOS 에서 스마트 한 'Lazy Loading' 이 프로젝트에서 and 를 사용하여 앱의 성능을 최적화하여 모든보기 ( UICollectionView또는 UITableView) 에서 여러 이미지를 다운로드 할 수 있습니다.OperationOperationQueue 동시성. 다음은이 프로젝트의 핵심 사항입니다. Smart Lazy Loading : 이미지 다운로드 서비스 생성. 셀의 가시성에 따라 다운로드 우선 순위를 정하십시오.

ImageDownloadService 클래스는 싱글 톤 인스턴스를 생성하고 다운로드 한 이미지를 캐시하기 위해 NSCache 인스턴스를 갖습니다. 필요에 따라 기능을 조작하기 위해 Operation 클래스를 TOperation으로 상속했습니다. 나는 기능 서브 클래스의 속성이 매우 명확하다고 생각합니다. KVO를 사용하여 상태의 작업 변경을 모니터링하고 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.