Swift: unexpectedly found nil while unwrapping an Optional value (lldb) - swift

On this line: let task = self.session.venues.get(self.foursquareId!) {
import UIKit
import QuadratTouch
class VenueDetailsViewController: UIViewController {
#IBOutlet var venueLabelName: UILabel!
var foursquareId:String?
var session: Session!
override func viewDidLoad() {
super.viewDidLoad()
let task = self.session.venues.get(self.foursquareId!) {
(result) -> Void in
if result.response != nil {
if let venue = result.response!["venue"] as? JSONParameters {
if let venueName = venue["name"] as? String {
self.venueLabelName.text = venueName
}
}
} else {
// Show error.
}
}
task.start()
}
}
It throws me a
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)

Either session is nil, or foursquareId is nil. Since session is implicitly unwrapped, it will throw an error on that line as well as if foursquaerId is nil. You'll need to make sure these values are set before you attempt to access them like this.

Related

Cannot convert value of type 'NSControl.StateValue' to expected argument type 'Int'

I'm not sure why I can't get this to work. I'm following a video tutorial and this doesn't happen in the video, any help or advice in learning Mac OS development would be greatly appreciated.
Thanks - Image attached in link
Line 31: Cannot convert value of type 'NSControl.StateValue' to expected argument type 'Int'
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file To_do_list/ViewController.swift, line 31
Line 31 = if importantCheckbox.state == 0 {
//
// ViewController.swift
// To do list
//
// Created by on 18/11/2021.
//
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var importantCheckbox: NSButton!
#IBOutlet weak var textField: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func addClicked(_ sender: NSButton) {
if textField.stringValue != "" {
if let context = (NSApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext {
let toDoItem = ToDoItem(context: context)
toDoItem.name = textField.stringValue
if importantCheckbox.state == 0 {
//Not Important
toDoItem.important = false
} else {
//Important
toDoItem.important = true
}
// (NSApplication.shared.delegate as? AppDelegate)?.saveAction(nil)
}
}
}
}
[Cannot convert value of type 'NSControl.StateValue' to expected argument type 'Int'][1]
NSControl.StateValue is a kind of enum. The cases are .on, .off and .mixed.
You have to check for one of the cases for example
if importantCheckbox.state == .off {
or check for the rawValue
if importantCheckbox.state.rawValue == 0 {

Found nil while unwrapping optional when accessing database using SQLite.Swift [duplicate]

This question already has answers here:
What does "Fatal error: Unexpectedly found nil while unwrapping an Optional value" mean?
(16 answers)
Closed 2 years ago.
I've got a SQL database using SQLite.Swift which I've got working with the functions I need in my main view controller. I've now tried to move the database, along with the functions, over to another class as I'll need to access it from another view controller (a total of two need access.
The database file and table are created fine but as soon as I go to view or modify the database I get:
// Unexpectedly found nil while implicitly unwrapping an Optional value
I've added the errors into the code where they occur. I'm new to Swift and am confused as everything works fine if the code is in the main view controller. Any help would be much appreciated!
My code for the class:
class testClass: UIViewController {
// db
var database: Connection!
//table
let starLinesTable = Table("starLinesTable")
// columns - "" = name
let id = Expression<Int>("id")
let date = Expression<String>("date")
let line = Expression<String>("line")
func createDBTable() {
// create db
do {
let documentDirectory = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let fileURL = documentDirectory.appendingPathComponent("starlineDB").appendingPathExtension("sqlite3")
let databse = try Connection(fileURL.path)
self.database = databse
} catch {
print("error creating documentDirectory")
}
// creates table ..................................................................................
let createTable = self.starLinesTable.create { (table) in
table.column(self.id, primaryKey: true)
table.column(self.date, unique: true)
table.column(self.line)
}
do {
try self.database.run(createTable)
print("created table")
} catch {
print("error creating table")
}
}
func functionTest() {
print("connection has been made")
}
func viewDate() {
do {
let viewToday = starLinesTable.filter(date == "today")
for i in try database.prepare(viewToday) { // Unexpectedly found nil while implicitly unwrapping an Optional value
print("id: \(i[id]). date: \(i[date]). line: \(i[line])")
}
} catch {
print(error)
print("error viewing today")
}
}
func viewAll() {
do {
let data = try self.database.prepare(self.starLinesTable) // Unexpectedly found nil while implicitly unwrapping an Optional value
for i in data {
print("id: \(i[self.id]). date: \(i[self.date]). line: \(i[self.line])")
}
} catch {
print(error)
print("couldn't view db")
}
}
func saveLine() {
let userDate = "dateInput.text"
let userLine = "this is a line"
let addLine = self.starLinesTable.insert(self.date <- userDate, self.line <- userLine)
do {
try self.database.run(addLine) // Unexpectedly found nil while implicitly unwrapping an Optional value
print("added new line")
} catch {
print(error)
print("didn't add new line")
}
}
}
My code for the view controller:
import UIKit
import SQLite
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
testClass().createDBTable()
}
#IBOutlet weak var dateInput: UITextField!
#IBOutlet weak var lineInput: UITextField!
#IBAction func saveButton(_ sender: Any) {
testClass().saveLine()}
#IBAction func viewAll(_ sender: Any) {
testClass().viewAll()}
#IBAction func viewTodayButton(_ sender: Any) {
testClass().viewDate()}
#IBAction func buttonFunctionTest(_ sender: Any) {
testClass().functionTest()}
}
This error is telling you that while you are expecting those fields to have values they actually don't. For example, in your try for the database in ViewDate, you are looking for viewToday but since that value is nil you app crashes. I would check to make sure your calls to the db are correct and if so make sure you have data there.
Also check the Apple documentation for unwrapping optionals so you don't get hard crashes but a simple error message.

