Adding childContainerView disables UITableView - ios

I have a chat that's setup as a UIViewController with a tableView added to it's view. This was working fine. I've since subclassed this viewController and added a childViewController as a header of the table:
- (void) createClassVideoView {
CGRect rect = CGRectMake(0.0f,
0.0f,
self.view.frame.size.width,
kWSClassVideoHeight);
WSClassVideoController *classVideoController = [[WSClassVideoController alloc] initWithFrame:rect mainUser:[[WSConversationManager shared] teacherObject] secondaryUsers:[[WSConversationManager shared] students]];
[self addChildViewController:classVideoController];
[self.view addSubview:classVideoController.view];
[classVideoController didMoveToParentViewController:self];
self.classVideoController = classVideoController;
}
It's not set as the actual tableHeaderView. It's just added as a childViewController to the subclass of the chat view controller, and I've just reset the frame of the tableView to accomodate it. This "header view" works fine and receives touches.
However, it's since disabled the superclass tableView's touches. The tableView displays, but I can't scroll it and tapping the UITextField does nothing.

Related

How do I set the size of UITableView as a subview in a Container View with Auto-layout

I currently have a UIViewController which contains a menu bar and container UIView.
On main view load the container has an embed segue with a separate main content UIViewController.
When I click a button in the menu bar I have a custom segue set up to load a UITableViewController into the UIView container using the following code
-(void) perform {
BlockDetailViewController *src = (BlockDetailViewController *)[self sourceViewController];
UIViewController *dst = (UIViewController *)[self destinationViewController];
//Clear view of all subviews
for (UIView *view in src.viewContainer.subviews) {
[view removeFromSuperview];
}
//save destination
src.currentViewController = dst;
//set placeholderOutlet to destination
[src.viewContainer addSubview:dst.view];
}
This loads the UITableViewController into the UIView fine, however, it seems the UITableViewController size is set as the default window size which means the bottom cells of the UITableViewController are hidden from view. You can see them if you drag up but when you let go the bounce takes them out of the view.
How do I make sure the size of the UITableViewController is the same size as the UIView it is being placed into?
Thanks
You just have to create a a CGRect (frame) and set it to the views frame:
dst.view.frame = CGRectMake( CGRectGetMinX(self.view.frame),
CGRectGetMinY(self.view.frame),
CGRectGetWidth(self.view.frame),
CGRectGetHeight(self.view.frame);
the values should be float values. This is just an example.
When you define dst, you can use CGRect to set its position, width and height.

Creating UIView in UITableViewController that doesn't moves with the table view

I would like to display a small UIView with some text in the center of a UITableViewController when I call the showHud method.
- (void) showHud {
UIView *paintView=[[UIView alloc]initWithFrame:CGRectMake(150, 150, 120, 30)];
[paintView setBackgroundColor:[UIColor yellowColor]];
[self.view addSubview:paintView];
}
Actually the problem with this code is that the view doesn't stays on its place, when I scroll the tableview it goes up with cells. Is it possible to pin it somehow?
I don't think you can achieve that with a UITableViewController because the view property of such controller is a UITableView, so the content will always scroll with it.
You need to create a regular UIViewController and add a UITableView to that controller's main view. Then anything else you add to that main view, will stay in place as it is outside of the table view.
Try implementing scrollViewDidScroll delegate method and change the frame of paintView according to tableview offset.
eg:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint offset = scrollView.contentOffset
[paintView setFrame:CGRectMake(150, 150+offset.y, 120, 30)];
}
But the best way would be to create a simple UIViewController.
You must use UItableViewController because of pullToRefresh controller?
UI could add a view to the window and position it to the very front:
UIView testView = [[UIIView alloc]initWithFrame:CGRectMake(10, [[UIScreen mainScreen]applicationFrame].size.height - 85 , 75, 75)]; [[[[[NSApplication sharedApplication] mainWindow] contentView] addSubview:testbox]; addSubview: testView]; testView.layer.zPosition = MAXFLOAT;
An UITableViewController is typically embedded in a "parent" view controller, like UINavigationController. Its UITableView will then have a superview, like UINavigationControllerWrapperView. Even if your table view controller is a root view controller, the table view's superview is UIWindow.
So you can safely assume that your table view always has a superview. Then add your UIView to this superview instead of the table itself:
//Note: frame should be different here as it's in the superview's coordinate system
UIView *paintView=[[UIView alloc]initWithFrame:CGRectMake(150, 150, 120, 30)];
[paintView setBackgroundColor:[UIColor yellowColor]];
[self.view.superview addSubview:paintView];

