在视图控制器之间保持值

时间:2010-08-08 01:18:56

标签: iphone uiviewcontroller

我有一个ItemAddViewController,它将自身显示为模态视图。其中一个字段推送一个新的视图控制器,CategorySelectionViewController,允许用户选择一个类别。

ItemAddViewController.h

@property (nonatomic, retain) Category *category;

CategorySelectionViewController.h

@property (nonatomic, retain) Category *category;

CategorySelectionViewController.m

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSManagedObject *currentCategory = category;

if (currentCategory != nil) {
    NSInteger   index = [categories indexOfObject:currentCategory];
    NSIndexPath *selectionIndexPath = [NSIndexPath indexPathForRow:index inSection:0];
    UITableViewCell *checkedCell = [tableView cellForRowAtIndexPath:selectionIndexPath];
    checkedCell.accessoryType = UITableViewCellAccessoryNone;
}

//set the checkmark accessory
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];

//update the category
category =[categories objectAtIndex:indexPath.row];
NSLog(@"%@", category);
// Deselect row
[tableView deselectRowAtIndexPath:indexPath animated:YES];

}

ItemAddViewController.m

- (void)viewWillAppear:(BOOL)animated {
  NSLog(@"%@", category);
}

在CategorySelectionViewController创建上设置类别。在类别选择屏幕上选择类别后,NSLog会报告正确的对象。当它返回到ItemAddViewController时,它再次为null。这两个应该是同一个对象,所以我不确定我做错了什么。

基本上,我需要一种好方法在两个视图控制器之间传递数据。

3 个答案:

答案 0 :(得分:1)

为了跟进已经说过的话,在类似问题中常采取的一种方法是让ItemViewController(父母)成为CategorySelectionViewController(孩子)的代表,以及何时tableView:didSelectRowAtIndexPath:CategorySelectionViewController中触发,向ItemAddViewController中的委托回调发送消息 - 将所选类别作为参数传递。

这个概念可以实现类似于以下内容:

@protocol CategorySelectionViewControllerDelegate;

// in CategorySelectionViewController.h
@interface CategorySelectionViewController : UITableViewController {
    id<CategorySelectionViewControllerDelegate> delegate;
}
@property (nonatomic, assign) id<CategorySelectionViewControllerDelegate> delegate;
@end

@protocol CategorySelectionViewControllerDelegate
// delegate callback skeleton
-(void)userDidSelectCategory:(Category *)categorySelected;
@end

// in CategorySelectionViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
   NSManagedObject *currentCategory = category;

    if (currentCategory != nil) {
        NSInteger   index = [categories indexOfObject:currentCategory];
        NSIndexPath *selectionIndexPath = [NSIndexPath indexPathForRow:index inSection:0];
        UITableViewCell *checkedCell = [tableView cellForRowAtIndexPath:selectionIndexPath];
        checkedCell.accessoryType = UITableViewCellAccessoryNone;
    }

    //set the checkmark accessory
    [[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];

    // here's where you message the delegate callback
    [self.delegate userDidSelectCategory:[categories objectAtIndex:indexPath.row]];
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

然后修改ItemAddViewController的骨架以符合CategorySelectionViewControllerDelegate协议:

// in ItemAddViewController.h
@protocol CategorySelectionViewControllerDelegate;
@interface ItemAddViewController :  UITableViewController <CategorySelectionViewControllerDelegate> 
{ /* etc.... */ }
@property (nonatomic, retain) Category *category;
// delegate callback
-(void)userDidSelectCategory:(Category *)categorySelected

// in ItemAddViewController.m
// set the CategorySelectionViewController delegate as this ItemViewController when you instantiate it
-(void)showCategorySelectionViewController {
    CategorySelectionViewController *myChild = [[CategorySelectionViewController alloc] init];
    myChild.delegate = self;
    [self presentModalViewController:myChild animated:YES];
}
// implement the delegate callback
-(void)userDidSelectCateogry:(Category *)categorySelected {
    self.category = categorySelected;
    // other handling code as needed...
}

关于通过调用[self parentViewController]中的CategorySelectionViewController来执行此操作,问题是ItemAddViewController继承自UITableView,因此当您发送消息[self parentViewController]时,编译器认为你正在与UITableView对话,而不是ItemAddViewController,除非你明确地转换它。因此,它不知道self.parentViewController具有名为category的属性。您可以通过添加类型转换来解决此问题:

ItemAddViewController *itemAddViewControllerParent = (ItemAddViewController *)[self parentViewController];
itemAddViewControllerParent.category = [categories objectAtIndex:indexPath.row]; 

希望这有帮助。

答案 1 :(得分:0)

UIViewController类的parentViewController方法应该为您提供指向“管理”当前视图的视图控制器的指针。完成后,您可以在其上设置category属性。

也就是说,我自己在iOS上的视图控制器上做的并不多,所以我不确定“parentViewController对于给定视图应该指向什么语义”是......但是我敢说你的ItemAddViewController实例可能应该是CategorySelectionViewController的父级。

以下是您可能会这样做的示例:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSManagedObject *currentCategory = category;

    if (currentCategory != nil) {
        NSInteger   index = [categories indexOfObject:currentCategory];
        NSIndexPath *selectionIndexPath = [NSIndexPath indexPathForRow:index inSection:0];
        UITableViewCell *checkedCell = [tableView cellForRowAtIndexPath:selectionIndexPath];
        checkedCell.accessoryType = UITableViewCellAccessoryNone;
    }

    //set the checkmark accessory
    [[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];

    //update the category
    [self parentViewController].category = [categories objectAtIndex:indexPath.row];
    NSLog(@"%@", category);
    // Deselect row
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

编辑:文档说明parentViewController方法:

  

父视图控制器与导航,标签栏和模态视图控制器层次结构相关。在每个层次结构中,父级是负责显示当前视图控制器的对象。

我认为这意味着模态视图控制器的parentViewController指向任何视图控制器收到消息presentModalViewController:animated:

答案 2 :(得分:0)

@ David's是一个很好的答案,但这会使数据保持在parentViewController。如果您希望数据是ItemAddViewController(子控制器)的本地数据,那么您可以在第二个视图中创建一个本地iVar,并在显示它或将其推送到导航控制器之前为其分配值。 See my answer to a previous SO question here了解它是如何完成的。