objective-c reload UITableView after back navigation - objective-c

I have a TableViewController embedded in a NavigationController, at some point I use a Segue to push to a new ViewController. When I navigate back from the ViewController I want to reload the tableView in the TableViewController.
I followed the solution posted here and here. For some reason it does not work. I miss something but I can't see it at the moment.
Has anybody a glue, why the code does not work? What do I have to do to get it work?
TableViewController.m
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// notification when comeing back from the cameraView
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(reloadMagazine:) name:#"reloadTable" object:nil];
}
return self;
}
//[...]
// notification reload
-(void)reloadMagazine:(NSNotification *)notification {
NSLog(#"notification reload");
[self.tableView reloadData];
}
//[...]
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
[[NSNotificationCenter defaultCenter] postNotificationName:#"reloadTable" object:self];
}
ViewController.m
-(void)uploadData:(id)sender {
// Upload and navigate back to the tableViewController
[[NSNotificationCenter defaultCenter] postNotificationName:#"reloadTable" object:self];
[self dismissViewControllerAnimated:YES completion:nil];
[self.navigationController popViewControllerAnimated:YES];
}

This does not answer your question "why the code does not work?", but the easiest
method to reload the table view when navigating back to it could be to
call reloadData in viewWillAppear.

I suspect that the code above does not work because initWithStyle is not being called. Put a breakpoint there to test my theory. If that is the case, then move that code to viewDidLoad.

Related

Cordova - Implementing the Privacy Screen functionality with the ASWebAuthenticationSession usage

I'm adding the privacy screen functionality to the hybrid Cordova app via a plugin and following the approach adviced by apple.
Though it leads to unexpected issues when I open ASWebAuthenticationSession window I use for the OAuth authentication. What happens is, when system dialogue appears with a text "Your app wants to use xxx for Sign In", it makes the app to lose a focus and the privacy screen appears behind the overlay. After I choose "Yes", the app gains focus back and the code removing the privacy screen fires, the same code also closes the freshly opened ASWebAuthenticationSession window.
The code in PrivacyScreenPlugin.m:
UIViewController *blankViewController;
#interface PrivacyScreenPlugin ()
#end
#implementation PrivacyScreenPlugin
- (void)pluginInitialize
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(onAppDidBecomeActive:) name:UIApplicationDidBecomeActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(onPageDidLoad) name:CDVPageDidLoadNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(onAppWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
}
-(UIViewController *)createViewWithGradient {
UIViewController *viewController;
viewController = [UIViewController new];
viewController.modalPresentationStyle = UIModalPresentationOverFullScreen;
return viewController;
}
-(void) applyPrivacyScreen
{
if (blankViewController == NULL) {
blankViewController = [self createViewWithGradient];
}
blankViewController.view.window.hidden = NO;
[self.viewController.view.window.rootViewController presentViewController:blankViewController animated:NO completion:NULL];
}
#pragma mark - Explicit Commands
- (void) hidePrivacyScreen:(CDVInvokedUrlCommand*)command
{
[self removePrivacyScreen];
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
- (void) showPrivacyScreen:(CDVInvokedUrlCommand*)command
{
[self applyPrivacyScreen];
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}
#pragma mark - Triggered functions
- (void) onPageDidLoad
{
[self removePrivacyScreen];
}
- (void)onAppDidBecomeActive:(UIApplication *)application
{
[self removePrivacyScreen];
}
- (void)onAppWillResignActive:(UIApplication *)application
{
[self applyPrivacyScreen];
}
#pragma mark - Helper functions
-(void) removePrivacyScreen
{
[self.viewController dismissViewControllerAnimated:NO completion:nil];
}
#end
So far I got that issue is related to the way view is dismissed, namely dismissViewControllerAnimated which dismisses the stack of modal windows:
[self.viewController dismissViewControllerAnimated:NO completion:nil];
Can it be helped or worked around? Maybe instead of removing a security screen, it can be hidden? Or is there a different way to draw the overlay which is free of the issue?
P.S. I tried to listen to UIApplicationDidEnterBackgroundNotification event, but it's not what I want. I'd like the app screen to be covered as soon as it's sent to the list of apps (via a double tap on the home button or long swipe).
To accomplish it, it's needed to render the privacy screen in a subview, instead of a modal view. It enables to hide/show a privacy screen view instead of adding/removing it:
-(void) removePrivacyScreen
{
blankViewController.view.hidden=YES;
}
-(void) applyPrivacyScreen
{
if (blankViewController == NULL) {
blankViewController = [self createViewWithGradient];
}
blankViewController.view.hidden = NO;
[self.viewController.view.window addSubview:blankViewController.view];
}

Calling UIKeyboard method on UITextView and not UITextFields

I have view with a UITextView for comments on the bottom. Since its on the bottom of the page, whenever someone edits it, a method is called to shift the view of the page, so that you can still see the comment box. My problem is that the same method also gets called when user are editing UITextFields.
Here's what I have. First I declare a notification:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:self.view.window];
Then the method itself
- (void)keyboardWillShow:(NSNotification *)notif{
...
}
My first thought was to add a condition, to check and see if the object was a TextView, and only then execute the code. But since I am not passing the object to the method, is there anyway to tell the method what type of object I am dealing with
Text fields and text views also send notifications. In the textFieldShouldBeginEditing and the textViewShouldBeginEditing implementations you could set a flag that you can read in your implementation of the keyboardWillShow method -- the keyboard notification is sent after the text field or text view notifications.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
self.sender = #"text field";
return YES;
}
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView {
self.sender = #"text view";
return YES;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWillShow:)
name:UIKeyboardWillShowNotification
object:self.view.window];
}
- (void)keyboardWillShow:(NSNotification *)notif{
NSLog(#"%#",self.sender);
}

How to reload the tableView after dismissing a NavigationController in uisplitviewcontroller?

I'm using a UISplitviewController as a template.
action for edit button:
newExViewController *editWindow =[[newExViewController alloc]initWithNibName:#"newExViewController" bundle:nil];
UINavigationController *navBar=[[UINavigationController alloc]initWithRootViewController:editWindow];
navBar.modalPresentationStyle = UIModalPresentationFormSheet;
navBar.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:navBar animated:YES];
[navBar release];
[editWindow release];
navBar has a UIBarButton for saveButton. This is called when you press SaveButton
[self dismissModalViewControllerAnimated:YES];
now is the problem:
any idea how to reload the data for both the main NavigationConteroller and the detailViewController when the modalView is dismissed??
I have no clue
thnx
You should look into NSNotificationCenter. In your view with the UITableView, create the notification listener. Then in the view that dismisses, call that notification.
To be more specific, the Notification will call a method that should contain reloadData.
Example
The following should go with the UITableView you want to reload:
This could go along with your [self dismissModalViewControllerAnimated:YES];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(someMethodToReloadTable) name:#"reloadTable" object:nil];
This is how you will call the notification center to reload the table:
[[NSNotificationCenter defaultCenter] postNotificationName:#"reloadTable" object:self];
Example of the notification method:
- (void)someMethodToReloadTable:(NSNotification *)notification
{
[myTableView reloadData];
}
And don't forget to remove the notificaiton observer:
-(void)viewDidUnload
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"reloadTable" object:nil];
}
In controllers, that contains view you want to reload, you should decline following method which will be called when the modalView will be dismissed (or when controller's main view will be first time loaded):
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
// here you can reload needful views, for example, tableView:
[tableView reloadData];
}

