I am new to Swift, FMDB and development in general and I and I am getting a fatal error at runtime : unexpectedly found nil while unwrapping an Optional Value. The error happens on the executeQuery line
Initial try and relevant code:
var rightAnswer:FMResultSet?
var memberDatabase:FMDatabase?
....
override func viewDidLoad() {
let path = NSBundle.mainBundle().pathForResource("1_celebs", ofType: "sqlite3")
memberDatabase = FMDatabase(path: path)
if memberDatabase!.open(){
print("database is ready")//it works if I comment out the stuff in loadquestion()
}
else{
print("error finding database")
}
...
func loadQuestion(){
let querySQL = "SELECT Quote, Answer, answerNumber, Celeb1, Celeb2, Celeb3, img1, img2, img3, feedbackImg, Context FROM celebs WHERE answeredRight = 'no' ORDER BY RANDOM() LIMIT 1"
rightAnswer = memberDatabase!.executeQuery(querySQL, withArgumentsInArray: queryParameters)
rightAnswer!.next()
So then I tried this in func loadQuestion()
let results:FMResultSet? = memberDatabase!.executeQuery(querySQL, withArgumentsInArray: nil)
while(results?.next() == true)
{...}
Then I tried this:
do{
rightAnswer = try memberDatabase!.executeQuery(querySQL, withArgumentsInArray: queryParameters)
while rightAnswer!.next(){...}
} catch let error as NSError {
print("failed: \(error.localizedDescription)")
}
Then, this:
do{
let rs = try memberDatabase!.executeQuery(querySQL, values: nil)
while rs.next(){...}
} catch let error as NSError {
print("failed: \(error.localizedDescription)")
}
and I get the same error on the executeQuery line every time! If I try to get away with getting rid of the exclamation and question marks then I get an error on the console saying that the database could not be opened.
The problem is that memberDatabase is nil.
You should make sure you are populating that variable.
Another suggestion, you should avoid the force unwrap operator. It does bypass the compiler check for nil (or possible nil) values.
Swift does offer better solutions like
Conditional Unwrapping
if let memberDatabase = memberDatabase {
try memberDatabase.executeQuery(querySQL, values: nil)
}
Guard
guard let memberDatabase = memberDatabase else { return }
try memberDatabase.executeQuery(querySQL, values: nil)
Related
Can't I use "getDataInBackgroundWithBlock" for PFQuery?
I tried to get picture from the server.
But the code doesn't work at all.
Xcode usually provides autocomplete code function.
But "getDataInBackgroundWithBlock" wasn't worked.
How can I fix this?
Please check the below code.
let information = PFQuery(className: "messages")
information.findObjectsInBackground { (objects, error) in
if error == nil {
for object in objects!{
self.messageLbl.text = object["message"] as? String
self.receiverLbl.text = object["receiver"] as? String
self.senderLbl.text = object["sender"] as? String
object["picture"].getDataInBackgroundWithBlock({ (data, error) in
if error == nil {
if data != nil{
self.picture.image = UIImage(data : data!)
}else{
print(error)
}
}
})
}
}else{
print(error)
}
}
the error message is "Value of type 'Any?' has no member 'getDataInBackgroundWithBlock'"
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
I want to remove force unwrap (fetchRequestError!) from this code. I know that It must not make problems because when mainQueuePosts is nil fetchRequestError has value. But I want to make it better. And I don't want the retu
func fetchMainQueuePost(predicate predicate: NSPredicate? = nil,
sortDescriptors: [NSSortDescriptor]? = nil) throws -> [SeenPosts] {
let fetchRequest = NSFetchRequest(entityName: "SeenPosts")
let mainQueueContext = coreDataStack.mainQueueContext
var mainQueuePosts: [SeenPosts]?
var fetchRequestError: ErrorType?
mainQueueContext.performBlockAndWait() {
do {
mainQueuePosts = try mainQueueContext.executeFetchRequest(fetchRequest) as? [SeenPosts]
} catch let error {
fetchRequestError = error
}
}
guard let posts = mainQueuePosts else {
throw fetchRequestError!
}
return posts
}
My solution, which is not good is:
guard let posts = mainQueuePosts else {
if let err = fetchRequestError {
throw err
}
fatalError()
}
fatalError() is never executed. but I think its not a good idea
The usual way to throw an error in a method which throws itself is to hand over the error to the caller by removing the do - catch block.
As a standard fetch is synchronous anyway you don't need performBlockAndWait() and you can safely forced downcast to [SeenPosts] because the fetch request is distinct.
If the fetch succeeds the array will be returned, in case of an error the error will be thrown.
func fetchMainQueuePost(predicate predicate: NSPredicate? = nil,
sortDescriptors: [NSSortDescriptor]? = nil) throws -> [SeenPosts] {
let fetchRequest = NSFetchRequest(entityName: "SeenPosts")
fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = sortDescriptors
return try coreDataStack.mainQueueContext.executeFetchRequest(fetchRequest) as! [SeenPosts]
}
I am not able to figure this one out by my self. I am retrieving some settings stored in Core Data, and print these setting to some UITextFields. This works fine in another VC in the same project but here I get "unexpexpectedly found nil while unwrapping optional value".
I XCode I can see that the values are there? Why do I get this crash?
Please see attached screenshot.
This is the current code I am down to now. Still the same error message in XCode
func getSettingsFromCoreData() {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "DeathMatchSettings")
do{
let results = try context.fetch(request)
let managedObject = results as! [NSManagedObject]
let getDMSettings = managedObject[0]
guard let playerOne = getDMSettings.value(forKey: "playerOne") else {
return
}
print(playerOne)
txtPlayerOne.text = String(describing: playerOne)
}catch{
fatalError("Error in retreiving settings from CoreData")
}
}
Player1 can be nil. You are trying to force downcast it to a value, but it is a fatal error in swift. Use an if let statement to test the value:
if let playerOne = getDMSSettings.value(forKey: "playerOne") as? String {
print(playerOne)
txtPlayerOne.text = playerOne
}
Read more about type casting in docs:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html
You can also use guard statement to unwrap your optional variable. It is better to use forced unwrapping only if you are confident that variable has non-optional value.
do {
guard let playerOne = getDMSettings.value(forKey:"playerOne") else {
return
}
print(playerOne)
txtPlayerOne.text = playerOne
}
I am new in Swift. My question is I am not sure how to unwrapping the optional value. When I print the object.objectForKey("profile_picture"), I can see Optional(<PFFile: 0x7fb3fd8344d0>).
let userQuery = PFUser.query()
//first_name is unique in Parse. So, I expect there is only 1 object I can find.
userQuery?.whereKey("first_name", equalTo: currentUser)
userQuery?.findObjectsInBackgroundWithBlock({ (objects: [PFObject]?, error: NSError?) -> Void in
if error != nil {
}
for object in objects! {
if object.objectForKey("profile_picture") != nil {
print(object.objectForKey("profile_picture"))
self.userProfilePicture.image = UIImage(data: object.objectForKey("profile_pricture")! as! NSData)
}
}
})
You'd use if let to perform "optional binding", only performing the block if the result in question is not nil (and binding the variable profilePicture to the unwrapped value in the process).
It would be something like:
userQuery?.findObjectsInBackgroundWithBlock { objects, error in
guard error == nil && objects != nil else {
print(error)
return
}
for object in objects! {
if let profilePicture = object.objectForKey("profile_picture") as? PFFile {
print(profilePicture)
do {
let data = try profilePicture.getData()
self.userProfilePicture.image = UIImage(data: data)
} catch let imageDataError {
print(imageDataError)
}
}
}
}
Or, if you want to get data asynchronously, perhaps:
userQuery?.findObjectsInBackgroundWithBlock { objects, error in
guard error == nil && objects != nil else {
print(error)
return
}
for object in objects! {
if let profilePicture = object.objectForKey("profile_picture") as? PFFile {
profilePicture.getDataInBackgroundWithBlock { data, error in
guard data != nil && error == nil else {
print(error)
return
}
self.userProfilePicture.image = UIImage(data: data!)
}
}
}
}
It would be something along those lines, using if let to unwrap that optional. And you then have to get the NSData associated with that the PFFile object (from the getData method or getDataInBackgroundWithBlock, presumably).
See Optional Binding discussion in The Swift Programming Language.