というエラーが出ています: "致命的なエラー:Optional値のアンラップ中に予期せず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!)
が、データがnilの場合は処理しないように既に指示しているのですが。 リンクの問題ではありません。 また、"data"にも問題はありません。プリントしてみましたが、nilではありませんでした。
エラーは、 imageURL
がnilである可能性が最も高いです。 コードの別の場所に値を割り当てていますか、それとも実際のコードでは「@IBOutlet」ですか? 値を割り当てないと、nilになりますが、そのタイプの UIImageViewです。!
は、「暗黙的にアンラップされたオプション」であることを意味します。つまり、コンパイラーは、nilであっても使用を停止しませんが、実行時にエラーが発生してクラッシュします。
コードの残りの部分は正しいです( の前に不足しているスペースを想定します。!=
はコンパイルコードに含まれていないタイプミスです)。ただし、オプションを「nil」に対してチェックしてから、force-unwrap演算子を使用するのではなく、「if let」を使用してオプションをアンラップすることをお勧めします。
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)
HTTP接続を使用していて、httpsを使用していない場合は、これを追加することを忘れないでください。
辞書としての「App Transport Security Settings」とその中への「任意の負荷を許可する」は、下の図のように値「はい」のブール値です。 。。
ここでは、画像をダウンロードする際にクラッシュすることのない方法を紹介します。 現在、あなたは以下のコードを使用しています:
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")
}
}
そして、あなたがそれを使うなら、あなたの無音クラッシュは解決されると確信しています。
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"]];
UIImageView+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"))
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)
}
}
これがコードです。 これを使用して、クラスやその他のものを含める必要はありません。 この拡張機能を使用してください。 これは非常に高速です。
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()
}
}
コードは正しいです。以下を使用してください。
if data != 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!)
}
}
**メトード
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
})
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 **//
}
URSessionとURLRequestを使用して画像をダウンロードし、jsonを解析するには、3.0をSwiftします。
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")
}
}
}
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)) }
}
}
}