【问题标题】:Add objects to an Array from another View Controller从另一个视图控制器将对象添加到数组
【发布时间】:2013-03-25 05:25:39
【问题描述】:

我有一个HomeViewController,它的tableView 填充了数组tableViewArray(最初为空)。当我点击 barButton 时,我会模态地转到另一个名为 OutsideViewController 的视图控制器,它有另一个由不同数组填充的 tableView。

我想做的是:

当我点击OutsideViewController 中的一行时,我想将选定的字符串值添加到tableViewArray,这样当我返回HomeViewController 时,tableView 会在 tableView 中列出该新项目.

到目前为止,这是我尝试过的:

在我的OutsideViewController.m-didSelectRowAtIndexPath 方法中,我有这段代码:

NSString *selectedRow = [outsideArray objectAtIndex:indexPath.row];
NSMutableArray *temporaryArray = [NSMutableArray arrayWithObject:selectedRow];

HomeViewController *homeVC = [[HomeViewController alloc] init];
homeVC.tableViewArray = temporaryArray;

该代码有效,但当我返回时,HomeViewController 中的 tableView 仍然是空的。我是否必须重新加载 tableView 数据? 我这样做对吗?

这就是我在 Storyboard 中设置视图控制器的方式:

HomeViewController -(modal segue)-> Navigation Controller --> OutsideViewController

另外,OutsideViewController 到 HomeViewController 的返回是通过这行代码完成的:

[self dismissViewControllerAnimated:YES completion:^{ }];

【问题讨论】:

  • 我使用了一个全局单例类,它可以存储需要从任何控制器访问的数组之类的东西。

标签: ios objective-c uitableview uiviewcontroller nsarray


【解决方案1】:

你做错了什么是你分配了一个新的HomeViewController。我要做的是在您的OutsideViewController 中保留对您的HomeViewController 的引用。方法如下。

首先,在OutsideViewController.h 中,创建一个属性,如下所示:

@property (nonatomic, weak) HomeViewController *homeVC;

别忘了在 .h 中添加 @class HomeViewController;,在 .m 中添加 #import "HomeViewController.h"

HomeViewController 中,像这样实现prepareForSegue: 方法(将ModalSegueIdentifier 替换为您的segue 标识符):

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"ModalSegueIdentifier"]) {
        OutsideViewController *modalVC = (OutsideViewController*)segue.destinationViewController;
        modalVC.homeVC = self;
    }
}

然后,在OutsideViewController.m,而不是这样做:

HomeViewController *homeVC = [[HomeViewController alloc] init];
homeVC.tableViewArray = temporaryArray;

这样做:

_homeVC.tableViewArray = temporaryArray;

当您离开模态 VC 时,您的 HomeVC 将拥有正确的数组。别忘了刷新你的UITableView

NB:当然,还有很多其他方法,而且它可能不是最好的方法。但是,它应该可以工作。

【讨论】:

  • 这工作得很好,我只需要修改这行:OutsideViewController *modalVC = (OutsideViewController*)segue.destinationViewController;OutsideViewController *modalVC = (OutsideViewController*)[segue.destinationViewController topViewController]; 因为导航控制器在视图之间
【解决方案2】:

您也可以使用委托来实现这一点。您必须在您的OutsideViewController 中创建一个协议,并使用负责将新对象发送到您的HomeViewController 的方法。在 OutsideViewController.h 中执行此操作:

@protocol OutsideViewDelegate <NSObject>
- (void)OutsideViewController:(OutsideViewController *)controller didAddObject:(NSString *)object;
@end

在实现文件中你必须稍微改变一下didSelectRowAtIndexPath:方法:

NSString *selectedRow = [outsideArray objectAtIndex:indexPath.row];
[self.delegate OutsideViewController:self didAddObject:selectedRow];

在您的 HomeViewController.h 中,您必须使您的类符合协议:

@interface HomeViewController : UIViewController <OutsideViewDelegate>

之后,为委托创建一个属性:

