web-dev-qa-db-ja.com

URLを使用して画像を表示する方法は?

エラーは次のとおりです。「致命的なエラー:オプション値のラップ解除中に予期せずnilが見つかりました」

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

一方、データがゼロの場合は先に進まないように指示しました。リンクの問題ではありません。 「データ」に問題もありません。私はそれを印刷しようとしましたが、それはゼロではありませんでした。

32
Macondo

エラーは、imageURLがnilである可能性が最も高いです。コードの他の場所に値を割り当てていますか、それとも実際のコードで実際に@IBOutletですか?値を割り当てない場合、nilになります-ただし、UIImageView!のタイプは、「暗黙的にアンラップされたオプション」であることを意味します。つまり、nilであってもコンパイラは使用を停止しません。ただし、実行時にエラーが発生してクラッシュします。

残りのコードは正しいです(!=の前にスペースがないと、コンパイルするコードのタイプミスであると仮定します)が、nilでチェックするよりも、if letを使用してオプションをアンラップする方が良いでしょう次に、force-unwrap演算子を使用します。

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

Swift 1.2ベータ版を使用している場合、2つのifを組み合わせることができます。

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

ここに私のコードが役立ちます

スイフト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)
            }        
        }
    }
}

スウィフト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)

httpsではなくHTTP接続を使用している場合は、これを追加することを忘れないでください

App Transport Security SettingsディクショナリとしてAllow Arbitrary Loadsブール値としてYES以下の図のように enter image description here

15

ここに、イメージをダウンロードするときにクラッシュが発生しない方法があります。現在、次のコードを使用しています。

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クラッシュが解決されると確信しています。

6
Gourav Joshi

URLから表示画像にSDWebImageを使用できます 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

IImageView + AFNetworkingを使用して画像ビューで画像を設定できます

UIImageView + AFNetworking Objective Cクラスをプロジェクトにドラッグし、プロジェクトのブリッジヘッダーファイルにUIImageView + AFNetworking.hクラスをインポートします。そして、この行を使用して、imageviewのプレースホルダーで画像を設定します。これにより、ビューに複数の画像をスタックすることなく設定できます。

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

書いてみてください:

if data != nil {}

代わりに:

if data!= nil {}

コンパイラは、感嘆符とオプション値をアンラップする操作を混同している可能性があります。

3

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)

            }        
        }
3
Async-

あなたのコードは正しいです、ただ使用してください:

if data != nil {

}
2
Rizwan Shaikh

これがそのためのコードです。私はこれを使用しましたが、クラスなどを含める必要はありません。この拡張機能を使用してください。これは非常に高速です。

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

Alamofireを使用している可能性はかなり大きく、そうであれば次のように簡単です。

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

これはオプションの値を返します。その説明を見てください。 An NSURL object initialized with URLString. If the URL string was malformed, returns nil.と表示されます

あなたのコードでは、url!を試行していますが、urlの値がnilの場合は常にクラッシュします。

1
iOS_Developer

問題は、viewDidLoadでimageURL 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!)
    }
}
 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  **//
    }                                                                        

URLSessionおよびURLRequestを使用して画像をダウンロードし、jsonを解析するためのSwift 3.0。

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

方法

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

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