UITableViewController inside UITabBarController inside UINavigationController - ios

My Problem
I am using a UITabBarController inside a UINavigationController. And there are three tableviews inside the UITabBarController. As shown in the picture, the first table view shows correctly while the other two tableviews are partially hidden behind the navigation bar. How can I fix this?
My hierarchy:
Root: UINavigationController
UITabBarController
UITableViewController (table1,table2,table3)
Here is my code:
AppDelegate.m
#import "AppDelegate.h"
#import "TableViewController.h"
#interface AppDelegate()
#property UINavigationController* nav;
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
TableViewController* table1 = [[TableViewController alloc]init];
TableViewController* table2 = [[TableViewController alloc]init];
TableViewController* table3 = [[TableViewController alloc]init];
table1.title = #"table1";
table2.title = #"table2";
table3.title = #"table3";
UITabBarController* t = [[UITabBarController alloc] init];
[t setViewControllers:#[table1,table2,table3]];
self.nav = [[UINavigationController alloc] initWithRootViewController:t];
[self.window setRootViewController:self.nav];
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application{}
- (void)applicationDidEnterBackground:(UIApplication *)application{}
- (void)applicationWillEnterForeground:(UIApplication *)application{}
- (void)applicationDidBecomeActive:(UIApplication *)application{}
- (void)applicationWillTerminate:(UIApplication *)application{}
#end
TableViewController.m
#import "TableViewController.h"
#implementation TableViewController
- (id)initWithStyle:(UITableViewStyle)style{
self = [super initWithStyle:style];
if (self) {}
return self;
}
- (void)viewDidLoad{
[super viewDidLoad];
[self.tabBarController.view layoutSubviews];
}
- (void)didReceiveMemoryWarning{
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell* c = [[UITableViewCell alloc] init];
[c.textLabel setText:[NSString stringWithFormat:#"%d", indexPath.row]];
return c;
}
#end

Typically, the hierarchy is
UITabBarController
- UINavigationController
- UITableViewController
Why are you trying to put the Navigation Controller on top? Try reorganizing using a tab bar full of navigation controllers instead.

I hit this same problem yesterday, and decided to work around it. It's just one class that gets in the way, so here's the rewrite:
DRTabBarController.h
//
// Created by Dan Rosenstark on 2/28/15.
// Copyright (c) 2015 Confusion Studios LLC. All rights reserved.
//
#import <UIKit/UIKit.h>
#interface DRTabBarController : UIViewController <UITabBarDelegate>;
#property (nonatomic, strong) NSArray *viewControllers;
#property (nonatomic, strong) UITabBar *tabBar;
#property (nonatomic, strong) UIView *mainView;
#end
DRTabBarController.m
//
// Created by dr2050 on 2/28/15.
// Copyright (c) 2015 Confusion Studios LLC. All rights reserved.
//
#import "DRTabBarController.h"
#implementation DRTabBarController {
}
- (instancetype)init {
self = [super init];
if (self) {
self.tabBar = [[UITabBar alloc] init];
self.tabBar.delegate = self;
self.tabBar.tintColor = [UIColor whiteColor];
self.tabBar.barStyle = UIBarStyleBlack;
self.tabBar.backgroundColor = [UIColor blackColor];
self.mainView = [[UIView alloc] init];
}
return self;
}
- (void)viewDidLoad {
[self.view addSubview:self.tabBar];
[self.view addSubview:self.mainView];
}
- (void)setViewControllers:(NSArray *)viewControllers {
_viewControllers = viewControllers;
NSMutableArray *tabBarItems = [NSMutableArray array];
for (UIViewController *controller in viewControllers) {
UITabBarItem *item = controller.tabBarItem;
[tabBarItems addObject:item];
}
self.tabBar.items = tabBarItems;
}
- (void)viewWillAppear:(BOOL)animated {
[self.tabBar setSelectedItem:self.tabBar.items.firstObject];
[self tabBar:self.tabBar didSelectItem:self.tabBar.items.firstObject];
}
- (void)viewDidAppear:(BOOL)animated {
}
-(void)viewDidLayoutSubviews {
CGRect frame = self.view.bounds;
UITabBarController *throwaway = [[UITabBarController alloc] init];
frame.size.height = throwaway.tabBar.frame.size.height;
frame.origin.y = self.view.bounds.size.height - frame.size.height;
self.tabBar.frame = frame;
self.tabBar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
frame = self.view.bounds;
frame.size.height -= self.tabBar.frame.size.height;
float navbarHeight = self.navigationController.navigationBar.frame.size.height;
// cannot use UIApplication.sharedApplication.statusBarFrame.size.height because
// reports are not right with in-call status bar
float statusBarHeight = UIApplication.sharedApplication.statusBarHidden ? 0 : 20;
float topBarHeight = navbarHeight + statusBarHeight;
frame.origin.y += topBarHeight;
frame.size.height -= topBarHeight;
self.mainView.frame = frame;
self.mainView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
}
- (void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item {
int index = [self.tabBar.items indexOfObject:item];
NSArray *subviews = self.mainView.subviews;
for (UIView *view in subviews) {
[view removeFromSuperview];
}
UIView *view = [[self.viewControllers objectAtIndex:index] view];
view.frame = self.mainView.bounds;
view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.mainView addSubview:view];
}
#end
Note: There's one magic variable in there -- 20 -- for the in-call status bar, which has a totally different relationship to the surrounding nav...
Any help with this would be appreciated, but does work.

Related

How to add static view to bottom of screen while in a table view?

First thing to note is that I don't use xibs or storyboards, so everything needs to be done programatically.
I have a UITableView and I need too add a custom static view to the bottom of the screen when the table view is open (it'll function as a toolbar). I can't add it as a direct subview of the tableview because then it scrolls with the table. Also worth mentioning is that all of this is sitting inside of a UINavigationController.
Anyone know how I can get around this?
You can add UIToolbar to the bottom of the screen with UIBarButtonItems and add UITableView to the top of the view controller with height equal tables view height - toolbar height.
Here is a implementation subclassing UIViewController and adding UITableView and UITabBarController to it.
#interface RKViewController ()<UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, strong) UITableView *tableView;
#property (nonatomic, strong) UITabBar *tabBar;
#property (nonatomic, strong) UITabBarController *tabBarController;
#end
#implementation RKViewController
-(id)init
{
self = [super init];
if (self) {
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 500)];
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.tabBarController = [[UITabBarController alloc] init];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
UIViewController *vc1 = [[UIViewController alloc] init];
vc1.tabBarItem.title = #"Item 1";
UIViewController *vc2 = [[UIViewController alloc] init];
vc2.tabBarItem.title = #"Item 2";
self.tabBarController.viewControllers = [NSArray arrayWithObjects:vc1,vc2, nil];
[self.view addSubview:self.tableView];
[self.view addSubview:self.tabBarController.view];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [UITableViewCell new];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#end

EXC_BAD_ACCESS while textField becomeFirstResponder

I am getting EXE_BAD_ACCESS exception when I hit "back" button on NavigationBar of my CreateViewController which is pushed on UINavigationController
When I enable following line in CreateViewController.m (full code at the bottom)
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.navigationBar.hidden = NO;
//[self.textField becomeFirstResponder];
}
I start getting Thread1:EXE_BAD_ACCESS(code=1, address=...)
int main(int argc, char * argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
If I keep the above line of code disabled, then hitting back button takes me to MainViewController as expected.
I am a newbie to iOS. What I am doing wrong? Please see my code below.
Appdelegate.h
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
Appdelegate.m
import "AppDelegate.h"
import "MainViewController.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
id controller = [[MainViewController alloc] initWithNibName:#"MainView" bundle:nil];
id navController = [[UINavigationController alloc] initWithRootViewController:controller];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
#end
MainViewController.h
#interface MainViewController : UIViewController
- (IBAction)create:(id)sender;
#end
MainViewController.m
import "MainViewController.h"
import "CreateViewController.h"
#implementation MainViewController
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated {
self.navigationController.navigationBar.hidden = YES;
}
- (IBAction)create:(id)sender {
id controller = [[CreateViewController alloc] initWithNibName:#"CreateView" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
}
#end
CreateView.h
#interface CreateViewController : UIViewController <UITextFieldDelegate>
#end
CreateView.m
- (void)viewDidLoad {
[super viewDidLoad];
[self.navigationController.navigationBar setTintColor:[UIColor purpleColor]];
self.textField=[[UITextField alloc] initWithFrame:CGRectMake(80, 10, 160, 30)];
[self.textField setBorderStyle:UITextBorderStyleRoundedRect];
self.textField.placeholder = #"Name";
[self.textField setBackgroundColor:[UIColor clearColor]];
self.textField.delegate = self;
[self.navigationController.navigationBar addSubview:self.textField];
self.navigationController.navigationBar.hidden = NO;
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.navigationController.navigationBar.hidden = NO;
//[self.textField becomeFirstResponder];
}
Go to breakpoint navigator and add exceptions breakpoint as shown below , 1st option :
Instead of adding self.textField as subview to navigation bar, set the textField as titleView of navigation item of the view controller.
[self.navigationItem setTitleView:self.textField];
This must help...

Implement a fixed SearchBar and TableView in a Custom UIViewController

The purpose is to implement a fixed search bar just like Contacts in iOS7.
I have a view controller called SearchViewController inherited from UIViewController.
And I add a searchBar and a tableView as its navigationController.view's subView.
But since searchBar and tableView are separated, when I start to search, no dim effect on tableView and result table view is shown in correctly.
I just want it behaves just like Contacts app.
Here is my code:
SearchViewController.h
#import <UIKit/UIKit.h>
#class UWTabBarController;
#class InfoSessionModel;
#interface SearchViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate>
SearchViewController.m
#import "SearchViewController.h"
#interface SearchViewController ()
#property (nonatomic, strong) UISearchBar *searchBar;
#property (nonatomic, strong) UISearchDisplayController *searchController;
#property (nonatomic, strong) UITableView *tableView;
#property (nonatomic, strong) NSArray *data;
#end
#implementation SearchViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// initiate search bar
NSInteger statusBarHeight = 20;
NSInteger navigationBarHeight = self.navigationController.navigationBar.frame.size.height;
_searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, statusBarHeight + navigationBarHeight, 320, 44)];
// _searchBar.tintColor = [UIColor clearColor];
_searchBar.delegate = self;
_searchBar.barStyle = UIBarStyleDefault;
//NSMutableArray *scopeTitles = [[NSMutableArray alloc] initWithObjects:#"Employer", #"Program", #"Note", nil];
_searchBar.scopeButtonTitles = [[NSArray alloc] initWithObjects:#"Employer", #"Program", #"Note", nil];//[#"Employer|Program|Note" componentsSeparatedByString:#"|"];
// initiate search bar controller
_searchController = [[UISearchDisplayController alloc] initWithSearchBar:_searchBar contentsController:self];
_searchController.delegate = self;
_searchController.searchResultsDataSource = self;
_searchController.searchResultsDelegate = self;
// initiate table view
_tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, statusBarHeight + navigationBarHeight, 320, [UIScreen mainScreen].bounds.size.height - statusBarHeight - navigationBarHeight)];
[_tableView setContentInset:UIEdgeInsetsMake(_searchBar.frame.size.height, 0, _tabBarController.tabBar.frame.size.height, 0)];
_tableView.delegate = self;
_tableView.dataSource = self;
[_tableView registerClass:[InfoSessionCell class] forCellReuseIdentifier:#"InfoSessionCell"];
[_tableView registerClass:[LoadingCell class] forCellReuseIdentifier:#"LoadingCell"];
[self.navigationController.view addSubview:_tableView];
[self.navigationController.view addSubview:_searchBar];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (_searchController.searchResultsTableView == tableView) {
return 1;
}
else {
return [data count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (_searchController.searchResultsTableView == tableView) {
static NSString *cellIdentifier = #"LoadingCell";
LoadingCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[LoadingCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.loadingLabel.text = #"Test cell for search result";
return cell;
}
else {
//... configure cell and return cell
return cell;
}
}
}
#pragma mark - UISearchDisplayController Delegate Methods
// hasn't been implemented
#pragma mark - UISearchBar Delegate Methods
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar {
//move the search bar up to the correct location
[UIView animateWithDuration:.3
animations:^{
searchBar.frame = CGRectMake(searchBar.frame.origin.x,
20,// status bar's height
searchBar.frame.size.width,
searchBar.frame.size.height);
}
completion:^(BOOL finished){
//whatever else you may need to do
}];
return YES;
}
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar {
//move the search bar down to the correct location
[UIView animateWithDuration:.25
animations:^{
NSInteger statusBarHeight = 20;
NSInteger navigationBarHeight = self.navigationController.navigationBar.frame.size.height;
searchBar.frame = CGRectMake(_searchBar.frame.origin.x,
statusBarHeight + navigationBarHeight,
_searchBar.frame.size.width,
_searchBar.frame.size.height);
}
completion:^(BOOL finished){
//whatever else you may need to do
}];
return YES;
}
This is the effects of my code:
All right, my problem is caused by my misunderstanding of views and navigationController's views.
In view did load method:
before is:
[self.navigationController.view addSubview:_tableView];
[self.navigationController.view addSubview:_searchBar];
but should be:
[self.view addSubview:_tableView];
[self.view addSubview:_searchBar];
In this way, the original table view and result table view will show correctly.
And other things are moving search bar up and down, these things should be done through UISearchBar delegate protocol methods and UISearchDisplayController delegate protocol methods.
This is a right way to implement a fixed searchBar and tableView bellow it.

didSelectRowAtIndexPath is not working in ios6 with side menu

I am working in application witch contain side menu .
when i select option in side menu its display UItableview, this Table is inside FirstViewController, when i select particular row in firstViewController its not navigate to SecondView Controller.
For side menu i am taking ready template from GitHUb, that contain
1)JWSlideMenuController
2)JWNavigationController
3)JWSlideMenuViewController
Here i attach code for JWNavigationCOntroller.h and JWNavigationCOntroller.m file
also FirstViewController.h and FirstViewController.m file
**JWNavigationController.h**
// JWNavigationController.h
// JWSlideMenu
//
// Created by Jeremie Weldin on 11/22/11.
// Copyright (c) 2011 Jeremie Weldin. All rights reserved.
//
#import <UIKit/UIKit.h>
#class JWSlideMenuController;
#interface JWNavigationController : UIViewController <UINavigationBarDelegate>
#property (nonatomic, retain) UINavigationBar *navigationBar;
#property (nonatomic, retain) UIView *contentView;
#property (nonatomic, retain) JWSlideMenuController *slideMenuController;
#property (nonatomic, retain, readonly) UIViewController *rootViewController;
- (id)initWithRootViewController:(UIViewController *)rootViewController;
- (void)pushViewController:(UIViewController *)controller;
- (UIViewController *)popViewController;
#end
JWNavigationController.m
// JWNavigationController.m
// JWSlideMenu
//
// Created by Jeremie Weldin on 11/22/11.
// Copyright (c) 2011 Jeremie Weldin. All rights reserved.
//
#import "JWNavigationController.h"
#import "JWSlideMenuViewController.h"
#interface JWNavigationController(Private)
-(UIViewController*)removeTopViewController;
#end
#implementation JWNavigationController
#synthesize navigationBar;
#synthesize contentView;
#synthesize slideMenuController;
#synthesize rootViewController=_rootViewController;
#pragma mark - View lifecycle
- (id)init
{
self = [super init];
if (self) {
CGRect masterRect = [[UIScreen mainScreen] bounds];
CGRect contentFrame = CGRectMake(0.0, 44.0, masterRect.size.width, masterRect.size.height - 44.0);
CGRect navBarFrame = CGRectMake(0.0, 0.0, masterRect.size.width, 44.0);
self.view = [[[UIView alloc] initWithFrame:masterRect] autorelease];
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.view.backgroundColor = [UIColor whiteColor];
self.contentView = [[[UIView alloc] initWithFrame:contentFrame] autorelease];
self.contentView.backgroundColor = [UIColor whiteColor];
self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[self.view addSubview:self.contentView];
self.navigationBar = [[[UINavigationBar alloc] initWithFrame:navBarFrame] autorelease];
self.navigationBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.navigationBar.delegate = self;
[self.view insertSubview:self.navigationBar aboveSubview:self.contentView];
self.navigationBar.backgroundColor=[UIColor whiteColor];
}
return self;
}
- (id)initWithRootViewController:(JWSlideMenuViewController *)rootViewController
{
self = [self init];
if(self) {
_rootViewController = rootViewController;
UIBarButtonItem *menuButton = [[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"menu_icon_20x20.png"] style:UIBarButtonItemStyleBordered target:self.slideMenuController action:#selector(toggleMenu)] autorelease];
rootViewController.navigationItem.leftBarButtonItem = menuButton;
[self addChildViewController:rootViewController];
[self.contentView addSubview:rootViewController.view];
[self.navigationBar pushNavigationItem:rootViewController.navigationItem animated:YES];
//rootViewController.navigationController = self;
}
return self;
}
#pragma mark - UINavigationBarDelegate
- (void)navigationBar:(UINavigationBar *)navigationBar didPopItem:(UINavigationItem *)item
{
UIViewController *controller = [self.childViewControllers lastObject];
if (item==controller.navigationItem) //Will now called only if a back button pop happens, not in manual pops
{
[self removeTopViewController];
}
}
- (void)navigationBar:(UINavigationBar *)navigationBar didPushItem:(UINavigationItem *)item
{
}
#pragma mark - Stack Interaction
- (void)pushViewController:(JWSlideMenuViewController *)controller
{
[self addChildViewController:controller];
[self.navigationBar pushNavigationItem:controller.navigationItem animated:YES];
controller.navigationController = self;
controller.view.frame = self.contentView.bounds;
if([self.childViewControllers count] == 1)
{
[self.contentView addSubview:controller.view];
}
else
{
UIViewController *previousController = [self.childViewControllers objectAtIndex:[self.childViewControllers count]-2];
[self transitionFromViewController:previousController toViewController:controller duration:0.5 options:UIViewAnimationOptionTransitionNone animations:NULL completion:NULL];
}
}
- (UIViewController *)popViewController
{
//Can use this to pop manually rather than back button alone
UIViewController *controller = [self.childViewControllers lastObject];
UIViewController *previousController = nil;
if([self.childViewControllers count] > 1)
{
previousController = [self.childViewControllers objectAtIndex:[self.childViewControllers count]-2];
previousController.view.frame = self.contentView.bounds;
}
[self transitionFromViewController:controller toViewController:previousController duration:0.3 options:UIViewAnimationOptionTransitionNone animations:NULL completion:NULL];
[controller removeFromParentViewController];
if(self.navigationBar.items.count > self.childViewControllers.count)
[self.navigationBar popNavigationItemAnimated:YES];
return controller;
}
- (void)viewDidUnload
{
_rootViewController = nil;
self.navigationBar = nil;
self.contentView = nil;
self.slideMenuController = nil;
[super viewDidUnload];
}
- (void)dealloc {
[_rootViewController release];
[navigationBar release];
[contentView release];
[super dealloc];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
-(UIViewController*)removeTopViewController
{
UIViewController *controller = [self.childViewControllers lastObject];
UIViewController *previousController = nil;
if([self.childViewControllers count] > 1)
{
previousController = [self.childViewControllers objectAtIndex:[self.childViewControllers count]-2];
previousController.view.frame = self.contentView.bounds;
}
[self transitionFromViewController:controller toViewController:previousController duration:0.3 options:UIViewAnimationOptionTransitionNone animations:NULL completion:NULL];
[controller removeFromParentViewController];
return controller;
}
#end
Here is code FirstViewController.h
// FirstViewController.h
// Created by mobile on 12/18/13.
// Copyright (c) 2013 Jeremie Weldin. All rights reserved.
//
#import "JWSlideMenuViewController.h"
#interface FirstViewController : JWSlideMenuViewController<UITableViewDataSource,UITableViewDelegate,UIScrollViewDelegate>
#property (strong,nonatomic) NSMutableArray *array;
#property (retain, nonatomic) IBOutlet UITableView *myTableView;
#end
Here is code for FirstViewController.m
// FirstViewController.m
//
//
// Created by mobile on 12/18/13.
// Copyright (c) 2013 Jeremie Weldin. All rights reserved.
//
#import "FirstViewController.h"
#import "SecondViewController.h"
#import "JWNavigationController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize array,myTableView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
array=[[NSMutableArray alloc]initWithObjects:#"One",#"Two",#"Three",#"Four",#"Five",#"Six",#"Seven",#"Eight",#"Nine",#"Ten" ,nil];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellidentifier=#"cell";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:cellidentifier];
if(cell==nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellidentifier];
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
}
cell.textLabel.text=[array objectAtIndex:indexPath.row];
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *controller = [[[SecondViewContRoller alloc] init] autorelease];
[self.navigationController pushViewController:controller];
}
- (void)viewDidUnload
{
[self setMyTableView:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc]; } #end
**I am also Try This Code but not working**
SecondViewController *second=[[SecondViewContRoller alloc]initWithNibName:#" SecondViewContRoller" bundle:nil];
[self.navigationController pushViewController:controller];
JWSlideMenuController.h contain following code
// JWSlideMenuController.h
// JWSlideMenu
//
// Created by Jeremie Weldin on 11/14/11.
// Copyright (c) 2011 Jeremie Weldin. All rights reserved.
//
#import <UIKit/UIKit.h>
#class JWNavigationController;
#class JWSlideMenuViewController;
#interface JWSlideMenuController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (retain, nonatomic) UITableView *menuTableView;
#property (retain, nonatomic) UIView *menuView;
#property (retain, nonatomic) UIToolbar *contentToolbar;
#property (retain, nonatomic) UIView *contentView;
#property (retain, nonatomic) UIColor *menuLabelColor;
-(IBAction)toggleMenu;
-(JWNavigationController *)addViewController:(JWSlideMenuViewController *)controller withTitle:(NSString *)title andImage:(UIImage *)image;
#end
JWSlideMenuController.m contain following code for didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if([contentView.subviews count] == 1){
[[contentView.subviews objectAtIndex:0] removeFromSuperview];
}
UIViewController* controller = (UIViewController*)[self.childViewControllers objectAtIndex:indexPath.row];
controller.view.frame = self.contentView.bounds;
[contentView addSubview:controller.view];
[self toggleMenu];
}
Try this.
download zib from github for MFSideMenu classes and use this code into did select method of table view. its working fine in ios6,ios7 also....
yourViewController *dealsVC = [[yourViewController alloc] initWithNibName:#"yourViewController" bundle:nil];
//[self.navigationController pushViewController:dealsVC animated:YES];
UINavigationController *navigationController = self.menuContainerViewController.centerViewController;
NSArray *controllers = [NSArray arrayWithObject:dealsVC];
navigationController.viewControllers = controllers;
[self.menuContainerViewController setMenuState:MFSideMenuStateClosed];

iOS (iPhone/iPad) SDK - UITableView not refreshing on reloadData (numberOfSectionsInTableView etc. does not get called on reloadData)

For some reason [tView reloadData] (where tView is a UITableView) does not refresh my UITableView. cellForRowAtIndexPath, numberOfSectionsInTableView and numberOfRowsInSection only get called once - at load. Those methods don't seem to be called after [tView reloadData]. Here's my code:
(AppDelegate.h):
#import <UIKit/UIKit.h>
#import "MBProgressHUD.h"
#class FirstNavViewController;
#class SecondTableViewController;
#interface <appname>AppDelegate : NSObject <UIApplicationDelegate, MBProgressHUDDelegate> {
UIWindow *window;
UITabBarController *rootController;
FirstNavViewController *viewController;
SecondTableViewController *viewController1;
NSMutableData *responseData;
NSMutableArray *blogEntries;
MBProgressHUD *HUD;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *rootController;
#property (nonatomic, retain) IBOutlet FirstNavViewController *viewController;
#property (nonatomic, retain) IBOutlet SecondTableViewController *viewController1;
#property (nonatomic, retain) NSMutableArray *blogEntries;
#end
(AppDelegate.m):
#import "AppDelegate.h"
#import "FirstNavViewController.h"
#import "SecondTableViewController.h"
#import "SBJson.h"
#define TMP NSTemporaryDirectory()
#implementation AppDelegate
#synthesize window = _window;
#synthesize rootController;
#synthesize viewController;
#synthesize viewController1;
#synthesize blogEntries;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
CGFloat width = self.rootController.view.bounds.size.width;
CGFloat height = self.rootController.view.bounds.size.height;
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, width, height)];
UIImage *imageView = [UIImage imageNamed:#"theme_frame.png"];
UIColor *kMainColor = [[UIColor alloc] initWithPatternImage:imageView];
[v setBackgroundColor:kMainColor];
[kMainColor release];
[self.rootController.tabBar insertSubview:v atIndex:0];
imageView = nil;
[v release];
responseData = [[NSMutableData data] retain];
blogEntries = [NSMutableArray array];
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:#"ENTER_JSON_URL_HERE"]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
NSAssert(nil != self.rootController, #"tab bar controller not hooked up!");
BOOL iPad = NO;
#ifdef UI_USER_INTERFACE_IDIOM
iPad = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
#endif
if (iPad) {
self.viewController = [[[FirstNavViewController alloc] initWithNibName:#"FirstNavViewController_iPad" bundle:nil] autorelease];
self.viewController1 = [[[SecondTableViewController alloc] initWithNibName:#"SecondTableViewController_iPad" bundle:nil] autorelease];
}
else {
self.viewController = [[[FirstNavViewController alloc] initWithNibName:#"FirstNavViewController_iPhone" bundle:nil] autorelease];
self.viewController1 = [[[SecondTableViewController alloc] initWithNibName:#"SecondTableViewController_iPhone" bundle:nil] autorelease];
}
self.rootController.viewControllers = [NSArray arrayWithObject:self.viewController];
self.rootController.selectedIndex = 0;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_4_0
self.window.rootViewController = self.rootController;
#else
[self.window addSubview:rootController.view];
#endif
[self.window makeKeyAndVisible];
HUD = [[MBProgressHUD alloc] initWithView:viewController.view];
[viewController.view addSubview:HUD];
[HUD show:NO];
// Regisete for HUD callbacks so we can remove it from the window at the right time
HUD.delegate = self;
HUD.labelText = #"Loading";
return YES;
}
#pragma mark NSURLConnection delegate methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[HUD hide:YES];
[connection release];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[connection release];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
[responseData release];
NSMutableArray *allBlogEntries = [responseString JSONValue];
[viewController1 setBlogEntries:allBlogEntries];
[responseString release];
[HUD hide:YES];
}
- (void)dealloc
{
[_window release];
[rootController release];
[viewController release];
[viewController1 release];
[super dealloc];
}
#end
(FirstNavViewController.h):
#import <UIKit/UIKit.h>
#interface FirstNavViewController : UIViewController {
UINavigationController *navController;
}
#property (nonatomic, retain) UINavigationController *navController;
#end
(FirstNavViewController.m):
#import "FirstNavViewController.h"
#import "SecondTableViewController.h"
#implementation FirstNavViewController
#synthesize navController;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
UITabBarItem *tabBarItem = [self tabBarItem];
UIImage *tabBarImage = [UIImage imageNamed:#"blog.png"];
[tabBarItem setImage:tabBarImage];
[tabBarItem setTitle:#"Blog"];
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
navController = [[UINavigationController alloc] initWithRootViewController:self];
SecondTableViewController *secondViewController = [[SecondTableViewController alloc] initWithNibName:#"BlogOverviewViewController_iPhone" bundle:nil];
[navController pushViewController:secondViewController animated:NO];
[blogOverviewViewController release];
[self.view addSubview:navController.view];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
(SecondTableViewController.h):
#import <UIKit/UIKit.h>
#import "SBJson.h"
#interface SecondTableViewController : UIViewController {
NSMutableArray *blogEntries;
IBOutlet UITableView *tView;
}
#property (nonatomic, retain) NSMutableArray *blogEntries;
#property (nonatomic, retain) NSArray *arryData;
#property (nonatomic, retain) IBOutlet UITableView *tView;
#end
(SecondTableViewController.m):
#import "SecondTableViewController.h"
#import "ThirdDetailViewController.h"
#import "NSString+HTML.h"
NSString *convertedString;
#implementation SecondTableViewController
#synthesize arryData;
#synthesize tView;
-(NSMutableArray*)blogEntries {
return [[blogEntries retain] autorelease];
}
-(void)setBlogEntries:(NSMutableArray*)newBlogEntries {
if(newBlogEntries != blogEntries) {
[newBlogEntries retain];
[blogEntries release];
blogEntries = newBlogEntries;
[tView reloadData];
}
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [blogEntries count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
NSDictionary *aBlogEntry = [blogEntries objectAtIndex:[indexPath row]];
NSArray *bPosts = (NSArray *)[aBlogEntry objectForKey:#"posts"];
NSString *stringToConvert = [bPosts valueForKey:#"title_plain"];
NSString *convertedString = [stringToConvert stringByConvertingHTMLToPlainText];
cell.textLabel.text = convertedString;
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.font = [UIFont systemFontOfSize:12];
cell.textLabel.minimumFontSize = 10;
cell.textLabel.numberOfLines = 4;
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
NSString *stringToConvert1 = [bPosts valueForKey:#"excerpt"];
NSString *convertedString1 = [stringToConvert1 stringByConvertingHTMLToPlainText];
cell.detailTextLabel.text = convertedString1;
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ThirdDetailViewController *detailViewController = [[ThirdDetailViewController alloc] initWithNibName:#"BlogContentViewController_iPhone" bundle:nil];
[self.navigationController pushViewController:detailViewController animated:YES];
NSDictionary *aBlogEntry = [blogEntries objectAtIndex:[indexPath row]];
NSArray *bPosts = (NSArray *)[aBlogEntry objectForKey:#"posts"];
NSString *stringToConvert = [bPosts valueForKey:#"title"];
NSString *convertedString = [stringToConvert stringByConvertingHTMLToPlainText];
[contentViewController changeTitleTextLabel:convertedString];
NSString *stringToConvert1 = [bPosts valueForKey:#"content"];
NSString *convertedString1 = [stringToConvert1 stringByConvertingHTMLToPlainText];
NSString *newConvertedString1 = [convertedString1 stringByReplacingOccurrencesOfString: #"\n" withString:#"\n\n"];
[detailViewController changeContentTextLabel:newConvertedString1];
[tableView deselectRowAtIndexPath: indexPath animated: YES];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
blogEntries = [[NSMutableArray alloc]init];
self.title = #"Blog";
[self.navigationItem setHidesBackButton:YES animated:NO];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)dealloc {
[blogEntries release];
[super dealloc];
}
#end
Does anyone know what the problem is? I am stuck on why the UITableView will not reloadData.
EDIT: Small background: I am using a UITabBarController (AppDelegate) with a UIViewController in it with a UINavigationController as a subview of that UIViewController (FirstNavViewController). The UINavigationController then has a subview with another UIViewController in it. The latter UIViewController (SecondTableViewController) includes a UITableView.
I've just been having this issue. Turned out to be a threading problem for me. For those those who end up here after a search, here is my quick fix:
[tView performSelectorOnMainThread:#selector(reloadData)
withObject:nil
waitUntilDone:false];
It seems reloadData needs to be called on the main thread. I hope this helps (^_^)
In your viewDidLoad method, add: tView.delegate = self;
Your view setup might be the cause of your problems.
I don't really understand the details of your implementation but right now you are adding that SecondTableViewController to both the tab bar controller and then on the stack of a navigation controller in your FistNavViewController viewDidLoad method.
Create the navigation controller with FistNavViewController as its rootViewController, then add the navigation controller as the first view controller to your UITabBarViewController
(code here is typed from memory so please excuse any typos)
FirstNavViewController *vc = [[FirstNavViewController alloc] initWithNibName:#"nibname" andBundleName:nil];
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:vc];
UITabBarController *tbc = [UITabBarController setViewControllers:[NSArray arrayWithObjects:nc, otherVc1Example, otherVc2Example, nil] animated:NO];
In your FirstNavViewController viewDidLoad method, you can then instantiate SecondTableViewController and push it onto the stack with
[self.navigationController pushViewController:secondTableViewController animated:YES];
Finally, within that nav controller you need to make sure you have your UITableView setup correcly either in Interface Builder (by connecting the datasource and delegate outlets to the file owner) or in code by manually setting the tableview delegate and datasource to self.
Bottom line is everything you are trying to do above is WAY easier and less error prone if you use Interface Builder. In MainWindow.xib simple add a tab bar controller and under it add navigation controllers and view controllers as you see fit. It should work "pretty much" out of the box.
Good luck.
Rog

Resources