2010-04-16 64 views
2

完全困惑在这里。NSArray/NSMutableArray:通过ref或通过值?

我有一个PARENT UIViewController需要传递一个NSMutableArray到一个CHILD UIViewController。我期待它通过引用传递,这样CHILD中所做的更改将反映在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同步?

更新与更多的代码...

在父母的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

你的直觉是正确的;如果两个属性确实是'retain'(而不是'copy'!),那么最后一个'NSLog'应该是2.看起来你需要发布更多的代码。父母的照片属性有可能在某个时候被修改过吗? – andyvn22 2010-04-16 01:47:45

+0

是的..这两个属性都是保留...并且不行,父母的照片属性没有被修改。如果我回到孩子控制器,计数仍然是“2”。这让我疯狂 – wgpubs 2010-04-16 02:06:02

+0

尝试发布孩子的'addObject:'行被取出的确切方法,以及在'c.photos = self.photos;'和'NSLog'之间的父代码... – andyvn22 2010-04-16 02:09:29

回答

2

你说得对,那些属性值是指针,所以在这里应该只有一个可变数组。我同意andyvn22还有其他事情正在发生,到目前为止您发布的代码中并不明显。

这里有一个可能的调试方法:在每个NSLog上设置一个断点,当你进入调试器时,使用调试窗口(cmd-shift-Y)检查photos属性的实际内存地址在每种情况下。只有两种可能:

  1. 的地址是相同的,在这种情况下,它确实是在同一个阵列,以及一些代码你没有想到的是变异的第一记录和第二之间的阵列;或者,

  2. 地址是不同的,即它们是不同的数组,并且一些你没有想到的代码是将一个新数组重新分配给子(或父)照片属性。

祝你好运!

+0

伟大的建议。这里的罪魁祸首是:“[[self mutableArrayValueForKey:@”photos“] addObject:[photo resizedImageWithContentMode:UIViewContentModeScaleAspectFit bounds:CGSizeMake(200.0f,300.0f)interpolationQuality:kCGInterpolationLow]];”它将实例更改为指向新的NSMutableArray。我认为这跟调用“[self.photos addObject ...]”是一样的,除非KVC友好。 – wgpubs 2010-04-16 02:39:32

+0

使用NSMutuable阵列做KVO是丑陋的。我刚放弃它,因为对“mutableArrayValueForKey:”的调用实际上最终改变了实例“照片”在每次调用时都会指向 – wgpubs 2010-04-16 07:09:38

+0

刚刚阅读了该方法中的KVC文档后,很明显您的邮件失败了,因为您尚未完全实现您的一对多属性,请查找“Accessor搜索模式在KVC编程指南中的“有序集合”中:http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/KeyValueCoding/Concepts/SearchImplementation.html#//apple_ref/doc/uid/20000955 You需要一些方法,如insertObjectInPhotosAtIndex:和removeObjectFromPhotosAtIndex:使这个工作不需要切换你的可变数组。 – JeremyP 2010-04-16 15:31:51

-2

最简单的方式做到这一点是不使用合成的存取方法,只是这卷专门设置指针自己的get/set方法引用相同。

看着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

'@ synthesize'为'retain'属性创建完美的访问器;其他事情正在导致这里的问题。 (另外,你的'setPhotos:'方法会泄露'photos_internal_pointer'。) – andyvn22 2010-04-16 01:52:01

+0

感谢你的提醒,尽管实际答案可能很快就会公布。 – 2010-04-16 01:59:57