I have this code here to check on the existence of the ViewController. And unfortunately it doesn't work. The thing is, it is executed at the moment of another VC popping from the Navigation Stack:
- (void) leftViewDidHide{
if ([((AppDelegate *)[UIApplication sharedApplication].delegate).frontViewController.navigationController.viewControllers objectAtIndex:1]) {
SGServerListViewController *sample = [[[((AppDelegate *)[UIApplication sharedApplication].delegate).frontViewController.navigationController.viewControllers objectAtIndex:1]childViewControllers] objectAtIndex:0];
[sample.serverTableView setUserInteractionEnabled:YES];
}
}
The app crashes with an exception breakpoint pointing me to the line with an if statement. Any ideas on what could be wrong here? I'm just trying to check if this VC is there and if it is - execute the code.
NSArray *viewControlles = [self.navigationController.viewControllers];
for (int i = 0 ; i <viewControlles.count; i++){
if ([YourVC isKindOfClass:[viewControlles objectAtIndex:i]]) {
//Execute your code
}
}
NSArray *controllerArray = [self.navigationController.viewControllers];
//will get all the controllers added to UINavigationController.
for (id controller in controllerArray)
{
// iterate through the array and check for your controller
if ([controller isKindOfClass:[checkYourController class]])
{
//do your stuff here
}
}
just for an idea containsObject: method of NSArray class might also work.
-(BOOL)isControllerAlreadyOnNavigationControllerStack{
for (UIViewController *vc in self.navigationController.viewControllers) {
if ([vc isKindOfClass:Controller.class]) {
[self.navigationController popToViewController:vc animated:NO];
return YES;
}
}
return NO;
}
if (![self isControllerAlreadyOnNavigationControllerStack]) {
//push controller
}
- (void) leftViewDidHide{
if ([((AppDelegate *)[UIApplication sharedApplication].delegate).frontViewController.navigationController.viewControllers count] == 1) {
SGServerListViewController *sample = [[[((AppDelegate *)[UIApplication sharedApplication].delegate).frontViewController.navigationController.viewControllers objectAtIndex:1]childViewControllers] objectAtIndex:0];
[sample.serverTableView setUserInteractionEnabled:YES];
}
}
You can do that (checking if a ViewController on Navigation Stack exists) with this code:
if navigationController?.viewControllers.count > 1 {
for root in (self.navigationController?.viewControllers)! {
if root is ViewController {
let i = root as? ViewController
i?.table.removeFromSuperview()
}
}
}
self.navigationController?.popToRootViewControllerAnimated(true)
NSArray *viewControlles = self.navigationController.viewControllers;
for (int i = 0 ; i <viewControlles.count; i++){
if ([[viewControlles objectAtIndex:i] isKindOfClass:[RequiredViewController class]]) {
//Enter your code
}
}
Related
In my iPad app. I'm working on UIPageViewController I want to set text at one page and image at another page. I have tried a lot and googled,but I did not find any solution. It's killing my time so if any one have worked on it please guide me and post sample code.
I have used the code which is there in below link
http://www.ioslearner.com/implementing-uipageviewcontroller-programatically-without-storyboarding/
here is the sample code. i used contentviewcontroller.
i want to use two view controllers with UIPageViewController
- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController
spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation
{
if(UIInterfaceOrientationIsPortrait(orientation))
{
//Set the array with only 1 view controller
UIViewController *currentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
NSArray *viewControllers = [NSArray arrayWithObject:currentViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
//Important- Set the doubleSided property to NO.
self.pageViewController.doubleSided = NO;
//Return the spine location
return UIPageViewControllerSpineLocationMin;
}
else
{
NSArray *viewControllers = nil;
ContentViewController *currentViewController = [self.pageViewController.viewControllers objectAtIndex:0];
NSUInteger currentIndex = [self.modelArray indexOfObject:[(ContentViewController *)currentViewController labelContents]];
NSUInteger currentIndex2 = [self.imagesArray2 indexOfObject:[(ContentViewController *)currentViewController imageContents]];
if(currentIndex == 0 || currentIndex %2 == 0 || currentIndex2 == 0||currentIndex2 %2 == 0)
{
UIViewController *nextViewController = [self pageViewController:self.pageViewController viewControllerAfterViewController:currentViewController];
viewControllers = [NSArray arrayWithObjects:currentViewController, nextViewController, nil];
}
else
{
UIViewController *previousViewController = [self pageViewController:self.pageViewController viewControllerBeforeViewController:currentViewController];
viewControllers = [NSArray arrayWithObjects:previousViewController, currentViewController, nil];
}
//Now, set the viewControllers property of UIPageViewController
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];
return UIPageViewControllerSpineLocationMid;
}
}
If I understood well then add an imageView in ContentPageView.xib file and make an outlet of. Set ImageView and label hidden or visible on your required pages.
Following steps can be helpful
Keep UILabel and and UIImageView in ContentViewController
Add UIImage OR NSString in the modelArray.
When you make a new ContantViewController check if object in model is image or string using following.
if ([myObject class] == [UIImage class])
{
//HERE ASSIGN IT TO UIIMAGEVIEW.image
}
else
{
//HERE ASSIGN IT TO UILABEL.text
}
post if you need more help....
Sorry if this is not what you are looking for.....
I came across SO posts with incorrect decrement of RC to +0 but none of them where appDelegate Method (as per my knowledge delegate can't be retained )
Following is the code where im having memory leak
iPlayerAppDelegate *appDelegate = (iPlayerAppDelegate *)[[UIApplication sharedApplication] delegate];
int currentTabIndex = appDelegate.tabcontroller.tabBarController.selectedIndex ;
UIButton *btn = (UIButton *)sender;
pageItem* selectedItem = nil;
selectedItem = [appDelegate.pageData.pageItems objectAtIndex:btn.tag];
appDelegate.bStatusValue = FALSE;
if(pageInfo.removeCaptureFile)
{
[appDelegate.commonUtils removeFileFromPath:#"snap.jpeg"];
[appDelegate.commonUtils removeFileFromPath:#"prevSnap.jpeg"];
}
if (appDelegate.launchTimer &&[appDelegate.launchTimer isValid])
{
[appDelegate.launchTimer invalidate];
appDelegate.launchTimer = nil;
// appDelegate.timerFlag = NO;
}
NSArray *viewarray = [self.view subviews];
for(int index=0;index< viewarray.count;index++)
{
UIView *view = [viewarray objectAtIndex:index];
if([view isMemberOfClass:[UITextField class]] || [view isMemberOfClass:[UITextView class]])
{
[view resignFirstResponder];
[view removeFromSuperview];
}
if([view isMemberOfClass:[scrollwinView class]])
{
scrollwinView* scrollView = (scrollwinView*) view;
[scrollView stopTimer];
}
}
if(appDelegate.tabsupport)
{ //to remove the cached view from stack after pressing back
CSNavigationController *navcon= (CSNavigationController*)appDelegate.tabcontroller.tabBarController.selectedViewController;
[navcon removeViewData:pageInfo.screenId];
}
int currentscrid=pageInfo.screenId;
clrScreenId = pageInfo.clrScreenId;
if (appDelegate.connMgr)
{
[appDelegate.connMgr closeHttpStream];
//[connMgr release];
appDelegate.connMgr = nil;
appDelegate.connectionstatus = FALSE;
if(appDelegate.initAnimation.startId == 5)
{
appDelegate.transition = NO ;
[appDelegate readPageData:currentscrid isBack:NO ];
appDelegate.transition = YES;
return ;
}
[appDelegate stopAnimation];
and here is the snapshots of memory leak Method returns an Objective-C object with a +0 retain count and Incorrect decrement of the reference count of an object that is not owned at this point by the caller
why am i getting this leak? am i reassigning appDelegate object?
I have not called release on the return value of that accessor(appDelegate) nor have set it nil, how should i fix this leak?
Thanks in Advance
I think you should read this thread about correct usage of the app delegate:
iPhone proper usage of Application Delegate
For example, in your code:
selectedItem = [appDelegate.pageData.pageItems objectAtIndex:btn.tag];
seems very messy. A possible better solution might be to use a singleton design pattern.
As for your memory leak, possibly check that your not retaining anything when your app delegate animations perform animation stop callbacks.
on language switch within my App, I need to access the views of the MoreViewController in a TabBar and change their titles.
Could anyone pls tell me how to do that?
Your help is much appreciated.
Cols
Here are some snippets that might work for you. Note that all of the below is subject to break on each and every new iOS release at it is not meant to be done.
Customizing the More view title as itself as well as the title while it is being edited by the user.
- (void)customizeTitleViewWithNavigationItem:(UINavigationItem *)navigationItem
{
VASSERT(navigationItem != nil, #"invalid navigationItem supplied", navigationItem);
UILabel *titleView = [[UILabel alloc] initWithFrame:CGRectZero];
titleView.backgroundColor = [UIColor clearColor];
titleView.font = [UIFont boldSystemFontOfSize:20.0f];
titleView.text = navigationItem.title;
[titleView sizeToFit];
navigationItem.titleView = titleView;
[titleView release];
}
This needs to be implemented within the UINavigationController's delegate;
- (void)navigationController:(UINavigationController *)navigationController
willShowViewController:(UIViewController *)viewController
animated:(BOOL)animated
{
if (navigationController == tabBarController_.moreNavigationController)
{
if ([viewController isKindOfClass:NSClassFromString(#"UIMoreListController")])
{
[self customizeTitleViewWithNavigationItem:viewController.navigationItem];
}
else
{
NSLog(#"viewController (%#) does not seem to be a UIMoreListController", viewController);
}
}
else
{
NSLog(#"navigationController (%#) does not seem to be the moreNavigationController", navigationController);
}
}
This needs to be implemented within the UITabBarController's delegate;
- (void)tabBarController:(UITabBarController *)controller willBeginCustomizingViewControllers:(NSArray *)viewControllers
{
//get the second view of the upcoming tabbar-controller
UIView *editView = [controller.view.subviews objectAtIndex:1];
//did we get what we expected, which is a UITabBarCustomizeView?
if (editView != nil && [editView isKindOfClass:NSClassFromString(#"UITabBarCustomizeView")])
{ //yes->get the navigation-view
UIView *navigationView = [editView.subviews objectAtIndex:0];
//is that a navigationBar?
if (navigationView != nil && [navigationView isKindOfClass:[UINavigationBar class]])
{ //yes->...
UINavigationBar *navigationBar = (UINavigationBar *)navigationView;
[self customizeTitleViewWithNavigationItem:navigationBar.topItem];
}
else
{
NSLog(#"the navigationView (%#) does not seem to be a navigationBar", navigationView);
}
}
else
{
NSLog(#"the editView (%#) does not seem to be a UITabBarCustomizeView", editView);
}
}
I was able to change the title of one of the tabBar items for my 6th view controller (the last one in the more list) with the following code:
NSArray *vcs = [(UITabBarController *)self.window.rootViewController viewControllers];
[[vcs.lastObject tabBarItem] setTitle:#"New Title"];
Is this what you want to do?
After Edit: To change these titles after they are set up the first time, you need to re-set the viewControllers property of the tabBar controller. In this code example, I connected a button in my 6th view controller to an action method that changes the titles of 3 of my controllers, 2 in the more list and one in the regular list.
-(IBAction)changeNames:(id)sender {
UITabBarController *tbc = (UITabBarController *)[[UIApplication sharedApplication] delegate].window.rootViewController;
NSArray *vcs = tbc.viewControllers;
[[vcs.lastObject tabBarItem] setTitle:#"New Title"];
[[[vcs objectAtIndex:4] tabBarItem] setTitle:#"New VC"];
[[[vcs objectAtIndex:3] tabBarItem] setTitle:#"New VC2"];
tbc.viewControllers = tbc.viewControllers;
}
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
ChatViewController *chatView;
if(contactView==nil)
{
chatView=[[ChatViewController alloc] initWithNibName:#"ChatViewController" bundle:nil];
}
[self.navigationController pushViewController:chatView animated:YES];
[messageDelegate newMessageReceived:m];
}
The above delegate method called for every incoming message.When it called, it goes to a new UIViewController.Here my problem is a view pushed multiple tinmes,so error will be occered.how can i fix this error in iphone
Add this snippet before pushing the view controller
BOOL viewControllerAlreadyPushed = NO;
for (UIViewController *controller in self.navigationController.viewControllers) {
if ([controller isKindOfClass:[ChatViewController class]]) {
viewControllerAlreadyPushed = YES;
}
}
if(!viewControllerAlreadyPushed) //if not pushed, push it
{
ChatViewController *chatView;
if(contactView==nil)
{
chatView=[[ChatViewController alloc] initWithNibName:#"ChatViewController" bundle:nil];
}
[self.navigationController pushViewController:chatView animated:YES];
[messageDelegate newMessageReceived:m];
}
In my SDK 3.0 core data based app, I have a tab bar controller managing 4 tabs. From time to time, apparently randomly, when I launch the app, it crashes with the following message:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Directly modifying a tab bar managed by a tab bar controller is not allowed.'
However, I am not modifying in my code any of the tabs except for the following. In practice, all of the navigation controllers or controllers in the tabs have been setup using IB, and in my code I have declared two of them as outlets, since I need to access them in my app delegate applicationDidFinishLaunching() method to setup their core data managedObjectContext as follows:
[self managedObjectContext];
[self managedObjectModel];
[self persistentStoreCoordinator];
[rootViewController retain];
rootViewController.managedObjectContext = self.managedObjectContext;
Is this not correct? If so, why?
The only reference to the problem I have seen on the web is here:
http://discussions.apple.com/thread.jspa?messageID=9716886
However, the problem still persists even after deleting and recreating the tab bar controller from scratch in IB.
Any clue?
Thanks in advance.
I've had this problem too. Do you have an outlet to the UITabBar itself (not the UITabBarController) in the nib? When I removed that, I stopped having problems.
Sorry this isn't a 100% reliable explanation, but this workaround cleared the problem up for me.
I've gotten this exception a few times, especially when changing things with localizations. Cleaning the targets and then rebuilding seems to work around the issue.
I quickly wrote the following class and showing/hiding tab views from UITabBarController worked like magic:
TabBarDesigner.h
#import <Foundation/Foundation.h>
#interface TabBarDesigner : NSObject
{
}
+(void) setTabBarController:(UITabBarController *)tabBarController
items:(NSArray *)tabBarItems
viewControllers:(NSArray *)viewControllers;
+(void) removeItemsInRange:(NSRange) range;
#end
TabBarDesigner.m
#import "TabBarDesigner.h"
static NSArray *_tabBarItems = NULL;
static NSArray *_viewControllers = NULL;
static UITabBarController *_tabBarController = NULL;
#implementation TabBarDesigner
+(void) setTabBarController:(UITabBarController *)tabBarController
items:(NSArray *)tabBarItems
viewControllers:(NSArray *)viewControllers
{
if (tabBarItems && viewControllers && tabBarController)
{
if ([tabBarItems count] == [viewControllers count])
{
[_tabBarItems release];
[_viewControllers release];
_tabBarItems = [tabBarItems copy];
_viewControllers = [viewControllers copy];
_tabBarController = tabBarController;
}
}
}
+(void) removeItemsInRange:(NSRange) range
{
if (_tabBarController)
{
if ( range.location < ([_tabBarItems count] - 1) )
{
if ( (range.length + range.location) < [_tabBarItems count] )
{
NSMutableArray *tabBarItems = [_tabBarItems mutableCopy];
[tabBarItems removeObjectsInRange:range];
NSMutableArray *viewControllers = [_viewControllers mutableCopy];
[viewControllers removeObjectsInRange:range];
[_tabBarController setViewControllers:viewControllers];
NSUInteger i;
for (i = 0; i< [viewControllers count]; i++)
{
UIViewController *vC = [viewControllers objectAtIndex:i];
vC.tabBarItem.image = [[tabBarItems objectAtIndex:i] image];
vC.tabBarItem.title = [[tabBarItems objectAtIndex:i] title];
vC.tabBarItem.tag = [[tabBarItems objectAtIndex:i] tag];
}
[tabBarItems release];
[viewControllers release];
}
}
}
}
#end
A sample of how to use this class:
In your MyAppDelegate.m
#import "TabBarDesigner.h"
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TabBarDesigner setTabBarController:_tabBarController
items:[_tabBarController.tabBar items]
viewControllers:[_tabBarController viewControllers]];
// remove the first 3 tabs
[TabBarDesigner removeItemsInRange:NSMakeRange(0,3)];
// show all tabs
[TabBarDesigner removeItemsInRange:NSMakeRange(0,0)];
// continue with your code
}
Cheers!