错误是: “致命错误:在打开可选值时意外发现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!)
虽然数据为零,但我已经告诉它不要继续。 这不是链接的问题。 “数据”也没有问题。我试图打印它,它不是零。
答案 0 :(得分:57)
错误很可能是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) }
答案 1 :(得分:15)
以下是我的代码可能会帮助您
斯威夫特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)
如果您使用HTTP连接而不是https,请不要忘记添加此
App Transport Security Settings
作为字典,并以Allow Arbitrary Loads
作为布尔值YES
,如下图所示
答案 2 :(得分:6)
在这里,我有一种方法,在下载图像时,您不会遇到任何类型的崩溃。 现在您正在使用以下代码:
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")
}
}
我相信如果你使用它,你的无故障将会解决。
答案 3 :(得分: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"]];
答案 4 :(得分:3)
尝试写作:
if data != nil {}
代替:
if data!= nil {}
编译器可能会将感叹号与操作混淆,以解开可选值。
答案 5 :(得分:3)
您可以使用UIImageView + AFNetworking在图像视图中设置图像
首先,在项目中拖动UIImageView + AFNetworking目标c类,并在项目的桥头文件中导入UIImageView + AFNetworking.h类。并使用此行在imageview中使用占位符设置图像。通过这种方式,您可以在视图中设置多个图像而不会卡住。
yourImageview.setImageWithURL(NSURL(string: self.yourArray.objectAtIndex(indexPath.row).objectForKey("imageurl") as! String), placeholderImage: UIImage(named:"NoUserimage.png"))
答案 6 :(得分: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)
}
}
答案 7 :(得分:2)
您的代码是正确的,只需使用:
if data != nil {
}
答案 8 :(得分:2)
您使用 Alamofire 的可能性非常大,如果是这样,它就像:
imageView.af_setImage(withURL: url)
答案 9 :(得分:2)
这是它的代码。我用过这个你不需要包含类或其他任何内容。只需使用此扩展程序。这非常快。
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()
}
}
答案 10 :(得分:1)
问题是在viewDidLoad中,imageURL UIImageView可能尚未设置。如果UIImageView为nil,我会使用可选链接
imageURL?.image = UIImage(data:data!)
我在viewDidLayoutSubviews()处设置了UIImageView的图像,此时您确定已经设置了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!)
}
}
答案 11 :(得分:1)
NSURL(string: "")
返回一个可选值。看看它的描述。它说An NSURL object initialized with URLString. If the URL string was malformed, returns nil.
在您的代码中,您尝试url!
只要url的值为nil就会崩溃。
答案 12 :(得分:0)
<强>了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
})
答案 13 :(得分:0)
Swift 3.0用于下载图像并使用URLSession和URLRequest解析json。
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")
}
}
}
答案 14 :(得分:0)
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 **//
}
答案 15 :(得分:0)
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)) }
}
}
}