【问题标题】:NSMutableArray Returns NULLNSMutableArray 返回 NULL
【发布时间】:2011-12-21 16:41:15
【问题描述】:

我尝试将对象从另一个类 (secondViewController) 添加到 NSMutableArray,然后将其添加到我的 FirstViewController 中的 UITableView,但是当我使用 NSLog 打印它时它返回 null。这是我的设置。

FirstViewController.h:

@interface FirstViewController : UIViewController <UITableViewDelegate,UITableViewDataSource>{
    IBOutlet UITableView *mytableview;
    NSMutableArray *mytableinfo;
}
@property (nonatomic,retain) IBOutlet UITableView *mytableview;
@property (retain) IBOutlet NSMutableArray *mytableinfo;

FirstViewController.m

#import "FirstViewController.h"
#import "SecondViewController.h"
@synthesize mytableinfo,mytableview;
-(IBAction)addShift:(id)sender{
SecondViewController *secondViewController = [[SecondViewController alloc]init];
[self presentModalViewController:secondViewController animated:YES];
}
- (void)viewDidLoad
{
    mytableinfo = [[NSMutableArray alloc]init];
    [super viewDidLoad];
}

SecondViewController.m

#import "SecondViewController.h"
#import "FirstViewController.h"

@implementation SecondViewController
@synthesize dateformatter,mydatepicker,startingTime;

-(IBAction)saveShift:(id)sender{
    FirstViewController *firstViewController = [[FirstViewController alloc]init];
    [firstViewController.mytableinfo addObject:@"Hello world"];
    NSLog(@"%@",firstViewController.mytableinfo);
    [self dismissModalViewControllerAnimated:YES];
}

我的目标是最终从mytableinfo 提供mytableview。我什至不确定这是否是最好的方法。任何建议将不胜感激。

【问题讨论】:

  • 如果您希望看到刚刚添加到 firstViewController.mytableinfo 的字符串 @"Hello world",那么您的代码应为 NSLog(@"%@", [firstViewController.mytableinfo objectAtIndex:0 ]);或 NSLog(@"%@", [firstViewController.mytableinfo lastObject]);
  • @Rickay 感谢您的评论伙伴。我今天从你那里学到了一些新东西。但是它仍然返回 null。

标签: objective-c ios uitableview delegates nsmutablearray


【解决方案1】:

在 SecondViewController 中,您正在使用 alloc init 创建一个 FirstViewController。此时,FirstViewController 上的 mytableinfo 为 nil,因为您直到 viewDidLoad 才分配。

什么加载 SecondViewController?因为你正在模态地解雇它。如果是 FirstViewController,那么当您分配初始化第一个视图控制器时,您不会调用以模态方式呈现它的实例。

让一个视图像那样戳另一个视图也不是 MVC。它创建在视图层耦合的代码并在视图层修改数据。最好创建一个模型并让两个视图都修改该模型。

How to create a NSMutable Array which can access from different view controllers

另一种在视图之间进行通信的方法是让一个视图将委托(回调)传递给另一个视图。这允许另一个视图不耦合到另一个视图 - 它只知道委托的协议。

What exactly does delegate do in xcode ios project?

【讨论】:

  • 在我的FirstViewController 中,我在右上角有一个系统添加按钮,点击它会调用addShift,看起来像这样。这里-(IBAction)addShift:(id)sender{ SecondViewController *secondViewController = [[SecondViewController alloc]init]; [self presentModalViewController:secondViewController animated:YES]; }
  • 这是我的project file。如果你想看看我的代码。
【解决方案2】:

在您的“SecondViewController”中有一点对我来说看起来很奇怪,您将其视为模态框。 那么我的问题是......谁开始了模态演示? “FirstViewController”?如果是这样,你为什么要创建一个新的,在解雇第二个时,启动它的第一个将恢复它的活动。
我不明白的另一件事是 UIViewController 的指定初始化程序是

- (id)initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle

如果不需要关联 nib,您可以将 nil 传递给两个参数。

最后,如果您需要将 NSMutableArray 从第 1 个模态呈现的第 2 个 VC 取回给第 1 个 ViewController (VC),您可以在第 2 个 VC 中执行此操作:

