I have subclassed UIViewController like so:
#interface MyClass : UIViewController
I dont have a xib file for the controller, instead I would just like to use a blank UIView and I will layout elements programmatically on that. The problem arrises when I try and push this view controller.
MyClass * thing = [[ImageGallery alloc] init];
[self.navigationController pushViewController:thing animated:YES];
A new title bar is animated in, but there is no view, its see through, so I end up seeing a static background I set on my main "window/view". How should I properly subclass a UIViewController without a xib?
What you have described is correct behaviour so far.
You will want to override the -(void)loadView method, and after the [super loadView]; call, you can set your background colour and begin to place the objects in programatically, that you desire.
Related
I have a problem on how to properly do a certain kind of action.
The image below shows a UIViewController, but the second part of the view is a custom UIView (the one with the profile pic, name and Show View button).
The subclassed UIView is allocated using this code:
profileView = [[GPProfileView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 70)];
profileView.myTripGradientColor = YES;
[self.view addSubview:profileView];
The problem is of course, that the button on the UIView can't show any view, since it's only the UIViewController that can push another ViewController to the window(correct?).
The UIView is used in several places in the app and needs to be added easily and have the same behavior across the application.
This worked great until I added the button, and I'm starting to think I've made this wrong, and there has to be a better way to do it (maybe change the UIView to something else?).
I was thinking I should be able to call:
self.superview
And then somehow get the ViewController so I can push another ViewController into the view hierarchy, but nope.
Any suggestions and a tips on how to do this correctly?
UPDATE:
I have no idea on how to push another UIViewController from the button.
What should I do in this method when pressing the button in the UIView:
- (void) showViewButtonTouched:(UIButton*)sender {
GPProfileSocialFriendsViewController *friendsSettings = [[GPProfileSocialFriendsViewController alloc] init];
}
How do I push GPProfileSocialFriendsViewController?
Your - (void) showViewButtonTouched:(UIButton*)sender method should be in your controller and would probably be better named - (void) showView:(UIButton*)sender or - (void) showProfile:(UIButton*)sender so it clearly denotes what it does (not how you got there).
It's not the view's responsibility to manage transitions from a state to another. If you move your method to your controller, your problem is no more (you can easily access self.navigationController or push directly if you don't have an navigation controller like this:
[self presentViewController:vcThatNeedsToBePushed animated:YES completion:nil];
I think you can create weak reference in GPProfileView on UIViewController. Like this:
#property (weak, nonatomic) UIViewController *rootController;
when you create GPProfileView, assign rootController-property:
profileView = [[GPProfileView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 70)];
profileView.myTripGradientColor = YES;
profileView.rootController = self; // if view created in view controller
[self.view addSubview:profileView];
and in implementation of button selector:
self.rootController push... // or pop
May be this not correct, but you can try
You could let the view controller push the next view controller when the button is pushed. The view controller can add a target/action on the button, so that the action method in the view controller is called on the touch up inside event.
I have a UIViewController (StoreViewController), and in it's .xib is a UITableView to the left, and a standard UIView to the right. I have created a UITableViewController called StoreTableController and want to somehow make it the the controller of the table view within the StoreView.xib.
Unfortunately, I need to keep the File Owner of the nib file as StoreViewController. I have a delegate within the StoreTableController which has been set as the StoreViewController (this is for calling certain methods), and within the StoreViewController I have an instance of the StoreTableController.
So far I have tried keeping an outlet of the UITableView within StoreViewController and then doing this:
[self addChildViewController:self.tableController];
[self.tableController setTableView:self.table];
[self.table setDataSource:self.tableController];
[self.table setDelegate:self.tableController];
Where self.table is the outlet, and self.tableController is the instance of the StoreTableController.
However, I do not fully understand how to use UIViewController containment, so this is obviously incorrect.
I have tried variations of this as well, but really don't know what to do.
I have avoided using a UISplitViewController here because not only is the left view larger than the right, but also there are various things I plan to do which mean this must be done in a single .xib file if possible.
Any help is very much appreciated.
First, put a regular UIView instead of a UIScrollView in your .xib. Connect it with an IBOutlet called "tableContentView".
Then, create a new instance of UITableViewController (or your custom class, derived from UITableViewController) in your code, and add its UIView to the tableContentView like so:
- (void)viewDidLoad
{
[super viewDidLoad];
// Add tableView
UITableViewController *someTableViewController = [[UITableViewController alloc] init];
someTableViewController.view.frame = self.tableContentView.bounds;
someTableViewController.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self.tableContentView addSubview:someTableViewController.view];
}
In my storyboard, I have a view (a subclass of UIScrollView called AQGridView) which is nested inside a view controller scene. I want to assign the AQGridView a controller delegate and datasource which is defined in a separate .m and .h file than the parent view controller. How do I do this? Storyboard only lets me drag connectors to AQGridView's parent view controller.
EDIT:
I've tried doing something in the parent view controller like this (where myGrid is an IBOutlet pointing to the AQGridView and myGridController is a property of the parent view controller):
- (void)awakeFromNib
{
// note: kzMyGridController is a subclass of AQGridViewController
myGridController = [[kzMyGridController alloc] init];
myGrid.delegate = myGridController;
myGrid.dataSource = myGridController;
}
But it doesn't appear to be working because none of its delegate methods are being called. What am I doing wrong?
If you are not allowed on the StoryBoard, just do it on the code. It makes more sense, because it actually forces you to have an object (the delegate) and set it when you need it.
It should be:
- (void)awakeFromNib
{
// note: kzMyGridController is a subclass of AQGridViewController
myGridController = [[kzMyGridController alloc] init];
myGrid.delegate = myGridController;
myGrid.dataSource = myGridController;
}
The answer was that I had to call reloadData on the AQGridView. The view is created before its delegate, so its initial data getting methods fire without a receiver.
I have made a very simple Navigation based app (UIViewController). The view has a single button on the Main RootViewController.
Next, I made 2 classes: TabOneViewController, TabTwoViewController. All good. I then created a new Class TabBarViewController. I opened up the NIB file and dropped on a ``UITabBarController onto it. The two tabs it creates in it by default were assigned (respectively) to my TabOne and TabTwo view controllers.
strong text
Then in my TabBarViewController, I made an IBOutlet for a UITabBarController, synthesized it etc etc. I linked it up in Interface builder via the "files owner".
In the RootViewController, I linked the button to my "pushView" method, and in this pushView method, I have the following code:
- (IBAction) pushView {
TabBarViewController *controller = [[TabBarViewController alloc] init];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
The end result is it DOES push a view, but I cannot see the tab bar at the bottom, let alone any of the pages I've added to the controller.
What am I doing wrong? Why can't I link it in IB?
I am not 100% sure if that's allowed.. because you already have one tabBarController as rootViewController, and you dropped one more tabBarController as first tab controller, tabs ll overlap, considering amount of real estate you have on your iPhone, it make sense to not allow a tabViewController inside another
First, you need to allocate your view controller with your nib:
TabBarViewController *controller = [[TabBarViewController alloc] initWithNibName:#"YourNibName" bundle:nil];
Secondly, in IB, click the UITabBarController and go to the identity inspector and make sure you select your custom class. That said, unless you are overriding or adding some functionality you probably don't need the custom class at all, simply use a UITabBarController directly:
UITabBarController *controller = [[UITabBarController alloc] initWithNibName:#"YourNibName" bundle:nil];
From withing a UIViewController that is tied to a UIView (drawn in a nib file), i try to add another view, as a subview to the first view.
In case you are confused: UIViewController -> UIView + GraphView (extends UIView)
So i am saying:
GraphView *myGraphView = [[GraphView alloc] init];
graphView = myGraphView;
[self.view addSubview:graphView];
[myGraphView release];
I have also tried with insertSubview.
The UIView shows up and the GraphView subview is instantiated correctly (its properties are there and i can access its methods). But it never shows on the screen!
Its drawRect method is never called (i have an NSLog in there that never shows), even if i manually call [graphView setNeedsDisplay].
Does anyone have a clue?
Thanks a lot!!!
Doesn't look like you're setting the GraphView frame rectangle, it will not display if it's offscreen. Also you probably should be calling the UIView initWithFrame: initializer if you aren't.