data of image from url is nil after unwrapping - swift

I'm using Swift 4 and trying to get images from my server. Using ipconfig in terminal, I know my localhost's ip is 10.43.229.215.
the following code is to retrieve the image data and turn it into UIImage:
func GetImage(url:String) {
let image = String(localIP + url).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!
let url = URL(string: image)
print(image)
URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
if error != nil {
print("Client error!")
return
}
guard let data = data else {
print("Error: did not receive data")
return
}
DispatchQueue.main.async {
self.LensImageView.image = UIImage(data: data)
}
}).resume()
}
What I don't understand is that, the image string did show the image I want if I copy/paste the string to my browser
(http://10.43.229.215:3000/lensPic/%E5%A4%AA%E5%A6%83%E7%B3%96%E6%9D%8F.png)
However, error appears at the line self.LensImageView.image = UIImage(data: data) saying Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value.
I'm really confused about:
How can data be nil if there is already a guard let method?
Why can the data be nil is I can show the image through my browser?
Any help is highly appreciated!

The problem lies in making a false assumption about what is nil. It has nothing to do with the image or the data. What’s nil is self.LensImageView, the outlet property.

Related

Why is UIImage? nil here?

I'm trying to bridge React and Swift code by passing a string for an image path, which I've verified appears correctly on the Native side, and having a bit of an issue. The image path comes from React as NSString, and my goal is to pass that as a String to a Native function that will ultimately send data back to React.
Here's a snippet of some code that handles part of this
classifyImage(value as String)
and some of the body of the classifiyImage is as follows:
#objc func classifyImage(_ image: String) {
let imageData = Data(base64Encoded: image, options: .ignoreUnknownCharacters)!
let uiImage = UIImage(data: imageData)
guard let orientation = CGImagePropertyOrientation(
rawValue: UInt32((uiImage?.imageOrientation.rawValue)!)) else {
return
}
...code
}
The exact error is at the line with the rawVale, reading
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
Here's more info if it may help...
Image data can come from the camera as such image NSMutableString "file:///var/mobile/Containers/Data/Application/54691469-2196-444E-9B45-C0D6F2CABEBC/Library/Caches/Camera/EEC3631C-3E96-44DA-B258-411363A2F10C.jpg" 0x00000002815a8420
or from the phone's gallery image String "ph://8F109DC0-CE95-4D0A-9D11-1B2E9CE6B8D3/L0/001"
Image from a file
First, we need to turn the string into a URL, then the URL into data like so:
let url = URL(string: image)
do {
let data = try Data(contentsOf: url)
} catch {
print(e)
}
Then we can use it to create the image.
do {
let data = try Data(contentsOf: url)
let image = UIImage(data: data)
guard let orientation = CGImagePropertyOrientation(
rawValue: UInt32(image.imageOrientation.rawValue)) else {
print("that didn't work")
return
}
} catch {
print(e)
}

How can i download images from multiple API urls but skip the unreachable

I am downloading images from an API (multiple urls into a CollectionView). Everything works fine until a link is not reachable and the app crashes. How can i download from the links that are reachable but skip the ones that are not?
guard let url = URL(string: self.photos[indexPath.item]) else { return cell }
cell.imageView.image = nil
DispatchQueue.global().async {
guard let image = UIImage(data: try! Data(contentsOf: url)) else { return }
let dataCompress = image.compress(to: 1000)
if let image = UIImage(data: dataCompress) {
DispatchQueue.main.async {
cell.imageView.image = image
self.photos.append(image)
}
}
}
return cell
}
"Fatal error: 'try!' expression unexpectedly raised an error: Error Domain=NSCocoaErrorDomain Code=256 "The file “665x10002.jpg” couldn’t be opened." UserInfo={NSURL=https://"*************}
Current code crashes when a link happens to be unreachable. Any help is appreciated.
As already mentioned, you should not be using try!.
You should never be using Data(contentsOf:) to fetch data from a remote server. This is explicitly mentioned in the documentation for that initializer.
Instead, you should use
URLSession.shared.dataTask(with: url) { data, response, error in
// process the data or handle the error
}
guard let image = UIImage(data: try? Data(contentsOf: url)) else { return }
The crash is occurring because you're using ! to force unwrap your try statement. Force unwrapping is dangerous (for this reason) and should only be used when you're certain that the information will be there, otherwise the app will crash. Replace ! with ?, as above, to gracefully return when the contents of the URL is not available.

do - try - catch code doesnt try or catch. just do's