iOS Fix search bar on top of the UITableViewController?

I'm adding search bar on table header and floating it in scrollViewDidScroll method, but when i scroll without click on search bar(i.e. i go to the view and do scroll) then search bar doesn't stay on top but it scroll up with table however once i click on search bar and click cancel button on search bar and then if i scroll the table, search bar stays on top.here is my code-
-(void)viewDidLoad {
[super viewDidLoad];
UISearchBar *searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
searchBar.delegate = self;
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
searchDisplayController.delegate = self;
searchDisplayController.searchResultsDataSource = self;
searchDisplayController.searchResultsDelegate = self;
UIView *tableHeaderView = [[UIView alloc] initWithFrame:searchDisplayController.searchBar.frame];
[tableHeaderView addSubview:searchDisplayController.searchBar];
[tableView setTableHeaderView:tableHeaderView];
isSearching = NO;
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
UISearchBar *searchBar = searchDisplayController.searchBar;
CGRect searchBarFrame = searchBar.frame;
if (isSearching) {
searchBarFrame.origin.y = 0;
} else {
searchBarFrame.origin.y = MAX(0, scrollView.contentOffset.y + scrollView.contentInset.top);
}
searchDisplayController.searchBar.frame = searchBarFrame;
}
- (void)searchDisplayControllerWillBeginSearch:(UISearchDisplayController *)controller {
isSearching = YES;
}
-(void)searchDisplayControllerWillEndSearch:(UISearchDisplayController *)controller {
isSearching = NO;
}
Note that I'm using UITableViewController sub class and don't want to change it to UIViewController.
Any help would be appreciated.
Edit: I also using section header in this UITableViewController, in other UITableViewController there is no section header and this code working fine.Is this a problem with section header and table header together?
The reason why your searchbar is scrolling with the table contents is that you have put it directly IN the table, thus making it a child header section of the table. and that section ALWAYS scrolls…
Here is how this this can be achieved. And it is actually quite simple. (The following example relies on Storyboard, but the mechanism is the same whatever you are using) :
1) Use a UIVIewController and NOT a UITableViewController
2) Add a UITableView as the child of the parent UIView
3) Add a UISearchBarController also as a child view of the UIView, NOT as a child of the UITableView (UITableView and UISearchController are siblings)
you should have the following layout :
EDIT : The important thing to remember is to put the UISearchBarController ABOVE the sibling UITableView. Otherwise you may see the UITableView overlap the UISearchBarController when the latter is focused.
EDIT 2 : BTW, if you are using AutoLayout, remember to set the TOP constraint of the tableView relative to the SearchBar…
Run it and admire the result.
Hope this helps.
There is not a way to maintain the header of a tableView fixed
1- could use an UIViewController instead of UITableViewController.
2- add subview (UIView) for header.
3- and add another subview for the tableview.

UIRefreshControl hidden / obscured by my UINavigationController's UINavigationBar

