在模态视图控制器内更新呈现视图控制器的属性

时间:2014-08-12 21:02:04

标签: ios objective-c modalviewcontroller presentmodalviewcontroller

我想知道如何从模态视图控制器内部调用的方法更新呈现视图控制器的视图控制器property?现在,我能想到的唯一方法是使用NSNotificationCenter,虽然这适用于词典项目,但我无法弄清楚如何将它用于自定义对象。

例如,我的展示视图控制器HomewViewController有一个名为PFObject的解析homeSelections,可以在模态显示的ModalViewController属性中更新newSelections(以及PFObject)。在用户进行选择之后,我希望HomeViewController homeSelections也具有从模态视图控制器传递的最新数据。

感谢帮助 - 谢谢。

更新1 :这就是我现在所做的事情(注意我正在使用一个精简的示例来测试)

ViewController中(这是父/呈现视图控制器)

@interface ViewController ()

@property (strong, nonatomic) NSArray *totalRamen;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    self.totalRamen = @[@"ramen1", @"ramen2", @"ramen3", @"moot"];

}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    NSLog(@"self.totalRamen: %@", self.totalRamen);
    NSLog(@"Done");
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"showModal"]){
        ModalViewController *destinationVC = (ModalViewController *)segue.destinationViewController;
        destinationVC.passedRamen = self.totalRamen;
    }
}

- (IBAction)showModalAction:(UIButton *)sender
{
    ModalViewController *destinaionViewController = [[ModalViewController alloc] init];
    destinaionViewController.selectionCallback = ^(id selectedItem) {
        self.totalRamen = (NSArray *)selectedItem;
        NSLog(@"self.totalRAmen %@", self.totalRamen);
        NSLog(@"done");
    };
    [self performSegueWithIdentifier:@"showModal" sender:self];
}

ModalViewController中(这是呈现的/模态视图控制器)

@interface ModalViewController : UIViewController

@property (strong, nonatomic) NSArray *passedRamen;
- (IBAction)dismissModal:(UIButton *)sender;

typedef void(^CallbackBlock)(id value);
@property (nonatomic, copy) CallbackBlock selectionCallback;

@end

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];

    NSLog(@"Passed ramen %@", self.passedRamen);
    NSLog(@"Done");

    self.passedRamen = @[@"moot is awesome"];
    NSLog(@"new ramen: %@", self.passedRamen);
    NSLog(@"%@", self.selectionCallback); //nil here

    //call back
    CallbackBlock selectionCallback = self.selectionCallback;
    if (selectionCallback){
        selectionCallback(self.passedRamen); //I want to send the newly updated self.passedRamen back
    } else {
        NSLog(@"No show"); //Means if isn't called
    }
}

- (IBAction)dismissModal:(UIButton *)sender
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

2 个答案:

答案 0 :(得分:4)

将回调块传递给呈现的视图控制器。这样,呈现的视图控制器就不知道有关呈现它的视图控制器的任何信息。更灵活,因为现在任何人可以呈现你的视图控制器,他们只是传递一个块!

PresentingViewController

PresentedViewController *vc = [[PresentedViewController alloc] init]; //or get your existing one
vc.selectionCallback = ^(id selectedItem) {
    //update selected items here
};
//present vc here

PresentedViewController

typedef void(^CallbackBlock)(id value);

@property (nonatomic, copy) CallbackBlock selectionCallback;

- (void)somethingWasSelected:(id)selectedItem {
    CallbackBlock selectionCallback = self.selectionCallback;
    if (selectionCallback) selectionCallback(selectedItem);
}

谨防保留周期。该块由所呈现的视图控制器保留,因此对块中呈现的视图控制器的引用而不首先削弱它将产生泄漏。有关此问题的更多信息,请访问here

答案 1 :(得分:0)

  

用户选择后,我想要HomeViewController   homeSelections也有从模态视图传递的最新数据   控制器。

简单的方法是避免ModalViewController更新HomeViewController。打开通讯 - 拥有HomeViewController查询ModalViewController并在模式被解除时自行更新。

HomeViewController已取决于ModalViewController - 它必须知道ModalViewController才能呈现它。因此,让它知道如何在适当的时间从newSelections中读取ModalViewController属性也没有什么害处。另一方面,ModalViewController无需了解其信息的来源。为了完成工作,它不需要知道HomeViewController。如果您无法告诉ModalViewController有关HomeViewController的任何内容,您可以轻松地使用来自其他视图控制器的ModalViewController,如果出现这种需要的话。更重要的是,如果ModalViewController更改,则无需更新HomeViewController

例如,您的HomeViewController可能会(部分)看起来像这样:

- (void)showModalViewController
{
    self.modalViewController = [[ModalViewController alloc] init]; // or otherwise get the modal controller
    [self presentViewController:self.modalViewController
                       animated:YES 
                     completion:];
}

- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
{
    self.homeSelections = self.modalViewController.newSelections;
    [super dismissViewControllerAnimated:flag completion:completion];
    self.modalViewController = nil;
}