save/load TextField after it has been edited

I have this app with a TextField and a Save Button that I want to save when I close after it has been edited and load when I open but I cannot figure it out.
I have written something but when I try to start there comes always the
error: "Fatal 1: Fatal error: Unexpectedly found nil while unwrapping
an Optional value"
This is the code (that is in the my ViewController) but I don't know if its the best way to do it:
#IBOutlet weak var numText: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
if UserDefaults.standard.object(forKey: "num") == nil {
numText.text = "15"
}
else {
let number = UserDefaults.standard.object(forKey: "num") as! String
numText.text = number
}
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func saveButtonPressed(_ sender: UIButton) {
if numText.text == nil {
UserDefaults.standard.set("15", forKey: "num")
}
else {
UserDefaults.standard.set(numText.text, forKey: "num")
}
}
Add the text as a computed Property in the ViewController:
var SAVEDTEXTKEY = "num"
var savedText: String? {
set{
guard let value = newValue else {
UserDefaults.standard.removeObject(forKey: SAVEDTEXTKEY)
UserDefaults.standard.synchronize()
return
}
UserDefaults.standard.set(value, forKey: SAVEDTEXTKEY)
UserDefaults.standard.synchronize()
}
get{
return UserDefaults.standard.string(forKey: SAVEDTEXTKEY)
}
}
After that, when you want to save just do :
self.savedText = self.numText?.text
And when you want to retrieve it just do:
self.numText.text = self.savedText
The problem I think is that you're not calling
UserDefaults.standard.synchronize()
after setting the value in user defaults.

How to populate table rows, using a [String] array sent from iPhone by Watch Connectivity?

Basically, it's passing the array fine. It's just when trying to use the enumerated array as the tablerows, it says nil found.
PHONE
import UIKit
import WatchConnectivity
class ViewController: UIViewController, WCSessionDelegate {
#IBOutlet weak var sendButton: UIButton!
var watchSession: WCSession?
var arrayCustom = ["thing1", "thing2"]
override func viewDidLoad() {
super.viewDidLoad()
if(WCSession.isSupported()) {
watchSession = WCSession.defaultSession()
watchSession?.delegate = self
watchSession?.activateSession()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func sendArray(sender: AnyObject) {
sendToWatch()
}
private func sendToWatch() {
do {
let applicationDict = ["Array1": arrayCustom]
try WCSession.defaultSession().updateApplicationContext(applicationDict)
}
catch {
print(error)
}
}
}
WATCHKIT
private func loadThCust() {
if (WCSession.isSupported()) {
watchSession = WCSession.defaultSession()
watchSession.delegate = self;
watchSession.activateSession()]
}
func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject]) {
dispatch_async(dispatch_get_main_queue()) { () -> Void in
if let retrievedArray1 = applicationContext["Array1"] as? [String] {
self.custArray = retrievedArray1
print(self.custArray)
}
for (index, thName) in self.custArray.enumerate() {
let row2 = self.choiceTable.rowControllerAtIndex(index) as! ChoiceTableRowController
row2.choiceLabel.setText(thName)
}
}
}
My problem is I'm getting this console output + error whenever I try and load the TableView:
["thing1", "thing2"]
2016-02-24 03:21:25.912 WristaRoo WatchKit Extension[9401:243561] Error - attempt to ask for row 0. Valid range is 0..0
fatal error: unexpectedly found nil while unwrapping an Optional value
Does anyone have any idea why the unwrapped value is still nil? I was hoping that once I get it set and can see that there are values in the [String] array, it could enumerate it, but it seems like they are just invisible.
You started the question with the statement, "Basically, It's passing the array fine" so it's not a Watch Connectivity issue.
You simply didn't specify the number of rows for choiceTable before iterating through your array.
choiceTable.setNumberOfRows(custArray.count, withRowType: "ChoiceTableRowController")
Determining the problem from the console output:
Error - attempt to ask for row 0. Valid range is 0..0
rowControllerAtIndex: returns (an Optional which is) nil when its index is out of bounds.
The row controller object, or nil if there are no row controllers yet or index is out of bounds.
You tried to access a row which didn't exist, leading to a bounds warning.
fatal error: unexpectedly found nil while unwrapping an Optional value
row2.choiceLabel.setText(thName)
row2 is nil.
You should be able to easily track down bugs like this in the debugger. If you examined row2 and saw that it was nil, you'd realize that the problem wasn't with the array itself, but that the table has no rows.

