0

私はiOS用のアプリを開発しています。これはゲームです。

ゲーム画面では、ユーザーは 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 を超えるアイテムを処理する必要がある場合、メモリが原因でアプリがクラッシュします。

インストルメントを使用してこのメ​​ソッドをデバッグしましたが、検出されたリークはありませんが、大量の RAM を使用するまで割り当てが増加します。

文字列の作成に 100 MB を超える VM が使用されるのは正常ではありません。

私がどれを失っているか知っている人はいますか?

ありがとう。

4

2 に答える 2

2

まず、文字列を作成ていません。現在、オブジェクトごとに O(50) 文字列を作成しています。これは非常に非効率的です — 空間的に (メモリ使用量でわかるように)、時間的にも (かなりの時間がかかるはずです)。

したがって、Mattias˚ の提案に従って、データを追加する変更可能な文字列を使用できます

これにより、現在発生している多くのメモリ プレッシャの問題が解決されますが、それでも遅くはありません。
フォーマット文字列の解析には比較的時間がかかり、保存操作はできるだけ高速にする必要があります。

それでは、症状を無視して問題を見てみましょう。

基本的に、オブジェクト階層のアーカイブが必要ですよね?

カスタム クラスで、 と を実装-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:(自動解放されたオブジェクトを返すことに注意してください!)

于 2012-05-18T17:18:13.793 に答える
1

NSMutableStringパーツから文字列を構築するときに使用する必要があります。

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

NSXMLDocumentただし、この場合、適切な XML シリアライザーなどを使用することもできます。

于 2012-05-18T16:41:16.710 に答える