स्विफ्ट पर URL से लोडिंग / डाउनलोडिंग इमेज


412

मैं अपने एप्लिकेशन में एक URL से एक छवि लोड करना चाहता हूं, इसलिए मैंने पहली बार ऑब्जेक्टिव-सी के साथ कोशिश की और यह काम किया, हालांकि, स्विफ्ट के साथ, मैं एक संकलन त्रुटि हूं:

'imageWithData' अनुपलब्ध है: ऑब्जेक्ट निर्माण का उपयोग करें 'UIImage (डेटा :)'

मेरा कार्य:

@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
}

उद्देश्य-सी में:

- (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:स्विफ्ट के साथ काम क्यों नहीं किया जाता है, और मैं समस्या को कैसे हल कर सकता हूं।


3
यह कोशिश करोimageURL.image = UIImage(data: myDataVar)
aleclarson

बिल्कुल सही काम किया! धन्यवाद, हालाँकि मैं नहीं जानता कि यह विधि वस्तुनिष्ठ C में क्यों काम करती है, और स्विफ्ट में नहीं ... अजीब
QuentR

जब आपको कोको वर्ग से परेशानी होती है, तो क्लास नाम पर क्लिक करके CMD + आज़माएँ और आपको क्लास के लिए स्विफ्ट इंटरफ़ेस देखने में सक्षम होना चाहिए!
एलेक्लेरसन

3
if url = NSURL (string: "imageurl") {अगर डेटा दें तो NSData (contentOfURL: url) {imageView.image = UIImage (डेटा: data)}}
हार्दिक बार

2
@ लिबो डबस यह प्रश्न स्विफ्ट 2 के लिए विशिष्ट नहीं है। कृपया उस टैग को इसमें जोड़ना बंद करें।
मिक मैक्लम

जवाबों:


769

Xcode 8 या बाद का • स्विफ्ट 3 या बाद का

तुल्यकालिक:

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

अतुल्यकालिक रूप से:

अपने यूआरएल से छवि डेटा प्राप्त करने के लिए एक पूरा हैंडलर के साथ एक विधि बनाएं

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 द्वारा अद्यतन की जाएगी, भले ही वह छवि उपयोगकर्ता के लिए मान्य नहीं है।
पॉल पीलें

1
इससे मेरी समस्या हल हो गई। जब मैं तालिका दृश्य में url के साथ छवि को लोड करने का प्रयास करता हूं, तो स्क्रॉल दृश्य वास्तव में जवाब नहीं देता है जब स्क्रॉल ऊपर या नीचे होता है। मैंने UIImageView एक्सटेंशन का उपयोग किया और इसने मेरी समस्या हल कर दी। धन्यवाद।
जेंग्गे चाओ

1
@LeoDabus ठीक है धन्यवाद। और एसओ पर इतने सारे सवालों के जवाब देने के लिए धन्यवाद! आप स्विफ्ट और iOS के प्रोफेसर की तरह हैं। :)
Crashalot

2
@LeoDabus आप डेटा का उपयोग कैसे करते हैं। डाउनलोड के बजाय डेटा का उपयोग करें?
Crashalot

3
पहला एक फ़ाइल को दूसरे में मेमोरी करने के लिए डाउनलोड करता है
लियो डबस

349

(स्विफ्ट 4 अपडेट) सीधे मूल प्रश्न का उत्तर देने के लिए, यहां पोस्ट किए गए ऑब्जेक्टिव-सी स्निपेट का तेज समकक्ष है।

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:)विधि यूआरएल की सामग्री को डाउनलोड करेगा तुल्यकालिक एक ही धागे कोड निष्पादित किया जा रहा है, इसलिए नहीं है अपने आवेदन के मुख्य थ्रेड में यह आह्वान।

समान कोड को अतुल्यकालिक रूप से चलाने का एक आसान तरीका, 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!)
    }
}

कहा कि, वास्तविक जीवन के अनुप्रयोगों में, यदि आप सर्वश्रेष्ठ उपयोगकर्ता अनुभव प्राप्त करना चाहते हैं और एक ही छवि के कई डाउनलोड से बचना चाहते हैं, तो आप उन्हें न केवल डाउनलोड करना चाहते हैं, बल्कि कैश भी कर सकते हैं। वहाँ पहले से ही काफी कुछ पुस्तकालय हैं जो बहुत सहज है और वे सभी वास्तव में उपयोग करने में आसान हैं। मैं व्यक्तिगत रूप से किंगफिशर की सिफारिश करता हूं :

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
"आसानी से" व्यक्तिपरक है, और नौसिखिए कोडर इस अवांछित व्यवहार की उम्मीद नहीं करेंगे, लेकिन इस स्निप को कॉपी / पेस्ट करें जैसा कि यह है। शायद आप अपना जवाब अपडेट कर सकते हैं?
ओर्लिन जॉर्जीव

