I wrote a working function for the application, but the error came out "The nil value was unexpectedly found when an optional value was implicitly deployed" limit Limit label.the text I can’t fix.
Properties:
@IBOutlet weak var limitLabel: UILabel!
Function:
func leftLabels(){
let limit = self.realm.objects(Limit.self)
guard limit.isEmpty == false else {return}
limitLabel.text = limit[0].limitSum //Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
let calendar = Calendar.current
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd HH:mm"
let firstDay = limit[0].limitDate as Date
let lastDay = limit[0].limitLastDate as Date
let firstComponent = calendar.dateComponents([.year, .month, .day], from: firstDay)
let lastComponent = calendar.dateComponents([.year, .month, .day], from: lastDay)
let startDate = formatter.date(from: "(firstComponent.year!)/(firstComponent.month!)/(firstComponent.day!) 00:00")
let endDate = formatter.date(from: "(lastComponent.year!)/(lastComponent.month!)/(lastComponent.day!) 23:59")
let filterLimit: Int = realm.objects(SpendingDB.self).filter("self.date >= %@ && self.date <= %@", startDate ?? "", endDate ?? "").sum(ofProperty: "cost")
ForThePeriod.text = "(filterLimit)"
let a = Int(limitLabel.text!)!
let b = Int(ForThePeriod.text!)!
let c = a - b
availableForSpending.text = "(c)"
I will be glad if you tell me the correct code
2
Answers
As from comments if appears that your view is not yet loaded and some of your views are still
nil
. Your app crashes because in linelimitLabel.text = limit[0].limitSum
thelimitLabel
isnil
. It would crash regardless of Realm even by callinglimitLabel.text = "Hello world!"
You can always guard data that you need to avoid changes in your code. Simply add
and so on.
I tried to clean up your code a bit. It is hard to understand what exactly are you trying to achieve but something like the following may seem a bit more appropriate:
Note some practices which help you better to structure and solve your code.
availableForSpendingLabel.text = { ... code here ... }()
let dates: (start: Date?, end: Date?)
availableForSpendingLabel
I would even further try and break this down into multiple methods. But I am not sure what this method does and assume that you have posted only part of it…
========== EDIT: Adding alternate approach ==========
From comments this is a financial application so probably at least dealing with
Decimal
numbers would make sense. Also introducing approach with adding a new structure which resolves data internally. A formatter is also used to format the number. And some other improvements:Matic provided a good, comprehensive answer to your question (voted). I thought I’d provide an answer narrowly focused on your crash and a "short and sweet" way to fix it:
The line in question could crash 2 different ways:
Your
limitLabel
IBOutlet is declared as an "implicitly unwrapped Optional" (Note the!
after the type,UILabel
:An implicitly unwrapped Optional is an Optional where, essentially, the compiler adds a hidden "!" force-unwrap every time you try to reference that object.
That means that
Is compiled as
and if
limitLabel
is nil, you crash.If you call your
leftLabels()
function before your view has been loaded, or if that outlet is never connected, you will crash.You can fix that by adding an optional unwrap to the statement:
(That construct is known as "optional chaining".)
Given that the crash message you’re getting mentions "implicitly unwrapping an Optional value" it’s likely that that is what is crashing in your case. However, you should fix the other issue as well.
The second way you can crash is in your array indexing.
When you fetch an object from an array by index, your app will crash if the array does not contain an item at that index. The expression
limit[0]
will crash if thelimit
array is empty.The array type has a computed property
first
that will return an optional if the array is empty.You should change that to
limit.first?.limitSum
.Change the whole line to be:
And it won’t crash any more.