【问题标题】:NSMutableArray Resetting Itself?NSMutableArray 重置自己?
【发布时间】:2013-09-08 21:14:27
【问题描述】:

我在使用 NSMutableArray 擦除其内容时遇到问题。

考虑我的代码:(int i; 和 NSMutableArray* newFileControllerArray 一样在我的文件的 .h 中)

-(void)awakeFromNib{
    i = 0;
    newFileWindowControllerArray = [[NSMutableArray alloc]init];
}

-(IBAction)newFileMenubar:(id)sender{    
    [newFileWindowControllerArray addObject:[[NewFileWindowController alloc]initWithWindowNibName:@"NewFileWindowController"]];
    NSUInteger elementsInArray = [newFileWindowControllerArray count];
    NSLog(@"%lu",(unsigned long)elementsInArray);
    [[newFileWindowControllerArray objectAtIndex:i] showWindow:nil];
}

-(IBAction)OKButtonClicked:(id)sender{
    NSUInteger elementsInArray = [newFileWindowControllerArray count];
    NSLog(@"THERE ARE %lu ELEMENTS IN THE ARRAY",(unsigned long)elementsInArray);
}

第一个调用的方法(awakeFromNib: 除外)是newFileMenubar: 这将向数组添加一个元素。我可以确认这是有效的,因为 1 打印在控制台中。但是,一旦调用 OKbutton 并打印出数组中的元素数,它就会说数组中没有元素。这是为什么呢?

我在这里遗漏了一些非常明显的东西吗?为什么我的阵列会自行重置?

编辑: cmets 变得又长又笨重,所以这里是带有 NSLogs 和输出的代码:

-(void)awakeFromNib{
    i = 0;
   newFileWindowControllerArray = [NSMutableArray array];


      NSLog(@"self=%p, array=%p", self, newFileWindowControllerArray);
   }

 -(IBAction)newFileMenubar:(id)sender{

     [newFileWindowControllerArray addObject:[[NewFileWindowController           alloc]initWithWindowNibName:@"NewFileWindowController"]];


[[newFileWindowControllerArray objectAtIndex:i] showWindow:nil];


i++;

    NSLog(@"self=%p, array=%p", self, newFileWindowControllerArray);

 }

-(IBAction)OKButtonClicked:(id)sender{
NSUInteger elementsInArray = [newFileWindowControllerArray count];


NSLog(@"self=%p, array=%p", self, newFileWindowControllerArray);


[documentController newDocument:sender];
[[newFileWindowControllerArray objectAtIndex:i]close];


 }

程序启动时,输出如下:self=0x100141480, array=0x100140f30 这应该来自 awakeFromNib:

下一个调用的方法是newFileMenubar:

这个的输出是

self=0x1001ac990, array=0x1005228a0 和 self=0x100141480, array=0x100140f30 之后

最后调用的方法是OKButtonClicked:

最后一个方法 (OKButtonClicked:) 的输出是 self=0x1001ac990, array=0x1005228a0

从代码中可以看出,数组的名称没有改变,但我的输出却不一样?这是什么原因造成的?

【问题讨论】:

  • 也打印数组本身 (%@),确保它不为空
  • 我们能看到数组的声明吗?可能的原因是它的声明方式没有保留
  • 数组声明如下: NSMutableArray *newFileWindowControllerArray;在我的界面中。我正在使用 ARC
  • 你确定它是你的对象在newFileMenubar和newFileMenubar中的同一个实例吗? newFileWindowControllerArray 还是同一个对象吗?或许还可以在 awakeFromNib 中添加一个 NSLog。
  • 我相信数组是同一个实例。当我添加一个日志来打印数组本身时,它在 awakeFromNib 中的值为 ():在 newFileMenubar 中,该数组具有十六进制值。在 OKButton 下:它恢复为 ( )

标签: objective-c macos cocoa nsmutablearray nsarray


【解决方案1】:

