[英]Unwrapping an Optional value in swift and realm
我為應用程序寫了一個有效的 function,但出現錯誤“當隱式部署可選值時意外發現 nil 值”限制限制 label.文本我無法修復。
特性:
@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)"
如果您告訴我正確的代碼,我會很高興
從評論看來,您的視圖尚未加載,並且您的某些視圖仍為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)
}
Matic 為您的問題提供了一個很好、全面的答案(已投票)。 我想我會提供一個專注於你的崩潰的答案和一個“簡短而甜蜜”的解決方法:
有問題的線路可能會以兩種不同的方式崩潰:
limitLabel.text = limit[0].limitSum //Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
您的limitLabel
IBOutlet 被聲明為“隱式解包 Optional”(注意!
類型后的UILabel
:
@IBOutlet weak var limitLabel: UILabel!
一個隱式展開的 Optional 是一個 Optional,本質上,編譯器添加了一個隱藏的“.”。 每次嘗試引用該對象時強制展開。
這意味着
limitLabel.text = //something
編譯為
limitLabel!.text = //something
如果limitLabel
為nil,你就會崩潰。
如果您在加載視圖之前調用leftLabels()
function,或者該插座從未連接,您將崩潰。
您可以通過在語句中添加可選的 unwrap 來解決此問題:
limitLabel?.text = //something
(該結構稱為“可選鏈接”。)
鑒於您收到的崩潰消息提到“隱式展開可選值”,這很可能是您的情況崩潰的原因。 但是,您也應該解決其他問題。
第二種崩潰的方法是在數組索引中。
limitLabel.text = limit[0].limitSum
當您按索引從數組中獲取 object 時,如果該數組不包含該索引處的項目,您的應用程序將崩潰。 如果limit
數組為空,表達式limit[0]
將崩潰。
數組類型first
有一個計算屬性,如果數組為空,它將返回一個可選項。 您應該將其更改為limit.first?.limitSum
。
將整行更改為:
limitLabel?.text = limit.first()?.limitSum
而且它不會再崩潰了。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.