我有一个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。这两个应该是同一个对象,所以我不确定我做错了什么。
基本上,我需要一种好方法在两个视图控制器之间传递数据。
答案 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了解它是如何完成的。