2012-05-18 3 views
0

Я разрабатываю приложение для iOS. Это игра.NSString из большого количества предметов

В игровом экране пользователь может загрузить объект подкласса из UIImageView. Чтобы сохранить игру, я разработал эту функцию, которая выполняет итерацию с помощью массива subviews основного представления и генерирует XML-строку.

#pragma mark I/O Functions 
-(NSString *)getXMLFromItemsView:(UIView *)items 
{ 
    int a; 
    NSString *XML = [[[NSString alloc] init] autorelease]; 

    XML = [XML stringByAppendingString:@"<PAGE>"]; 

    for (a=0;a<[items.subviews count];a++) 
    { 
     iItem *item = [items.subviews objectAtIndex:a]; 

     if ([item isKindOfClass:[iItem class]] || [item isKindOfClass:[iText class]]) 
     { 
      NSLog(@"INFO -> Saving...Item Id: %d",item.itemId); 

      XML = [XML stringByAppendingString:@"<ITEM>\n"]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<CLASS>%@</CLASS>\n",[item class]]]; 

      //OriginalTransform 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<originalTransform.a>%f</originalTransform.a>\n",item.originalTransform.a]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<originalTransform.b>%f</originalTransform.b>\n",item.originalTransform.b]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<originalTransform.c>%f</originalTransform.c>\n",item.originalTransform.c]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<originalTransform.d>%f</originalTransform.d>\n",item.originalTransform.d]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<originalTransform.tx>%f</originalTransform.tx>\n",item.originalTransform.tx]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<originalTransform.ty>%f</originalTransform.ty>\n",item.originalTransform.ty]]; 

      //InitialTransform 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<initialTransform.a>%f</initialTransform.a>\n",item.initialTransform.a]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<initialTransform.b>%f</initialTransform.b>\n",item.initialTransform.b]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<initialTransform.c>%f</initialTransform.c>\n",item.initialTransform.c]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<initialTransform.d>%f</initialTransform.d>\n",item.initialTransform.d]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<initialTransform.tx>%f</initialTransform.tx>\n",item.initialTransform.tx]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<initialTransform.ty>%f</initialTransform.ty>\n",item.initialTransform.ty]]; 

      //OriginalFrame 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<originalFrame.x>%f</originalFrame.x>\n",item.originalFrame.origin.x]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<originalFrame.y>%f</originalFrame.y>\n",item.originalFrame.origin.y]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<originalFrame.w>%f</originalFrame.w>\n",item.originalFrame.size.width]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<originalFrame.h>%f</originalFrame.h>\n",item.originalFrame.size.height]]; 

      //zOrder 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<zOrder>%d</zOrder>\n",item.zOrder]]; 

      //itemId 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<itemId>%d</itemId>\n",item.itemId]]; 

      //itemIdColor 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<itemIdColor>%d</itemIdColor>\n",item.itemIdColor]]; 

      //itemIdTexture 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<itemIdTexture>%d</itemIdTexture>\n",item.itemIdTexture]]; 

      //itemIdStyle 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<itemIdStyle>%d</itemIdStyle>\n",item.itemIdStyle]]; 

      //textureLevel 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<textureLevel>%d</textureLevel>\n",item.textureLevel]]; 

      //currentSizePercent 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentSizePercent>%f</currentSizePercent>\n",item.currentSizePercent]]; 

      //currentRotation 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentRotation>%f</currentRotation>\n",[item currentRotation]]]; 

      //holdItem 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<holdItem>%d</holdItem>\n",item.holdItem]]; 

      //isInverted 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<isInverted>%d</isInverted>\n",item.isInverted]]; 

      //isMerged 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<isMerged>%d</isMerged>\n",item.isMerged]]; 

      //selectedFrame 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<selectedFrame>%@</selectedFrame>\n",item.selectedFrame]]; 

      //mergedFrame 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<mergedFrame>%@</mergedFrame>\n",item.mergedFrame]]; 

      //NSLog(@"Item Saved Frame: X:%f Y:%f W:%f H:%f",item.frame.origin.x,item.frame.origin.y,item.frame.size.width,item.frame.size.height); 

      //currentFrame 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentFrame.x>%f</currentFrame.x>\n",item.frame.origin.x]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentFrame.y>%f</currentFrame.y>\n",item.frame.origin.y]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentFrame.w>%f</currentFrame.w>\n",item.frame.size.width]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentFrame.h>%f</currentFrame.h>\n",item.frame.size.height]]; 

      //currentBounds 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentBounds.x>%f</currentBounds.x>\n",item.bounds.origin.x]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentBounds.y>%f</currentBounds.y>\n",item.bounds.origin.y]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentBounds.w>%f</currentBounds.w>\n",item.bounds.size.width]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentBounds.h>%f</currentBounds.h>\n",item.bounds.size.height]]; 

      //currentTransform 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentTransform.a>%f</currentTransform.a>\n",item.transform.a]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentTransform.b>%f</currentTransform.b>\n",item.transform.b]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentTransform.c>%f</currentTransform.c>\n",item.transform.c]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentTransform.d>%f</currentTransform.d>\n",item.transform.d]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentTransform.tx>%f</currentTransform.tx>\n",item.transform.tx]]; 
      XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentTransform.ty>%f</currentTransform.ty>\n",item.transform.ty]]; 

      if ([[NSString stringWithFormat:@"%@",[item class]] isEqual:@"iText"]) 
      { 
       XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<currentText>%@</currentText>\n",[item text]]]; 

      } 

      XML = [XML stringByAppendingString:@"</ITEM>\n"]; 

     } 
    } 

    if (fondo) 
    { 
     XML = [XML stringByAppendingString:@"<FONDO>\n"]; 

     XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<selectedFrame>%@</selectedFrame>",fondo.selectedFrame]]; 
     XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<picturePath>%@</picturePath>",fondo.picturePath]]; 

     XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<idCurrentColor>%d</idCurrentColor>",fondo.idCurrentColor]]; 
     XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<idCurrentTexture>%d</idCurrentTexture>",fondo.idCurrentTexture]]; 
     XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<idCurrentStyle>%d</idCurrentStyle>",fondo.idCurrentStyle]]; 
     XML = [XML stringByAppendingString:[NSString stringWithFormat:@"\t<textureLevel>%d</textureLevel>",fondo.textureLevel]]; 

     XML = [XML stringByAppendingString:@"</FONDO>\n"]; 
    } 

    XML = [XML stringByAppendingString:@"</PAGE>"]; 
    NSLog(@"INFO -> ItemsViewXML: %@",XML); 
    return XML; 
} 

