【问题标题】: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 的建议使用委托解决。协议方法有点过头了,但我会回来练习。谢谢大家!!

标签: ios objective-c cocoa-touch uiviewcontroller modalviewcontroller


【解决方案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:...]
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-23
        • 1970-01-01
        • 2021-06-28
        • 2019-01-24
        相关资源
        最近更新 更多