web-dev-qa-db-fra.com

Comment afficher une image en utilisant une URL?

L'erreur est la suivante: "Erreur irrécupérable: trouvé de manière inattendue nil lors du déroulement d'une valeur facultative"

Je fais ce qui suit dans ViewController:

var imageURL:UIImageView!

override func viewDidLoad() {
    super.viewDidLoad()
    let url = NSURL(string:"http://cdn.businessoffashion.com/site/uploads/2014/09/Karl-Lagerfeld-Self-Portrait-Courtesy.jpg")
    let data = NSData(contentsOfURL:url!)
    if data!= nil {
        imageURL.image = UIImage(data:data!)
    }
}

Je ne comprends vraiment pas pourquoi il va signaler une erreur sur

imageURL.image = UIImage(data:data!)

alors que je lui ai déjà dit de ne pas continuer si les données sont nulles. Ce n'est pas le problème du lien. Il n'y a pas non plus de problème avec les "données". J'ai essayé de l'imprimer et ce n'était pas nul.

32
Macondo

L'erreur est probablement que imageURL est nul. Attribuez-vous une valeur ailleurs dans le code, ou s'agit-il réellement de @IBOutlet dans le vrai code? Si vous ne lui attribuez pas de valeur, ce sera nil - mais son type de UIImageView! signifie que c'est un "facultatif implicitement non enveloppé", ce qui signifie que le compilateur ne vous empêchera pas de l'utiliser même s'il est nul, mais se plantera au moment de l'exécution avec l'erreur que vous obtenez.

Le reste du code est correct (en supposant que l'espace manquant avant != n'est pas une faute de frappe dans votre code de compilation), mais vous feriez mieux d'utiliser if let pour déballer vos options, plutôt que de les comparer à nil, puis d’utiliser l’opérateur de décompression forcée:

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

Si vous utilisez la Swift 1.2 beta), vous pouvez combiner les deux ifs ensemble:

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

Ou, si vous préférez, utilisez flatMap:

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

Voici mon code pourrait vous aider

Swift 2:

extension UIImageView{

    func setImageFromURl(stringImageUrl url: String){

        if let url = NSURL(string: url) {
            if let data = NSData(contentsOfURL: url) {
                self.image = UIImage(data: data)
            }        
        }
    }
}

Swift 3:

extension UIImageView{

func setImageFromURl(stringImageUrl url: String){

      if let url = NSURL(string: url) {
         if let data = NSData(contentsOf: url as URL) {
            self.image = UIImage(data: data as Data)
         }
      }
   }
}

Usage

 let imgURL = "https://yourdomain.com/picturepath/picname.png" // or jpg
 self.myImage.setImageFromURl(stringImageUrl: imgURL)

si vous utilisez une connexion HTTP et non https, n'oubliez pas d'ajouter ceci

App Transport Security Settings comme dictionnaire et en elle Allow Arbitrary Loads comme booléen avec la valeur YES comme dans la figure ci-dessous enter image description here

15
Anirudh R.Huilgol.

Ici, j'ai une approche à partir de laquelle vous ne recevrez aucun type d'accident lors du téléchargement de l'image. Actuellement, vous utilisez le code suivant:

override func viewDidLoad() {
    super.viewDidLoad()
    let url = NSURL(string:"http://cdn.businessoffashion.com/site/uploads/2014/09/Karl-Lagerfeld-Self-Portrait-Courtesy.jpg")
    let data = NSData(contentsOfURL:url!)
    if data!= nil {
        imageURL.image = UIImage(data:data!)
    }
}

Maintenant changez le code avec celui-ci, Si vous continuez avec cette approche:

override func viewDidLoad() {
    super.viewDidLoad()
    let url = NSURL(string:"http://cdn.businessoffashion.com/site/uploads/2014/09/Karl-Lagerfeld-Self-Portrait-Courtesy.jpg")
    let data = NSData(contentsOfURL:url!) 

    // It is the best way to manage nil issue. 
    if data.length > 0 {
        imageURL.image = UIImage(data:data!)
    } else {
        // In this when data is nil or empty then we can assign a placeholder image 
        imageURL.image = UIImage(named: "placeholder.png")
    }
}

Et je suis sûr que si vous l'utilisez, votre crash nul sera résolu.

6
Gourav Joshi

Vous pouvez utiliser SDWebImage pour l’affichage de l’image à partir de l’URL https://github.com/rs/SDWebImage

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

Vous pouvez définir l'image dans la vue d'image en utilisant UIImageView + AFNetworking

Faites glisser les classes UIImageView + AFNetworking Objective C dans votre projet et importez la classe UIImageView + AFNetworking.h dans le fichier d’en-tête de pont de votre projet. Et utilisez cette ligne pour définir une image avec un espace réservé dans imageview. par là, vous pouvez définir plusieurs images dans une vue sans aucune image collée.

yourImageview.setImageWithURL(NSURL(string: self.yourArray.objectAtIndex(indexPath.row).objectForKey("imageurl") as! String), placeholderImage: UIImage(named:"NoUserimage.png"))
3
pawan gupta

Essayez d'écrire:

if data != nil {}

au lieu:

if data!= nil {}

Le compilateur est peut-être déroutant avec un point d'exclamation avec l'opération visant à décompresser la valeur facultative.

3

