Как заменить объект в NSMutableArray по заданному индексу новым объектом - PullRequest
34 голосов
/ 17 июня 2010

У меня есть объект NSMutableArray (сохранен, синтезирован как все), который инициируется очень хорошо, и я легко могу добавить к нему объекты, используя метод addObject: Но если я хочу заменить объект с определенным индексом новым в этом NSMutableArray, это не сработает.

Например:

ClassA.h

@interface ClassA : NSObject {
    NSMutableArray *list;
}

@property (nonatomic, copy, readwrite) NSMutableArray *list;

@end

ClassA.m:

#import "ClassA.h"

@implementation ClassA

@synthesize list;

- (id)init 
{
    [super init];
    NSMutableArray *localList = [[NSMutableArray alloc] init];
    self.list = localList;
    [localList release];
    //Add initial data
    [list addObject:@"Hello "];
    [list addObject:@"World"];
}


// Custom set accessor to ensure the new list is mutable
- (void)setList:(NSMutableArray *)newList 
{
    if (list != newList) 
    {
        [list release];
        list = [newList mutableCopy];
    }
}

-(void)updateTitle:(NSString *)newTitle:(NSString *)theIndex
{
    int i = [theIndex intValue]-1;
    [self.list replaceObjectAtIndex:i withObject:newTitle];
    NSLog((NSString *)[self.list objectAtIndex:i]);  // gives the correct output
}

Однако изменение остается верным только внутри метода. из любого другого метода,

NSLog((NSString *)[self.list objectAtIndex:i]);

дает то же самое старое значение.

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

Я даже модифицировал метод следующим образом, но результат тот же:

-(void)updateTitle:(NSString *)newTitle:(NSString *)theIndex
{
    int i = [theIndex intValue]-1;

    NSMutableArray *localList = [[NSMutableArray alloc] init];
    localList = [localList mutableCopy];
    for(int j = 0; j < [list count]; j++)
    {
        if(j == i)
        {
            [localList addObject:newTitle];
            NSLog(@"j == 1");
            NSLog([NSString stringWithFormat:@"%d", j]);
        }
        else
        {
            [localList addObject:(NSString *)[self.list objectAtIndex:j]];
        }
    }
    [self.list release];
    //self.list = [localList mutableCopy];
    [self setList:localList];
    [localList release];
}

Пожалуйста, помогите, ребята:)

Ответы [ 6 ]

125 голосов
/ 20 апреля 2013

Это делает трюк:

[myMutableArray replaceObjectAtIndex:index withObject:newObject];
8 голосов
/ 17 июня 2010

ОК, здесь есть несколько недоразумений.

Вам не нужно брать mutableCopy недавно созданного NSMutableArray, чтобы сделать его изменчивым.Это уже изменчиво - ключ в названии.Это нужно делать в установщике только в том случае, если вы хотите, чтобы свойство имело семантику copy (которую вы установили и, конечно, для этого могут быть веские причины).Но вам определенно не нужно было бы делать это, как показано в обновленном коде updateTitle, и при этом просачивается localList.

Также вы смешиваете доступ к свойству через self.list и прямое использование.list в том же методе.Это не является недействительным, но это плохая практика, потому что это означает, что все, что делают методы доступа, случайно обходит.Обычно свойства, подобные этим, делают все через self , за исключением в самих средствах доступа, или в dealloc, и, возможно, в init (мнения по этому поводу расходятся), где вы могли бы получить доступнепосредственно к ивару.

Кроме того, никогда не звоните [self.list release] - средство доступа к собственности не дает владения вызывающей стороне.Делая это, вы закончите слезами, запомните мои слова.

Ничто из этого не дает ответа на реальный вопрос, вот почему ваши изменения исчезают.Исходный код updateTitle, насколько я вижу, не объясняет этого - он должен работать.Поэтому я подозреваю, что где-то еще вы звоните self.list = theOriginalList и, следовательно, отменяете ваши изменения.

