I'm appending code to an existing app to add a modal loginView, the old project does not use xib, and the new view controller does.
The present project load its rootViewController this way
- (void) loadView
{
// this should take up the entire screen...
UIView * view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];
view.backgroundColor = [UIColor blueColor];
self.view = view;
sideBar =
[[SideBarView alloc] init];
sideBar.rootViewController = self;
[self.view addSubview:sideBar];
pageView =
[[PageView alloc] initWithTitle:DataEntryTitle
client:client];
pageView.rootViewController = self;
//I added this to instantiate the new view controller
_aLoginView = [[LoginViewController alloc]initWithUser:aUser];
[self.view addSubview:pageView];
}
To launch the modal view controller I'm using this code.
-(void)viewDidAppear:(BOOL)animated{
_aLoginView.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:_aLoginView animated:YES completion:nil];
}
As long as I understand the reason for the modal LoginView appearing blank is that I'm creating a new instance of it, instead of calling the existing xib definition. Does someone know what should I do to reference the xib? The old project does not use storyboard, nor xib files.
Thanks,
With your info I think I'm doing something wrong in LoginViewController.m, but I don't know exactly what.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (id)initWithUser:(verifyUser *)aUser
{
self = [super initWithNibName:#"LoginViewController" bundle:[NSBundle mainBundle]];
if (self) {
// Custom initialization
_UserModel = aUser;
}
return self;
}
You want to create the view controller by loading it from the nib
[[LoginViewController alloc] initWithNib:#"nib file name" bundle:[NSBundle mainBundle]]];
If you want to keep your initWithUser: initializer you should be able to do
self = [super initWithNib:#"nib file name" bundle:[NSBundle mainBundle]];
The files owner of your xib is not set.
Open your xib and select the file owner option in the top left
Then on the right pane set the files owner to your view controller:
FOOTNOTE
As an aside, you don't need to set the frame of your view controller in viewDidLoad. It isn't a ViewControllers responsibility to evaluate its own size. A view controller is merely responsible for maintaining the relationship between the model and the view. It is the responsibility of the container or parent ViewController to set the size.
Happy coding
Related
Programmatically created segue crashes the app on performSegueWithIdentifier:, I really don't want to use the storyboard though.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
ViewController *viewController = [[ViewController alloc] init];
self.segue = [[UIStoryboardSegue alloc] initWithIdentifier:#"showInfo" source:self destination:viewController];
//change the background color to white
self.view.backgroundColor = [UIColor whiteColor];
//create the table view
UITableView *tableView = [[UITableView alloc] init];
//initialize the data source and the delegate to self - as the methods are going to be specified in this script
tableView.dataSource = self;
tableView.delegate = self;
//register the class for the tableView
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"cell"];
//now assign the table view to our our viewController's property
self.view = tableView;}
Segues can't be created programmatically. Apple's documentation says:
You do not create segue objects directly. Instead, the storyboard runtime creates them when it must perform a segue between two view controllers.
The initWithIdentifier:source:destination: method is for subclassing purposes.
That said, if you're not using storyboards you don't really need segues anyway. Just instantiate and present the destination view controller when you need to.
I want to display a programmatically created ViewController in a storyboard ViewController. The ViewController of the Storyboard is of a different class as the 'programmatically' created ViewController.
I've got the following classes:
ViewController (linked to storyboard scene, and implementation happens here)
OnboardingVC (all elements are created over here)
I've tried the following:
-(id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if(self){
self.onboardVC = [self generateFirstDemoVC]; // returns in an instance ofOnboardingViewController
self = (ViewController*)self.onboardVC;
}
return self;
}
This (obviously) crashes.
What I don't want is this:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window setRootViewController:self.onboardVC];
[self.window makeKeyAndVisible];
Because this doesn't take the setup in the storyboard into account, and I don't want that, because the VC needs to managed by a NavigationController. How do I accomplish that?
It sounds like you have a UINavigationController as the entry point to your storyboard. You can manipulate this navigation controller when the application launches, to add, remove, or replace view controllers, etc.
For example:
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{
UIViewController* initialVc = [OnboardingViewController generateFirstDemoVC]; // or whatever
UINavigationController* nav = (id)_window.rootViewController;
nav.viewControllers = #[ initialVc ];
return YES;
}
I have a view controller called "Help". I placed a label on the view controller story board, but in simulation I couldn't see the label. I used REMenu to put a menu at the top of the view. I can see the menu bar, but I cannot see the label. Here are the files.
#import "Help.h"
#interface Help ()
#end
#implementation Help
#synthesize helpText1;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view setBackgroundColor:[UIColor whiteColor]];
self.navigationItem.leftBarButtonItem =
[[UIBarButtonItem alloc] initWithTitle:#"Back"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(handleBack:)];
helpText1.text=#"Hiii";
helpText1.hidden=NO;
// Do any additional setup after loading the view.
}
-(void)handleBack:(id)otherView{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController *myVC = (Controller *)[storyboard instantiateViewControllerWithIdentifier:#"QRList"];
[self.navigationController pushViewController:myVC animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Here is the code that calls the "Help" view controller.When we click on the help option in the menu, it will call the "help" view controller.
REMenuItem *helpItem = [[REMenuItem alloc] initWithTitle:#"Help"
subtitle:nil
image:[UIImage imageNamed:#"Ic"]
highlightedImage:nil
action:^(REMenuItem *item) {
NSLog(#"Item: %#", item);
Help *controller = [[Help alloc] init];
[weakSelf setViewControllers:#[controller] animated:NO];
}];
The "Help" view controller is getting called but I couldn't see the label which I dragged on storyboard. I couldn't figure out the issue.
I guess, that your label is being at a wrong view. Probably, your pushed controller doesn't contain the label you put in your nib file. Try to add other objects and see what's happening. If the problem is that I just guessed, then find the exact controller, choose a view and put there the label. Hope you solve that!
Use debug, put breakpoints, to see where you lose label. Check your layouts, maybe...tie your lable to top Space to superView, leading or tralling space to supeView or bottom space to superView. And beginning Xcode 4.4 we don't need synthesize, each added default
I am trying to fix someone's code and am running into a problem. Here is the situation:
I have a full screen UIViewController that has a bottom bar button. When I press that button, it shows a popup view controller in the bottom left of the screen. That view controller inside the popup also has a button, and when I press THAT button it pushes a new view controller into my popup window. That new view controller is a UITableView that can have some large number of elements. The problem is that when I try to scroll down to see some offscreen elements, the scroll bounces back to the first position in the table, i.e. it does not really scroll.
More specifically here is some code:
In FullScreenVC.h:
#property (nonatomic, retain) NSMutableArray* stuffInList;
#property (nonatomic, retain) UIPopoverController *namePopover;
#property (nonatomic, retain) UINavigationController *nameNav;
#property (nonatomic, retain) UIBarButtonItem* addButton;
Inside FullScreenVC buttonPressed (called when addButton is pressed):
FirstPopupVC *vc=[FirstPopupVC alloc] initWithNibName#"FirstPopupVC" bundle:nil];
vc.delegate=self;
vc.stuffInList=self.stuffInList; // This is just the NSArray of list items
self.nameNav = [[[UINavigationController alloc] initWithRootViewController:vc] autorelease];
self.namePopover = [[[UIPopoverController alloc]
initWithContentViewController:self.nameNav] autorelease];
[vc release];
[self.namePopover presentPopoverFromBarButtonItem:self.addButton
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
In other words, the FirstPopupVC object vc is the root view controller of a UINavigationViewController nameNav, and nameNav is the navigationcontroller that is the content inside the namePopover UIPopoverController. I think the last line launches FirstPopupVC as a popup from the addButton. Note also that the XIB file FirstPopupVC.xib is a simple NIB file that has a few simple views (label etc) and a little button that a user can press to get the second popup, as we'll see.
Inside FirstPopupVC we have:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// some other irrelevant initialization stuff here ...
self.contentSizeForViewInPopover = CGSizeMake(320, 340);
}
return self;
}
-(void)littleButtonClicked:(id)sender {
SecondPopupVC * secondVC=[[SecondPopupVC alloc]
initWithNibName:"#SimpleTableView" bundle"nil];
secondVC.delegate=self;
secondVC.stuffInList=self.stuffInList;
[self.navigationController pushViewController:secondVC animated:YES];
[secondVC release];
}
This of course presents the second view controller inside the popop.
Inside SecondPopupVC we have:
- (id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.contentSizeForViewInPopover = CGSizeMake(320, 340);
}
return self;
}
Apparently the contentSizeForViewInPopover call here will set the size of the popover view with the table view. It looks like this is called inside initWithNibName in both the first and second view controllers.
So again, the problem is that if my listOfStuff is large, ie if the set of items in the table is large, then the table will not stay scrolled beyond the first visible set of rows. I can scroll down to see these items but as soon as I release the mouse pointer (on the emulator) or my finger (on the device), it bounces back to the top of the list.
I tried to add autoresizingmak code as discussed in table view in popover is not scrolling but that didn't work for me.
So how can I fix the above code so that my table stays scrolled when I try to scroll it?
Well, it appears that the problem has something to do with the fact that secondVC is created from a NIB file rather than programmatically. I tried doing this instead:
-(void)littleButtonClicked:(id)sender {
SecondPopupVC * secondVC=[[SecondPopupVC alloc] init];
CGSize contentSize = CGSizeMake(320, 320);
UIView* popoverView = [[UIView alloc] initWithFrame:CGRectMake(0, 0,
contentSize.width, contentSize.height)];
popoverView.autoresizingMask = (UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight);
UITableView *tblView = [[UITableView alloc]initWithFrame:popoverView.bounds];
tblView.autoresizingMask = (UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight);
tblView.delegate = secondVC;
tblView.dataSource = secondVC;
tblView.rowHeight = 44;
[popoverView addSubview:tblView];
secondVC.view = popoverView;
secondVC.contentSizeForViewInPopover = contentSize;
secondVC.stuffInList=self.stuffInList;
[self.navigationController pushViewController:secondVC animated:YES];
[secondVC release];
}
and guess what? It works fine. So why would there be such a problem when SecondPopupVC is initialized from a NIB file rather than using code?
(I know this has been asked before, unfortunately none of the related StackOverflow answers I've looked through and tried out while trying to figure this problem out have worked for me. Any help would be much appreciated.)
I'm building a simple news app. The opening screen grabs the latest news entry using Parse's API.
And when you tap the menu button, you get a UITableView of past news days:
I want to be able to pass the id from the selected Parse table cell back to the main view.
I'm using ECSlidingViewController for the sliding menu and a Storyboard for the various screens:
But because of the way I'm using ECSlidingViewController, I can't figure out how to pass data via segues like I otherwise would be able to, so I'm trying to just pass it via the view controllers with a custom init.
Here's my MainViewController.h code:
#interface MainViewController : UIViewController
#property (nonatomic) NSString *detailId;
- (id)initWithDetailId:(NSString*)theId;
#end
Here's my didSelectRowAtIndexPath code in MenuViewController.m:
MainViewController *mainVC = [[MainViewController alloc] initWithDetailId:#"test"];
[self.navigationController pushViewController:mainVC animated:YES];
Here's MainViewController.m's initWithDetailId:
- (id)initWithDetailId:(NSString*)theId
{
NSLog(#"initWithDetailId");
self = [super initWithNibName:nil bundle:nil];
if (self) {
detailId = theId;
}
return self;
}
And here's MainViewController.m's viewDidLoad:
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"detailId equals: %#", self.detailId);
}
But all I get from the NSLog is "detailId equals: (null)". What am I doing wrong here? Thanks!
you have forgot to put self. in front of detailId = theId;
self.detailId = theId;
that is
- (id)initWithDetailId:(NSString*)theId
{
NSLog(#"initWithDetailId");
self = [super initWithNibName:nil bundle:nil];
if (self) {
self.detailId = theId;
}
return self;
}
there is one another method of doing this:
MainViewController *mainVC = [self.storyBoard instantiateViewControllerWithIdentifier:#"yourIdentifier"];
mainVc.detailId=#"test";
[self.navigationController pushViewController:mainVC animated:YES];