В настоящий момент этот метод работает нормально, если количество элементов для итерации невелико> 20. Но когда ему приходится обрабатывать более 50 элементов, приложение вылетает из-за памяти.

Я отлаживал этот метод с помощью инструментов и не обнаруживал утечек, но распределения увеличиваются до тех пор, пока не будет использоваться большой объем оперативной памяти.

Это не нормально, что для создания строки используется более 100 МБ виртуальной машины.

Кто-нибудь знает, что я теряю?

Спасибо.

ответ

1

Вы должны использовать NSMutableString при построении струны из деталей.

NSMutableString *xml = [NSMutableString string]; 
[xml appendFormat:@"....", ...]; 
[xml appendFormat:@"....", ...]; 

Но в этом случае вы даже можете захотеть использовать правильный XML сериалайзер как NSXMLDocument и т.д.

+0

Holly Мать дерьмо! Это работает как шарм !!!! Большое спасибо!!!! – NemeSys

2

Во-первых, вы не создаете строку, вы в настоящее время создание O (50) строк за объект. Это очень неэффективно - пространственно (как вы видите в использовании памяти) и временно (это должно занимать время).

Итак, вы можете указать с предложением Маттиаса и использовать изменяемую строку, к которой вы добавляете данные.

Это исправит много памяти-барометрическую вопросу вы видите, но по-прежнему будет медленным:
строки формата разбора относительно время и операция сохранения должна быть как можно быстрее.

Так что давайте просто игнорировать симптомы и посмотреть на проблему:

Вы в основном хотите архив иерархии объектов, не так ли?

В ваших пользовательских классах реализуют -initWithCoder: и -encodeWithCoder:.

Ваша операция сохранение затем становится таким же простым, как

NSData *encodedObjectGraph = [NSKeyedArchiver archivedDataWithRootObject:yourObjectGraphsRootGoesHere]; 
NSError *saveError; 
if ([encodedObjectGraph writeToURL:storeURL options:NSDataWritingAtomic error:&saveError]) 
    return; 

NSLog(@"Uh oh: %@", saveError); 

и ваша операция загрузки просто становится

NSError *loadError; 
NSData *savedObjectData = [NSData dataWithContentsOfURL:storeURL options:0 error:&loadError]; 
if (!savedObjectData) { 
    NSLog(@"No data at %@: %@", storeURL, loadError); 
    return; 
} 

objectGraphRoot = [NSKeyedUnarchiver unarchiveRootObjectWithData:savedObjectData]; 

(Обратите внимание, что unarchiveRootObjectWithData: возвращает autoreleased объекта!)

+0

Это похоже на сериализацию объекта, не так ли? Спасибо за подробный ответ. – NemeSys

+0

Да, это сериализация объекта. – danyowdee

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