NSMutablearray verschiebt das Objekt von Index zu Index

74

Ich habe eine UItableview mit wiederordnbaren Zeilen und die Daten befinden sich in einem NSarray. Wie verschiebe ich ein Objekt im NSMutablearray, wenn der entsprechende Tableview-Delegat aufgerufen wird?

Eine andere Möglichkeit, dies zu fragen, besteht darin, ein NSMutableArray neu zu ordnen.

Jonathan.
quelle
1
Listing 8-2 auf dieser Seite im Programmierhandbuch für die Tabellenansicht zeigt, wie das geht.

Antworten:

118
id object = [[[self.array objectAtIndex:index] retain] autorelease];
[self.array removeObjectAtIndex:index];
[self.array insertObject:object atIndex:newIndex];

Das ist alles. Es ist wichtig, sich um die Anzahl der Aufbewahrungen zu kümmern, da möglicherweise nur das Array auf das Objekt verweist.

Joost
quelle
Wenn Sie einen Zeiger auf die Sache behalten, gibt es nicht viel Grund für eine automatische Freigabe, oder? Anstatt vor dem Entfernen zu behalten und nach dem Einsatz freizugeben.
Sixten Otto
Ja das stimmt. Es ist nur so, dass es eine Codezeile weniger ist, aber ich verstehe Ihren Standpunkt, dass die direkte Veröffentlichung weniger teuer sein wird. Ich habe nichts gegen ein Objekt, aber Sie sollten dies besser in einer (engen) Schleife vermeiden.
Joost
3
Warum nicht - (void) exchangeObjectAtIndex: (NSUInteger) idx1 withObjectAtIndex: (NSUInteger) idx2;
Saren Inden
4
@SarenInden Da diese Methode die angegebenen Objekte vertauscht, verschieben Sie kein einzelnes Objekt an eine andere Position.
Joost
48

ARC-konforme Kategorie:

NSMutableArray + Convenience.h

@interface NSMutableArray (Convenience)

- (void)moveObjectAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex;

@end

NSMutableArray + Convenience.m

@implementation NSMutableArray (Convenience)

- (void)moveObjectAtIndex:(NSUInteger)fromIndex toIndex:(NSUInteger)toIndex
{
    // Optional toIndex adjustment if you think toIndex refers to the position in the array before the move (as per Richard's comment)
    if (fromIndex < toIndex) {
        toIndex--; // Optional 
    }

    id object = [self objectAtIndex:fromIndex];
    [self removeObjectAtIndex:fromIndex];
    [self insertObject:object atIndex:toIndex];
}

@end

Verwendung:

[mutableArray moveObjectAtIndex:2 toIndex:5];
Oliver Pearmain
quelle
6
Du solltest besser dekrementieren, toIndexwenn dein fromIndexkleiner ist als dein toIndex.
Richard
2
Richards Punkt ist gültig, vorausgesetzt, Sie geben einen toIndex an, der sich auf die Position im Array vor dem Verschieben bezieht. Wenn dies Ihre Erwartung ist, sollten Sie den toIndex wahrscheinlich wie vorgeschlagen dekrementieren. Wenn Sie jedoch einen toIndex angeben, der sich auf seine endgültige Position im Array bezieht, sollten Sie ihn nicht dekrementieren.
Oliver Pearmain
2
@OliverPearmain Entschuldigung, ich habe Mühe, diese Idee zu verstehen. Mit Ihrer Methode (mit dem vorgeschlagenen Dekrement) einer Anordnung [A,B,C]nach einem Aufruf moveObjectAtIndex:0 toIndex:1würde zu [A,B,C]. Ist das logisch?
Stuart
1
removedekrementiert effektiv die Indizes aller Objekte nach fromIndex.
Richard
13

Mit Swift's ist Arrayes so einfach:

Swift 3

extension Array {
    mutating func move(at oldIndex: Int, to newIndex: Int) {
        self.insert(self.remove(at: oldIndex), at: newIndex)
    }
}

Swift 2

extension Array {
    mutating func moveItem(fromIndex oldIndex: Index, toIndex newIndex: Index) {
        insert(removeAtIndex(oldIndex), atIndex: newIndex)
    }
}
Tomasz Bąk
quelle
2

Wenn Sie eine haben NSArray, können Sie nichts verschieben oder neu anordnen, da es unveränderlich ist.

Du brauchst eine NSMutableArray. Damit können Sie Objekte hinzufügen und ersetzen, was natürlich auch bedeutet, dass Sie das Array neu anordnen können.

bbum
quelle
0

Das kannst du nicht. NSArrayist unveränderlich. Sie können dieses Array in ein Array kopieren NSMutableArray(oder es zuerst verwenden). Die veränderbare Version verfügt über Methoden zum Verschieben und Austauschen ihrer Elemente.

Sixten Otto
quelle
Entschuldigung, ich meinte veränderlich, aber es gibt keine Verschiebungsmethode für nsmutablearray.
Jonathan.
5
Sicher gibt es. Versuchen Sie es -exchangeObjectAtIndex:withObjectAtIndex:. Auch die verschiedenen Sortiermethoden.
Sixten Otto
2
Nein, das 2 Objekte wechselt, ich möchte 1 bewegen.
Jonathan.
Wie andere Poster bereits erwähnt haben, müssen Sie sie entfernen und erneut hinzufügen.
Sixten Otto
0

Ich denke, wenn ich richtig verstehe, können Sie Folgendes tun:

- (void) tableView: (UITableView*) tableView moveRowAtIndexPath: (NSIndexPath*)fromIndexPath toIndexPath: (NSIndexPath*) toIndexPath

{
    [self.yourMutableArray moveRowAtIndex: fromIndexPath.row toIndex: toIndexPath.row]; 
    //category method on NSMutableArray to handle the move
}

Anschließend können Sie NSMutableArray mit der Methode - insertObject: atIndex: eine Kategoriemethode hinzufügen, um die Verschiebung zu handhaben.

saurb
quelle
Ja, ich versuche, den Code für die zu implementierende Kategoriemethode zu finden. Sollte es sich um eine Einfügung handeln und diese dann entfernen?
Jonathan.
0

Ähnlich wie Tomasz, jedoch mit Fehlerbehandlung außerhalb des Bereichs

enum ArrayError: ErrorType {
    case OutOfRange
}

extension Array {
    mutating func move(fromIndex fromIndex: Int, toIndex: Int) throws {
        if toIndex >= count || toIndex < 0 {
            throw ArrayError.OutOfRange
        }
        insert(removeAtIndex(fromIndex), atIndex: toIndex)
    }
}
David Pettigrew
quelle