I have a variable copiedURL which contains a URL string, I am trying to use that string variable to display an image programmatically
let url = NSURL(string: copiedURL)
let data = NSData(contentsOfURL: url!)
let image2 = UIImage(data: data!)
When I build and run I get a EXC_BAD_INSTRUCTION error fatal error: unexpectedly found nil while unwrapping an Optional value
I am certain that copiedURL has a value because I used print() to debug and everything printed just fine.
Also, I also tried:
let url = NSURL(string: "\(copiedURL)")
but that didn't solve it.
NSURL(string:) is a failable initializer. In the case that the URL isn't valid, it will not initialize a new NSURL instance, but will instead return nil.
Check that your copiedURL is a valid URL.
Related
I am currently downloading an m4a file from firebase and trying to play the file with AVAudio Player.
How the system works
Get path of downloaded file as String
let pathForAudio: String = UserDefaults.standard.string(forKey: "path") ?? "There is no path for the audio"
Convert to URL
let url = URL(string: pathForAudio)
Pass URL into AVAUDIOPLAYER Function
soundPlayer = try AVAudioPlayer(contentsOf: url!)
When doing soundPlayer.play() I get "Unexpectedly found nil while implicitly unwrapping an Optional value"
I have seen this problem on Stack Before and they just enable permissions on a static file. Here the file path always changes so I cannot perform their solution.
Any help is much appreciated, let me know if you need other code blocks. Thanks so much!
You define your path this way:
let pathForAudio: String = UserDefaults.standard.string(forKey: "path") ?? "There is no path for the audio"
This could result in:
A valid file path stored in UserDefaults
An invalid file path stored in UserDefaults
Nothing stored in UserDefaults, which would then cause it to be "There is no path for the audio"
Unless you get scenario #1, then your next call (let url = URL(string: pathForAudio)) will fail, returning a nil value (which is what's happening right now. Then, upon calling try AVAudioPlayer(contentsOf: url!), because you're force unwrapping with !, you'll have a crash because you have a nil value that you're telling the system isn't nil by using !
In short, you need to put a valid path into UserDefaults in order for this system to work.
I'd also do some error checking along the way. Something like:
guard let pathForAudio = UserDefaults.standard.string(forKey: "path") else {
//handle the fact that there wasn't a path
return
}
guard let url = URL(string: pathForAudio) else {
//handle the fact that a URL couldn't be made from the string (ie, invalid path
return
}
//see if the file exists
guard FileManager.default.fileExists(atPath: pathForAudio) else {
//handle no file
return
}
do {
soundPlayer = try AVAudioPlayer(contentsOf: url) //notice there's now no !
} catch {
//handle error
print(error)
}
I guess this is basic Swift, so I'm a bit embarrassed to ask:
In my app, I download a plist file from a server as such:
Alamofire.download(url, to: destination).response { response in
if let url = response.destinationURL {
self.holidays = NSDictionary(contentsOf: url)!
}
}
The file is a valid file, and it is succesfully dowloaded and sitting physically in my Documents folder.
However, the app crashes on
self.holidays = NSDictionary(contentsOf: url)!
saying
Fatal error: Unexpectedly found nil while unwrapping an Optional value
What gives?
Your NSDictionary is failing to initialize, so when you try to force unwrap it (with the exclamation mark) it fails and crashes.
Try something like this:
if let dictionary = NSDictionary(contentsOf: url) {
self.holidays = dictionary
}
Alternatively you can use the guard statement:
guard let dictionary = NSDictionary(contentsOf: url) else {
print("NSDictionary failed to initialise")
return
}
self.holidays = dictionary
This question already has answers here:
What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean?
(16 answers)
Closed 6 years ago.
Hi I'm having a problem with NSJSONSerialization reading JSON from api
code:
func json() {
let urlStr = "https://apis.daum.net/contents/movie?=\etc\(keyword)&output=json"
let urlStr2: String! = urlStr.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
let url = NSURL(string: urlStr2)
let data = NSData(contentsOfURL: url!)
do {
let ret = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions(rawValue: 0)) as! NSDictionary
let channel = ret["channel"] as? NSDictionary
let item = channel!["item"] as! NSArray
for element in item {
let newMovie = Movie_var()
// etc
movieList.append(newMovie)
}
catch {
}
}
And I am getting this error
let ret = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions(rawValue: 0)) as! NSDictionary
fatal error: unexpectedly found nil while unwrapping an Optional value
How do I fix it?
The return type of the contentsOfURL initializer of NSData is optional NSData.
let data = NSData(contentsOfURL: url!) //This returns optional NSData
Since contentsOfURL initializer method returns an optional, first you need to unwrap the optional using if let and then use the data if it is not nil as shown below.
if let data = NSData(contentsOfURL: url!) {
//Also it is advised to check for whether you can type cast it to NSDictionary using as?. If you use as! to force type cast and if the compiler isn't able to type cast it to NSDictionary it will give runtime error.
if let ret = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions(rawValue: 0)) as? NSDictionary {
//Do whatever you want to do with the ret
}
}
But in case of your code snippet you're not checking the whether data that you get from contentsOfURL is nil or not. You're forcefully unwrapping the data and in this particular case the data is nil so the unwrapping is failing and it is giving the error - unexpectedly found nil while unwrapping an Optional value.
Hope this helps.
How can I open the Messages app to the compose screen, with the message body preloaded with specific text?
Benjy's answer is almost correct, but has one issue.
Since urlSafeBody isn't unwrapped, string interpolation yields
sms:&body=Optional("Hello%20World!")
which is causing NSURL initialization to return nil, since the URL string is malformed.
Here's a working example which conditionally unwraps optionals. This removes any possibility of crashes related to nil optionals being force-unwrapped.
let messageBody = "Hello World!"
let urlSafeBody = messageBody.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
if let urlSafeBody = urlSafeBody, url = NSURL(string: "sms:&body=\(urlSafeBody)") {
WKExtension.sharedExtension().openSystemURL(url)
}
Thanks to #Jatin for finding the openSystemURL(url: NSURL) function.
Here's the code:
let messageBody = "Hello World!"
let urlSafeBody = messageBody.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
WKExtension.sharedExtension().openSystemURL(NSURL(string: "sms:&body=\(urlSafeBody)")!)
Before upgrading to XCode6.1 I was using the method NSData.dataWithContents() and it was working perfectly all the images were downloading. Today I have updated to XCode 6.1 and it forces me to use the function like this:
NSData(contentsOfURL: NSURL(string: completeUrl)!)!
and when I run the application it crashes on it with message:
fatal error: unexpectedly found nil while unwrapping an Optional value
I have tried many things but nothing works. I am looking for any simple alternative for this to download images from a given URL.
Since the initalization of NSURL may fail due to several reasons you should better use it this way:
if let url = NSURL(string: completeUrl) {
if let data = NSData(contentsOfURL: url) { // may return nil, too
// do something with data
}
}
More better way to download files is:
let request:NSURLRequest = NSURLRequest(URL: NSURL(string: completeUrl)!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: { (response:NSURLResponse!, imageData:NSData!, error:NSError!) -> Void in
var filePath:String = pathString + "/" + fileName
imageData.writeToFile(filePath, atomically: true)
})
It is working very nicely and also it gives you more control on the request.