将属性从模态视图控制器传递给父级

Posted

技术标签:

【中文标题】将属性从模态视图控制器传递给父级【英文标题】:Pass property from Modal View Controller to Parent 【发布时间】:2014-06-07 18:53:10 【问题描述】:

我有一个 tableview 作为父视图控制器和一个子模态视图控制器。在模态视图控制器中,当用户点击一行时,我想设置父级的属性“过滤器”。但是,它只是返回 null。

如何将 NSString 过滤器属性传递回其父视图?我应该在 didSelectRowAtIndexPath 方法中实例化父视图控制器吗?

更新:使用 Delegates 解决,关注 this tutorial。

下面是模态视图控制器的代码:

#import "FilterViewController.h"
#import "ContactsTableViewController.h"


@interface FilterViewController ()

@end

@implementation FilterViewController


- (void)viewDidLoad

    [super viewDidLoad];
    self.filterTable.dataSource = self;
    self.filterTable.delegate = self;
    [self performSelector:@selector(retrieveFilteredEvents)];


-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    return [self.filterEvents count];


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

    static NSString *cellIdentifier = @"filterTableCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];


     NSDictionary *tempDict = [self.filterEvents objectAtIndex:indexPath.row];

    self.eventTitle = [tempDict objectForKey:@"eventType"];
    cell.textLabel.text = self.eventTitle;

    return cell;


-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    NSDictionary *tempDict = [self.filterEvents objectAtIndex:indexPath.row];
    NSString *string = [tempDict objectForKey:@"eventType"];

    ContactsTableViewController *contactVC = [[ContactsTableViewController alloc] init];
    contactVC.filter = string;

    [self dismissViewControllerAnimated:YES completion:nil];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"updateParent" object:nil];


#pragma mark - Helper Methods

- (IBAction)done:(id)sender

    [self dismissViewControllerAnimated:YES completion:nil];


-(void)retrieveFilteredEvents

    PFQuery *retrieveEvents = [PFQuery queryWithClassName:@"eventTypes"];
    [retrieveEvents orderByAscending:@"eventOrder"];
    [retrieveEvents findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) 
        if (!error) 
            self.filterEvents = [[NSArray alloc] initWithArray:objects];
        
        [self.filterTable reloadData];
    ];



@end

【问题讨论】:

按照 Ankush Agrawal 和 CrimsonChris 的建议使用委托解决。协议方法有点过头了,但我会回来练习。谢谢大家!! 【参考方案1】:

有多种方法可以解决这个问题。我认为最简单的方法是在您的父类中设置一个属性,该属性会在您每次更新子类时更改。

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    NSDictionary *tempDict = [self.filterEvents objectAtIndex:indexPath.row];
    NSString *string = [tempDict objectForKey:@"eventType"];

    self.parentViewController.filter = string;

    [self dismissViewControllerAnimated:YES completion:nil];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"updateParent" object:nil];

另一种选择是使用委托。这可能是一种更简洁的解决方案,但对初学者不太友好。

http://iosdevelopertips.com/objective-c/the-basics-of-protocols-and-delegates.html

【讨论】:

self.parentViewController 不允许我访问 filter 属性。可能是因为模态视图控制器嵌入在导航控制器中?【参考方案2】:

你在这里做什么:

ContactsTableViewController *contactVC = [[ContactsTableViewController alloc] init];
contactVC.filter = string;

正在实例化一个全新的控制器,它与提供您的FilterViewController 的实际控制器无关。

尝试使用它来访问呈现@9​​87654323@ 的视图控制器:

ContactsTableViewController *contactVC = (ContactsTableViewController*)self.presentingController;
contactVC.filter = string;

希望这会有所帮助。

【讨论】:

【参考方案3】:

Alloc init 为您提供了一个全新的对象,而不是对您现有对象的引用。有几种方法可以引用您的表格视图。我推荐委托,这是一种灵活的方法,即使您以不同于模态的方式呈现视图,它也将继续有效。

【讨论】:

【参考方案4】:

创建协议

@protocol PassSomeData

-(void)childViewController:(UIViewController *)viewController passedSomeData:(id)data;
@end

在子视图控制器中创建一个委托

@interface ViewControllerThatIsPresentedModally :UIViewController
@property(nonatomic,assign) id<PassSomeData>delegate;
@end

在呈现模态的视图控制器的prepareForSegue 中写下这个

UIViewController *vc = [segue destinationViewController];
if ([vc isKindOfClass:[ViewControllerTahIsPresentedModally class])
[((ViewControllerThatIsPresentedModally *)vc) setDelegate:self];

当您的用户点击允许收集某些数据的内容时 你会的

[self.delegate viewController:self passedSomeData:yourData];

你在父视图控制器中的方法会被你的数据调用

您的呈现视图控制器需要符合 PassedSomeData 协议并实现给定的方法

【讨论】:

如果您使用 ARC,请使用 weak 而不是为您的委托属性分配,这是您应该使用的。 在这方面遇到了真正的困难。当我发布您写的最后一条消息时,我收到错误“No known instance for selector 'viewController:passedSomeData:' 我想我不确定我需要在呈现视图控制器中实现的方法是什么。 @kerbelda 解决您的问题的“代表”的定义完全像这样......!【参考方案5】:

如果它是一个简单的属性集,你可以这样做

[self.parentViewController performSelector:@selector(setSomething:) withObject:...]

[self.presentingViewController performSelector:@selector(setSomething:) withObject:...]

不过,委托是一种更好的方式 :-)

【讨论】:

以上是关于将属性从模态视图控制器传递给父级的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据从先前的 segue 传递给子视图控制器?

将 NSMutableArray 从模态视图控制器传递到父视图

将信息传递给模态视图控制器

UIView 旋转,模态视图横向和纵向,父级无法渲染

将变量传递给父视图?

访问模态视图控制器父级