Swift 3: (dans ce cas, l'image correspond à des données binaires de 64 bits)

if let url = NSURL(string: route) {
            if let imageData = NSData(contentsOf: url as URL) {
                let str64 = imageData.base64EncodedData(options: .lineLength64Characters)
                let data: NSData = NSData(base64Encoded: str64 , options: .ignoreUnknownCharacters)!
                let dataImage = UIImage(data: data as Data)

            }        
        }
3
Async-

Votre code est correct, utilisez simplement:

if data != nil {

}
2
Rizwan Shaikh

Ceci est le code pour cela. J'ai utilisé cela, vous n'avez pas besoin d'inclure des cours ou quoi que ce soit d'autre. Il suffit d'utiliser cette extension. C'est très rapide.

extension UIImageView {
    public func imageFromURL(urlString: String) {

        let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
        activityIndicator.frame = CGRect.init(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height)
        activityIndicator.startAnimating()
        if self.image == nil{
            self.addSubview(activityIndicator)
        }

        URLSession.shared.dataTask(with: NSURL(string: urlString)! as URL, completionHandler: { (data, response, error) -> Void in

            if error != nil {
                print(error ?? "No Error")
                return
            }
            DispatchQueue.main.async(execute: { () -> Void in
                let image = UIImage(data: data!)
                activityIndicator.removeFromSuperview()
                self.image = image
            })

        }).resume()
    }
}
2
Sandip Gill

Il est fort probable que vous utilisiez Alamofire et si c'est aussi simple que:

imageView.af_setImage(withURL: url)
2
Andrey
NSURL(string: "") 

Ceci retourne une valeur optionnelle. Regardez sa description. Ça dit An NSURL object initialized with URLString. If the URL string was malformed, returns nil.

Dans votre code, vous essayez de url! qui se plantera chaque fois que la valeur de l'URL est nulle.

1
iOS_Developer

Le problème est que, dans viewDidLoad, l'imageURL UIImageView n'a peut-être pas encore été définie. J'utiliserais un chaînage optionnel au cas où UIImageView serait à zéro

imageURL?.image = UIImage(data:data!)

Je définissais l'image de UIImageView à viewDidLayoutSubviews (). Vous êtes alors certain que les prises de ViewController ont été définies.

La façon dont je le ferais ressemblerait à ceci:

@IBOutlet weak var imageURL: UIImageView!
var data: NSData?

override func viewDidLoad() {
    super.viewDidLoad()
    let url = NSURL(string:"http://cdn.businessoffashion.com/site/uploads/2014/09/Karl-Lagerfeld-Self-Portrait-Courtesy.jpg")
    data = NSData(contentsOfURL:url!)
    if data != nil {
        imageURL?.image = UIImage(data:data!)
    }
}

override func viewDidLayoutSubviews() {
    if data != nil {
        imageURL.image = UIImage(data:data!)
    }
}
 let urlImg = NSURL(string:"https://firebasestorage.googleapis.com/v0/b/fanism-dccfe.appspot.com/o/Heros%2FIMG-20171116-WA0003.png?alt=media&token=b31a6d9e-cea6-422a-b198-82365abd845e")

    data = NSData.init(contentsOf: urlImg! as URL)
    if data != nil {
        imageView?.image = UIImage(data:data! as Data) //**Here imageView our ImageView outlet  **//
    }                                                                        
0

Swift 3.0 pour le téléchargement d'images et l'analyse de JSON à l'aide de URLSession et URLRequest.

static func getRequest(_ urlString:String, completion:@escaping (Any?) -> ()) {
    guard let url = URL(string: urlString) else { return }
    let session = URLSession.shared
    let request = URLRequest(url: url)

    let task = session.dataTask(with: request, completionHandler: {
        (data, response, error) -> Void in

        if let data = data {
            do {
                let json = try JSONSerialization.jsonObject(with: data, options: [])
                completion(json)
            } catch {
                print(error)
            }
        }
    })
    task.resume()
}

static func downloadImage(_ url: String, completion:@escaping(UIImage?)->()) {
    let aUrl = URL(string: url)
    DispatchQueue.global().async {
        do {
            let data = try? Data(contentsOf: aUrl!)
            completion(UIImage(data: data!))
        } catch {
            print("Unable to download image")
        }
    }
}
0
Yogesh Bharate

Méthode

extension UIImage {

/// Loads image asynchronously
///
/// - Parameters:
///   - url: URL of the image to load
///   - callback: What to do with the image

class func loadFromURL(url: NSURL, callback: (UIImage)->()) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), {

        let imageData = NSData(contentsOfURL: url)
        if let data = imageData {
            dispatch_async(dispatch_get_main_queue(), {
                if let image = UIImage(data: data) {
                    callback(image)
                }
            })
        }
    })
}

}

tilisation

    let logoUrl = ImageService().buildImageString((self.uiConfig?.headerImage)!, imageMode: .Uniform, size: self.headerImage.frame.size)
    UIImage.loadFromURL(logoUrl, callback: { (image: UIImage) -> () in
        self.headerImage.image = image
    }) 
0
Stack_Striker

Swift 4: Un chargeur simple pour les petites images (ex: vignettes) qui utilise NSCache et qui s'exécute toujours sur le thread principal:

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)) }
    }
  }
}
0
Vishal Davara