@property (nonatomic, weak) id <OutsideViewDelegate> delegate;

要完成这个过程,请在 HomeViewController.m 中实现协议以从 OutsideViewController 接收新对象:

- (void)OutsideViewController:(OutsideViewController *)controller didAddObject:(NSString *)object
{
     if (object != nil)
     {
          [self.tableViewArray addObject:object];
     }

     [self dismissViewControllerAnimated:YES completion:nil];
}

上面的代码取决于你的tableViewArray 对象是否可变。如果不是,您可以将协议方法中的对象参数类型更改为不可变数组对象,然后将tableViewArray 分配给新数组。

编辑:

prepareForSegue: 方法中不要忘记设置委托:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"SEGUE_IDENTIFIER"]) {
        OutsideViewController *outsideVC = (OutsideViewController *)[segue destinationViewController];
        [outsideVC setDelegate:self];
    }
}

【讨论】:

  • 如果我使用委托,那么在视图之间放置导航控制器是否重要?
  • 我认为不是。如果我没记错的话,委托与实现协议方法的 viewController 一起工作。它不应该影响其他控制器。如果我错了,请纠正我。
【解决方案3】:

首先确保你allocinit你的tableViewArrayHomeViewController

第二,在这一行

HomeViewController *homeVC = [[HomeViewController alloc] init]

您正在创建对 HomeViewController 的新引用,这是不正确的,您需要传递正确的引用,可能会在 OutsideViewController 中创建 HomeViewController 变量

即使你正确地执行了第一个和第二个建议,你仍然会看到一个空的 tableview,因为你没有重新加载 tableview,不知何故你需要触发 [self.tableview reloadData]; 方法。

这意味着;您需要学习 DelegateNSNotifications 模式来在 child->parent 场景之间进行通信

How do I set up a simple delegate to communicate between two view controllers?

http://mobile.tutsplus.com/tutorials/iphone/ios-sdk_nsnotificationcenter/

对于您的问题,只需在您的 Outside 中创建一个代表; 在你的 OutsideViewController.h

#import <UIKit/UIKit.h>

@protocol OutsideDelegate;

@interface{}//bunch of interface stuff

// Declare a property for the delegate
@property (weak) id <OutsideDelegate> delegate;
@end

// Protocol Header
@protocol OutsideDelegate <NSObject>
@optional
- (void)dismissPop:(NSMutableArray *)list;
@end

在您的 OutsideViewController.m 中

@synthesize delegate;


//run delegate method
[delegate dismissPop:temporaryArray];
[self dismissViewControllerAnimated:YES completion:^{ }];

在您的 HomeViewController.h 中

#import "OutsideViewController.h"
@interface OutsideViewController : UITableViewController<OutsideDelegate>
{}
@property (strong, nonatomic) OutsideViewController *pvc;

在您的 HomeViewController.m 中

@synthesize pvc;

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if ([[segue identifier] isEqualToString:@"your segue"]) {
        pvc = [segue destinationViewController];
        [pvc setDelegate:self];
    }
}
// delegate callback function

- (void)dismissPop:(NSMutableArray *)list {

    self.tableViewArray=list;
    [self.tableView reloadData];
}

另一种解决方案是

将您的视图堆栈更改为:

Navigation Controller --> HomeViewController -(push segue)--> OutsideViewController

并应用 rdurand 的答案

并将其添加到您的 HomeViewController 中:

-(void)viewDidAppear:(BOOL)animated
{
   [self.tableview reloadData];
}

在这个解决方案中,因为你只是一个 nabigation 堆栈中的推送视图控制器viewDidAppear 每次你弹出 OutsideViewController 时都会在 HomeViewController 中调用。

【讨论】:

  • 如果我使用委托,在视图之间有导航控制器是否重要?
  • 不,没关系,它不起作用检查delegate 设置是否正确我没有测试代码,但我也用额外的解决方案更新了我的答案,你需要学习委托和 nsnotification 迟早
猜你喜欢
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多