2015-06-26 91 views
0

使用解析函數執行每週一次,我試圖減少網絡的通話量,以努力限制非基本數據的我的API請求進行解析。要做到這一點,我認爲最好在同一天每週只調用一次函數,並將前一週的任何差異上傳到安裝類(用於在我的情況下同步推送通知通道)的iOS解析(減少API請求)在每週的同一天

那麼如何你每週在特定的一天每週打一次功能?如果這一天已經過去了,你會怎麼樣?所以說你想在每個星期四發生一些事情,但是用戶在週四之後的星期天才打開應用程序,你應該同步數據?

回答

3

在實踐中,我發現一個固定的時間間隔更有意義比日曆里程碑更多的病例。有了這個NSDate邏輯,我可以讓我的模型保證它的數據至多N秒過期。

要做到這一點,我有模型單隻保留最後更新日期的軌跡:

// initialize this to [NSDate distantPast] 
@property(nonatomic,strong) NSDate *lastUpdate; 

該接口還提供了一個非同步更新方法,如:

- (void)updateWithCompletion:(void (^)(BOOL, NSError *))completion; 

我覆蓋lastUpdate的合成獲取/設置器以包裹餘輝:

// user defaults in this case, but there are several ways to persist a date 
- (NSDate *)lastUpdate { 
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    return [defaults valueForKey:@"lastUpdate"]; 
} 

- (void)setLastUpdate:(NSDate *)lastUpdate { 
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    [defaults setValue:lastUpdate forKey:@"lastUpdate"]; 
    [defaults synchronize]; 
} 

最後,非同步更新不透明決定當前的數據是否足夠好,或者我們是否應該調用API parse.com ...

- (void)updateWithCompletion:(void (^)(BOOL, NSError *))completion { 

    NSTimeInterval sinceLastUpdate = -[self.lastUpdate timeIntervalSinceNow]; 
    NSTimeInterval updatePeriod = [self updatePeriod]; 
    if (sinceLastUpdate < updatePeriod) { 
     // our current data is new enough, so 
     return completion(YES, nil); 
    } else { 
     // our current data is stale, so call parse.com to update... 
     [...inBackgroundWithBlock:(NSArray *objects, NSError *error) { 
      if (!error) { 
       // finish the update here and persist the objects, then... 
       self.lastUpdate = [NSDate date]; 
       completion(YES, nil); 
      } else { 
       completion(NO, error); 
      } 
     }]; 
    } 
} 

的方法updatePeriod回答任何NSTimeInterval應用程序認爲是可以接受的年齡數據。通常,我會以相當高的頻率(如每日)從parse.config中獲取此信息。這樣,我可以調整模型更新的頻率,因爲我認爲適合野外客戶。

因此,我很少用NSDate邏輯來保持客戶端「最新足夠」,甚至可以動態地決定「足夠」的部分。

編輯 - 我們仍然可以保持簡潔並將我們的模型過期設置爲日曆日。我會做如下:

- (NSDate *)lastSaturday { 

    NSDate *now = [NSDate date]; 
    NSCalendar *calendar = [NSCalendar currentCalendar]; 

    NSDate *startOfWeek; 
    [calendar rangeOfUnit:NSCalendarUnitWeekOfMonth startDate:&startOfWeek interval:NULL forDate:now]; 

    NSDateComponents *components = [[NSDateComponents alloc] init]; 
    [components setDay:-1]; 
    return [calendar dateByAddingComponents:components toDate:startOfWeek options:0]; 
} 

現在,而不是當間隔到期更新,更新如果最後一次更新是在上週六(或週日什麼之前,你想...通過調整setDay調整: - N)

