2010-03-27 50 views
1

UPDATE 11/18/2011 檢查接受的答案。它的作品和它的救星!在單獨線程上加載XML文件,覆蓋舊的並保存

嘿大家...所以我試圖找出如何做到這一點。我已經反彈了很多論壇,試圖找到我的答案,但沒有成功。要麼他們的流程對我來說太複雜了,要麼就是矯枉過正。我正在試圖做的是這個。我的應用程序中有一個XML文件。它是一個500k xml文件,我不希望用戶在加載時不得不等待。所以......我把它放在我的應用程序中,它會導致加載時間縮短,並使應用程序脫機。我想要做的是,當應用程序加載時,在後臺(單獨線程)下載可能更新新數據的SAME xml文件。一旦xml​​文件完成,我想替換用來加載文件的xml文件。任何建議或代碼提示將不勝感激。提前致謝!

+0

你的問題到底是什麼?如何解析XML文件?如何通過HTTP下載文件?如何使用線程?如何比較兩個文件?這裏已經有所有這些答案。你需要提出一個更簡潔明確的問題。 – 2010-03-27 06:52:24

+0

感謝您的回覆毛茸茸的...我的問題是,如何在單獨的線程(在後臺)下載文件,並替換現有的應用程序中的文件。就像我說過的,我看了看,但看不到一個合適的答案。 – Louie 2010-03-27 07:06:01

回答

0

我最終弄清楚了這一點。它是一箇舊帖子,但它似乎仍然有很多觀點,所以我想我會幫助一些人。請記住,這段代碼並不完美......有很多方法可以爲一隻貓蒙皮......而這就是我剝皮的方式。它的作品,這就是最重要的!

簡而言之,它是如何工作的... 該應用程序啓動>檢查,看看是否有一個保存的「日期/ ID」。它將採用「MMDD」格式。如果沒有保存的日期/ ID,則會創建一個空白的日期以供日後比較。

當它比較id是否不匹配時,它會下載一個新文件。 今天的日期是2011年11月18日,所以ID將是「1118」。如果您今天再次啓動應用程序,這些ID將匹配,所以應用程序將解析本地xml文件,而不是下載另一個。 (它對我來說是一個巨大的節省時間,我的XML文件是2-4 mbs)。

此代碼將每天下載一個新的xml文件,除非應用程序已經在當天運行。然後它將使用本地文件。

//////////  applicationDidFinishLaunching  /////////// 
lastSyncArray = [[NSMutableArray alloc] initWithCapacity:0]; 

//check documents directory to see if you have a saved "date/ID" from earlier 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *docDir = [paths objectAtIndex:0]; 
NSString *fullFileNameSavedLastSyncArray = [NSString stringWithFormat:@"%@/lastSyncArray", docDir]; 
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:fullFileNameSavedLastSyncArray]; 

if (fileExists == YES) { 
    // yes you have a saved "date/ID" from earlier 
    NSArray * temp = [[NSArray alloc] init]; 
    temp = [NSKeyedUnarchiver unarchiveObjectWithFile:fullFileNameSavedLastSyncArray]; 

    for (int i=0; i<[temp count]; i++){ 

     [lastSyncArray addObject:[temp objectAtIndex:i]]; 

    }// end for loop 


} 
else { 

    //insert blank data for comparison later 
    [lastSyncArray addObject:@""]; 
} 

[NSThread detachNewThreadSelector:@selector(checkXMLFile) toTarget:self withObject:nil]; 

/////////// end applicationDidFinishLaunching ///////////// 




// own function in App Delegate 
-(void)checkXMLFile { 


    //get current month/day 
    NSDateComponents *components = [[NSCalendar currentCalendar] components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit fromDate:[NSDate date]]; 
    NSInteger day = [components day]; 
    NSInteger month = [components month]; 
    NSString * currentTimeString = [NSString stringWithFormat:@"%d%d",month,day]; 


    //check if file exists first 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString * fileName = [NSString stringWithFormat:@"inventory.xml"]; 
    NSString *xmlPath = [documentsDirectory stringByAppendingPathComponent:fileName]; 
    BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:xmlPath]; 

    if (fileExists == YES) { 
     //yes there is a saved xml file 
     NSLog(@"There is a saved file from before"); 

     //compare last sync date and current date. if they mismatch... download new file 
     NSString * sToCompare = [[lastSyncArray objectAtIndex:0] description]; 

     if ([sToCompare compare:currentTimeString]==0) { 
      //its a match this has been downloaded today. no need to re download. 
     } 
     else { 

      //clear out old download date and save new 
      [lastSyncArray removeAllObjects]; 

      //save new date   
      [lastSyncArray addObject:currentTimeString]; 

      // we are downloading a new xml file and saving it 
      NSString * pdfURL2 = [NSString stringWithFormat:@"http://myfile.com/inventory.xml"]; 
      NSString *urlString = pdfURL2; 
      NSURL *url = [NSURL URLWithString:urlString]; 
      NSData * xmlData = [NSData dataWithContentsOfURL:url]; 

      if (!xmlData) { 


      } 
      else{ 
       NSLog(@"EXISTS"); 
       NSLog(@"Begin to save xml"); 
       NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
       NSString *documentsDirectory = [paths objectAtIndex:0]; 
       NSString * fileName = [NSString stringWithFormat:@"inventory.xml"]; 
       NSLog(@"File to save: %@",fileName); 
       NSString *xmlPath = [documentsDirectory stringByAppendingPathComponent:fileName]; 
       [xmlData writeToFile:xmlPath atomically:YES]; 
       NSLog(@"XML saved"); 


      } 
     } 



    } 
    else { 
     NSLog(@"MISSING XML"); 
     //no there is not a saved xml file this must be first load go ahead and download 
     NSString * pdfURL2 = [NSString stringWithFormat:@"http://myfile.com/inventory.xml"]; 
     NSString *urlString = pdfURL2; 
     NSURL *url = [NSURL URLWithString:urlString]; 
     NSData * xmlData = [NSData dataWithContentsOfURL:url]; 

     if (!xmlData) { 


     } 
     else{ 
      NSLog(@"EXISTS"); 
      NSLog(@"Begin to save xml"); 
      NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
      NSString *documentsDirectory = [paths objectAtIndex:0]; 
      NSString * fileName = [NSString stringWithFormat:@"inventory.xml"]; 
      NSLog(@"File to save: %@",fileName); 
      NSString *xmlPath = [documentsDirectory stringByAppendingPathComponent:fileName]; 
      [xmlData writeToFile:xmlPath atomically:YES]; 
      NSLog(@"XML saved"); 


     } 
    } 


    [self sendToParser]; 


} 



