エラーは次のとおりです。「致命的なエラー:オプション値のラップ解除中に予期せず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!)
一方、データがゼロの場合は先に進まないように指示しました。リンクの問題ではありません。 「データ」に問題もありません。私はそれを印刷しようとしましたが、それはゼロではありませんでした。
エラーは、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) }
ここに私のコードが役立ちます
スイフト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
以下の図のように
ここに、イメージをダウンロードするときにクラッシュが発生しない方法があります。現在、次のコードを使用しています。
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クラッシュが解決されると確信しています。
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"]];
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"))
書いてみてください:
if data != nil {}
代わりに:
if data!= nil {}
コンパイラは、感嘆符とオプション値をアンラップする操作を混同している可能性があります。
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)
}
}
あなたのコードは正しいです、ただ使用してください:
if data != nil {
}
これがそのためのコードです。私はこれを使用しましたが、クラスなどを含める必要はありません。この拡張機能を使用してください。これは非常に高速です。
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()
}
}
Alamofireを使用している可能性はかなり大きく、そうであれば次のように簡単です。
imageView.af_setImage(withURL: url)
NSURL(string: "")
これはオプションの値を返します。その説明を見てください。 An NSURL object initialized with URLString. If the URL string was malformed, returns nil.
と表示されます
あなたのコードでは、url!
を試行していますが、urlの値がnilの場合は常にクラッシュします。
問題は、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")
}
}
}
方法
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
})
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)) }
}
}
}