// change the date condition in updateWithCompletion 
if (self.lastUpdate == [self.lastUpdate earlierDate:[self lastSaturday]) { 
    // do the update 
} else { 
    // no need to update 
} 
+1

我喜歡你的答案,你的右邊,非常少的代碼,更簡潔的眼睛,但我的朋友是有這個問題是具有'updatePeriod'被設置爲一個特定的日期,而不是一個intervalPeriod儘管間隔時間在技術上是一週,但他們希望在週五專門上傳它,因爲他們在週六向特定頻道發送推送通知。所以那些在週五打開應用程序的人在下一次推送前同步他們的數據。但是對於那些只需要一般時間框架的人來說,你的答案非常棒! – soulshined

+0

謝謝,我更新了處理週週年紀念並保持相對較低的代碼。 – danh

+0

...並容易在眼睛上 – soulshined

1

你想要做的第一件事是檢查,如果今天是你想要的數據同步的一天。因此,舉例來說,我希望每個星期四都會調用一個函數將一個對象數組同步到「頻道」列。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 

    if ([self isTodayThursday]) { 

    } else { 

    } 
} 

- (BOOL) isTodayThursday { 
    NSDateFormatter *nameOfDayOfWeekFormatter = [[NSDateFormatter alloc] init]; 
    [nameOfDayOfWeekFormatter setDateFormat:@"EEEE"]; 

    if ([[nameOfDayOfWeekFormatter stringFromDate:[NSDate date]] isEqualToString:@"Thursday"]) { 
    return YES; 
    } 
    return NO; 
} 

很簡單,我們在這裏檢查星期幾的名稱是星期四。現在,我們要確保我們不會堆疊同步,並確保我們今天已經或未同步,如果是星期四。我們通過在NSUserDefaults驗證針對的對象:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 

    if ([self isTodayThursday]) { 
     if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"lastSynced"] isEqualToString:[[self dateFormatter] stringFromDate:[NSDate date]]]) { 
      //So we check against a custom date formatter that we want of the last sync date we performed, and if it's already been synced today, then do nothing 
     } else { 
      //if not, sync plist (or whatever we want) to channels array 
      [self syncPlistToParse]; 
     } 
    } else { 

    } 
} 

- (NSDateFormatter *)dateFormatter { 

    NSDateFormatter *formatedDate = [[NSDateFormatter alloc] init]; 
    [formatedDate setDateFormat:@"yyyyMMdd"]; 
    NSLog(@"Today is %@", [formatedDate stringFromDate:[NSDate date]]); 
    return formatedDate; 
} 

同步的plist到PFInstallation通道陣列

-(void)syncPlistToParse { 
    //First obtain whatever data you have from where ever you store it for the week. I chose to save all the data in a plist until the next sync date to reduce API calls. 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *path = [paths objectAtIndex:0]; 
    NSString *plistPath = [path stringByAppendingPathComponent:@"AlertSubscriptions.plist"]; 
    NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:plistPath]; 

    PFInstallation *currentInstallation = [PFInstallation currentInstallation]; 
    [currentInstallation addUniqueObjectsFromArray:array forKey:@"channels"]; 
    [currentInstallation saveInBackgroundWithBlock:^(BOOL success, NSError *error) { 
     if (success) { 
     //if successful save lastSynced date to NSUserDefaults to today 
     [[NSUserDefaults standardUserDefaults] setObject:[[self dateFormatter] stringFromDate:[NSDate date]] forKey:@"lastSynced"]; 
     } else { 
     //It wasn't a successful save so you can do whatever you want on an unsuccessful save, but I chose to use `saveEventually` as a back-up for connectivity issues etc 
     PFInstallation *currentInstallation = [PFInstallation currentInstallation]; 
     [currentInstallation addUniqueObjectsFromArray:array forKey:@"channels"]; 
     [currentInstallation saveEventually]; 
     } 
    }]; 
} 

所以,如果今天是週四我們如何確定它是否之前或之後的lastSynced日期以及我們如何確定如何設置下一個同步日期?

現在讓我們使用這些日期作爲一個例子:

    June 2015 
--------------------------------------------- 
|SUN | MON | TUES | WED | THURS | FRI | SAT | 
--------------------------------------------- 
| |  |  |  | 18 | 19 | 20 | 
--------------------------------------------- 
| 21 | 22 | 23 | 24 | 25 | 26 | 27 | 
--------------------------------------------- 
| 28 | 29 | 30 | 1 | 02 | 03 | 04 | 
--------------------------------------------- 

