web-dev-qa-db-ja.com

特定のインデックスにあるNSMutableArray内のオブジェクトを新しいオブジェクトに置き換える方法

正常に開始される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];
}

みんな助けてください:)

34
user339076

これはトリックを行います:

[myMutableArray replaceObjectAtIndex:index withObject:newObject];
125
Mário Carvalho

さて、ここでいくつかの混乱があります。

変更可能にするために、新しく作成されたmutableCopyNSMutableArrayを取る必要はありません。すでに変更可能です。名前にヒントがあります。プロパティにcopyのセマンティクスを設定したい場合にのみ、セッターでそれを行う必要があります(設定したので、もちろん正当な理由があるかもしれません)。ただし、更新されたupdateTitleコードに示されているように実行する必要はないので、そうするとlocalListがリークします。

また、self.listを介したプロパティアクセスと、同じメソッドでのlistの直接使用を組み合わせています。これは無効ではありませんが、アクセサメソッドが行うその他の処理がランダムにバイパスされることを意味するため、悪い習慣です。このようなプロパティでは、アクセサー自体またはselfdeallocexceptを介してすべてを実行するのが一般的です。 ivarに直接アクセスするinit(これについては意見が異なるようです)にある可能性があります。

また、[self.list release]を呼び出さないでください。プロパティアクセサーは呼び出し側に所有権を与えません。これを行うことは涙で終わる、私の言葉をマークします。

これのどれも本当の質問に答えません。それがあなたの変化が消える理由です。元のupdateTitleコードは、私が見る限りこれを説明していません-動作するはずです。だから、どこかであなたがself.list = theOriginalListを呼んでいるので、あなたの変更を取り消すのではないかと思う。

更新:

引数のためだけに、投稿したコードはおそらくmeantのように見えると思うものを投稿します。 updateTitleにインデックスを渡すための文字列の使用は保存しましたが、この方法で行うことはwrong。それは数字なので、そのまま渡す必要があります。番号がテキストフィールドなどからのものであっても、それは呼び出し側の関心事です。クラスインターフェイスは番号を指定する必要があります。同様に、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をどこかで確実にリセットしています。

8
walkytalky

より簡単な答えは次のとおりです。

self.list[i] = newTitle;

これはちょうどのように動作します

[self.list replaceObjectAtIndex:i withObject:newTitle];
6
antonio081014

Swift=を試すことができます:

 //if you have indexPath
   self.readArray.removeAtIndex((indexPath?.row)!)
   self.readArray.insert(tempDict, atIndex: (indexPath?.row)!)
 //tempDict is NSDictionary object.
0
Avijit Nagare

最後に完璧なコードを手に入れた、

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"
  }
]

この行を見てください:

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

copyは、self.listにアクセスするたびに、オブジェクトの「_list」インスタンス変数ではなく、そのリストのコピーを取得することを意味します。 [self.list replaceObjectAtIndex ...]と記述すると、リストのコピー内のオブジェクトを置き換えます。元の_listは変更されていません。使うだけ

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

混乱を避けるため、「list」インスタンス変数と@synthesizeステートメントを削除し、_listを使用してインスタンス変数にアクセスします。

0
gnasher729