13
मैं अभी भी सहमत नहीं हूं। कुछ उत्तरों को सरल रखा जाना चाहिए, यहां आने वाले बहुत से लोग कोड के छोटे स्निपेट को कॉपी और पेस्ट करना पसंद करते हैं। मैंने मूल प्रश्न से उद्देश्य-सी कोड को स्विफ्ट करने के लिए अनुवाद किया, इसके अलावा सब कुछ एक बोनस है। और वैसे, इस तरह के बोनस जानकारी प्रदान करने वाले इस प्रश्न में पहले से ही एक उत्तर है, जो जानकारी की नकल करने के लिए कम समझ में आता है।
लुकास एडुआर्डो

1
@ बस image.urlकिसी भी स्ट्रिंग यूआरएल द्वारा प्रतिस्थापित , हार्डकोड या नहीं :)
लुकास एडुआर्डो

1
@IanWarburton बेशक आप जो चाहें उपयोग कर सकते हैं :)। 1) यह उत्तर मूल प्रश्न में आधारित है, जो उद्देश्य-सी में समान दृष्टिकोण का उपयोग कर रहा था, इसलिए मैंने बस "अनुवाद" में तेजी लाने में मदद की। 2) इस दृष्टिकोण को हटाने का कोई मतलब नहीं है और URLSession.dataTaskक्योंकि यहां बहुत सारे अन्य उत्तर पहले से ही दिखाते हैं कि यह कैसे करना है, विभिन्न विकल्पों को खोलकर रखना बेहतर है।
लुकास एडुआर्डो

2
अरे, सुझाए गए ढांचे, किंगफिशर, जैसा कि उत्तर में कहा गया है, सभी भारी उठाने का काम करेंगे। सलाह के लिये धन्यवाद!
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
यह दिखाई नहीं दे रहा है, और मुझे लगता है कि जीसीडी की आवश्यकता है। मैं कैसे रिफ्रेश करूं?
jo3birdtalk

@ jo3birdtalk यह GCD की समस्या नहीं है। अपने बाइंडिंग को दृश्य के साथ जांचें।
स्काईविन्दर

6
NSURLConnection को iOS 9 और इसी तरह चित्रित किया गया है। NSURLSession इंटीड का उपयोग करें।
मुहूर्तक

2
sendAsynchronousRequest को iOS 9
Crashalot

धन्यवाद Skywinder, मैं सरणी से छवियों को डाउनलोड करने के लिए इस पद्धति का उपयोग कर रहा हूं। मैं चाहता हूं कि जब उपयोगकर्ता cancelबटन दबाए तो वह डाउनलोड करना बंद कर दे। क्या आपके पास कोई विचार है कि मैं इस पद्धति का उपयोग करके ऐसा कैसे कर सकता हूं? मुझे रद्द कार्यक्षमता जोड़ने की आवश्यकता है।
ZAFAR007

44

स्विफ्ट 2.2 || एक्सकोड 7.3

मुझे अद्भुत परिणाम मिले !! AlamofireImage के साथ स्विफ्ट लाइब्रेरी

यह कई विशेषताएं प्रदान करता है जैसे:

  • एसिंक्रोनस रूप से डाउनलोड
  • यदि ऐप के लिए मेमोरी चेतावनियां हैं तो ऑटो पर्जिंग इमेज कैश
  • छवि URL कैशिंग
  • छवि कैशिंग
  • डुप्लिकेट डाउनलोड से बचें

और अपने ऐप के लिए लागू करना बहुत आसान है

Step.1 पॉड्स स्थापित करें


अल्मोफायर 3.3.x

पॉड 'आलमोफायर'

एलामोफायरमैज 2.4.x

फली 'आलमोफायरइमेज'

Step.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)

बस!! यह सब कुछ ध्यान रखेगा


ग्रेट धन्यवाद करने के लिए Alamofire लोग , आसान iDevelopers जीवन बनाने के लिए;)


8
स्विफ्ट 3: फोरग्राउंड आईमैज.फैसेटसेट (withURL: यूआरएल के रूप में डाउनलोड करें)
जेजुकी

28

Xcode 8स्विफ्ट 3