因此,可以說最後的同步週四月18日,並且用戶不打開他們的應用程序,直到六月(星期五)26我們需要驗證反對。我們已經檢查過,如果今天是星期四,而且我們知道這不是星期五26日以來的情況。因此,我們需要做兩項檢查和平衡,最重要的是,我們需要檢查星期五是否在當前同步週期(第19週五)的同一周內,但在這種情況下,自本週週期以來通過因爲我們沒有打開,直到過去的下一個週期(這應該是6月25日)

if ([self isTodayThursday]) { 
     if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"lastSynced"] isEqualToString:[[self dateFormatter] stringFromDate:[NSDate date]]]) { 
      //So we check against a custom date formatter that we want of the last sync date we performed, and if it's already been synced today, then do nothing 
     } else { 
      //if not, sync plist (or whatever we want) to channels array 
      [self syncPlistToParse]; 
     } 
    } else { 
     //Not Thursday. So we need to check if its within the same week of the sync cycle or passed that date 
     int lastSyncDate = [[self lastSyncDate] intValue]; 
     NSLog(@"lastSyncDate int %d", lastSyncDate); 
     int nextSyncDate = [[self nextSyncDate] intValue]; 
     NSLog(@"nextSyncDate int %d", nextSyncDate); 

     if (lastSyncDate < nextSyncDate) { 
      NSLog(@"next sync date is this coming thursday"); 
     } else { 
      // if not before thursday (already passed Thursday), sync and save today as lastSynced 
      [self syncPlistToParse]; 
     } 
    } 
} 

- (NSString *)lastSyncDate { 
    NSString *date = [[NSUserDefaults standardUserDefaults] objectForKey:@"lastSynced"]; 
    return date; 
} 

- (NSString *)nextSyncDate { 

    NSCalendar *cal = [NSCalendar currentCalendar]; 
    NSDate *lastSync = [[self dateFormatter] dateFromString:[self lastSyncDate]]; 
    NSDateComponents *components = [cal components:(NSCalendarUnitDay) fromDate:lastSync]; 
    [components setDay: +[self daysUntilNearestThursday]]; 
    NSDate *nextSync = [cal dateByAddingComponents:components toDate:lastSync options:0];  
    return [[self dateFormatter] stringFromDate:nextSync]; 
} 

-(int)daysUntilNearestThursday { 
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 
    [dateFormatter setDateFormat:@"EEEE"]; 
    //Note the day of the week is including today thats why it's always +1 
    if ([[dateFormatter stringFromDate:[NSDate date]] isEqualToString:@"Monday"]) { 
     return 4; 
    } 
    if ([[dateFormatter stringFromDate:[NSDate date]] isEqualToString:@"Tuesday"]) { 
     return 3; 
    } 
    if ([[dateFormatter stringFromDate:[NSDate date]] isEqualToString:@"Wednesday"]) { 
     return 2; 
    } 
    if ([[dateFormatter stringFromDate:[NSDate date]] isEqualToString:@"Friday"]) { 
     return 7; 
    } 
    if ([[dateFormatter stringFromDate:[NSDate date]] isEqualToString:@"Saturday"]) { 
     return 6; 
    } 
    if ([[dateFormatter stringFromDate:[NSDate date]] isEqualToString:@"Sunday"]) { 
     return 5; 
    } 
    return 0; 
} 

注意不要緊的nextSyncDate是什麼,因爲我們經常檢查它是否週四,然後再採取相應的行動

這是我個人的看法,有人問我這件事,這是我想出了。我覺得自己像一個孤單簡單的解決方案,在那裏,準確因此,通過各種手段重置nextSync到最近的週四,而不是[components setDay: +[self daysUntilNearestThursday]];,請加輸入/建議和意見,使這個爲未來的問題,求職者一個更好的機會。我認爲解析是太棒了,但同時它是一個業務,他們必須採取相應的行動,但像一切永遠爲可擴展的應用程序(2000個+用戶)API請求某些事情是怎麼樣的壞習慣,如果你打算在保持開發人員。這是我想要幫助我的朋友出門的一種選擇,它需要工作,並不是說它是唯一的方式,而是我認爲可以爲他們的項目工作的方式。請不要害羞,添加編輯或更正。