2013-04-13 79 views
0

對於從Web服務中獲取Web的應用程序,如果第一次運行是因爲數據在Docs目錄中不可用,或者可能需要很長時間才能從Web中獲取,那麼我已經包含了一個plist來解析爲CoreData。當網絡抓取/同步成功時,我確實有NSNotifications信號。第一次運行的邏輯應該是什麼?

目前在AppDelegate中applicationDidFinishLaunchingWithOptions我打電話:

[self checkIfFirstRun]; 

這是這樣的:

-(void)checkIfFirstRun{ 
    NSString *bundleVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:(NSString *)kCFBundleVersionKey]; 
    NSString *appFirstStartOfVersionKey = [NSString stringWithFormat:@"first_start_%@", bundleVersion]; 
    NSNumber *alreadyStartedOnVersion = [[NSUserDefaults standardUserDefaults] objectForKey:appFirstStartOfVersionKey]; 

    if(!alreadyStartedOnVersion || [alreadyStartedOnVersion boolValue] == NO) { 
     // IF FIRST TIME -> Preload plist data 
     UIAlertView *firstRun = [[UIAlertView alloc] initWithTitle:@"1st RUN USE LOCAL DB" 
                   message:@"FIRST" 
                   delegate:self 
                 cancelButtonTitle:@"Cancel" 
                 otherButtonTitles:@"Ok", nil]; 
     [firstRun show]; 
     NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; 
     [prefs setObject:[NSNumber numberWithBool:YES] forKey:appFirstStartOfVersionKey]; 
     [prefs synchronize]; 

     //Use plist 
     [self parsePlistIntoCD]; 

    } else { 
     UIAlertView *secondRun = [[UIAlertView alloc] initWithTitle:@"nTH RUN WEB FETCH" 
                  message:@"nTH" 
                  delegate:self 
               cancelButtonTitle:@"Cancel" 
               otherButtonTitles:@"Ok", nil]; 
     [secondRun show]; 


    } 
} 

這樣就OK了,我讓我的plist解析完美地融入我的CoreData分貝。

這裏是parsePlistIntoCD:

-(void)parsePlistIntoCD{ 
    self.managedObjectContext = [[SDCoreDataController sharedInstance] backgroundManagedObjectContext]; 
    // 3: Now put the plistDictionary into CD...create get ManagedObjectContext 
    NSManagedObjectContext *context = self.managedObjectContext; 
    NSError *error; 

    //Create Request & set Entity for request 
    NSFetchRequest *holidayRequest = [[NSFetchRequest alloc] init]; 
    NSEntityDescription *topicEntityDescription = [NSEntityDescription entityForName:@"Holiday" inManagedObjectContext:context]; 
    [holidayRequest setEntity:topicEntityDescription]; 

    //Create new NSManagedObject 
    //Holiday *holidayObjectToSeed = nil; 
    Holiday *newHoliday = nil; 
    //Execute fetch just to make sure? 
    NSArray *holidayFetchedArray = [context executeFetchRequest:holidayRequest error:&error]; 
    if (error) NSLog(@"Error encountered in executing topic fetch request: %@", error); 

    // No holidays in database so we proceed to populate the database 
    if ([holidayFetchedArray count] == 0) { 
     //Get path to plist file 
     NSString *holidaysPath = [[NSBundle mainBundle] pathForResource:@"PreloadedFarsiman" ofType:@"plist"]; 
     //Put data into an array (with dictionaries in it) 
     NSArray *holidayDataArray = [[NSArray alloc] initWithContentsOfFile:holidaysPath]; 
     NSLog(@"holidayDataArray is %@", holidayDataArray); 
     //Get number of items in that array 
     int numberOfTopics = [holidayDataArray count]; 
     //Loop thru array items... 
     for (int i = 0; i<numberOfTopics; i++) { 
      //get each dict at each node 
      NSDictionary *holidayDataDictionary = [holidayDataArray objectAtIndex:i]; 
      //Insert new object 
      newHoliday = [NSEntityDescription insertNewObjectForEntityForName:@"Holiday" inManagedObjectContext:context]; 
      //Parse all keys in each dict object 
      [newHoliday setValuesForKeysWithDictionary:holidayDataDictionary]; 
      //Save and or log error 
      [context save:&error]; 
      if (error) NSLog(@"Error encountered in saving topic entity, %d, %@, Hint: check that the structure of the pList matches Core Data: %@",i, newHoliday, error); 
     }; 
    } 
    [[SDSyncEngine sharedEngine] startSync]; 

} 