लियो डबस का जवाब कमाल का है! मैं सिर्फ एक ऑल-इन-वन फ़ंक्शन समाधान प्रदान करना चाहता था:

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
मार्क, शायद वहाँ अंत में "async" का मतलब था
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
क्या हमें वास्तव में उन अतिप्रश्न की आवश्यकता है? वैसे भी विरासत में नहीं मिली है? लगता है जैसे हम सिर्फ यहाँ पर खुद को सुपर कह रहे हैं, जो मुझे निरर्थक मानता है।
एनवाईसी टेक इंजीनियर

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
यह काम करता हैं। बस गतिविधि को कॉपी करें। त्रुटि मामले में संकेतक हटाने भी।
djdance

1
मेरी परियोजना के लिए बहुत उपयोगी है।
पार्टिकल्स

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
यूजर

किसी भी मौका आप कुछ अतुल्यकालिक लिख सकते हैं?
जेड ग्रांट

@JedGrant आप एक और धागे और एक कॉलबैक में लाने के लिए dispatch_async का उपयोग कर सकते हैं
Matej

मुझे NSData को "!" (ध्यान दें! अंत में) इसे इस तरह से काम करने के लिए: var imageData: NSData = NSData (contentOfURL: url, Options: NSDataReadingOptions.DataReadingMappedIfatafe, error: & इरेट)!
बॉटबोट 22

13

FYI करें: स्विफ्ट-2.0 Xcode7.0 बीटा 2 के लिए

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 और
एक्सकोड

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
फेथिका

1
निजी कैश मुझे त्रुटि दे रहा था इसलिए इसे स्थैतिक में बदल दिया और यह काम कर गया! धन्यवाद
हमाद तारिक

7

आप करना चाहते हैं:

UIImage(data: data)

स्विफ्ट में, उन्होंने नियमित निर्माता के साथ अधिकांश उद्देश्य सी कारखाने के तरीकों को बदल दिया है।

देख:

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: ...)स्विफ्ट के रूप में भी कहेंगे ।
ब्रायन निकल

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.saring.dataTask (with: url) {" "" "" "प्रकार के तर्क सूची के साथ 'dataTask' को आमंत्रित नहीं कर सकता है (साथ: URL, (डेटा? URLResponse ?, त्रुटि) ) -> शून्य) '
अयमन ब्रोमधेन

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
    }

यह कैशिंग कैसे है? और कब तक?
रमीज

यह स्थायी रूप से संग्रहीत होने लगता है, जो अजीब है, इसे लाइब्रेरी> कैश फ़ोल्डर में संग्रहीत किया जाता है। सिम्युलेटर पर चलने पर अपने कंप्यूटर पर इस स्थान को प्राप्त करने के लिए प्रिंट (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) इस विधि को वीसी या एक्सटेंशन में जोड़ें।

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

किंगफिशर यूआरएल में लोड इमेज के लिए सबसे अच्छी लाइब्रेरी में से एक है।

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 स्वचालित रूप से और डाउनलोड करने से पहले प्लेसहोल्डर छवि प्रदर्शित करें और वास्तविक छवि लोड करें (स्विफ्ट 4 कोड)।

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 का प्रकार लेता है, इसलिए मुझे इस विधि का उपयोग करना पड़ा।
::46 पर झॉनीटाक

4

छवि प्राप्त करने के लिए एक विधि जो सुरक्षित है और स्विफ्ट 2.0 और एक्स-कोड 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 में छवि का उपयोग कर रहे हैं तो इसका अंतिम भाग आवश्यक है क्योंकि नेटवर्क कॉल में समय लगता है। यदि आप ऊपर दिए गए जैसे डिस्पैच_सिंक कॉल किए बिना छवि का उपयोग करके यूआई को अपडेट करने का प्रयास करते हैं, तो कंप्यूटर छवि की तलाश करेगा जबकि छवि अभी भी प्राप्त की जा रही है, यह पता लगाएं कि कोई छवि नहीं है (अभी तक), और आगे बढ़ें जैसे कि कोई छवि नहीं थी मिल गया। एक डिस्पैच_संस पूरा होने के अंदर अपना कोड डालते हुए, कंप्यूटर से कहता है, "जाओ, इस छवि को प्राप्त करो और जब तुम हो जाओ, तब इस कोड को पूरा करो।" इस तरह, आपके पास छवि होगी जब कोड कहा जाता है और चीजें अच्छी तरह से काम करेंगी।


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

    }

