在解除ModalViewController后刷新父ViewController

时间:2014-09-02 05:08:31

标签: ios objective-c uiviewcontroller nsnotificationcenter presentviewcontroller

在我的iOS应用程序中,用户可以从列表中选择一个图像,在该图像上显示一个包含图像的模式和删除图像的选项。如果用户选择删除图像,则返回到包含图像列表的原始viewController。我需要刷新原始ViewController以考虑删除的图像。

我尝试使用NSNotificationCenter在将图像删除到父视图控制器时进行广播。但是,似乎从未收到广播。

还有其他方式

  1. 在解除模式后将数据发送回父ViewController,并
  2. 检测何时从父ViewController中解除模态?
  3. (我尝试按照here概述的示例,但它似乎没有效果)

    以下是我的代码:

    EditStepViewController(原始视图控制器):

    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    MediaPreviewViewController *mediaPreviewVC = (MediaPreviewViewController *)[storyboard instantiateViewControllerWithIdentifier:@"MediaPreviewViewController"];
    mediaPreviewVC.selectedImageURL = [NSString stringWithFormat:@"%@",gestureRecognizer.view.tag];
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:mediaPreviewVC];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(didDismissMediaPreview)
                                                 name:@"MediaPreviewDismissed"
                                               object:nil];
    [self presentViewController:navigationController animated:YES completion:nil];
    

    MediaPreviewViewController(第二个ViewController):

     ...
     [self deleteImage];
     [[NSNotificationCenter defaultCenter] postNotificationName:@"MediaPreviewDismissed" object:nil userInfo:nil];
     [self dismissViewControllerAnimated:YES completion:^(){
       NSLog(@"dismissed controller");
      }];
    

    然后,回到EditStepViewController:

    -(void)didDismissMediaPreview{
        NSLog(@"dismissed media preview"); // this is never logged!
        [self.view setNeedsDisplay]; // refresh view to account for deleted image
    }
    

    提前感谢您的帮助!

3 个答案:

答案 0 :(得分:19)

在我的情况下,我通常在这里使用阻止。

例如,你有 ParentViewController.h

@interface ParentViewController : UIViewController
@end

实施 ParentViewController.m

// INCLUDE HERE THE MODAL CONTROLLER TO HAVE ACCESS TO ITS PUBLIC PROPERTY
#import ModalViewController.h

@implementation ParentViewController

// implement your modal dismiss block here
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
   // DEFINE HERE THE CALLBACK FUNCTION
   // 1. get the model view controller
   ModalViewController *mvc = [segue destinationViewController];

   // 2. Your code after the modal view dismisses
   mvc.onDismiss = ^(UIViewController *sender, NSObject *objectFromModalViewController)
   {
       // Do your stuff after dismissing the modal view controller
       .
       .
       .
   }
} 
@end

并且, ModalViewController.h

@interface ModalViewController : UIViewController

// call back function, a block
@property (nonatomic, strong) void (^onDismiss)(UIViewController *sender, NSObject *objectYouWantToPassBackToParentController)
@end

<强> ModalViewController.m

@implementation ModalViewController

.
.
.

// your dismiss function say
- (IBAction)dismissViewController:(id)sender
{
   ... 

   [self deleteImage];

   [self dismissViewControllerAnimated:YES completion:^
   {
      // MAKE THIS CALL
      self.onDismiss(self, theOjectYouWantToPassBackToParentVC);
   }];
}
@end

答案 1 :(得分:1)

您应该在MediaPreviewViewController中制作协议。然后删除图像时,发送一个委托方法,以便父视图控制器可以处理它。

你也不应该让viewcontroller自行解散(尽管有可能,但建议创建模态的视图也负责删除模态...)

所以你应该得到这样的东西:

在MediaPreviewViewController.h中:

@protocol MediaPreviewViewControllerDelegate <NSObject>

-(void)didRemovedImage;

@end

@interface MediaPreviewViewController : NSObject {
    id< MediaPreviewViewControllerDelegate > delegate;
}

@property (nonatomic, assign) id < MediaPreviewViewControllerDelegate> delegate;

在MediaPreviewViewController.m中:

@synthesize delegate = _delegate;

然后在MediaPreviewViewController中删除图像的方法中,只需调用:

[_delegate didRemoveImage];

在父视图控制器中,您需要实现此协议,就像您习惯使用委托一样..然后您也可以在此委托方法中从父级中删除视图

答案 2 :(得分:1)

这可以帮助任何在UIPopovePresentationController上遇到相同问题的人。根据我的经验,艾伦的答案也可以解决同样的问题。

我刚刚遇到有关ViewController委托的问题,因为UIPopoverPresentingController没有向其根视图发送调用。 Allan的回答可以解决这个问题。

我的示例代码:

-(IBAction)choosePic:(id)sender
{
    UIButton *picButton = (UIButton *)sender;

    // Set PopoverPresentation view controller

    PicViewController *picVC = [self.storyboard instantiateViewControllerWithIdentifier:@"PicViewController"];

    UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:picVC];

    picVC.preferredContentSize = CGSizeMake(500., 500.);


    // Set this function as described in Allan's answer

    picVC.dismissPopover = ^(UIViewController *controller, UIImage *image) 
    {

       _myImage = image;

       .....

       .....

       .....

    };

    navController.modalPresentationStyle = UIModalPresentationPopover;

    _picPopover = navController.popoverPresentationController;

    _picPopover.delegate = self;

    _picPopover.sourceView = self.view;

    _picPopover.sourceRect = [picButton frame];

    navController.modalPresentationStyle = UIModalPresentationPopover;

    navController.navigationBarHidden = YES;

    [self presentViewController:navController animated:YES completion:nil];

}