Подтвердить что ты не робот

Как отобразить изображение с помощью URL-адреса?

Ошибка:    "Неустранимая ошибка: неожиданно найдено нуль при развертывании необязательного значения"

Я делаю следующее в 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!)
    }
}

Я действительно не понимаю, почему он сообщит об ошибке на

imageURL.image = UIImage(data:data!)

хотя я уже сказал, что не продолжать, если данные равны нулю. Это не проблема связи. Также нет проблем с "данными". Я попытался напечатать его, и это было не ноль.

4b9b3361

Ответ 1

Вероятнее всего, ошибка imageURL равна нулю. Вы присваиваете ему значение в другом месте кода, или это действительно @IBOutlet в реальном коде? Если вы не присвоите ему значение, оно будет равно nil, но его тип UIImageView! означает, что он "неявно разворачивается необязательно", что означает, что компилятор не остановит вас, используя его, даже если он равен нулю, но будет сбой при выполнении с ошибкой, которую вы получаете.

Остальная часть кода верна (предполагается, что недостающее пространство до != является опечаткой не в вашем компиляционном коде), но вам лучше использовать if let, чтобы развернуть ваши опции, а не проверять их на nil, а затем с помощью оператора force-unwrap:

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

Если вы используете бета-версию Swift 1.2, вы можете объединить два ifs вместе:

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

Или, если хотите, используйте flatMap:

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

Ответ 2

Вот мой код может помочь вам

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

Использование

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

если вы используете HTTP-соединение, а не https, не забудьте добавить это

App Transport Security Settings в качестве словаря и в него Allow Arbitrary Loads как Boolean со значением YES, как на рисунке ниже введите описание изображения здесь

Ответ 3

Здесь у меня есть подход, из которого вы не получите никакого сбоя при загрузке изображения. Теперь вы используете следующий код:

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

Теперь измените код на этот, если вы продолжаете этот подход:

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

И я уверен, что если вы его используете, то ваш nil crash будет разрешен.

Ответ 4

Вы можете использовать SDWebImage для отображения изображения с 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"]];

Ответ 5

Попробуйте написать:

if data != nil {}

вместо:

if data!= nil {}

Компилятор, возможно, путает восклицательный знак с операцией, чтобы развернуть необязательное значение.

Ответ 6

Вы можете установить изображение в режиме просмотра изображений с помощью UIImageView + AFNetworking

Вы можете перетащить объектные классы UIImageView + AFNetworking в свой проект и импортировать класс UIImageView + AFNetworking.h в файл заголовка моста проекта. И используйте эту строку для установки изображения с помощью заполнителя в представлении изображения. благодаря этому вы можете установить несколько изображений в виде без застревания.

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

Ответ 7

Swift 3: (изображение в этом случае - 64-битные двоичные данные)

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)

            }        
        }

Ответ 8

Ваш код прав, просто используйте:

if data != nil {

}

Ответ 9

Довольно большая вероятность того, что вы используете Alamofire, и если это так просто:

imageView.af_setImage(withURL: url)

Ответ 10

Это код для него. Я использовал это, вам не нужно включать классы или что-то еще. Просто используйте это расширение. Это очень быстро.

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

Ответ 11

Проблема заключается в том, что в viewDidLoad изображениеURL UIImageView, возможно, еще не установлено. Я бы использовал необязательную цепочку, если UIImageView равен nil

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

Я установил изображение UIImageView в viewDidLayoutSubviews(), после чего вы убедитесь, что установлены точки просмотра ViewController.

То, как я это сделаю, будет выглядеть так:

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

Ответ 12

NSURL(string: "") 

Возвращает необязательное значение. Взгляните на его описание. В нем говорится An NSURL object initialized with URLString. If the URL string was malformed, returns nil.

В вашем коде вы пытаетесь url!, который будет сбой, когда значение url равно нулю.

Ответ 13

Methode

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

}

Использование

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

Ответ 14

Swift 3.0 для загрузки изображения и синтаксического анализа json с помощью URLSession и 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")
        }
    }
}

Ответ 15

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

Ответ 16

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