- (id)initWithMutableArray:(NSMutableArray *)theArray    {
//... put standard init code here   }

并使其成为您的第二个 VC 的默认初始化程序。但这只有在第二个 VC 绝对需要一个可变数组时才有意义。


现在出于好奇,因为我不明白这一行

@property (retain) IBOutlet NSMutableArray *mytableinfo;

为什么这是一个 IBOutlet?这看起来像是一个潜在的问题根源。 IBOutlet 通常是指向 xib 文件中 UI 元素的指针。

【讨论】:

  • 好的。我已经编辑了我的问题,并提供了有关 secondveiwcontroller 如何进入的更多详细信息。感谢@property 行的提醒。我只是关注我在网站上看到和阅读的内容。正如你所看到的,有些并不是那么可靠。如果你想看看整个事情,这里是我的项目的所有墨水。 Download xCode Project
  • 好的,但是您仍然有一个问题,即在 SecondView 中创建新的 firstview 时,当您关闭 SecondView 时,您创建的视图将返回到第一个 firstView(那个启动了modalPresentation)。因此,在 firstView 中附加的内容是无关紧要的,但为了论证,就像另一个人所说的那样,您将 addObject 方法发送到“nil”指针。在 Objective-C 中,这不是崩溃的原因,在 Java 中,该调用会使您的应用程序崩溃。
  • 我希望我可以选择两个答案作为解决方案。你在提到@property 时帮了我很多忙。它恰好是问题的根源......在大多数情况下。再次感谢。
【解决方案3】:

当使用一个数组填充 UITableView 时,该数组可以在您的应用程序过程中被多个模态视图修改,我发现最好的方法之一是使用 NSUserDefaults。您可以像这样创建一个 NSUserDefaults 对象以供参考:

NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];

然后您可以在默认情况下将对象分配给每个键,这实际上只是一个 plist(它只是一个键的列表,其中包含与之关联的对象。

那么,当你想将数组存储为默认值时,你可以说:

[defaults setObject:mytableinfo forKey:@"tableInformationKey"];

然后,每当您想访问该数据时,您都可以说:

NSMutableArray* tableInfoCopy = [defaults mutableArrayValueForKey:@"tableInformationKey"];

这将使您成为存储在 NSUserDefaults 中的数组的副本(可以从应用程序中的任何位置访问 NSUserDefaults),因此您可以对刚刚创建的可变数组进行更改。完成更改后,您可以将其重新分配给 NSUserDefaults,如下所示:

[defaults setObject:tableInfoCopy forKey@"tableInformationKey"];

所以当你填充你的 UITableView 时,在

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 

输入类似:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Foobar"];
    if (cell == nil) {
        // No cell to reuse => create a new one
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Foobar"] autorelease];

        // Initialize cell with some customization
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
        cell.textLabel.textColor = [UIColor blackColor];
    }

    NSArray* arrayOne = [defaults objectForKey:@"tableInformationKey"];

    NSString* title = [arrayTwo objectAtIndex:indexPath.row]; 
    //this goes to the index in the array of whatever cell you are
    // at, which will populate your table view with the contents of this array (assuming the array contains strings)

    // Customize cell
    cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:25];

    return cell;
}

【讨论】:

  • Apple 建议您不要以这种方式使用 NSUserDefault,而是通过实现“单例实例”来模仿它。这应该更有效,并且会给你一些延迟初始化。
  • 代码看起来很有希望。我今晚会试一试,看看效果如何。 @VinceBurn 现在我正处于一个非常渴望拥有一个工作应用程序的阶段,苹果的建议是我最不关心的。当然,这样的细节可以在以后进行编辑。感谢您的提醒。
  • @VinceBurn 你有那个文档的链接吗?我想看看
  • @Rickay 我不记得单身人士的文档,进行搜索,您应该会找到它。至于不使用 NSUserDefault,它是在斯坦福大学 Apple 员工提供的课程视频中。它在 iTunesU 上。 NSUserDefault 的问题在于,如果你有很多重物,即使你只是在启动时检查一个标志,它们也会全部被带入内存。这可能会导致巨大的性能损失。
  • 有趣。我倾向于 NSUserDefaults 的唯一原因是它是简单的持久数据,这正是我想要的。我想我可以将它存储在一个文本文件中,但这不会带来与您上述相同的问题吗?
【解决方案4】:

使用它们最简单的方法是将数组放入您的 AppDelegate

// populate appDelegate's array
AppDelegate *appDelegate = (myAppDelegate *) [[UIApplication sharedApplication] delegate];  
[appDelegate.arrayMyTableInfo addObject:@"HelloWorld"];

【讨论】:

    【解决方案5】:

    您可以按照我的建议执行以下操作: (这是您更新的代码的一部分)
    这是在您的第二个视图中,这是将数组传递给您的第二个视图的多种方法之一。

    @synthesize array4Test;
    - (id)initWithMutableArray:aMutableArray
    {
    self = [self initWithNibName:nil bundle:nil];
    if (self)
    {
        self.array4Test = aMutableArray;
    }
    return  self;
    }
    - (void)dealloc 
    {    
    //  HERE clean up the property is set to retain.
    self.array4Test = nil;
    [super dealloc];
    }
    

    这是第一个视图的代码

    -(IBAction)addShift:(id)sender{
    SecondViewController *secondViewController = [[SecondViewController alloc] initWithMutableArray:self.mytableinfo];
    [self presentModalViewController:secondViewController animated:YES];
    }
    -(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self.mytableview reloadData];
    NSString *aString = [mytableinfo lastObject];
    if (aString)
    {
        NSLog(@"This just came back from the second View\n%@", aString);
    }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多