NSMutablearray переміщує об'єкт з індексу в індекс


74

У мене є UItableview із рядками, що можна перезаписувати, і дані знаходяться в NSarray. Отже, як я переміщую об’єкт у NSMutablearray, коли викликається відповідний делегат tableview?

Інший спосіб запитати це - як змінити порядок NSMutableArray?


1
Лістинг 8-2 на цій сторінці в Керівництві з програмування в табличному режимі показує, як це зробити.

Відповіді:


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

Це все. Подбати про кількість утримувань важливо, оскільки масив може бути єдиним, що посилається на об’єкт.


Поки ви тримаєте вказівник на річ, немає великих причин для автоматичного випуску, чи не так? Замість того, щоб утримувати перед видаленням і відпускати після вставки.
Sixten Otto

Так, це правда. Просто це на один рядок коду менше, однак я розумію вашу думку, що його безпосереднє випуск буде дешевшим. Я насправді не проти одного об’єкта, однак вам краще уникати цього в (щільному) циклі.
Joost

3
чому б не використовувати - (void) exchangeObjectAtIndex: (NSUInteger) idx1 withObjectAtIndex: (NSUInteger) idx2;
Сарен Інден,

4
@SarenInden Оскільки цей метод міняє місцями зазначені об'єкти, а не переміщує жоден в інше положення.
Joost

50

Категорія, що відповідає ARC:

NSMutableArray + Зручність.h

@interface NSMutableArray (Convenience)

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

@end

NSMutableArray + Зручність.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

Використання:

[mutableArray moveObjectAtIndex:2 toIndex:5];

6
Краще зменшіть, toIndexякщо ваш fromIndexменше, ніж ваш toIndex.
Річард

2
Точка Річарда дійсна за умови, що ви вказали toIndex, який посилається на позицію в масиві перед переміщенням. Якщо це ваше очікування, то вам, мабуть, слід зменшити toIndex, як запропоновано. Однак якщо ви вказуєте toIndex, який посилається на його остаточну позицію в масиві, тоді вам не слід зменшувати.
Олівер Пірмен

2
@OliverPearmain Вибачте, я намагаюся зрозуміти цю ідею. Використання вашого методу (із запропонованим зменшенням) масиву [A,B,C]після виклику до moveObjectAtIndex:0 toIndex:1призведе до [A,B,C]. Це логічно?
Стюарт

1
removeефективно зменшує індекси всіх об'єктів після fromIndex.
Річард

13

З Swift's Arrayце так просто:

Стрімкий 3

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

Стрімкий 2

extension Array {
    mutating func moveItem(fromIndex oldIndex: Index, toIndex newIndex: Index) {
        insert(removeAtIndex(oldIndex), atIndex: newIndex)
    }
}

2

Якщо у вас є NSArray, ви не можете нічого переміщати або впорядковувати, оскільки воно незмінне.

Вам потрібен NSMutableArray. Завдяки цьому ви можете додавати та замінювати об'єкти, що, звичайно, також означає, що ви можете змінити порядок масиву.


0

Ви не можете. NSArrayє незмінним. Ви можете скопіювати цей масив у NSMutableArray(або використовувати його в першу чергу). Змінна версія має методи переміщення та обміну своїми елементами.


вибачте, я мав на увазі змінність, але для nsmutablearray немає методу переміщення.
Джонатан.

5
Звичайно, є. Спробуйте -exchangeObjectAtIndex:withObjectAtIndex:. Також різні методи сортування.
Sixten Otto

2
Ні, хто перемикає 2 об’єкти, я хочу перемістити 1.
Джонатан.

Як зазначали інші афіші, вам потрібно видалити та додати заново.
Сікстен Отто

0

Я думаю, якщо я правильно розумію, ви можете зробити:

- (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
}

Тоді, що ви можете зробити, це додати метод категорії до NSMutableArray за допомогою методу - insertObject: atIndex: для обробки переміщення.


Так, я намагаюся знайти код для реалізації методу категорії, чи має це бути вставка, а потім видалити?
Джонатан.

0

Подібно до Tomasz, але з обробкою помилок поза діапазоном

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)
    }
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.