Frage

Gibt es eine eingebaute Funktion, die mir tiefe Kopie erlaubt eine NSMutableArray?

Ich sah mich um, manche Leute sagen, [aMutableArray copyWithZone:nil] als tiefe Kopie funktioniert. Aber ich habe versucht, und es scheint eine flache Kopie zu sein.

Im Moment bin ich manuell die Kopie mit einem for Schleife zu tun:

//deep copy a 9*9 mutable array to a passed-in reference array

-deepMuCopy : (NSMutableArray*) array 
    toNewArray : (NSMutableArray*) arrayNew {

    [arrayNew removeAllObjects];//ensure it's clean

    for (int y = 0; y<9; y++) {
        [arrayNew addObject:[NSMutableArray new]];
        for (int x = 0; x<9; x++) {
            [[arrayNew objectAtIndex:y] addObject:[NSMutableArray new]];

            NSMutableArray *aDomain = [[array objectAtIndex:y] objectAtIndex:x];
            for (int i = 0; i<[aDomain count]; i++) {

                //copy object by object
                NSNumber* n = [NSNumber numberWithInt:[[aDomain objectAtIndex:i] intValue]];
                [[[arrayNew objectAtIndex:y] objectAtIndex:x] addObject:n];
            }
        }
    }
}

, aber ich würde eine sauberere, prägnante Lösung gefällt.

War es hilfreich?

Lösung

Als Apple-docs Zustand,

  

Wenn Sie nur eine einstufiges-tiefe Kopie benötigen, können Sie explizit für einen Anruf ...

NSMutableArray *newArray = [[NSMutableArray alloc] 
                             initWithArray:oldArray copyItems:YES];

Der obige Code erstellt ein neues Array, dessen Mitglieder sind flache Kopien der Mitglieder des alten Arrays.

Beachten Sie, wenn Sie brauchen, um tief eine ganze verschachtelte Datenstruktur zu kopieren - was die verknüpften Apple-docs ein „true tiefe Kopie“ aufrufen - dann wird dieser Ansatz nicht ausreichen - siehe die anderen Antworten hier.

Andere Tipps

Der einzige Weg, ich weiß einfach, dies zu tun ist zu archivieren und dann sofort Ihren Array dearchivieren. Es fühlt sich ein bisschen wie ein Hack, ist aber tatsächlich explizit in der Apple-Dokumentation auf Sammlungen kopieren, in dem es heißt:

  

Wenn Sie eine echte tiefe Kopie benötigen, wie zum Beispiel, wenn Sie ein Array von Arrays haben, können Sie archivieren und dearchivieren dann die Sammlung, vorausgesetzt, die alle Inhalte auf dem NSCoding Protokoll entsprechen. Ein Beispiel für diese Technik ist in Listing 3 gezeigt.

     

Listing 3 Eine echte tiefe Kopie

NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
          [NSKeyedArchiver archivedDataWithRootObject:oldArray]];

Der Haken ist, dass das Objekt der NSCoding Schnittstelle unterstützen muß, werden, da diese verwendet werden, um die Daten zu speichern / laden.

Swift 2 Version:

let trueDeepCopyArray = NSKeyedUnarchiver.unarchiveObjectWithData(
    NSKeyedArchiver.archivedDataWithRootObject(oldArray))

Kopieren von Standard gibt eine flache Kopie

Das ist, weil copy Aufruf die gleichen wie copyWithZone:NULL ist auch das Kopieren mit der Standardzone bekannt. Der copy Anruf führt nicht zu einer tiefen Kopie. In den meisten Fällen wäre es Ihnen eine flache Kopie geben, aber in jedem Fall hängt es von der Klasse. Für eine gründliche Diskussion empfehle ich die Kollektionen Programmierung Themen auf der Apple Developer Website.

initWithArray: CopyItems: gibt einen einstöckigen tiefe Kopie

NSArray *deepCopyArray = [[NSArray alloc] initWithArray:someArray copyItems:YES];

NSCoding wird das Apple empfohlen, eine tiefe Kopie

schaffen

Für eine echte tiefe Kopie (Array von Arrays) Sie NSCoding und Archiv / unarchive das Objekt benötigt:

NSArray *trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:oldArray]];

Für Dictonary

NSMutableDictionary *newCopyDict = (NSMutableDictionary *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)objDict, kCFPropertyListMutableContainers);

Für Array

NSMutableArray *myMutableArray = (NSMutableArray *)CFPropertyListCreateDeepCopy(NULL, arrData, kCFPropertyListMutableContainersAndLeaves);

Nein, es ist etwas nicht in den Rahmen dafür gebaut. Cocoa Sammlungen unterstützen flache Kopien (mit copy oder den arrayWithArray: Methoden), aber nicht einmal über ein tiefes Kopie Konzept sprechen.

Das ist, weil „tiefe Kopie“ beginnt schwierig zu werden, wie der Inhalt Ihrer Sammlungen einschließlich Ihrer eigenen benutzerdefinierten Objekte beginnen zu definieren. Ist „tiefe Kopie“ bedeuten alle Objekt im Objektdiagramm ist eine eindeutige Referenz in Bezug auf alle Objekt im ursprünglichen Objektgraphen?

Wenn es einige hypothetische NSDeepCopying Protokoll ist, kann man diese einrichten und Entscheidungen in all Ihren Objekten, aber leider ist es nicht. Wenn Sie die meisten Objekte in Ihrem Diagramm gesteuert, können Sie dieses Protokoll selbst erstellen und implementieren es, aber Sie würden eine Kategorie der Stiftung Klassen nach Bedarf hinzufügen müssen.

@ AndrewGrant Antwort darauf hindeutet, die Verwendung von Schlüsseln Archivierung / Aufheben der Archivierung ist ein nonperformant aber richtig und saubere Art und Weise dies für beliebige Objekte zu erreichen. Dieses Buch sogar so weit, so deutet darauf hin, geht eine Kategorie für alle Objekte hinzufügen, die genau das tun tief Kopieren zu unterstützen.

Ich habe eine Abhilfe, wenn versucht, tiefe Kopie für JSON kompatible Daten zu erreichen.

Einfach NSData von NSArray nehmen NSJSONSerialization und anschließend JSON-Objekt erstellen, das wird eine ganz neue und frische Kopie NSArray/NSDictionary mit neuen Speicherreferenzen von ihnen erstellen.

Aber stellen Sie sicher, dass die Objekte von NSArray / NSDictionary und ihre Kinder müssen JSON serialisiert.

NSData *aDataOfSource = [NSJSONSerialization dataWithJSONObject:oldCopy options:NSJSONWritingPrettyPrinted error:nil];
NSDictionary *aDictNewCopy = [NSJSONSerialization JSONObjectWithData:aDataOfSource options:NSJSONReadingMutableLeaves error:nil];
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top