Обновление родительского ViewController после отклонения ModalViewController
В моем приложении iOS пользователь может выбрать изображение из списка, на котором им будет представлен модальный код, содержащий изображение и параметры для удаления изображения. Если пользователь хочет удалить изображение, она возвращается в исходный viewController, содержащий список изображений. Мне нужно затем обновить исходный ViewController, чтобы принять во внимание удаленное изображение.
Я попытался использовать NSNotificationCenter для трансляции, когда изображение будет удалено в родительский View Controller. Однако похоже, что трансляция так и не была получена.
Есть ли другой способ
- отправить данные обратно в родительский ViewController после отклонения модальности и
- обнаруживает, когда модаль отклоняется из родительского ViewController?
(я попробовал следующий пример здесь, но он не работал)
Ниже мой код:
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
}
Заранее благодарим за помощь!
Ответы
Ответ 1
В моем случае я обычно использую блок здесь.
Например, у вас есть 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
Ответ 2
Вы должны сделать протокол в своем MediaPreviewViewController. Затем, когда изображение будет удалено, отправьте метод делегата, чтобы родительский контроллер представления мог справиться с этим.
Вы также не должны позволять диспетчеру просмотра самому себя (хотя это возможно, но рекомендуется, чтобы представление, которое создало модальный, также отвечало за удаление модального...)
Итак, вы должны получить что-то вроде этого:
В 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];
В вашем родительском контроллере представления вам необходимо реализовать этот протокол, как вы привыкли с делегатами. Затем вы также можете удалить представление из родительского объекта в этом делетете
Ответ 3
Это может помочь любому, у кого такая же проблема, в UIPopovePresentationController. По моему опыту, ответ Аллана может решить ту же проблему.
У меня только проблема с делегатом Viewcontroller, который присутствует, поскольку UIPopoverPresentingController не отправил вызов в свой корневой вид. И ответ Аллана может решить эту проблему.
Мой пример кода:
-(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 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];
}