如何用Swift处理空对象?
问题描述:
我有一个应用程序,记录每月的开支。我有一个费用实体与月属性,跟踪当前月费用创建。然后我会在表格视图中显示每月的费用,如下所示。用户只能转左,右仅当在未来或过去的一个月如何用Swift处理空对象?
@IBAction func backMonthButtonPressed(sender: AnyObject) {
print("Back Button Pressed")
currentMonth = NSCalendar.currentCalendar().dateByAddingUnit(.Month, value: -1, toDate: currentMonth, options: [])!
if checkMonth(currentMonth) {
updateFetch()
setMonth()
} else {
currentMonth = NSCalendar.currentCalendar().dateByAddingUnit(.Month, value: 1, toDate: currentMonth, options: [])!
}
tableView.reloadData()
}
@IBAction func nextMonthButtonPressed(sender: AnyObject) {
print("Next Button Pressed")
currentMonth = NSCalendar.currentCalendar().dateByAddingUnit(.Month, value: 1, toDate: currentMonth, options: [])!
if checkMonth(currentMonth) {
updateFetch()
setMonth()
} else {
currentMonth = NSCalendar.currentCalendar().dateByAddingUnit(.Month, value: -1, toDate: currentMonth, options: [])!
}
tableView.reloadData()
}
func checkMonth(month : NSDate) -> Bool {
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext //scratch pad
let fetchRequest = NSFetchRequest(entityName: "Expense")
fetchRequest.predicate = NSPredicate(format: "month == %@", month.MonthYearDateFormatter())
let count = context.countForFetchRequest(fetchRequest, error: nil)
if count > 0 {
print("There are expenses for this month \(month.MonthYearDateFormatter()). Show expenses")
return true
} else {
print("There are no expenses for this month \(month.MonthYearDateFormatter()). Do Nothing")
return false
}
}
我的问题是支出是这样的,在用户创建的费用在6月份并没有创造不可能的情况8月份的费用。我如何让用户在8月份仍然可以看到他/她的费用而不会跳过它。有任何想法吗?
答
我做了阐述之前的一些优化:
@IBAction func backMonthButtonPressed(sender: AnyObject) {
self.processMonth(step: -1)
}
@IBAction func nextMonthButtonPressed(sender: AnyObject) {
self.processMonth(step: 1)
}
// a method uses almost the same code for both cases, so it was merged
func processMonth(step: Int) {
let direction = (step < 1 ? "Back" : "Next")
print("\(direction) Button Pressed")
currentMonth = NSCalendar.currentCalendar().dateByAddingUnit(.Month, value: step, toDate: currentMonth, options: [])!
//if checkMonth(currentMonth) {
// I wouldn't test this because it locks you out from seeing empty month.
updateFetch()
setMonth()
//}
tableView.reloadData()
}
的答案是什么你究竟问:
如果您的UITableView数据源设置正确,你应该能够去通过空个月,虽然
// changed return type from `Bool` to `void` as I suggested in the method not to test empty month, as it could be useless
func checkMonth(month : NSDate) {
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext //scratch pad
let fetchRequest = NSFetchRequest(entityName: "Expense")
fetchRequest.predicate = NSPredicate(format: "month == %@", month.MonthYearDateFormatter())
let count = context.countForFetchRequest(fetchRequest, error: nil)
if count > 0 {
print("There are expenses for this month \(month.MonthYearDateFormatter()). Show expenses")
} else {
print("There are no expenses for this month \(month.MonthYearDateFormatter()). Do Nothing")
// here you can make some additional actions, like seeting the empty table with "no expenses this month"
}
}
无论如何,@ Paulw11注意,如果您的数据源不是大小疲惫,您可以在viewDidLoad/viewDidAppear中获取数据模型中的数据,然后根据currentMonth
变量(关于用户当前看到的月份)每月呈现数据。
因此,您只需在控制器的加载和每次用户更改当前月视图时调用setMonth()
方法。
答
在@ Paulw11和@pedrouan的帮助下,我能够做我想做的事。
抓取所有费用
func fetchExpenses() {
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext //scratch pad
let fetchRequest = NSFetchRequest(entityName: "Expense")
//Always Sort Budget by the date it's created
let sortDescriptor = NSSortDescriptor(key: "created", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
do {
let results = try context.executeFetchRequest(fetchRequest)
self.expenses = results as! [Expense]
} catch let err as NSError {
print(err.debugDescription)
}
}
设置约束,第一个和最后一个月以确定从过去的第一个和最后一个月
去多远,用户可以在viewDidLoad中通过几个月导航//If array is not empty, set first and last month
if expenses.count > 0 {
guard let first = expenses.first?.month else {
return
}
firstMonth = first
guard let last = expenses.last?.month else {
return
}
lastMonth = last
}else {
//Set current month to be first and last
firstMonth = currentMonth.MonthYearDateFormatter()
lastMonth = currentMonth.MonthYearDateFormatter()
}
限制用户
@IBAction func backMonthButtonPressed(sender: AnyObject) {
print("Back Button Pressed")
if currentMonth.MonthYearDateFormatter() != firstMonth {
self.processMonth(step: -1)
}
}
@IBAction func nextMonthButtonPressed(sender: AnyObject) {
print("Next Button Pressed")
if currentMonth.MonthYearDateFormatter() != lastMonth {
self.processMonth(step: 1)
}
}
返回当月的所有费用,如果有n一个清除提取并返回空表。
func updateFetch() {
setFetchResults()
do {
try self.fetchedResultsController.performFetch()
} catch {
let error = error as NSError
print("\(error), \(error.userInfo)")
}
}
func setFetchResults() {
let app = UIApplication.sharedApplication().delegate as! AppDelegate
let context = app.managedObjectContext //scratch pad
//Fetch Request
let fetchRequest = NSFetchRequest(entityName: "Expense")
let sortDescriptor = NSSortDescriptor(key: "created", ascending: false)
fetchRequest.predicate = NSPredicate(format: "month == %@", currentMonth.MonthYearDateFormatter())
fetchRequest.sortDescriptors = [sortDescriptor]
let count = context.countForFetchRequest(fetchRequest, error: nil)
let controller = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: ad.managedObjectContext , sectionNameKeyPath: section, cacheName: nil)
//If there is none, empty fetch request
if count == 0 {
print("There are no expenses for this month. Show nothing")
controller.fetchRequest.predicate = NSPredicate(value: false)
} else {
print("There are expenses for this month. Show expenses")
}
fetchedResultsController = controller
controller.delegate = self
}
随着pedroruan的processMonth(),我是能够通过空tableViews导航,使用户可以看到,八月是空的,同时仍然能够去六月的月份。多谢你们。
立即获取所有费用并将它们存储在数组中,并按月排序。然后只需浏览数组 – Paulw11