Load UITableViewController programmatically and add view as subview - ios

I want to load a UITableViewController inside a UIView because I want to change the view on button click (like UITabBar but with my own buttons). I'm using a storyboard and have defined a TableViewController with custom class "InitialTableViewController" and identifier "InitialView".
My code look like this:
#import "MyViewController.h"
#import "InitialTableViewController.h"
#interface MyViewController ()
#end
#implementation MyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
InitialTableViewController *tableControl = [self.storyboard instantiateViewControllerWithIdentifier:#"InitialView"];
[[self view] addSubview:[tableControl view]];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
#end
The view starts and I can see my table but the code inside "InitialTableViewController" doesn't work.
What can I do?

Well, it would be easier to just have a normal UIViewController with a UIView as root of the Nib and then put a UITableView. My answer is based on your need to have buttons on that UIView.

Related

Checking when a TabBar item is clicked - Objective C

I have a ViewController with 2 sub containers. The first sub container points to a ViewController with a TabBar inside it. The second sub container is a ViewController that contains a collection view. Now my issue is trying to access the first sub containers TabBar so that when an Item is clicked, I can know which item is clicked and process my data.
The main ViewController has a class. All the other sub containers for that ViewController also have a class. Here is the .h for my sub container with the Tab Bar:
#import <UIKit/UIKit.h>
#interface home_tab : UIViewController <UITabBarControllerDelegate>{
}
#end
.m:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
NSLog(#"working");
}
Now when clicking on the Tab Bar that is populated, didSelectViewController is never called.
I am using storyboard.
Suggestions and thoughts?
Try this on your viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
[[self tabBarController]setDelegate:self];
// Do any additional setup after loading the view, typically from a nib.
}
It's just an suggestion :)
[[self tabBarController]selectedIndex] This will return the index of the selected tab.
I think you have a couple problems atleast from what I can see here,
You are using a TabBar inside of a ViewController, not a UITabBarController, thus you need to use UITabBarDelegate not UITabBarControllerDelegate. You will have to manage the view controllers or whatever view you will want to be loaded on your own most likely with the delegate callback:
-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item;
Also you dont have a UITabBar defined in your controller, therefore your ViewController has no idea you have a UITabBar in your Storyboard. You need something like this:
#interface ViewController : UIViewController <UITabBarDelegate>
#property (weak, nonatomic) IBOutlet UITabBar *tabBar;
#end
Then you will need to Control drag from the ViewController to your UITabBar and back to connect the Delegate in your Storyboard.
Id recommend using a UITabBarController so you dont have to manage the views yourself depending on what you are trying to accomplish.
Hope this helps!
the didSelectViewController method is part of the UITabBarControllerDelegate Protocol and is called on the UITabBarController's delegate. Did you set the delegate of the tab bar controller to the current instance of your subcontainer? Inside ViewDidLoad: do something like this:
[self.tabBarController setDelegate:self];
You can also set a delegate on the UITabBar rather than the controller, and the UITabBarDelegate Protocol contains a method tabBar:didSelectItem: that would be called.

Can't get a scroll view to work

I've been trying all day to get a very simple screen scroll working in Xcode 5 and just can't do it.
Even this simple tutorial doesn't work for me http://www.youtube.com/watch?v=m5Knw41Tz_M. All that does is add a scroll view to the view controller and when run, it shows a blank screen that can scroll - seen by the bars at the side. No matter what I do, I can't get this to work. First time I've needed scrolling and I am obviously missing something incredibly simple.
Simple .h code:
#interface ViewController : UIViewController {
IBOutlet UIScrollView *Scroller;
}
The .m code is
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[Scroller setScrollEnabled:YES];
[Scroller setContentSize:CGSizeMake(320, 1000)];
}
#end
The Scroller is connected to the scroll view, and that is about it! I've tried adding in a UIView to the UIScrollview, but nothing seems to work.
Your code needs to move to viewdidAppear or viewWillAppear
Try changing your method to this
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[Scroller setScrollEnabled:YES];
[Scroller setContentSize:CGSizeMake(320, 1000)];
}
This is wired, I followed your code and something happened to reset scroll view content size as CGSizeZero if I add subview into UIScrollView in IB. If I add subview by code, the scroll view would be properly. I haven't figure out reason yet.
But one thing you can work around is that you can set scroll view content size in
- (void) viewDidAppear:(BOOL)animated.
Or add subview by code in ViewDidLoad.
i am not good at english, i just will show code what is work..
Simple .h code:
#interface ViewController : UIViewController {
IBOutlet UIScrollView *Scroller;
}
The .m code is
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[NSTimer scheduledTimerWithTimeInterval:1.0/60 target:self selector:#selector(something) userInfo:nil repeats:YES];
}
- (void)something {
//[Scroller setScrollEnabled:YES]; !!!This don't need..
[Scroller setContentSize:CGSizeMake(320, 1000)];
}
#end

