2012-03-31 21 views
0

在当前项目中,我管理实体Month,其中包含关于传递月份的信息,其中一个当然代表当前月份。coredata对象的月度更新

每个月都包含一个number属性,该属性充当年份的标识符。该属性包含一个NSNumber of type int32,用于标识月份的格式为:YYYYMM。所以例如2011年2月有属性number = 201102

在应用程序中,用户输入的数据总是受当前月份的影响。用户无法编辑,删除或添加月份的月份数据。

因此,我的coredata会保存当前月份的1 month,这些月份将会更新,以及其他用户输入数据的月份。

我有一个函数

-(void)archiveMonth:(NSNumber *)month; 

在我的DAO类,在coredata创建一个新的month对象,如果传入的NSNumber当月匹配更新当前的月份。

每次用户打开了一个新的月份的第一次应用程序时来这里的棘手的部分

,我需要应用程序归档不具有相应的核心数据对象尚未全部passed month

我是如何做的,到目前为止(用于测试目的)看起来像这样:

NSDate *rootDate = [NSDate dateWithTimeIntervalSinceReferenceDate:(10*365*24*60*60)]; 
    // somewhere in 2010 so to be sure to catch all passed month 

    NSNumber *rootMonth = [dataHandler getMonthNumber:rootDate] ; 
    NSNumber *iterator; // acts as the monthnumber currently active in the loop 
    int now = [dataHandler getMonthNumber:[NSDate date]].intValue; 

    iterator = [NSNumber numberWithInt:rootMonth.intValue]; 
    while (now >= iterator.intValue) { 
     iterator = [NSNumber numberWithInt:iterator.intValue+1]; 
     if (iterator.intValue%100 > 12) { //jump all invalid month numbers 

      while (iterator.intValue%100 != 1) { 
       iterator = [NSNumber numberWithInt:iterator.intValue+1 ]; 
      } 
     } 

     NSArray *temp = [dataHandler fetchMonth:iterator]; 
     if (temp.count == 0) {       
      // no data = needs archive 
      [dataHandler archiveMonth:iterator]; 
     } 
    } 

我在工厂被称为在申请开始有这个。

问题这是非常丑陋,创造了很多的开销

  • 我怎么能如果在一个月内第一次用户打开应用程序,所以我没有存档每一个确定他何时启动应用程序?
  • 做任何你看到更好的方式来遍历通过月?
  • 可能还有一种方法,我不必每个月都取一次来确定它是否已经存在?
  • 我可以以某种方式找出上个月归档的内容,并从那里开始迭代?

我真的很感激一些帮助,在此先感谢=) 如果你需要更多的代码,或者找到一些可能的问题丢失,生病很乐意提供它。

这是一个样机的代码,我用于测试,问题不在于如何提高代码,但如何提高算法=)

+0

一非常简单的变化就是从当前月份开始并向后退出,直到你到达一个月没有数据。 – lnafziger 2012-04-02 16:48:20

+0

我之前有这个 - 但是,它可能实际上是一个没有数据=的月份),所以它会中止。它可能与应用程序让可以说有数据为1月1日,但没有在四月和可能=) 更重要的问题是如何将通话限制为每月1次=) – 2012-04-02 16:53:19

+0

好吧,以及下注的方式来做到这一点将存储您上次在NSUserDefaults中检查的日期,并比较每次启动时的情况,但现在我没有时间写代码,对不起! – lnafziger 2012-04-02 17:02:33

回答

2

我会做这种方式:

  1. 运行您的月度支票并将yyyyMM值存储到NSUserDefaults
  2. 每次启动应用程序时,计算当前日期的yyyyMM值并将其与NSUserDefaults中存储的值进行比较。
  3. 如果不匹配,那么这是一个新的月份,所以再次运行您的月度检查。

它看起来像这样:

#define KEY_FOR_MONTHLY_LAST_CHECKED @"monthlyCheckedKey" 

- (NSInteger)yyyyMMFromDate:(NSDate *)date { 
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 
    [formatter setDateFormat:@"yyyyMM"]; 

    NSString *yyyyMMString = [formatter stringFromDate:date]; 
    return [yyyyMMString intValue]; 
} 

- (void)runMonthly { 
    // This code is run once per month 

    // Update NSUserDefaults 
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    [defaults setInteger:[self yyyyMMFromDate:[NSDate date]] forKey:KEY_FOR_MONTHLY_LAST_CHECKED]; 
    [defaults synchronize]; 
} 

- (void)checkMonthly { 
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    NSInteger lastCheckedyyyyMM = [defaults integerForKey:KEY_FOR_MONTHLY_LAST_CHECKED]; 
    NSInteger currentyyyyMM  = [self yyyyMMFromDate:[NSDate date]]; 

    if (lastCheckedyyyyMM != currentyyyyMM) { 
     [self runMonthly]; 
    } 
} 

所有您需要做的就是添加[self checkMonthly];,使其运行的每个应用程序启动。

而且,我会改变这样的:

if (iterator.intValue%100 > 12) { //jump all invalid month numbers 
    while (iterator.intValue%100 != 1) { 
     iterator = [NSNumber numberWithInt:iterator.intValue+1 ]; 
    } 
} 

要这样:

if (iterator.intValue % 100 == 13) { //jump all invalid month numbers 
    iterator = [NSNumber numberWithInt:iterator.intValue+88]; 
} 

它只是增加87到数字,当它击中13改变像201113至201201

+0

这看起来很有前途=)生病今天晚些时候试试,我现在手机:)提前致谢。 – 2012-04-03 07:15:09

+0

好的:-) 我实施了你的建议,在这里和那里做了一些调整(即我第一次称它为userdefaults中的值将返回0,所以它将不得不做200'000次迭代,这将使用户等待为3,5分钟):P 但感谢你的伟大的职位,和灵感。你已经赢得了它;-) – 2012-04-03 14:02:50

+0

是的,这只是为了告诉你如何每月运行一次代码并存储上次运行的代码。我为问题的底部添加了另一个小优化,可以节省一些时间。 – lnafziger 2012-04-03 16:47:33