MBProgresshud with tableview

I am making a application with a tableview in it. I would like to implement a loading screen, using MBProgressHUD such that it will display before data is read from internet. However the data's not shown using following code:
- (void)viewDidLoad
{
HUD = [[MBProgressHUDalloc] initWithView:self.view];
[self.viewaddSubview:HUD];
HUD.delegate = self;
[HUD showWhileExecuting:#selector(load_data) onTarget:self withObject:nil animated:YES];
}
the data can be shown in tableview using the function load_data alone (i.e [self load_data], but not with HUD.
In my experience, when using the HUD to display while loading or waiting for data to load, you should call the HUD in the -viewDidAppear method. I also noticed that you didn't include the [super viewDidLoad]; call in your code. If you are going to present your HUD, you will have to call it after you call on the super viewDidLoad if you want it to appear. Hopefully these help you out.
I like to present and hide the HUD with separate methods that only do that. e.g.
#pragma mark - The HUD
-(void)showHudWithText:(NSString *)text {
if (self.hud == nil) {
self.hud = [[[MBProgressHUD alloc] initWithWindow:self.window] autorelease];
[self.window addSubview:hud];
}
[self.hud setLabelText:text];
[self.hud setMode:MBProgressHUDModeIndeterminate];
[self.hud show:YES];
}
-(void)hideHud {
[self.hud hide:YES];
}
This allows the HUD to be controlled independently of the view life cycle, as well as from asynchronous methods, timers, etc. e.g:
-(void)viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(showHudWithText:) name:kSomethingImportantStartedNotification object:#"Starting..."];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(hideHud) name:kSomethingImportantEndedNotification object:nil];
}
Or something like that.

Dismiss modal view controller on application exit

I have a view controller (view A) presenting a modal view (B) when the user pushed a button and the view B has itself a button to present view C. My problem is that if the user exits the application when the view B or C is shown, the same view will appear next time the application is launched. Is there a way to dismiss the views B and C on exit or to show view A when the application starts?
Thanks for your help
I assume by close you mean when the application enters the background.
In your app delegate you can via the applicationDidEnterBackground: method dismiss your controller.
Best way would probably be to add an observer in your view controller class:
- (void) viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(appClosing) name:#"appClosing" object:nil];
}
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:#"appClosing" object:nil];
[super dealloc];
}
- (void) appClosing
{
[self dismissModalViewControllerAnimated:YES];
}
And post the notification in your app delegate:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"appClosing" object:nil];
}