的事情是,我還需要確保,如果有互聯網可用,我的CoreData數據庫獲取與所獲取的網絡數據重新填充。

但是,如果我將呼叫留給[self parsePlistIntoCD];只有plist數據存在於CoreData中。第一或第n輪,我只得到plist數據。如果我評論這條線,我會得到我的網頁抓取數據。

爲什麼網頁抓取的數據替換了plist解析的數據?

回答

1

所以parsePlistIntoCD的邏輯基本上是

  • 如果在店內沒有對象,從plist中
  • 加載它們總是在[SDSyncEngine sharedEngine],它處理網絡下載和同步調用startSync

它在我看來像你的startSync將實際上被調用。所以我會在那裏尋找錯誤。您可以添加一條日誌語句或設置斷點,以驗證該代碼路徑實際上是否被遵循。

plist解析和Web數據獲取可能需要一些時間。這表明您應該在後臺執行這些操作,可能是使用GCD隊列。你不知道他們中的任何一個是否會成功。所以不要設置偏好,直到他們完成。

備註:您可以查詢BOOL的首選項數據庫,使您的代碼更短,因此更易於閱讀。

BOOL alreadyStartedOnVersion = [[NSUserDefaults standardUserDefaults] boolForKey:appFirstStartOfVersionKey]; 

[prefs setBool:YES forKey:appFirstStartOfVersionKey];    

您也可以簡單地@(YES)@(NO)更換numberWithBool:

爲了您的程序邏輯,我認爲是這樣的:

  • -applicationDidFinishLaunchingWithOptions:,檢查是否啓動的plist數據已經加載。忘記它是否是第一次運行。只要看看plist數據是否需要加載。也許稱之爲shouldLoadPlistData。或者,也許你需要將它與你正在運行的版本綁定,在這種情況下,你會存儲一個字符串latestPlistVersionLoaded
  • 如果您還沒有加載它,排隊一個塊來執行plist加載。在plist加載結束時,將shouldLoadPlistData設置爲NO,以注意不再需要加載plist數據。如果由於某種原因導致plist加載失敗(也許手機用完電池或者您的應用程序被用戶或系統中止),那麼在下次啓動時,您又回到了開始的位置。
  • 也檢查是否有網絡訪問。如果你這樣做,排列一個塊來檢索基於Web的數據,解析數據,然後在結束時更新首選項。

如果數據大,你可能要檢查點這項工作:

  • 我是否有完整的網頁更新?然後我完成了。否則...
  • 下載是否完成?耶,我有數據,讓我們加載它。
  • 如果沒有,我開始下載了嗎?

如果您的應用在下載過程中退出,此階段檢查點還將允許您向系統要求額外的時間。

parseListIntoCD感覺有點臃腫給我。它不僅僅是它的名字所暗示的。也許你可以將它重構爲一個檢查(shouldLoadPlist),一種可以導入(importPlist:intoContext:)的方法,以及一個可以觸發同步的方法。

我強烈建議你在通過工作NSManagedObjectContext作爲參數,而不是一些全局對象,分配MOCS(如[SDCoreDataController sharedInstance]出現的事情。它給你更多的控制,並允許你寫單元測試更如果你也通過plist的路徑,你現在有乾淨的代碼,應該在你每次調用時都有相同的行爲方式

你使用NSError **參數是一致的,NSError的值是未定義的你必須測試操作的結果,而不是錯誤的值,以確定你是否成功。成語總是

if (![someObject doTaskWithObject:foo error:&error]) { 
    // handle the error 
} 

請看看countForFetchRequest:error。通過執行提取和計數結果,它可以爲您提供與當前提取的信息相同的信息,但無需實例化NSManagedObjects。

+0

我在parsePlistIntoCD末尾調用webfetch ... lemme編輯... – marciokoko

相關問題