2010-03-27 3 views
1

UPDATE 11/18/2011 Проверьте принятый ответ. Он работает и спасает жизнь!Загрузите XML-файл на отдельную тему, перезапишите старые и сохраните

Эй, все ... поэтому я пытаюсь выяснить, как это сделать. Я отскакивал от многих форумов, чтобы попытаться найти ответ, но не удался. Либо их процесс слишком сложный для меня, чтобы понять, либо просто переборщить. Я пытаюсь это сделать. У меня есть XML-файл в моем приложении. Его файл размером 500 тыс. Xml, который я не хочу, чтобы пользователю приходилось ждать при загрузке. SO ... Я положил его в свое приложение, которое убивает время загрузки, и делает приложение доступным в автономном режиме. То, что я хочу сделать, когда приложение загружается, в фоновом режиме (отдельный поток) загружает САМЫЙ XML-файл, который МОЖЕТ быть обновлен новыми данными. Когда файл xml будет завершен, я хочу ЗАМЕНИТЬ xml-файл, который использовался для загрузки файла. Любые предложения или подсказки кода были бы высоко оценены. Заранее спасибо!

+0

В чем ваш вопрос? Как анализировать XML-файл? Как загрузить файл через HTTP? Как использовать потоки? Как сравнить два файла? Здесь уже есть ответы на все.Вам нужно задать более сжатый и конкретный вопрос. –

+0

Спасибо за ответ shaggy ... мой вопрос в том, как загрузить файл по отдельному потоку (в фоновом режиме) и заменить существующий файл, который уже находится в приложении. Как я уже сказал, я посмотрел и посмотрел, но не смог найти подходящий ответ. – Louie

ответ

0

Я закончил тем, что понял это. Его старый пост, но он, похоже, получает много просмотров, поэтому я думал, что помогу некоторым людям. Имейте в виду, что этот код НЕ идеален ... есть много способов скинуть кошку .. и вот как я снимал мои. Это работает, вот и все!

Вкратце, как это работает ... Приложение запускает> проверки, есть ли сохраненная «дата/идентификатор». Он будет в формате «MMDD». Если нет сохраненной даты/ID, она создаст пустую, чтобы сравнить ее позже.

Когда сравнивается, не совпадает ли идентификатор, он загрузит новый файл. Сегодняшний день - 11/18/2011, поэтому идентификатор будет «1118». Если вы снова запустите приложение сегодня, идентификаторы будут соответствовать, поэтому приложение будет анализировать локальный XML-файл вместо загрузки другого. (его огромная экономия времени для меня, мой XML-файл составляет 2-4 мб.)

Этот код будет загружать новый 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, чтобы сохранить файл в папке Документы приложения.

Edit:

Вы пытаетесь записать файл в вашем пакете приложения. Вы не можете писать ни в какие файлы в комплекте - это часть безопасности Sandbox.

Вы должны поместить файл в каталог Документов приложения и написать там.

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

спасибо Shaggy, ваши предложения помогли, но у меня все еще есть небольшая проблема. Я обновил свой пост, чтобы показать, что это такое. – Louie

0

У вас есть контроль над XML на сервере? Вместо того, чтобы загружать XML-файл, независимо от того, отличается он или нет, сделать подпись SHA1 файла и сравнить его с сигнатурой SHA1 файла, который вы уже кэшировали.

Если подписи совпадают, нет необходимости обременять пользователя второй, бессмысленной загрузкой (особенно в сетях WWAN). Если подписи разные, только тогда вы запустите запрос загрузки в фоновом режиме.

Смежные вопросы