我為應用程式撰寫了一個作業函式,但出現錯誤“隱式部署可選值時意外發現 nil 值”限制限制標簽。我無法修復的文本。
特性:
@IBOutlet weak var limitLabel: UILabel!
功能:
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)"
如果你告訴我正確的代碼,我會很高興

uj5u.com熱心網友回復:
從評論看來,如果您的視圖尚未加載,而您的某些視圖仍在加載nil。你的應用程式崩潰,因為線limitLabel.text = limit[0].limitSum的limitLabel是nil。即使呼叫 Realm 也會崩潰limitLabel.text = "Hello world!"
您始終可以保護您需要避免更改代碼的資料。只需添加
guard let limitLabel = limitLabel else { return nil }
guard let ForThePeriod = ForThePeriod else { return nil }
等等。
我試著稍微清理一下你的代碼。很難理解您到底想要實作什么,但以下內容似乎更合適:
func leftLabels() {
// Elements needed for method to execute.
guard let limitLabel = limitLabel else { return }
guard let forThePeriodLabel = forThePeriodLabel else { return }
guard let availableForSpendingLabel = availableForSpendingLabel else { return }
// Items that will be reused throughout the method later on
let limits: [Limit]
let firstLimit: Limit
let dates: (start: Date?, end: Date?)
let filterLimit: Int
limits = self.realm.objects(Limit.self)
guard limits.isEmpty == false else { return }
firstLimit = limits[0]
// limitLabel
limitLabel.text = firstLimit.limitSum
// Date components
dates = {
let calendar = Calendar.current
let formatter = DateFormatter()
formatter.dateFormat = "yyyy/MM/dd HH:mm"
let firstDay = firstLimit.limitDate as Date
let lastDay = firstLimit.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")
return (startDate, endDate)
}()
// forThePeriodLabel
filterLimit = realm.objects(SpendingDB.self).filter("self.date >= %@ && self.date <= %@", startDate ?? "", endDate ?? "").sum(ofProperty: "cost")
forThePeriodLabel.text = String(filterLimit)
// availableForSpendingLabel
availableForSpendingLabel.text = {
guard let a = Int(firstLimit.limitSum) else { return "" }
let b = filterLimit
let c = a - b
return String(c)
}()
}
請注意一些有助于您更好地構建和解決代碼的實踐。
- 第一時間守護危險資料
- 為您的方法創建一個可重復使用的專案串列(應該盡可能少,在大多數情況下沒有)。請注意稍后如何將這些分配給。如果您在分配之前嘗試使用它,您的編譯器會警告您。
- 將盡可能多的代碼包裝到封閉的部分中,例如
availableForSpendingLabel.text = { ... code here ... }() - 使用元組,例如
let dates: (start: Date?, end: Date?) - 不要害怕使用長名稱,例如
availableForSpendingLabel
我什至會進一步嘗試將其分解為多種方法。但是我不確定這個方法是做什么的,并假設你只發布了它的一部分......
========== 編輯:添加替代方法 ==========
從評論來看,這是一個金融應用程式,所以可能至少處理Decimal數字是有意義的。還介紹了添加新結構的方法,該結構在內部決議資料。格式化程式也用于格式化數字。以及其他一些改進:
struct Limit {
let amount: Decimal
let startDate: Date
let endDate: Date
}
struct Spending {
let cost: Decimal
let date: Date
}
struct LimitReport {
let limitAmount: Decimal
let spendingSum: Decimal
let balance: Decimal
init(limit: Limit) {
let limitAmount: Decimal = limit.amount
let spendingSum: Decimal = {
let calendar = Calendar.autoupdatingCurrent // Is this OK or should it be some UTC or something?
func beginningOfDate(_ date: Date) -> Date {
let components = calendar.dateComponents([.day, .month, .year], from: date)
return calendar.date(from: components)!
}
let startDate = beginningOfDate(limit.startDate)
let endDate = calendar.date(byAdding: .day, value: 1, to: startDate)
let spendings: [Spending] = realm.objects(Spending.self).filter { $0.date >= startDate && $0.date < endDate }
return spendings.reduce(0, { $0 $1.cost })
}()
let balance = limitAmount - spendingSum
self.limitAmount = limitAmount
self.spendingSum = spendingSum
self.balance = balance
}
}
func leftLabels() {
// Elements needed for method to execute.
guard let limitLabel = limitLabel else { return }
guard let forThePeriodLabel = forThePeriodLabel else { return }
guard let availableForSpendingLabel = availableForSpendingLabel else { return }
guard let limit = self.realm.objects(Limit.self).first else { return }
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.currencySymbol = "$"
let report = LimitReport(limit: limit)
limitLabel.text = formatter.string(from: report.limitAmount)
forThePeriodLabel.text = formatter.string(from: report.spendingSum)
availableForSpendingLabel.text = formatter.string(from: report.balance)
}
uj5u.com熱心網友回復:
Matic 為您的問題提供了一個很好的、全面的答案(已投票)。我想我會提供一個僅針對您的崩潰的答案以及一種“簡短而甜蜜”的解決方法:
有問題的線路可能會以兩種不同的方式崩潰:
limitLabel.text = limit[0].limitSum //Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
您的limitLabelIBOutlet 被宣告為“隱式解包的 Optional”(注意!后面的型別,UILabel:
@IBOutlet weak var limitLabel: UILabel!
隱式解包的 Optional 是一個 Optional,本質上,編譯器添加了一個隱藏的“!” 每次嘗試參考該物件時都強制展開。
這意味著
limitLabel.text = //something
編譯為
limitLabel!.text = //something
如果limitLabel是零,你就會崩潰。
如果您leftLabels()在加載視圖之前呼叫您的函式,或者如果該插座從未連接過,您將崩潰。
您可以通過在陳述句中添加一個可選的 unwrap 來解決這個問題:
limitLabel?.text = //something
(該構造稱為“可選鏈接”。)
鑒于您收到的崩潰訊息提到“隱式解開一個 Optional 值”,很可能這就是您的案例崩潰的原因。但是,您還應該解決另一個問題。
第二種可能導致崩潰的方式是在陣列索引中。
limitLabel.text = limit[0].limitSum
當您按索引從陣列中獲取物件時,如果陣列不包含該索引處的專案,您的應用程式將崩潰。limit[0]如果limit陣列為空,則運算式將崩潰。
陣列型別有一個計算屬性first,如果陣列為空,它將回傳一個可選項。您應該將其更改為limit.first?.limitSum.
將整行更改為:
limitLabel?.text = limit.first()?.limitSum
而且它不會再崩潰了。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/394790.html
上一篇:使用Firebase存盤用戶影像