您的日志输出中有很好的线索。视图控制器有多个实例(查看 'self' 的不同值?)。他们每个人都有自己的数组。看这段代码...

-(IBAction)newFileMenubar:(id)sender{    
    [newFileWindowControllerArray addObject:[[NewFileWindowController alloc]initWithWindowNibName:@"NewFileWindowController"]];

当您按下与该操作关联的按钮时,您的应用会构建另一个视图控制器并将其放入数组中。该视图控制器从 nib 消息中获取唤醒并分配 另一个 数组,依此类推。

要确认这一点,请按如下方式更改代码:

-(IBAction)newFileMenubar:(id)sender{    
    [newFileWindowControllerArray addObject:@"Hello world"];

    // and comment this out, for now:
    // [[newFileWindowControllerArray objectAtIndex:i] showWindow:nil]; 

在其他方法中,注释掉您对数组中除了字符串以外的任何内容的期望,然后看看您会得到什么。例如...

- (IBAction)OKButtonClicked:(id)sender {

    NSUInteger elementsInArray = [newFileWindowControllerArray count];
    NSLog(@"self=%p, array=%p", self, newFileWindowControllerArray);
    [documentController newDocument:sender];

    // and comment this out, for now:
    // [[newFileWindowControllerArray objectAtIndex:i]close];

    // instead...
    NSLog(@"danh thinks my array will be ok: %@", newFileWindowControllerArray);
}

您可能并不是要在每次按下按钮时创建另一个视图控制器,但我不确定您想要什么功能。也许您想要一系列视图? (要在另一个控制下创建许多视图控制器,您需要阅读container view controllers, here)。

【讨论】:

  • 谢谢!当我注释掉我的行并添加你的 NSLog 时,我得到了一个地址。这段代码都在一个标有“NewFileHandler”的类中,它是 NSObject 的子类。这是否仍然意味着一旦 newFileMenubar: 完成运行, awakeFromNib: 会再次被调用?如果是这样,我应该将 awakeFromNib: 中的代码放在哪里以进行所有设置。我基本上只需要一个数组来存储这些 NSWindowController,这样我就可以引用它们在 newFileMenubar: 和 OKButton: 中打开新窗口。我不知道应该把我的新方法放在哪里。任何帮助表示赞赏,再次感谢!
  • 从笔尖唤醒是可以的(你可以使用它,尽管 initWithCoder 是更常见的选择)。问题是这个 vc 分配自己的新实例并将它们保存在一个数组中的想法。如果您真的要创建容器视图控制器,请参阅我发布的链接,例如方法 addChildViewController: on UIViewController。
  • 您的视图控制器已经有一个视图,更常见的做法是创建 at 视图的子视图(您通过说 [self.view addSubview:someNewView] 添加的 UIView 实例)。您可以预先完成所有操作(甚至在笔尖中)并将它们全部隐藏起来。当用户按下按钮时,您会取消隐藏它们。
  • 我没有使用任何视图控制器,因为我的项目是针对 OS X 而不是 iOS。相反,我用 NSWindowControllers 填充我的数组。我试图做的是将 NSWindowControllers 存储在 NSMutableArray 中,这样我就可以在 IBAction 上“动态”创建新实例。然后,我将 NSWindowControllers 放在特定索引处,并使用数组中该索引上的方法显示窗口。我想知道为什么我会用你的代码得到一个地址......关于如何让这件该死的事情发生的任何想法?我真诚地感谢您给我的所有建议!
  • 天哪,我应该更仔细地查看帖子的标签。我是 osx 中的一种离水之鱼。我未受过教育的意见是,这需要在 NewFileWindowController 或其任何子类之外进行。其他一些不是 NewFileWindowController 的对象应该负责分配它们并将它们添加到数组中。让您发布的课程自行分配会产生递归,这首先会让您陷入困境。在 iOS 中,我们会说您正在创建一个视图控制器容器,它与它所包含的视图控制器完全不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-08
  • 2020-01-02
  • 2011-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多