I'm using XCode 4.2 and have built my UI using Storyboards. I need to create a view that has content above and below a UITableView and I can achieve this by using a UIViewController. A UITableViewController does not let you add content above or below the table. You can use the table header/footer but that doesn't work for what I would like to achieve.
I now have a UIViewController with a UITableView embedded in it. I can adjust the height and width of the UITableView accordingly which provides me the UI layout that I am looking for.
I can customize the static cells in the UITableView but when I try to build I get the following error:
Illegal Configuration: Static table views are only valid when embedded in UITableViewController instances
My question is how are others getting around this? Creating a tableview with static cells and laying them out visually is very nice but apparently that is not allowed for some reason that I cannot understand. I can't switch to a UITableViewController because of my visual layout requirements.
Any assistance would be greatly appreciated.
You can achieve this in Xcode 4.5 and later versions, assuming your app is targeted at iOS 6+.
In the Storyboard simply create a UIViewController with a View Container inside it's main view. Then hook up that View Container to a UITableViewController that contains static cells.
Just like this:
You don't need a single line of code. Just control click, drag and select embed. The view controller containment is handled for you.
You are right. In storyboard, you cannot have a tableView with static cells embedded in a viewController. One way around it (I have not tried it myself, though, so I am not sure if it works) can be that you create an instance of UITableViewController in storyboard with static cells. Add an instance of UIView to your viewController, and then programmatically load the tableView of the UITableViewController into the UIView of your viewController.
pmd's answer works but in the event that backward compatibility with iOS 5 is required as well, you can do the embedding programatically using the View Containment API.
In the viewDidLoad method of your parent UIViewController:
- (void)viewDidLoad
{
[super viewDidLoad];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
MyTableViewController* vc =[storyboard instantiateViewControllerWithIdentifier:#"MyTableVC"];
[self addChildViewController:vc];
[self.view addSubview:vc.view];
// ensure embedded view is aligned to top
CGRect frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
vc.view.frame = frame;
[vc didMoveToParentViewController:self];
}
Don't forget to specify a storyboard ID for your UITableViewController with the static cells.
I know this is an old question but I have a scrappy solution to this issue.
I needed 3 static cells on a UIViewController so this is what I did:
Drag in some Table View Cells into your interface (not into UITableView) - add text and whatever else you need.
Make IBOutlet properties for your cells and synthesise them.
Drag a button and make it cover the entire cell. Set the button to type 'Custom' so it appears invisible - repeat for all cells
Add numeric tags to your buttons
Implement the following functions. buttonDown is connected to the buttons 'Touch Down' event. buttonUp is connected to 'Touch Up Inside' AND 'Touch Up Outside'
-(IBAction)buttonDown:(id)sender {
if ([sender tag] == 1) {
myFirstCell.selected = YES;
}
else if ([sender tag] == 2) {
mySecondCell.selected = YES;
}
else if ([sender tag] == 3) {
myThirdCell.selected = YES;
}
}
-(IBAction)buttonUp:(id)sender {
myFirstCell.selected = NO;
mySecondCell.selected = NO;
myThirdCell.selected = NO;
}
You can do whatever else you like in the buttonDown event and use the button to go directly to a new view. I find this pretty useful.
I am not sure what you mean by static cells, but if you are trying to build the cells in IB, and then want to use it in your tableView, what you could do is in your cellForRowAtIndex you can call loadNibNamed passing the name of the .nib file you created for the cells as the parameter. Make sure that you have an outlet in your viewController which maps to the cell's .nib. Try exploring in these directions if that's what you are trying to achieve
You can make it dynamic and then switch of scrolling:
[yourTableName setScrollEnabled:NO];
Related
I have viewController that have fabric create methods, depending on specific integer. What i want is, to make collection view, with each cell is representing that controller.
Problem is, UICollectionViewCell is a view, but I've ViewController.
What I tried is subclass UICollectionViewCell like follow (paste that code in subclass of UICollectionViewCell):
CalendarViewController *vc = [CalendarViewController create];
UIView *vw = vc.view;
[self addSubview:vw];
[vw mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.bottom.equalTo(self);
}];
Last line is simply added constraints.
Now I've 2 problems:
It treated like a view, and i cant click on specific areas (cells, CalendarViewController is collection view also)
Sometimes view vanish and there is only blank view on a screen.
View controller in UICollectionViewCell is a tricky situation as it is respective view controller's responsibility to handle views touches. You can refer to this SO answer for some approaches.
But, this situation when UICollectionViewCell needs to be a UIViewController is handled here: https://github.com/zats/Voltron, if you can use third party code:
I have a UITableViewController with a dynamic tableView. Now, I want to add a second tableview as subview to my UITableViewController on button click, but I want to design this static tableView using storyboard. So I added another UITableViewController and changed the class of the tableView to my custom class. But when I instantiate it on my firs TVC, it doesn't load the one from storyboard. I think it just instantiates a new object of my custom class but not the one on the storyboard file. And I can't connect the outlet of the tableView to my first TVC, it doesn't let me.
So I guess my option here would be to implement a new UITableViewController and add it as subview, instead of just adding the table, right? I just thought I didn't need another UITableViewController and could just use the tableview but I guess I'm wrong.
Any suggestions?
UPDATE:
This code works fine, I'm just wondering if this is the right approach.
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Treinamento" bundle:nil];
TabRelTableView *tabRelatorio = [sb instantiateViewControllerWithIdentifier:#"TabRelTableView"];
tabRelatorio.tableView.frame = CGRectMake(0, 38, 320, 466);
[self addChildViewController:tabRelatorio];
[self.view addSubview:tabRelatorio.tableView];
TabRelTableView is a UITableViewController.
Have you thought of view controller containment? This way you can have a custom controller with dynamic table view as well as storyboard-designed static tableView. Then you can switch between dynamic and static ones based on your needs.
I have an application developed in iOS4 using XiBs. I got it working all good with iOS6.1 and earlier. But for some buttons, IBAction is not getting called if it is iPhone and iOS 7.0. Also it is working fine with iPad and iOS 7.0. Of course, I am using different Xibs for iPhone and iPad.
Here is the code. It is pretty basic. But just not getting into it.
- (IBAction) didReceiveMapButtonPress {
NSLog(#"IN DID RECEIVE MAP BUTTON PRESS");
if ([self wasReferredFromMap]) {
[[self navigationController] popViewControllerAnimated:YES];
} else {
[self pushMapViewController];
}
}
Many of the developer used custom view to show custom cell on Table view for older version of iOS. If you are one of them, then you will have to face a problem that your button click action will no longer work with iOS7.
How to resolve this:
You have three options:
Option 1: Create the new lay out with new table cell instead of taking view. and put all layouts again in table cell.
I know, this will require a lot of effort.If you don't want to do this, we have a very small hack for it:option 2
Option 2: Create a IBOutlet for your button and add this button as a subview of your cell's content view.
[self.myCell.contentView addSubview:self.btn_click];
The above line of code will add btn_click as a subview of you content view. Now button click action should work.
Option 3:
The best way :
i) Take An outlet UITableViewCell.
ii) Make existing view as subview of new table cell.
iii) Disconnect the connection of custom cell to existing view and connect it to new UITableViewCell.
thats it, Your IBAction will work now.
May be you got the crash with error message that "class is not key value coding - compliant.". Check your old view connection and remove all connection having yellow mark.
When I faced with this problem, I had tons of cells from xibs. That's way I've create the category for UITableViewCell
#implementation UITableViewCell (customs)
- (void)awakeFromNib {
[super awakeFromNib];
[self reAddSubviews];
}
- (void)reAddSubviews {
for (UIView * o_vw in [[[self subviews] objectAtIndex:0] subviews]) {
if (o_vw != self.contentView) {
[o_vw removeFromSuperview];
[self.contentView addSubview:o_vw];
}
}
}
#end
Please make sure the TCell.xib for your UITableViewCell is correct.
Double check if this xib file has "Content view". If you can not see this item, that means your view is not a UITableViewCell, it probably is a UIView.
The correct method is to recreate this XIB file. you can do it like this:
NewFile(User Interface)--->Empty--->Device Family(iphone)--->Save as TCell.xib.
add UITableViewCell
copy your subview from your previous xib file to this view and connect the outlets. http://i.stack.imgur.com/WB4j3.png
I created an uiview , that contained , many textfields , and I have an uiviewcontroller with xib file responsible for making signature .Is it possible to add this viewcontroller to my uiview in order to have this componant of drawing signature in the footer of my uiview ??
- (void)init { //parent view
...
FooterViewController *fvc = [[FooterViewController alloc] initWithNibName:#"myNibName" bundle:nil];
[self addSubview: fvc.view];
fvc.view.origin = CGPointMake(0, self.frame.size.height - fvc.view.frame.size.height);
}
this is how you can create your viewController from xib file and add its view to the main view. assuming this is what you are trying to do.
If you are using storyboards, the easiest way to go is to drag a Container View object from the Object library (where buttons, labels, etc. are) to your view controller's view. This will create a child view controller that you can handle separately and that will be already resized to mirror the size of the container view controller.
I'd like to place an ADBannerView object onto my UITableView screen statically, what means that I want it to always stay above my toolbar (self.navigationController.toolbar), even when the user is scrolling the tableview. I've solved this by adding by ADBannerView as a subview to my toolbar and given it negative values for the frames origin:
[self setBannerViewSize];
[self.navigationController.toolbar addSubview:bannerView];
The only problem is: I can't click and open the iAd this way - I can see the banner but nothing happens when I tap on it.
Since I'm also using a refreshControl, the option to use a UIViewController instead of UITableViewController and add a tableView manually wouldn't work for me. Is there any other way I can get my ADBannerView statically showing in my table view controller AND still being tappable?
Thank you in advice!
Yay!! After all I succeeded in solving this (really annoying) problem by myself (and a lot of reading around)!
First, I found this really world-changing post. Basically this post handles with the topic that a UITableViewController uses self.view for its tableView property, so overriding the tableView property (or synthesizing it manually) plus giving self.view a new view (from application) and adding tableView as its subview would make it possible to reach the real superview of tableView.
But this still didn't solve my problem, although I was sure it would, because it all made sense. My bannerView appeared in the right place (and was fixed) but it still didn't do anything when clicked. But there was a second minor thing I didn't know about:
As I read in this post the superview of a subview doesn't only have to be userInteractionEnabled but also have a non-transparent backgroundColor. Because my superviews background color was set to [UIColor clearColor] it all didn't work - but setting its backGroundColor to e.g. blackColor solved the whole problem: the bannerView got finally tappable! :)
So, my code is now looking like this:
#synthesize tableView;
- (void)viewDidLoad
{
[super viewDidLoad];
if (!tableView && [self.view isKindOfClass:[UITableView class]]) {
tableView = (UITableView *)self.view;
}
self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
self.tableView.frame = self.view.bounds;
[self.view addSubview:self.tableView];
[self resizeTableToFitBanner];
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:bannerView];
// some other code
}
BannerViewController in Apple's iAdSuite sample code solves this problem very elegantly:
https://developer.apple.com/library/ios/samplecode/iAdSuite/Introduction/Intro.html
I think you should use a container view, and set things up in IB. You can add a tool bar and ADBannerView to the bottom of the view of your navigation controller's root view controller. Fill the rest of the space with a container view - this will give you an embedded view controller automatically. You should delete this one and then drag in a tableViewController and control drag from the container view to the tableViewController to hook up the embed segue.