2010-06-17 38 views
32

來替換對象在一個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]; 
} 

請大家幫幫忙傢伙:)

+1

很抱歉,但你真的需要工作通過Objective-C文檔,內存管理文件(很棒)和屬性章節。這個代碼*真的*是越野車... – Eiko 2010-06-17 19:41:55

回答

8

OK,這裏有混淆的幾個位。

您不需要將新創建的NSMutableArraymutableCopy設置爲可變。它已經是可變的 - 線索就是這個名字。如果你想要屬性具有copy語義(你已經設置了,當然可能有很好的理由),你只需要在setter中這樣做。但是你肯定不需要按照你更新的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某處。

+0

感謝您的建議walkytalky。我相應地修改了我的代碼。現在,我已經通過我的代碼,我找不到任何一個self.list = theOriginalList調用。但是我想知道是否在'replaceObjectAtIndex'被使用時調用'setList:'方法。有任何想法嗎? 再次感謝:) – user339076 2010-06-17 18:37:34

+1

'replaceObjectAtIndex'絕對不應該調用'setList' - 它是數組本身的一個方法,它既不知道也不關心它碰巧屬於的對象的屬性訪問器。 – walkytalky 2010-06-17 23:04:46

+0

你能告訴我嗎。關於'replaceObjectAtIndex'方法。如果我調用'list [i] = newTitle;'編譯沒有錯誤或警告。這種用法有什麼問題嗎?謝謝:) – hqt 2014-08-09 19:34:29

119

該做的伎倆:

[myMutableArray replaceObjectAtIndex:index withObject:newObject]; 
+0

你能告訴我嗎?關於'replaceObjectAtIndex'方法。如果我調用'list [i] = newTitle;'編譯沒有錯誤或警告。這種用法有什麼問題嗎?謝謝:) – hqt 2014-08-09 19:35:22

+9

@Mario你甚至沒有讀過這個問題,是嗎?但是,嘿,52個其他人也沒有... – walkytalky 2014-08-12 11:24:24

5

一個更直接的答案是:

self.list[i] = newTitle; 

這只是工程樣

[self.list replaceObjectAtIndex:i withObject:newTitle]; 
+0

你沒有注意到在財產導致每個變化行爲不端的「複製」。 – gnasher729 2015-12-01 21:13:54

0

看這句話:

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

拷貝意味着無論何時訪問self.list,都不會獲得對象的「_list」實例變量,而是該列表的副本。如果您編寫[self.list replaceObjectAtIndex ...],則替換該列表副本中的對象;原始_list不變。只需使用

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

而且爲了避免混淆,刪除了「列表」實例變量和@synthesize語句,然後使用_list訪問實例變量。

+0

如果我沒有弄錯,「複製」屬性意味着只有在「設置」實例創建一個副本。但是它不會像你提到的那樣發生在「獲得」上。請參閱https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html – 2015-12-16 13:41:41

+0

@OdedRegev,文檔中的'copy'屬性僅適用於新創建的屬性。據我所知,吸氣劑將返回原始對象,但不允許您在所有者的類中修改它(它只會保留在原始的未修改的屬性中)。 – 2016-02-15 13:25:47

0

對於斯威夫特,你可以嘗試:

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

最後得到了一些完美的代碼,

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" 
    } 
] 
相關問題