thanks for any help upfront.
url session works perfect with connection, it prints the error as nil. but without it it prints the .localizedDescription just fine and shows me the right error, but then continues to do the do{ try } and crashes with this error in the try line:
Thread 6: Fatal error: Unexpectedly found nil while unwrapping an
Optional value
now I am not even sure if this has anything to do with the errorhandling. thanks for any help with understanding whats going on or just solving the problem!
func getData(completion: (() -> ())?) {
let urlString = URL(string: "https://api.coinmarketcap.com/v1/ticker/")
URLSession.shared.dataTask(with: urlString!, completionHandler: { (data, response , error) in
print("before entering do-try-catch", error?.localizedDescription)
do {
//create Dictionary
print("downloading content")
self.coinData = try JSONSerialization.jsonObject(with: data!) as! [[String:Any]]
//set connection status
self.connection = true
//update tableView
DispatchQueue.main.async {
completion?()
}
} catch {
print("catch", error.localizedDescription)
//set connection status
self.connection = false
//update tableView
DispatchQueue.main.async {
completion?()
}
}
}).resume()
}
Thread 6: Fatal error: Unexpectedly found nil while unwrapping an Optional value is a common problem for beginners.
You try to work with data that is not there.
So for example in your code you force to execute try JSONSerialization.jsonObject(with: data!)
When data is nil the code will crash.
The same at the beginning URLSession.shared.dataTask(with: urlString!, completionHandler: { (data, response, error) {}
When urlString is not a valid URL the code will be crash. (In this case the url seems to be valid).
For more information have a look here:
https://stackoverflow.com/a/24034551/4420355
Try the following snipped it should work
if let data = data {
self.coinData = try JSONSerialization.jsonObject(with: data) as? [[String:Any]]
//... work with coinData
}
Reason why it is crashing is because data is Optional and it should be nil or has some value. On line
self.coinData = try JSONSerialization.jsonObject(with: data!) as! [[String:Any]]
Compiler thinks:
Let's take a look and unwrap this Optianal variable. But it's nil, there is "nothing"! So what should I unwrap? Let's crash and throw Fatal Error message.
How to easily avoid this with Optional binding:
if let data = data {
....do something with data
} else {
...print error message
}
For more information take look at this brilliant answer.
https://stackoverflow.com/a/32170457/3046686

Explicitly specified type 'NSURL?' issue while updating to Swift 3

I am having issues while updating my iOS app's code to the latest version of Swift.
I have a function:
public class func gifWithURL(gifUrl:String) -> UIImage? {
// Validate URL
guard let bundleURL:NSURL? = NSURL(string: gifUrl)
else {
print("SwiftGif: This image named \"\(gifUrl)\" does not exist")
return nil
}
// Validate data
guard let imageData = NSData(contentsOf: bundleURL! as URL) else {
print("SwiftGif: Cannot turn image named \"\(gifUrl)\" into NSData")
return nil
}
return gifWithData(data: imageData)
}
And am getting a warning on the following line:
guard let bundleURL:NSURL? = NSURL(string: gifUrl)
and am getting the warning:
Explicitly specified type 'NSURL?' adds an additional level of optional to the initializer, making the optional check always succeed
Xcode allows me to fix the problem automatically. When I do this auto-fix, my code changes to:
guard let bundleURL:NSURL NSURL(string: gifUrl)
Which is obviously not the correct syntax.
I am unsure what I need to add/remove to get my code fully up to date with Swift 3 standards and working.
NSURL(string:) will return optional NSURL? instance and you are already optionally wrapping it with guard so remove the : NSURL? because you are setting it again optional instead of non-optional also, in Swift 3 use native URL and Data instead of NSURL and NSData. The whole code would be like.
guard let bundleURL = URL(string: gifUrl), let imageData = try? Data(contentsOf: bundleURL) else {
print("SwiftGif: This image named \"\(gifUrl)\" does not exist")
return nil
}
//Access the imageData here
Note: Data(contentsOf:) will throws exception so you need to catch it using do try catch block.
You are doing it too complicated. In Swift 3, we don't use NSURL. It's just URL:
guard let bundleURL = URL(string: gifUrl) else {
print("SwiftGif: This image named \"\(gifUrl)\" does not exist")
return nil
}
Then you can also get rid of your dangerous force-cast:
guard let imageData = NSData(contentsOf: bundleURL) else {
print("SwiftGif: Cannot turn image named \"\(gifUrl)\" into NSData")
return nil
}

Parse Video Upload - Fatal error: unexpectedly found nil while unwrapping an Optional Value

I am trying to upload a video to Parse
If I just try to upload the video like so:
let videoData = NSData(contentsOfURL: url)
let videoFile = PFFile(name: "video.mov", data: videoData)
videoUploadObject["Video"] = videoFile
I will receive the error. I tried to remove this by running something like the following.
Main.sharedMain.userVideoOutputURL
returns:
file:///private/var/mobile/Containers/Data/Application/3B78A154-4340-432B-817A-2857EBA8064A/tmp/video.mov
Here is my full code:
let url = Main.sharedMain.userVideoOutputURL!
if let videoData = NSData(contentsOfURL: url) {
let videoFile = PFFile(name: "video.mov", data: videoData)
videoUploadObject["Video"] = videoFile
print("Video File \(videoFile)")
} else {
print("Else")
}
Else is always printed? What can I do to fix this? Thank you!
The URL looks fine (iOS doesn't use "/User/blah/blah/blah" for applicaion storage).
My first thought would be to check the data is writing correctly. NSData has a "writeToFile: options:" method that returns a bool. This will return false if writing has failed, and also throw an error which should give you some extra information.
let url = <YOUR_URL>
do {
// put your options in here
try data.writeToURL(url, options: NSDataWritingOptions.DataWritingAtomic)
} catch _ {
print(error.localizedDescription)
}
If writing has succeeded, then you'll want to try loading the data using "contentsWithUrl: options:". This also throws an error if it fails, and so using the "localisedDescription" property of the thrown error object you should be able to get to the bottom of why it isn't loading.
let url = <YOUR_URL>
var data: NSData? = nil
do {
// put your options in here
try data = NSData(contentsOfURL: url, options: NSDataReadingOptions.DataReadingUncached)
} catch _ {
print(error.localizedDescription)
}
Hope that helps :)