- (void)sendToParser{ 

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 


    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString *documentsDirectory = [paths objectAtIndex:0]; 
    NSString * fileName = [NSString stringWithFormat:@"inventory.xml"]; 
    NSString *xmlPath = [documentsDirectory stringByAppendingPathComponent:fileName]; 

    [self parseXMLFileAtURL:xmlPath]; 

    [pool release]; 

} 


- (void)parseXMLFileAtURL:(NSString *)URL //URL is the file path (i.e. /Applications/MyExample.app/MyFile.xml) 
{ 
    //you must then convert the path to a proper NSURL or it won't work 
    NSURL *xmlURL = [NSURL fileURLWithPath:URL]; 
    NSData * data = [[NSData alloc] init]; 
    data = [NSData dataWithContentsOfURL:xmlURL]; 

    // here, for some reason you have to use NSClassFromString when trying to alloc NSXMLParser, otherwise you will get an object not found error 
    // this may be necessary only for the toolchain 
    NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; 

    // Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks. 
    [parser setDelegate:self]; 

    // Depending on the XML document you're parsing, you may want to enable these features of NSXMLParser. 
    [parser setShouldProcessNamespaces:NO]; 
    [parser setShouldReportNamespacePrefixes:NO]; 
    [parser setShouldResolveExternalEntities:NO]; 

    [parser parse]; 

    [parser release]; 
} 




- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespace qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
{ 

    //your code here 
    return; 

} 

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 
{ 
    //your code here 
} 


- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespace qualifiedName:(NSString *)qName 
{ 
    //your code here 
    return; 
} 


- (void)parserDidEndDocument:(NSXMLParser *)parser{ 
    //your code here 

} 






////////// application will terminate ///////////// 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *docDir = [paths objectAtIndex:0]; 
NSString *fullFileNameSavedLastSyncArray = [NSString stringWithFormat:@"%@/lastSyncArray", docDir]; 
NSFileManager *fileManager = [NSFileManager defaultManager]; 
BOOL fileExists fileExists = [[NSFileManager defaultManager] fileExistsAtPath:fullFileNameSavedLastSyncArray]; 

//check to see we have a last sync array 
fileExists = [[NSFileManager defaultManager] fileExistsAtPath:fullFileNameSavedLastSyncArray]; 
if (fileExists == YES) { 
    //file exists delete it so we can recreate it here in a sec 
    [fileManager removeItemAtPath:fullFileNameSavedLastSyncArray error:NULL]; 
} 
if ([lastSyncArray count] >=1) { 
    [NSKeyedArchiver archiveRootObject:lastSyncArray toFile:fullFileNameSavedLastSyncArray]; 
} 


////// end application will terminate /////////// 
2

您可以使用NSOperation異步下載文件。

您可以使用NSFileManager將文件保存到應用程序的Documents目錄中。

編輯:

您正在嘗試寫入應用程序包中的文件。您不能寫入該包中的任何文件 - 它是Apple安全沙箱模型的一部分。

您應該將文件放在應用程序的Documents目錄中並寫入它。

NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString* documentsDirectoryPath = [paths objectAtIndex:0]; 
NSString* filePath = [documentsDirectoryPath stringByAppendingPathComponent:@"myfile.xml"]; 
+0

謝謝Shaggy,你的建議有幫助,但我仍然有一個小問題。我已更新我的帖子,以顯示它是什麼。 – Louie 2010-03-30 21:10:33

0

您是否可以控制服務器上的XML?不要下載XML文件,不管它是否不同,請爲該文件創建SHA1簽名,並將其與您已緩存的文件的SHA1簽名進行比較。

如果簽名相同,則無需爲第二個無意義的下載(特別是在WWAN網絡上)下載用戶。如果簽名不同,那麼只有在後臺纔會觸發下載請求。