आप सही हैं, क्योंकि डाउनलोड करना और कंप्रेस करना मुख्य धागे पर हो रहा है। आपको आदर्श रूप से इन 2 चरणों को पृष्ठभूमि के धागे में अतुल्यकालिक रूप से करना चाहिए, हो सकता है कि
डिस्पैच_संकल

हां, बैकग्राउंड थ्रेड का उपयोग करके हम डाउनलोड करने की गति को अनुकूलित कर सकते हैं और यदि आवश्यक हो तो हम तर्क को बदल सकते हैं इसके बजाय हम sdWebImage या अन्य ढांचे का उपयोग कर सकते हैं।
गौरव जोशी

2

मैं किंगफिशर लाइब्रेरी का उपयोग करने की सलाह देता हूं ताकि छवियों को अतुल्य रूप से डाउनलोड किया जा सके। किंगफ़िशर का उपयोग करने के बारे में सबसे अच्छी बात यह है कि यह सभी डाउनलोड की गई छवियों को डिफ़ॉल्ट रूप से एक आईडी के रूप में छवि यूआरएल के साथ कैश करता है। अगली बार जब आप उस विशेष यूआरएल के साथ छवि डाउनलोड करने का अनुरोध करते हैं, तो वह इसे कैश से लोड करेगा।

उपयोग:

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

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

देर से उत्तर के लिए क्षमा करें, क्या आप अधिक त्रुटियों पर सटीक हो सकते हैं?
सिमोन जेन्सन

1

स्विफ्ट 2.x उत्तर जो फ़ाइल को डाउनलोड करने के लिए डाउनलोड करता है (जैसा कि लियो डबस के उत्तर के विपरीत है, जो छवि को मेमोरी में संग्रहीत करता है)। सिंह Dabus के जवाब और से रोब के जवाब के आधार पर पूरा करने हैंडलर से NSURLSession DownloadTaskWithRequest से डेटा प्राप्त करें :

    // 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

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एक्सेस कर सकते हैं और आपकी छवियों को NSCache ImageCaching.swiftक्लास में उपयोग करके बचाया जाता है

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। मेरे नमूने इसके गिठुब से हैं

प्लेसहोल्डर छवियां उदाहरण:

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)

इसमें चित्रों के साथ काम करने के लिए कई उपयोगी कार्य और विस्तार हैं। कैशिंग से स्केलिंग और आकार बदलने और यहां तक ​​कि छवि पर फिल्टर लगाने के लिए। यदि आपके ऐप में छवियां महत्वपूर्ण हैं, तो मैं इस रूपरेखा का उपयोग करने और अपना समय बचाने का सुझाव देता हूं।


1

तेज ५

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>")
}

0

Ascyimageview का उपयोग आप इमेजव्यू में इमेजुरल को आसानी से लोड कर सकते हैं।

चलो image1Url: URL = URL (स्ट्रिंग: "(इमेजल)" स्ट्रिंग के रूप में)! 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लाइट वेट लाइब्रेरी का उपयोग करें स्मार्ट आलसी लोड हो रहा है यदि आप यूआरएल अतुल्यकालिक से छवियों को लोड करना चाहते हैं इस आलसी लोड हो रहा है दृष्टिकोण का उपयोग कर सकते हैं

में स्मार्ट 'लेज़ी लोड हो रहा है' UICollectionViewया UITableViewका उपयोग करते हुए NSOperationऔर NSOperationQueueआईओएस तो में इस परियोजना में हम किसी भी देखें (में एकाधिक चित्र डाउनलोड कर सकते हैं UICollectionViewया UITableViewका उपयोग करके किसी एप्लिकेशन के प्रदर्शन का अनुकूलन द्वारा) Operationऔर OperationQueueसंगामिति के लिए। निम्नलिखित इस परियोजना के मुख्य बिंदु स्मार्ट आलसी लोड हो रहे हैं: छवि डाउनलोड सेवा बनाना। कोशिकाओं की दृश्यता के आधार पर डाउनलोडिंग को प्राथमिकता दें।

ImageDownloadService क्लास एक सिंगलटन इंस्टेंस बनाएगी और जो इमेज डाउनलोड की गई हैं उन्हें कैश करने के लिए NSCache इंस्टेंस है। हमने अपनी आवश्यकता के अनुसार कार्यक्षमता को निर्धारित करने के लिए ऑपरेशन क्लास टूपरेशन को विरासत में मिला है। मुझे लगता है कि कार्यक्षमता के संदर्भ में ऑपरेशन उपवर्ग के गुण बहुत स्पष्ट हैं। हम KVO का उपयोग करके राज्य के संचालन परिवर्तनों की निगरानी कर रहे हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.