I'm attempting to use a UIRefreshControl inside my UITableViewController which itself is inside a UINavigationController, which has its hidesNavigationBar property set to NO (so the navigation bar is visible).
The UIRefreshControl works, but is obscured by the UINavigationBar. I'm surprised I can't find anyone else who has run into this problem.
Possible relevant points:
I set the rootViewController of my UIWindow to be my UINavigationController.
I set the initial view controller of the UINavigationController by setting the viewControllers property of the UINavigationController.
My UITableViewController subclass is instantiated with a nib.
I instantiate my UIRefreshControl in the viewDidLoad method of my UITableViewController subclass. I set the refreshControl property of the UITableViewController subclass in this method.
The UIRefreshControl works perfectly fine, and I can see a portion of it, but it is obscured by my UINavigationBar. It looks completely normal if I set hidesNavigationBar to YES (but I don't want to hide it).
Edit:
The code used to create and position my UIRefreshControl is:
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
[refreshControl addTarget:self
action:#selector(toggleRefresh:)
forControlEvents:UIControlEventValueChanged];
self.refreshControl = refreshControl;
This code snippet is in the viewDidLoad method of my UITableViewController subclass, which is a child view controller of a UINavigationViewController.
For those targeting iOS 7, there seems to be a new issue present where the UIRefreshControl is drawn behind the UITableView's backgroundView. I experienced this both when initializing the UIRefreshControl programatically and from a storyboard. A simple workaround is to update the zPosition of the UIRefreshControl in viewDidLoad of your UITableViewController:
self.refreshControl.layer.zPosition = self.tableView.backgroundView.layer.zPosition + 1;
I've find a real solution, here it is:
I've a UIViewController inside a UINavigationController with a translucent NavigationBar. Inside the UIViewController there is the UITableView.
I want to add a UIRefreshControl but when I do it, it's hidden by the NavigationBar, like you explain.
Here is my code to make it work:
// Add a UITableViewController
self.tblViewController = [[UITableViewController alloc] init];
// Set the UITableView to it
self.tblViewController.tableView = self.tblView;
// Initialize the UIRefreshControl and set it's method
self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:#selector(refreshTable) forControlEvents:UIControlEventValueChanged];
// Set the RefreshControl to the UITableViewController
self.tblViewController.refreshControl = self.refreshControl;
// Here is the thing ! Just change the contentInset to push down the UITableView content to 64 pixels (StatusBar + NavigationBar)
self.tblView.contentInset = UIEdgeInsetsMake(64.f, 0.f, 0.f, 0.f);
With this code, your UITableViewController will show the RefreshControl perfectly and keep the translucent NavigationBar effect when you scroll down the cells.
It looks like a bug to me, because it only occures when the contentOffset property of the tableView is 0
see this question
UIRefreshControl not showing spiny when calling beginRefreshing and contentOffset is 0
I fixed that with the following code (method for the UITableViewController) :
- (void)beginRefreshingTableView {
[self.refreshControl beginRefreshing];
if (self.tableView.contentOffset.y == 0) {
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^(void){
self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);
} completion:^(BOOL finished){
}];
}
}
In iOS 7, self.view is under the navigationBar, except that you write something as follows,
self.edgesForExtendedLayout = UIRectEdgeNone; // or UIRectEdgeAll & ~UIRectEdgeTop
or
self.navigationViewController.navigationbar.translucent = NO;
Using #Jonathan's answer I got this working well. But since I am using storyboard I set the content inset there like so: Which in case someones needs:
(xcode 6.4)
Do not call -setTranslucent: on your UINavigationBar. Then, your refresh control will be positioned properly, below the navigation bar.

UITableView: Painting-Behavior of Header- and Footer-View

Why does the header and footer of a tableview always stays on top of the view hierarchy, but not the cells of the table?
Here is what I got:
A table view with custom cells, a footer and a header
A Navigationbar with a menu-Button on the right
When the user taps the menu-button, a semi-transparent menu (UIView) fades in from the top, but not over the navigationbar, only over the view of my tableviewcontroller
When the user tabs a menu-button, the menu slides back to (0,-menuHeight)
But when the menu is over the header, this menu-region is behind my header
I anchored the menu on the view of my tableviewcontroller, beacause I want the navigationbar allways be visible. the solution to anchor it on the navigationbar solves the problem with the header-view, but covers the navigationbar.
Has anyone an idea how to solve this problem? Why are the cells painted correctly?
You should probably not interfere directly with the internal view hierarchy of UITableView. Apple is free to order a table view's subviews as they see fit (and change it in future releases).
Instead, place the table view and your menu view into a common container view and make the latter the main view of your view controller. That way, you can be certain that your menu view will always be above the table view.
I changed my design, but now I do not get touch-events in my table.
But when I add this method - I see, that I'm touching the tableviewcontroller...
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(#"ShieldingViewController received touch");
[self.buttonMenu shieldingViewTouched];
}
Here is what I changed:
- (void)viewDidLoad
{
[super viewDidLoad];
CGRect viewFrame = self.view.frame;
viewFrame.origin.y = 0;
UIView *rootView = [[UIView alloc] initWithFrame:viewFrame];
rootView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
// Setup the table view
UITableView *newTableView = [[UITableView alloc] initWithFrame:viewFrame style:self.tableView.style];
newTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
newTableView.backgroundColor = [UIColor darkGrayColor];
UIView *menuLayerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 500)];
self.tableView = newTableView;
[rootView addSubview:self.tableView];
[rootView addSubview: menuLayerView];
self.view = rootView;
[[CustomNavigationController instance] setCurrentViewForMenu: menuLayerView];
[[CustomNavigationController instance] showMenuInNavigationBarForController:self];
[newTableView release];
[menuLayerView release];
[rootView release];
}

Resources