Learning Swift, Value of optional type not unwrapped when creating an object

I'm learning Swift right now, and in the course we have a lesson to make a simple app. Now I'm having problems with some text fields programming that it's not working properly.
Here is my code:
class ViewController: UIViewController {
#IBOutlet weak var refeicaoField: UITextField?
#IBOutlet weak var felicidadeField: UITextField?
#IBAction func addRefeicao(sender: UIButton) {
if refeicaoField == nil || felicidadeField == nil {
return
}
let nomeRefeicao = refeicaoField!.text
let valorFelicidade = felicidadeField!.text
let valorFelicidadeInt = Int(valorFelicidade!)
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt)
}
}
The problem starts here:
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt)
Where it says: value of optional 'Int?' not unwrapped; did you mean to use '!' or '?' and also value of optional 'String?' not unwrapped; did you mean to use '!' or '?'
I'm little confused, because in the lesson example they have done like this:
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt!)
And worked, but for me no. And if I try to put '!' at the two variables, I have an exclamation warning prompting no use for let novaRefeicao.
What's wrong?
EDIT:
Done some changes using all the tips found here, now my code is like:
class ViewController: UIViewController {
#IBOutlet weak var refeicaoField: UITextField!
#IBOutlet weak var felicidadeField: UITextField!
#IBAction func addRefeicao(sender: UIButton) {
if refeicaoField == nil || felicidadeField == nil {
return
}
let nomeRefeicao = refeicaoField!.text
let valorFelicidade = felicidadeField!.text
if nomeRefeicao == nil {
return
}
if let valorFelicidadeInt = Int(valorFelicidade!) {
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt)
} else {
return
}
}
}
Now I receive the error on unwrapped again, but now with the "nomeRefeicao" instead. Tried to put the '!' in it, but then it shows that let novaRefeicao is immutable value.
You should understand that the Swift language has changed a lot over the past year and that exclamation point has moved quite a bit over time. If your examples are from even mid-2015, you're looking at out-dated syntax.
Having a value with ? means that this item may contain a value... or it may not.
Having a value with ! means that you are forcibly unwrapping an object which can be rather dangerous, use it sparingly and only when you know for certain that it will not cause a crash.
If you have an optional value, you can safely unwrap it like this:
guard let unwrapped = wrapped else {
return
}
or
if let unwrapped = wrapped {
print(unwrapped)
}
A little more info, if you have an initialized optional value, what you've really got is this:
enum Optional<A> {
case None
case Some(A)
}
This is why you cannot use your value without unwrapping it... it's 'wrapped' in an optional enum that either has a value or doesn't.
Your code with a little safeguard added:
class ViewController: UIViewController {
#IBOutlet weak var refeicaoField: UITextField?
#IBOutlet weak var felicidadeField: UITextField?
#IBAction func addRefeicao(sender: UIButton) {
guard let refeicaoField = refeicaoField!.text else {
return
}
guard let felicidadeField = felicidadeField!.text else {
return
}
let nomeRefeicao = refeicaoField ?? "error" // added protection
let valorFelicidade = felicidadeField ?? "error" // added protection
let valorFelicidadeInt = Int(valorFelicidade) ?? 0 // defaults to '0' in case of issue
}
}
Both the text property of UITextField and the result of the Int(string:String) initializer return an optional value.
So you have to unwrap both in case the method expects non optional parameters.
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao!, alegriaEmComer: valorFelicidadeInt!)
The most compact syntax is
class ViewController: UIViewController {
#IBOutlet weak var refeicaoField: UITextField!
#IBOutlet weak var felicidadeField: UITextField!
#IBAction func addRefeicao(sender: UIButton) {
if let nomeRefeicao = refeicaoField.text, valorFelicidade = felicidadeField.text, valorFelicidadeInt = Int(valorFelicidade) {
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt)
// do something with novaRefeicao
}
}
}
The Meal initializer is only called if
refeicaoField.text is not nil
felicidadeField.text is not nil and can be converted to Int
There is no need to check the UITextField instances for nil.
If you get a runtime error, one of the fields is not connected in IB.
The message Initialization of immutable value ... is a warning, because the created Meal instance assigned to novaRefeicao is never used. That's why I added the comment line do something …
The line:
let valorFelicidadeInt = Int(valorFelicidade!)
converts a String value into an Int. What should your code do if the string cannot be converted to an integer? You need to address that explicitly.
In Swift, the conversion has a type of Optional - either the conversion worked or it did not. You thus have two cases to cover. The following is a possible approach:
if let valorFelicidadeInt = Int(valorFelicidade!) {
let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt)
// continue using `Meal`
}
else {
// User error; text not an int
}
The if let will succeed if Int(...) returns a non-nil optional; you'll then build the Meal.
The same approach to unwrapping by handling the two options applies to other parts of your code.