I want to reset my UISearch when app is entering background, or entering foreground again. It would be enough when the tableview from UISearch gets hidden.
But when I try to hide it from AppDelegate.m it doesn't work. I have also logged the UIElements, there are also (null).
Here is how I try to access it:
- (void)applicationWillEnterForeground:(UIApplication *)application
{
XLog(#"");
/*
Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
*/
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
XLog(#"");
searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchViewController_iPad" bundle:[NSBundle mainBundle]];
} else {
XLog(#"");
searchViewController = [[SearchViewController alloc] initWithNibName:#"SearchViewController_iPhone" bundle:[NSBundle mainBundle]];
}
XLog(#"searchViewController.searchBar.text: %#", searchViewController.searchBar.text);
searchViewController.tableViewSearch.hidden = YES; // is (null)
XLog(#"searchViewController.tableViewSearch: %#", searchViewController.tableViewSearch); // is (null)
}
How can I access that? Do I something wrong here, or is it not allowed to access elements from other classes thru appdelegate.m?
NSArray *ary_navigationControllerViews = [[NSArray alloc] initWithArray:[self.navigationController viewControllers]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self.class.description == %#", [[SearchViewController class] description]];
NSArray *ary_viewController = [[NSArray alloc] initWithArray:[ary_navigationControllerViews filteredArrayUsingPredicate:predicate]];
if ([ary_viewController count] > 0)
{
SearchViewController *sVw = (SearchViewController*) [ary_viewController objectAtIndex:0] ;
sVw.tableViewSearch.hidden = YES;
}
You are initializing new instance of your view controller, instead you need to get existing instance of your view controller and hide your view. Hope this helps.
Related
I have set up my class with UITabBarDelegate and implemented its method didSelectItem to detect when a certain tabBar item is pressed. Works great. In each tabBar item I have one containerView that can show a "you have to login"-page if the user is not logged in, and another containerView that present viewControllers that are embedded in a navigationController.
I would like to keep track of the viewController that is presented in the current tab item, and/or the root viewController of that tab.
I have tried a number of different approaches, but most of them return nil or I can't get it to work. I think the whole container situation makes it harder to handle.
It looks something like this:
#interface MyTabBarController () <UITabBarDelegate>
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
NSUInteger indexOfTab = [[tabBar items] indexOfObject:item];
switch (indexOfTab) {
case 0: {
NSLog(#"🐳PRESSIIING %lu", (unsigned long)[[tabBar items] indexOfObject:item]);
break;
}
case 1: {
NSLog(#"🐳PRESSIIING %lu", (unsigned long)[[tabBar items] indexOfObject:item]);
break;
}
case 2: {
NSLog(#"🐳PRESSIIING %lu", (unsigned long)[[tabBar items] indexOfObject:item]);
//These return nil
NSLog(#"🐳AAAAAA %#", ((UINavigationController*)_appD.window.rootViewController).visibleViewController);
NSLog(#"🐳AAAAAA %#", ((UITabBarController*)_appD.window.rootViewController).selectedViewController);
NSLog(#"🐳AAAAAA %#", self.navigationController.topViewController);
NSLog(#"🐳AAAAAA %#", self.navigationController.visibleViewController);
//This returns with a value, but can't get it to work with conditionals, that is, when I'm in root, the else is triggered
NSLog(#"🐳AAAAAA %#", self.tabBar.window.rootViewController);
if(!self.tabBar.window.rootViewController) {
NSLog(#"🐳🐳🐳THIS IS NOT ROOT🐳🐳🐳");
}else {
NSLog(#"🐳🐳🐳this is ROOT🐳🐳🐳");
}
// This returns nil
((UINavigationController*)_appD.window.rootViewController).visibleViewController;
((UITabBarController*)_appD.window.rootViewController).selectedViewController;
//Doesn't work
if([self.navigationController.viewControllers[0] isKindOfClass:[ExperiencesListViewController class]]) {
NSLog(#"🐳IS KIND OF CLASS LIST");
}
if([self.navigationController.viewControllers[0].childViewControllers isKindOfClass:[ExperiencesContainerViewController class]]) {
NSLog(#"🐳IS KIND OF CLASS CONTAINER");
}
break;
}
case 3: {
NSLog(#"🐳PRESSIIING %lu", (unsigned long)[[tabBar items] indexOfObject:item]);
break;
}
case 4: {
NSLog(#"🐳PRESSIIING %lu", (unsigned long)[[tabBar items] indexOfObject:item]);
break;
}
default:
break;
}
}
So, what else can I try? Seems like I have to use `self.tabBar.window.rootViewController` in some way, no?
***EDIT***
Oh, and I have tried the `tabBarController` delegate but that doesn't trigger. Also, the `tabBar` is constructed programmatically if that helps.
Sorry to have not read your question correctly. Here's what I suggest you do.
All of these view controllers that you're interested in keeping track of: you should have them send a custom notification from within their -viewDidAppear: (or -viewWillAppear:) method. Then let your ApolloTabBarController object register for that notification. When it gets the notification, you could then store a reference to the view controller. That reference will always point to the active view controller.
In your individual view controllers, do something like the following:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
[nc postNotificationName:#"XYZViewControllerDidBecomeActiveNotification"
object:self];
}
Of course, you would want to use some kind of constant for the notification name.
In your ApolloTabBarController class, register for XYZViewControllerDidBecomeActiveNotification and implement something like:
- (void)viewControllerDidBecomeActive:(NSNotification *)notification
{
self.activeViewController = [notification object];
}
I hope that helps!
When you're setting up each view controller for each of the tabs, set the tag property of the UITabBarItem to correspond to the index of the view controller in the tab bar's viewControllers array.
UIViewController* myFirstVC = [[UIViewController alloc] init];
UIViewController* mySecondVC = [[UIViewController alloc] init];
// "self" is your ApolloTabBarController.
[self setViewControllers:#[myFirstVC, mySecondVC]];
myFirstVC.tabBarItem =
[[UITabBarItem alloc] initWithTitle:#"First" image:nil tag:0];
mySecondVC.tabBarItem =
[[UITabBarItem alloc] initWithTitle:#"Second" image:nil tag:1];
Then, you'll be able to grab a reference to view controller.
// In your example, your ApolloTabBarController acts as its own delegate.
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item
{
UIViewController* activeVC =
[[self viewControllers] objectAtIndex:[item tag]];
}
I want to include some UIKeyCommands in my app. My app consists of one UISplitViewController that forces the master to be always visible on iPad full screen. On smaller screen it works like it normally would.
Now, I've implemented some UIKeyCommands in the MasterViewController and some in the DetailViewController. However, the app will only show those in DetailViewController. So I put all of them in the RootSplitViewController, but that will show all of them, even when the MasterViewController is hidden in iOS 9's splitview.
What I want though, is for it to show all when the app is fullscreen on iPad and thus the MasterViewController is forced on screen together with the DetailViewController. And when the view is small (ie 50-50) and the MasterViewController is hidden, I want it to only show those of the window that's on screen.
Any ideas on how to achieve this?
In the end I managed to do this - although in a not-so-pretty way.
The UIKeyCommands are added to the RootSplitViewController.
- (NSArray *)keyCommands {
if (self.view.traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassRegular) {
return #[
[UIKeyCommand keyCommandWithInput:#"r" modifierFlags:UIKeyModifierCommand action:#selector(changeRestaurant:) discoverabilityTitle:#"Change restaurant"],
[UIKeyCommand keyCommandWithInput:#"t" modifierFlags:UIKeyModifierCommand action:#selector(changeTable:) discoverabilityTitle:#"Change table"]
];
} else {
if (self.masterIsVisible == YES) {
return #[
[UIKeyCommand keyCommandWithInput:#"t" modifierFlags:UIKeyModifierCommand action:#selector(changeRestaurant:) discoverabilityTitle:#"Change restaurant"]
];
} else {
return #[
[UIKeyCommand keyCommandWithInput:#"t" modifierFlags:UIKeyModifierCommand action:#selector(changeTable:) discoverabilityTitle:#"Change table"]
];
}
}
}
Those methods call the actual methods in the specific UIViewController.
- (void)changeRestaurant:(id)sender {
UINavigationController *nav = (UINavigationController *)[self.viewControllers objectAtIndex:0];
RestaurantController *master = [nav.viewControllers objectAtIndex:0];
[master changeRestaurant];
}
- (void)changeTable:(id)sender {
UINavigationController *nav = (UINavigationController *)[self.viewControllers objectAtIndex:1];
TableController *detail = [nav.viewControllers objectAtIndex:0];
[detail changeTable:sender];
}
In order for this to work I added a BOOL to the UISplitViewController.
#interface RootSplitViewController : UISplitViewController
#property (nonatomic) BOOL masterIsVisible;
#end
Which is then called in the MasterViewController.
- (void)viewDidDisappear:(BOOL)animated {
RootSplitViewController *rootView = (RootSplitViewController *)self.splitViewController;
rootView.masterIsVisible = NO;
}
- (void)viewDidAppear:(BOOL)animated {
RootSplitViewController *rootView = (RootSplitViewController *)self.splitViewController;
rootView.masterIsVisible = YES;
}
I know this might not be the pretties method, but it works. If anyone knows a better way to do it, I'd love to hear your feedback.
I'm using SWRevealViewController to get the side menu to show different content based on which tab the user is currently on. I've created a global variable in called location in AppDelegate to find out where the user is. For my sidebar, I'm using this condition to change the content:
- (void)viewWillAppear:(BOOL)animated {
[super viewDidAppear:animated];
AppDelegate *del=(AppDelegate*)[[UIApplication sharedApplication] delegate];
if ([del.location isEqualToString: #"Secure"]){
self.menu = [NSMutableArray
arrayWithObjects:#"secure1",#"secure2",#"secure3",#"secure4",#"secure5", nil];
self.menu2 = [NSMutableArray
arrayWithObjects:#"s1",#"s2",#"s3",nil];
NSLog(#"THIS IS %# menu",del.location);
}
else if ([del.location isEqualToString: #"Employee"]){
self.menu = [NSMutableArray
arrayWithObjects:#"emp1",#"emp2",#"emp3",#"emp4",#"emp5",#"emp6", nil];
self.menu2 = [NSMutableArray
arrayWithObjects:#"e1",#"e2",#"e3",nil];
NSLog(#"THIS IS %# menu",del.location);
}
else if ([del.location isEqualToString: #"Patient"]){
self.menu = [NSMutableArray
arrayWithObjects:#"patient1",#"patient2",#"patient3",#"patient4",#"patient5",#"patient6", nil];
self.menu2 = [NSMutableArray
arrayWithObjects:#"p1",nil];
NSLog(#"THIS IS %# menu",del.location);
}
}
It seems to be working as the NSLog statements all come out correctly, but the content for menu and menu2 still do not change. Where am I going wrong?
I wasn't adding the
[self.tableView reload];
after closing the if-statement, and instead added it under cellForRowAtIndexPath (which lead the cells to constantly reload, but not the table -- if my understanding is correct.)
Added it in the viewWillAppear after closing my if-statement and problem solved.
Thanks to Anbu.Karthik for pointing it out!
I'm working on a Tabbed Application with one tab showing information about the current neighbourhood if the user is within this specific region. If the user leaves the area the tab should be removed, if he enters the region the tab should be added again to the TabBar.
I achieved to calculate if the user is inside or outside the area using CLLocation. But I fail to remove and add the Tab again afterwards:
UITabBarController.m:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
currentposition = [[CLLocation alloc] initWithLatitude:newLocation.coordinate.latitude longitude:newLocation.coordinate.longitude];
[self userisincity];
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error
{
[self userisincity];
}
- (void)userisincity
{
if ((currentposition.coordinate.longitude > 17.50) && (currentposition.coordinate.longitude < 17.70) && (currentposition.coordinate.latitude > 37.45) && (currentposition.coordinate.latitude < 37.65)){
NSLog(#"inside city");
//add tab
} else {
NSLog(#"outside city");
//remove tab
NSUInteger indexToRemove = 0;
NSMutableArray *controllersToKeep = [NSMutableArray arrayWithArray:self.viewControllers];
UIViewController *removedViewController = [controllersToKeep objectAtIndex:indexToRemove];
[controllersToKeep removeObjectAtIndex:indexToRemove];
NSLog(#"%#", controllersToKeep);
[self.tabBarController setViewControllers:controllersToKeep animated:YES];
}
}
The log shows if the user is inside or outside so the location part works properly. controllersToKeep has 4 entries first and one gets removed. But setViewControllers has no effect.
How can I add the Tab afterwards again? It's a ViewController done and linked using Storyboards right now.
Change the last line of code from:
[self.tabBarController setViewControllers:controllersToKeep animated:YES];
to:
[self setViewControllers:controllersToKeep animated:YES];
since self is the UITabBarController.
this solution works so far:
i also had to update the name of the tabs after adding/removing one.
if ((currentposition.coordinate.longitude > XY) && (currentposition.coordinate.longitude < XY) && (currentposition.coordinate.latitude > XY) && (currentposition.coordinate.latitude < XY)){
//add view
NSMutableArray *ViewControllers = [NSMutableArray arrayWithArray:self.viewControllers];
if (ViewControllers.count == 3) {
UINavigationController *nextomeNavigationController = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:#"ViewControllerID"];
//set the name of your Storyboard containing the ViewController and the ID you gave to the ViewController here
[ViewControllers insertObject:nextomeNavigationController atIndex:0];
[self setViewControllers:ViewControllers animated:YES];
}
} else {
//remove view
NSMutableArray *ViewControllers = [NSMutableArray arrayWithArray:self.viewControllers];
if (ViewControllers.count == 4) {
[ViewControllers removeObjectAtIndex:0];
[self setViewControllers:ViewControllers animated:YES];
}
}
I have a small problem.
I try for a push notification to control a View Controller.
I come to go there, however, the new "page" not open.
If I send forth the same but with an action button it works.
Thank you, Chris
AppDelegate.m
RootViewController *rootViewController = (RootViewController*)self.window.rootViewController;
[rootViewController openLinkNews];
RootViewController.m
- (void)awakeFromNib {
self.contentViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"contentController"];
self.menuViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"menuController"];
}
-(void)openLinkNews {
NewsTab *theLink = [[NewsTab alloc] init];
[theLink openNewsPerLink];
}
NewsTab.m
-(void)openNewsPerLink{
NSLog(#"You are here!");
dbConnect = [[DbConnect alloc] init];
getNewsLast = [dbConnect getNewsLast];
DbConnect *news = [getNewsLast objectAtIndex:0];
NewsTab * infoController = [self.storyboard instantiateViewControllerWithIdentifier:#"NewsOpenViewController"];
NewsOpen *detailViewController = (NewsOpen *) infoController;
detailViewController.NewsHeadline = news.NewsHeadline;
detailViewController.NewsInformation = news.NewsInformation;
detailViewController.NewsFrom = news.NewsFrom;
detailViewController.NewsDate = news.NewsDate;
[self.navigationController pushViewController:infoController animated:YES];
}
-(IBAction)ButtonTest:(id)sender {
[self openNewsPerLink];
}
You posted code from your app delegate, but what method is that in?
The app delegate can retrieve information about the notification and respond to it in its - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo method. From there you you can do whatever you wish and use the notification to inform your decisions.
Please see the UIApplicationDelegate protocol reference