如何用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月份仍然可以看到他/她的费用而不会跳过它。有任何想法吗?

+0

立即获取所有费用并将它们存储在数组中,并按月排序。然后只需浏览数组 – Paulw11

我做了阐述之前的一些优化:

@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导航,使用户可以看到,八月是空的,同时仍然能够去六月的月份。多谢你们。