Overriding loadView causes viewDidLoad and loadView to fire everytime a VC appears

My view heirarchy sits on several custom "root" UIViewController subclasses. I'm trying to set a custom self.view for one of my root VC subclasses. There, I am doing:
MyRootViewController_With_Scroll.h
// Import lowest level root VC
#import "MyRootViewController.h"
// my custom scroll view I want to use as self.view
#class MyScrollView;
#interface MyRootViewController_With_Scroll : MyRootViewController {
}
#property (strong) MyScrollView *view;
#end
MyRootViewController_With_Scroll.m
#import MyRootViewController_With_Scroll.h;
#interface MyRootViewController_With_Scroll ()
#end
#implementation MyRootViewController_With_Scroll
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)loadView
{
NSLog(#"loading view");
CGRect windowSize = [UIScreen mainScreen].applicationFrame;
MyScrollView *rootScrollView = [MyScrollView scrollerWithSize:windowSize.size];
self.view = rootScrollView;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// Getter and setter for self.view
- (MyScrollView *)view
{
return (MyScrollView *)[super view];
}
- (void)setView:(MyScrollView *)view
{
[super setView:view];
}
According to the iOS6 docs, viewDidLoad in only suppose to fire once per view controller for the entire lifecycle of the app.
What am I doing wrong here? What is causing my view controllers to repeatedly call loadView/viewDidLoad? Strangely, my apps "home screen" VC loads the view just once, but all its subsequent views in the navigation heirachy fires loadView everytime they appear. What is going on?
edit I've changed the property to strong. Same issue happens.
edit 2 I've stopped overriding loadView and its still happening. Now I'm really confused.
This is expected behaviour. If you're popping view controllers off a navigation stack, and nothing else has a reference to them, then they're going to get deallocated. Therefore when it appears again, it will be a new instance, so it has to perform loadView and so on all over again. Include self in your logging, you should see that it is a different object each time.
You've also redefined the view controller's view property as weak - if you are re-using the view controller objects, then this will be nilled out as soon as the view has no superview.
Prior to iOS 6, a view controller that was mid-way in your navigation stack would get its view unloaded under memory pressure:
root --> VC1 --> VC2
VC2 is on screen, a memory warning is received. VC1 would unload its view. When you pop VC2 off the stack, VC1 would call loadView again. This no longer happens.
However, if you've popped back to VC1, and nothing has a strong reference to VC2, then VC2 is deallocated. When you push another VC2 onto the stack, this is a new instance and loadView will be called again. Presumably you are creating these new instances of VC2 in code, so you should be able to tell that you are creating a new instance.
Thats because you have weak view property. So it get realloced all the time. Also, I don't think that you need to override view property at all.

Connect together: AppDelegate, ViewController and XIB

I am new to the iOS programming and got stuck with one problem.
What was done:
I have created iOS application.
Initially it had main.m, AppDelegate.h, AppDelegate.m and some other supporting files (not with code) that are usually created.
Then I manually created XIB file with interface (LoginView.xib) and manually added LoginViewController.h and LoginViewController.m to control XIB.
Added outlets to LoginViewController.h.
After all I set up file's owner class (LoginViewController) and made connections between XIB and LoginViewController.h.
Problem description:
I need to show instantiate login view controller and show login view immediately at the application's start.
I tried several attempts and read a dozen of forum threads, but no way. Nothing is shown except white window background.
How can I do it correct?
Reference code:
LoginViewController.h
#import <UIKit/UIKit.h>
#interface LoginViewController : UIViewController
{
IBOutlet UIView *_loginView;
IBOutlet UITextField *_tfLogin;
IBOutlet UITextField *_tfPassword;
IBOutlet UIButton *_btnLoginToSystem;
}
- (IBAction)attemptLogin:(id)sender;
#end
LoginViewController.m
#import "LoginViewController.h"
#interface LoginViewController ()
#end
#implementation LoginViewController
- (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.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)attemptLogin:(id)sender
{
}
#end
AppDelegate.h
#import <UIKit/UIKit.h>
#import "LoginViewController.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) LoginViewController *loginViewController;
#end
AppDelegate.m
#import "AppDelegate.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];
self.loginViewController = [[LoginViewController alloc] initWithNibName:#"LoginView" bundle:nil];
[self.window.rootViewController presentModalViewController:self.loginViewController animated:NO];
[self.window makeKeyAndVisible];
return YES;
}
UPDATE!!!
Guys, thanks to you all I've found another issue. Once I got your approve that my code (after appropriate edition, of course) is correct, I started simulator and saw that my app crashes with the following exception:
NSInternalInconsistencyException with the reason [UIViewController _loadViewFromNibNamed:bundle:] loaded the ... nib but the view outlet was not set.
Thanks to StackOverflow I fixed it.
Loaded nib but the view outlet was not set - new to InterfaceBuilder
Quotation of Josh Justice comment from the topic I provided link to:
Open the XIB file causing problems
Click on file's owner icon on the left bar (top one, looks like a yellow outlined box)
If you don't see the right-hand sidebar, click on the third icon above "view" in your toolbar. This will show the right-hand sidebar
In the right-hand sidebar, click on the third tab--the one that looks a bit like a newspaper
Under "Custom Class" at the top, make sure Class is the name of the ViewController that should correspond to this view. If not, enter it
In the right-hand sidebar, click on the last tab--the one that looks like a circle with an arrow in it
You should see "outlets" with "view" under it. Drag the circle next to it over to the "view" icon on the left bar (bottom one, looks like a white square with a thick gray outline
Save the xib and re-run
Probably this information aggregated into one point will help other newcomers to pass the way I passed faster.
Set the LoginViewController as your root view controller in your application:didFinishLaunchingWithOptions: method.
self.window.rootViewController = self.loginViewController;
remove this line:
[self.window.rootViewController presentModalViewController:self.loginViewController animated:NO];
You have to set the rootViewController like this in your AppDelegate.m
self.window.rootViewController = self.loginViewController;
Have you worked with creating your interface with storyboards yet? (Storyboards are new as of iOS 5) They are basically a way of laying out all your view controllers in one file and visually setting connections between them. What you are wanting to do is really easy with storyboards. When you set up view controllers on your storyboard file you will see an arrow pointing to the first storyboard you set up. That means when you run your app that is the initial view that will load. If you prefer a different view to load first simply drag that arrow to a different view controller.

iOS: UIViewController doesn't display another UIViewController using storyboards

I am tryin to display multiple UIViewController objects inside a single view. For the time being I want to display a single UIViewController object when the app loads. But the app screen appears blank, while it should be displaying a label inside the child view controller.
Here is what I did:
ParentViewController.h
#import <UIKit/UIKit.h>
#interface ParentViewController : UIViewController
{
UIViewController *child1Controller;
UIViewController *child2Controller;
}
#end
ParentViewController.m
#import "ParentViewController.h"
#import "Child1Controller.h"
#import "Child2Controller.h"
#interface ParentViewController ()
#end
#implementation ParentViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { ... }
- (void)viewDidLoad
{
child2Controller = [[Child2Controller alloc] init];
[self.view addSubview:child2Controller.view];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)viewDidUnload { ... }
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { ... }
#end
Then in the storyboard in interface builder
add 3 view controllers
assigned a class to each one of them ParentViewController, Child1Controller & Child2Controller
in Child2Controller object, added a UILabel inside View.
in Child2Controller.h defined the IBOutlet for UILabel and added a synthesize statement for the same in Child2Controller.m
finally in project-Info.plist set the main storyboard file
Did I miss something over here?
Starting from iOS 5 it's possible to take advantage of View Controller Containment. This is a new methodology that allows you to create a custom controller container like UINavigationController or UITabBarController.
In your case, this could be very useful. In fact, in your storyboard you could create the parent controller and the two child controllers. The parent could be linked to another scene while the two children are not linked. They are independent scenes that you can use within your parent controller.
For example in viewDidLoad method of your parent controller you could do the following:
- (void)viewDidLoad
{
[super viewDidLoad];
UIStoryboard *storyboard = [self storyboard];
FirstChildController *firstChildScene = [storyboard instantiateViewControllerWithIdentifier:#"FirstChildScene"];
[self addChildViewController:firstChildScene];
[firstChildScene didMoveToParentViewController:self];
}
Then in your FirstChildController override didMoveToParentViewController
- (void)didMoveToParentViewController:(UIViewController *)parent
{
// Add the view to the parent view and position it if you want
[[parent view] addSubview:[self view]];
CGRect newFrame = CGRectMake(0, 0, 350, 400);
[[self view] setFrame:newFrame];
}
And voilĂ ! You have a controller that contains one view that is managed by a child controller.
For further info see how-does-view-controller-containment-work-in-ios-5.
Hope it helps.

Resources