2010-04-16 2 views
2

Полностью смущен здесь.NSArray/NSMutableArray: передано по ссылке или по значению?

У меня есть PARENT UIViewController, которому необходимо передать NSMutableArray в CHILD UIViewController. Я ожидаю, что он будет передан по ссылке, чтобы изменения, внесенные в РЕБЕНОК, отражались в PARENT и наоборот. Но это не тот случай. Оба имеют имущество, объявленное как ..

@property (nonatomic, retain) NSMutableArray *photos;

Пример:

В РОДИТЕЛЕЙ:

self.photos = [[NSMutableArray alloc] init]; 

ChildViewController *c = [[ChildViewController alloc] init ...]; 
c.photos = self.photos; 
... 
... 

...

В РЕБЕНКА:

[self.photos addObject:obj1]; 
[self.photos addObject:obj2]; 

NSLog(@"Count:%d", [self.photos count]) // Equals 2 as expected 

...

Назад в РОДИТЕЛЕЙ:

NSLog(@"Count:%d", [self.photos count]) // Equals 0 ... NOT EXPECTED 

Я думал, что они оба получат доступ к одной и той же памяти. Разве это не так? Если это не так ... как я могу синхронизировать два NSMutableArrays?

UPDATE с некоторыми более кода ...

В РОДИТЕЛЕЙ UIViewController:

 - (void)loadView { 

     self.photos = [[NSMutableArray alloc] init]; 

     // Create view for root controller 
    UIView *rootView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)]; 
    self.view = rootView; 
    self.view.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed:@"green_felt_bg.jpg"]]; 
    [rootView release]; 

    ChildViewController *c = [[ChildViewController alloc] initWithNibName:@"ChildView" bundle:nil]; 
    self.childViewController = c; 
    [c release]; 

    self.childViewController.photos = self.photos; 
    self.childViewController.delegate = self; 

    [self.view insertSubview:self.childViewController.view atIndex:0]; 
} 

В РЕБЕНКА ViewController я просто добавить объекты в него. Вызов метода делегата, когда выполняется добавление объектов ... которые обрабатывает PARENT. Ничего существенного не происходит. Код ребенок использует, чтобы изменить его свойство «фото» ..

[[self mutableArrayValueForKey:@"photos"] 
     addObject:[photo resizedImageWithContentMode:UIViewContentModeScaleAspectFit bounds:CGSizeMake(200.0f, 300.0f) interpolationQuality:kCGInterpolationLow]]; 
+0

Ваша интуиция верна; если оба свойства действительно «сохраняются» (а не 'copy'!), то последний' NSLog' должен давать 2. Похоже, вам придется опубликовать еще какой-нибудь код. Возможно ли, что свойство 'photos' родителя изменяется в какой-то момент? – andyvn22

+0

Yup .. оба свойства сохраняются ... и нет, свойство родительских фотографий не изменяется. Если я вернусь к дочернему контроллеру, счет будет по-прежнему «2». Это сводит меня с ума – wgpubs

+0

Попробуйте отправить точный метод, из которого берутся строки 'addObject:' ребенка, и код в родительском объекте, который находится между 'c.photos = self.photos;' и 'NSLog' ... – andyvn22

ответ

2

Вы правы, эти значения свойств являются указателями, поэтому здесь должен быть только один изменяемый массив. Я согласен с andyvn22, что что-то еще происходит, что-то неявное в коде, который вы опубликовали до сих пор.

Это возможный способ его отладки: установить точку останова в каждом из этих NSLogs, а когда вы заходите в отладчик, используйте окно отладки (cmd-shift-Y), чтобы изучить фактический адрес памяти свойства фотографии в каждом случае.Есть только две возможности:

  1. адреса одинаковы, и в этом случае он действительно является тот же массив, и некоторый код, вы не думаете о мутирует массива между первым бревном и второй; или,

  2. Адреса разные, т. е. они разные массивы, а некоторый код, о котором вы не думаете, переназначает новый массив для свойства фотографий ребенка (или родителя).

Удачи вам!

+0

Большой совет. Виновником здесь является: [[self mutableArrayValueForKey: @ "photos"] addObject: [фото resizedImageWithContentMode: ограничения UIViewContentModeScaleAspectFit: интерполяция CGSizeMake (200.0f, 300.0f)Качество: kCGInterpolationLow]]; " Он меняет экземпляр на новый NSMutableArray. Я думал, что это то же самое, что и вызывать «[self.photos addObject ...], кроме KVC. – wgpubs

+0

Выполнение KVO с массивом NSMutuable уродливо. Я просто отказался от него, так как вызовы« mutableArrayValueForKey: »фактически в конечном итоге меняют Экземпляр «фотографии» указывал также каждый раз, когда он вызывается. – wgpubs

+0

Просто прочитав документы KVC по методу, ясно, что ваше сообщение терпит неудачу, потому что вы не полностью внедрили свое свойство для многих. Найдите «Шаблоны поиска Accessor» в папках с заказом "в Руководстве по программированию KVC: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/SearchImplementation.html#//apple_ref/doc/uid/20000955 Вы нужен целый ряд методов, таких как insertObjectInPhotosAtIndex: и removeObjectFromPhotosAtIndex: чтобы эта работа работала без изменения вашего изменяемого массива. – JeremyP

-2

Самый простой способ сделать это было бы не использовать синтезированные методы доступа, и просто катить свои собственные методы получения/установки, которые специально установить указатель ссылки равны.

Глядя на apple documentation on properties, вы все равно можете использовать удобную точечную нотацию со свойствами, даже если вы не используете директиву @synthesize.

Я думаю, вы хотите, чтобы выглядеть примерно так:

-(NSMutableArray*)photos 
{ 
    return photos_internal_pointer; 
} 
-(void)setPhotos:(NSMutableArray*)newValue 
{ 
    [newValue retain]; 
    [photos_internal_pointer release]; 
    photos_internal_pointer = newValue; 
} 

Где photos_internal_pointer имеет тип NSMutableArray*, конечно. Это должно синхронизировать их, поскольку установка указателей, равных друг другу, заставит их указывать на один и тот же объект.

+0

'@ synhesize' создает прекрасные средства доступа для свойства' keep'; что-то другое вызывает здесь проблему. (Кроме того, ваш метод 'setPhotos:' утечки 'photos_internal_pointer'.) – andyvn22

+0

Спасибо, что поймали это, отредактировано, хотя фактический ответ, вероятно, скоро будет обнаружен. –

Смежные вопросы