Обновление:

Просто ради аргумента, я собираюсьнапишите, что я думаю, что код, который вы разместили, вероятно, означал , чтобы выглядеть.Я сохранил ваше использование строки для передачи индекса в updateTitle, но я хотел бы отметить, что делать это таким образом неправильно .Это число, вы должны передать его как таковое.Даже если номер взят из текстового поля или чего-то еще, это вызывает беспокойство вызывающего абонента;интерфейс класса должен указывать число.Точно так же очевидное изменение от 1 на основе индексации на основе 0.Пожалуйста, не делайте этого неявно, это рецепт для слез и скрежета зубов.

ClassA.h:

#import <Cocoa/Cocoa.h>
@interface ClassA : NSObject
{
    NSMutableArray* list;
}
- (void) setList:(NSMutableArray*)newList;
- (void) updateTitle:(NSString*)newTitle forIndex:(NSString*)theIndex;
@property (nonatomic, copy, readwrite) NSMutableArray* list;
@end

ClassA.m:

#import "ClassA.h"

@implementation ClassA
@synthesize list;

- (id) init
{
    if ( self = [super init] )
    {
        list = [[NSMutableArray alloc] init];
        [list addObject:@"Hello "];
        [list addObject:@"World"];
    }
    return self;
}

- (void) setList:(NSMutableArray*) newList
{
    if ( list != newList )
    {
        [list release];
        list = [newList mutableCopy];
    }
}

- (void) updateTitle:(NSString*)newTitle forIndex:(NSString*)theIndex
{
    int i = [theIndex intValue] - 1;
    [self.list replaceObjectAtIndex:i withObject:newTitle];
}

- (void) dealloc
{
    [list release];
    [super dealloc];
}

@end

Это устраняет различные проблемы, но обратите внимание, что updateTitle в основном одинаковы.Если вы бросите все это, и изменения все еще не сохранятся, вы определенно сбрасываете list куда-то.

6 голосов
/ 01 декабря 2015

Более прямой ответ:

self.list[i] = newTitle;

Это просто работает как

[self.list replaceObjectAtIndex:i withObject:newTitle];
0 голосов
/ 23 декабря 2016

Наконец-то есть идеальный код,

let DuplicateArray: NSArray = array
let DuplicateMutableArray: NSMutableArray = []
DuplicateMutableArray.addObjectsFromArray(DuplicateArray as [AnyObject])
var dic = (DuplicateMutableArray[0] as! [NSObject : AnyObject])
dic["is_married"] = "false"
DuplicateMutableArray[self.SelectedIndexPath] = dic
array = []
array = (DuplicateMutableArray.copy() as? NSArray)!

// Вывод будет похож на

array =  [
  {
    "name": "Kavin",
    "Age": 25,
    "is_married": "false"
  },
  {
    "name": "Kumar",
    "Age": 25,
    "is_married": "false"
  }
]
0 голосов
/ 28 марта 2016

Для Swift вы можете попробовать:

 //if you have indexPath
   self.readArray.removeAtIndex((indexPath?.row)!)
   self.readArray.insert(tempDict, atIndex: (indexPath?.row)!)
 //tempDict is NSDictionary object.
0 голосов
/ 02 декабря 2015

Посмотрите на эту строку:

@property (nonatomic, copy, readwrite) NSMutableArray *list;

copy означает, что всякий раз, когда вы обращаетесь к self.list, вы не получаете переменную экземпляра "_list" вашего объекта, нокопия этого списка.Если вы пишете [self.list replaceObjectAtIndex ...], вы заменяете объект в этой копии вашего списка;исходный список _ остается неизменным.Просто используйте

@property (nonatomic, strong, readwrite) NSMutableArray *list;

. Чтобы избежать путаницы, удалите переменную экземпляра list и оператор @synthesize, а затем используйте _list для доступа к переменной экземпляра.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...