2012-03-31 16 views
0

in einem aktuellen projekt verwalte ich entities Month, die informationen über vergangene monat 'enthalten und einer von ihnen steht natürlich für den aktuellen monat.monatliche update von coredata objekten

Jeder Monat enthält ein number Attribut, das als Kennung für das Jahr dient. Das Attribut enthält eine NSNumber of type int32, die den Monat mit dem Format identifiziert: YYYYMM. So hat beispielsweise Februar 2011 das Attribut number = 201102.

In der Anwendung gibt der Benutzer Daten ein, die immer mit dem aktuellen Monat behaftet sind. Der Benutzer hat keine Möglichkeit, Monatsdaten des abgelaufenen Monats zu bearbeiten, zu löschen oder hinzuzufügen.

so hält meine coredata 1 month für den aktuellen Monat, der aktualisiert wird, und so viele andere Objekte wie Monat sind vergangen, in denen der Benutzer Daten eingegeben hat.

Ich habe eine Funktion

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

in meiner DAO-Klasse, die ein neues month Objekt in Coredata erstellt oder aktualisiert den aktuellen Monat, wenn der übergebene NSNumber den aktuellen Monat entspricht.

hier der schwierige Teil

der Benutzer jedes Mal kommt in einem neuen Monat, um die Anwendung zum ersten Mal öffnet, muss ich die Anwendung alle passed month zu archivieren, die noch einen entsprechenden Kern-Datenobjekt nicht haben.

, wie ich es tat bisher (zu Testzwecken) sieht wie folgt aus:

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]; 
     } 
    } 

ich habe dies in meiner Fabrik, die bei Start der Anwendung aufgerufen wird.

Fragendiese sehr hässlich ist und schafft eine Menge Aufwand

  • wie kann ich, wenn es das erste Mal im Monat bestimmen der Benutzer die App öffnet, so dass ich jede einzelne nicht archiviert werden müssen Zeit beginnt er die App?
  • sieht jemand von Ihnen eine bessere Möglichkeit, durch bestandenen Monat zu iterieren?
  • könnte es sogar einen Weg geben, den ich nicht jeden Monat holen muss, um festzustellen, ob es bereits existiert?
  • kann ich irgendwie herausfinden, was der letzte Monat archiviert wurde, und die Iteration von dort starten?

ich würde wirklich etwas Hilfe, Dank im Voraus zu schätzen wissen =) wenn Sie mehr Code benötigen, oder etwas finden, könnte in der Frage fehlt, schlecht glücklich sein, es zu schaffen.

note dies ein Mock-up-Code ist, dass ich für den Test verwendet wird, ist die Frage nicht, wie Sie den Code zu verbessern, aber wie der Algorithmus zu verbessern =)

+0

A zu ändern Eine ziemlich einfache Änderung wäre, mit dem aktuellen Monat zu beginnen und rückwärts zu gehen, bis Sie einen Monat ohne Daten erreichen. – lnafziger

+0

Ich hatte diese vorherige - aber, es ist möglich, dass es tatsächlich war ein Monat ohne Daten =), so würde es abbrechen. es ist möglich mit der Anwendung zu lassen, sagen wir haben Daten für Jan März, aber keine im April und Mai =) die wichtigere Frage ist, wie Sie den Anruf auf 1 Mal pro Monat =) –

+0

Okay, nun die Wette, um es zu tun wäre, das Datum, das Sie zuletzt in NSUserDefaults eingecheckt haben, zu speichern und das bei jedem Start zu vergleichen, aber ich habe keine Zeit, den Code jetzt zu schreiben, sorry! – lnafziger

Antwort

2

ich es auf diese Weise tun würde:

  1. Führen Sie Ihren monatlichen Scheck aus und speichern Sie den JJJJMM-Wert unter NSUserDefaults.
  2. Jede Anwendung starten, berechnen Sie den JJJJMM Wert für das aktuelle Datum und vergleichen Sie es mit dem Wert in NSUserDefaults gespeichert.
  3. Wenn es nicht übereinstimmt, dann ist es ein neuer Monat, also führen Sie Ihre monatlichen Schecks erneut aus.

Es sieht wie folgt aus:

#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]; 
    } 
} 

Alles, was Sie tun müssen, ist [self checkMonthly]; hinzuzufügen, so dass sie bei jedem Programmstart ausgeführt wird.

Auch würde ich das ändern:

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

Um dies:

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

Es kommt noch hinzu, 87 auf die Zahl, wenn es 13 trifft so etwas wie 201.113-201.201

+0

das sieht sehr vielversprechend aus =) krank versuche es später später heute bin ich mobil :) danke im voraus. –

+0

allright :-) Ich habe Ihren Vorschlag mit ein paar Verbesserungen hier und dort implementiert (dh wenn ich es das erste Mal nenne, gibt der Wert in userdefaults 0 zurück, also müsste es 200'000 Iterationen machen, was den Benutzer warten lassen würde für 3,5 Minuten): P aber danke für Ihren tollen Beitrag und die Inspiration. Sie haben es gut verdient ;-) –

+0

Ja, das war nur dazu gedacht, Ihnen zu zeigen, wie Sie den Code einmal im Monat ausführen und speichern, wann das letzte Mal ausgeführt wurde. Ich habe eine andere kleine Optimierung, die ich am Ende der Frage für Sie hinzugefügt habe, die einige Zeit sparen wird. – lnafziger