Swift 3.0 - Core Data / Unexpectedly found nil - swift

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
}

Related

How To Update A Label In Swift 3 With JSON Data Inside Of A Function?

For some reason whenever I try to update my label with the current temperature using self.infoLabel.text = String(temp!) inside of the DispatchQueue code block, I get the following fatal error message:
unexpectedly found nil while unwrapping an Optional value.
I'd appreciate if someone could help me figure out why the code below isn't working. Thanks.
func getCurrentTemp(city: String){
let weatherRequestURL = URL(string: "\(openWeatherMapBaseURL)?APPID=\(openWeatherMapAPIKey)&q=\(city)")!
// The data task retrieves the data.
URLSession.shared.dataTask(with: weatherRequestURL) { (data, response, error) in
if let error = error {
// Case 1: Error
print("Error:\n\(error)")
}
else {
//print("Raw data:\n\(data!)\n")
//let dataString = String(data: data!, encoding: String.Encoding.utf8)
//print("Human-readable data:\n\(dataString!)")
do {
// Try to convert that data into a Swift dictionary
let weather = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String:AnyObject]
if let main = weather["main"] as? [String: Any] {
let temp = main["temp"] as? Double
print("temp\(temp!)")
DispatchQueue.main.sync(execute: {
self.infoLabel.text = String(temp!)
})
//return temp as? String
//let temp_max = main["temp_max"] as? Double
//print("temp\(temp_max!)")
//let temp_min = main["temp_min"] as? Double
//print("temp\(temp_min!)")
}
}
catch let jsonError as NSError {
// An error occurred while trying to convert the data into a Swift dictionary.
print("JSON error description: \(jsonError.description)")
}
}
}
.resume()
}
There are two possibilities here: 1) either temp is nil (and it shouldn't be because you already force unwrap it in the print statement above) 2) or infoLabel is nil which happens if you broke your outlet connection.
Its easy to check; make a breakpoint above your assignment and in the debug console you can type:
po self.infoLabel
to see if its nil. For good measure you an also check temp.
You can also add a print statement to check self.infoLabel or an assert.
Alright, so I found a makeshift solution to this issue (See Below). Rather than placing the code inside of the function I made, I placed it in the viewDidLoad() function. For whatever reason, self.infoLabel? would be nil anywhere inside of the function I made.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print("Sucessful launched weather page.")
let weatherRequestURL = URL(string: "\(openWeatherMapBaseURL)?APPID=\(openWeatherMapAPIKey)&q=\(city)")!
// The data task retrieves the data.
URLSession.shared.dataTask(with: weatherRequestURL) { (data, response, error) in
if let error = error {
// Case 1: Error
print("Error:\n\(error)")
}
else {
//print("Raw data:\n\(data!)\n")
//let dataString = String(data: data!, encoding: String.Encoding.utf8)
//print("Human-readable data:\n\(dataString!)")
do {
// Try to convert that data into a Swift dictionary
let weather = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String:AnyObject]
if let main = weather["main"] as? [String: Any] {
let temp = main["temp"] as? Double
print("temp\(temp!)")
var tempInFarenheit = ((9/5)*((temp!)-273) + 32).rounded()
DispatchQueue.main.sync(execute: {
self.infoLabel.text = "\(tempInFarenheit) + °"
})
}
}
catch let jsonError as NSError {
// An error occurred while trying to convert the data into a Swift dictionary.
print("JSON error description: \(jsonError.description)")
}
}
}
.resume()
}
Although this isn't the most effective way of doing things, hopefully it can help others who are having the same problem. If I find a more effective way of doing this, I'll be sure to edit this post and include it.

Swift 3 error: Type 'Any' has no subscript members

So I know this question has been asked and answered numerous times before, but I just migrated my project to Swift 3 and Im getting a ton of these errors in my code that parses JSON and I couldn't quite find answers that made me understand how to resolve my specific issue.
guard let result = try JSONSerialization.jsonObject(with: data!, options: []) as? [String:AnyObject] else {
return
}
guard let responseData = result["Data"] else { return }
guard let userData = responseData["UserProfile"] else { return }
var userProfileFieldsDict = [String: String]()
if let sessionToken = userData!["CurrentSessionToken"] as? NSString {
userProfileFieldsDict["sessionToken"] = String(sessionToken)
}
}
The if let sessionToken line throws the aforementioned error, but not quite sure how you're supposed to deal with this in Swift 3? Could someone explain and suggest a best practice fix?
Thanks a bunch!
If responseData["UserProfile"] is also a dictionary you'll probably want to cast it as such in you guard by saying guard let userData = responseData["UserProfile"] as? [String : AnyObject] else { return }. I suspect this will solve your problem.
As a small aside, you don't need to force unwrap userData in your if let, because you've already unwrapped it in the guard.

unexpectedly found nil while unwrapping an Optional value: Swift - FMDB - executeQuery

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)

UIImage as Optional

Hi I want users to be able to Register even if they don't choose a profile picture
Right now I use this code for the profile picture:
let profileImageData = UIImageJPEGRepresentation((userImage.image!), 1)
if (profileImageData != nil) {
let profileImageFile = PFFile (data: profileImageData!)
myUser.setObject(profileImageFile!, forKey: "profile_picture")
}
And each time a user don't choose a profile picture while registering I get this error
fatal error: unexpectedly found nil while unwrapping an Optional value
I want the user to be able to register even if the value is nil.
Thank you very much
I am modifying your code here:
if let profileImageData = UIImageJPEGRepresentation((userImage.image!), 1){
let profileImageFile = PFFile (data: profileImageData!)
myUser.setObject(profileImageFile!, forKey: "profile_picture")
}else{
print("No image selected")
}
Hope this helps!
The problem is that you are trying to force unwrap the userImage.image variable even when its not set. You should force unwrap only when you are sure that the variable has a value.
The below modification should work
if let profileImage = userImage.image{
let profileImageData = UIImageJPEGRepresentation((profileImage), 1)
let profileImageFile = PFFile (data: profileImageData!)
myUser.setObject(profileImageFile!, forKey: "profile_picture")
}else{
//! Handle part when no image is selected
}

Unexpectedly found nil while unwrapping an Optional value in Json parsing in swift

code:
var json:NSString;
json = NSString(format:"{\"und\":[{\"value\":\"2324\"}]")
var data:NSData = json.dataUsingEncoding(NSUTF8StringEncoding)!
var dataDic:NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error:nil) as! NSDictionary
I formed my own json and when i try yo parse it give error as "Unexpectedly found nil while unwrapping an Optional value".I assume that the cause of issue is passing empty json for pasing.I do not know how to solve this problem?.thanks in advance
let jsonString = "{\"und\":[{\"value\":\"2324\"}]}"
if let jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
var error: NSError?
if let jsonDict = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers, error: &error) as? [String:AnyObject] {
if let dictionaries = jsonDict["und"] as? [AnyObject] {
for dictionary in dictionaries {
if let value = dictionary["value"] as? String {
println(value)
}
}
}
}
}
As Martin R suggested The problem is in your json String. so just modify it like this:
"{\"und\":[{\"value\":\"2324\"}]}"
You forgot to add } at last.
Without } it can not be cast as NSDictionary thats why it become nil at run time.
You cant declare a variable uninitialized as you did. Replace
var json:NSString
to
var json:NSString!
The exclamation declaration will automatically unwrap the optional value where it is used (so you do not need to write json!) but you need to ensure that it is initialized somehow.