我有一个跟踪每月费用的应用。我有一个费用实体,其月属性可以跟踪创建的当前月费用。然后,我会在表格视图中显示每个月的费用,如下所示。只有在下一个月或上个月有费用时,用户才能左右切换
@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月份仍然可以看到他/她的费用而不会跳过它。有任何想法吗?
答案 0 :(得分:1)
我在详细说明之前做了一些优化:
@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的数据模型中获取数据,然后每月渲染一次根据{{1}}变量(关于用户当前看到的月份)。
因此,您只能在控制器的负载中调用currentMonth
方法,并且每次用户更改当前月份视图时都会。{/ p>
答案 1 :(得分:0)
在@ 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)
}
}
返回当月的所有费用,如果没有明确的提取并返回空表。
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,以便用户可以看到August仍然是空的,但仍然能够进入6月的月份。谢谢你们。