Search Display Controller result tableview cannot scroll in iOS 6 - ios

I'm encountering this weird bug regarding UISearchDisplayController's table view, which occurs only in iOS 6. I just created my tableview in a nib file and then programmatically added a search bar above it and a search display controller to filter data in the table view:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.mpSearchBar = [[MPSearchBar alloc] initWithFrame:CGRectMake(0, 0, 250, 44)];
self.mpSearchBar.placeholder =#"Card Search";
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.mpSearchBar contentsController:self];
self.searchController.delegate = self;
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
self.resultTableView.delegate = self;
self.resultTableView.dataSource = self;
[self.resultTableView reloadData];
}
When I first enter some query in the search bar, the search display controller filters the data and the controller's result table view works fine. However when I tap the clear button in the search bar and type something else, the result table view which contains the new set of filtered data can no long scrollable. What's weird is, when I try to log the frame and contentSize of the table view, the content size height is larger than the frame height, as it's supposed to be:
- (void)searchDisplayController:(UISearchDisplayController *)controller willShowSearchResultsTableView:(UITableView *)tableView {
tableView.scrollIndicatorInsets = UIEdgeInsetsZero;
tableView.contentInset = UIEdgeInsetsZero;
[tableView hideEmptySeparators];
if (IOS_EQUAL_OR_NEWER_THAN_7){
tableView.separatorInset = UIEdgeInsetsZero;
}
NSLog(#"Frame height %f, Content height %f", tableView.frameHeight, tableView.contentSize.height);
}
And this is what I get from the log:
Frame height 504.000000, Content height 1402.000000
This happens only when I test on iOS 6 devices and I have no clue how to debug this issue.
Please suggest and thanks.

Turns out this is a (not well) known issue of UISearchController's table view in iOS 6. My temporary solution is to get the contentSize from willShowSearchResultsTableView and programmatically set it to the table view in viewDidLayoutSubviews:
- (void) viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
if ([self.searchController isActive]){
// fix wrong content size due to search bar glitch in iOS 6
self.searchController.searchResultsTableView.contentSize = newContentSize;
}
}
Hope this helps anyone who encounters the same problem as mine.

Related

Tableview in scrollview not showing

I was trying to implement a view like twitter's iOS app. The view controller contains a scroll view can scroll horizontally, in each page of the scrollview, there is a tableview. For simplicity I just created two UITableView, and add them inside two UIView containers, because besides tableView, I also have some view to show, so the tableView and all other views are added as subViews of the viewContainer for each page.
The view hierarchy is like this:
UIViewController
--view
--scrollView
--view1
--tableView1
--someOtherViews
--view2
--tableView2
--someOtherViews
In the viewDidLoad methods, I implemented something like this:
-(void)viewDidLoad
{
//Some other setup...
scrollView = [[UIScrollView alloc]initWithFrame(0,y0,self.view.frame.size.width,self.view.frame.size.height-offset)];
scrollView.pageEnabled = YES;
scrollView.contentSize = CGSizeMake(self.view.frame.size.width * 2, self.view.frame.size.height - offset);
[self.view addSubView:scrollView];
view1 = [[UIView alloc]initWithFrame:CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height-offset)];
tableView1 = [[UITableView alloc]initWithFrame:CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height-offset) style:UITableViewStyleGrouped];
tableView1.delegate = self;
tableView1.dataSource = self;
//other setup...
[view1 addSubView:tableView1];
[scrollView addSubView:view1];
view2 = [[UIView alloc]initWithFrame:CGRectMake(self.view.frame.size.width,0,self.view.frame.size.width,self.view.frame.size.height-offset)];
tableView2 = [[UITableView alloc]initWithFrame:CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height-offset) style:UITableViewStyleGrouped];
tableView2.delegate = self;
tableView2.dataSource = self;
//other setup...
[view2 addSubView:tableView2];
[scrollView addSubView:view2];
}
For test purpose, I populate the same datasource for both tables. The problem is if I only add one tableView container (for instance view1, which includes tableView1) as the subView of the scrollView, the view shows perfect, one can page to second page, which is blank, and the view controller can be load and show. The same for the second one.
However, if I use the code above, which adds both view containers as the subView of the scrollView, the app would crash when load this view controller. However, if I add the second view container (view2 or view1), but in the view container, I am not adding tableView as its subView, but has other subViews, it works perfectly.
So I figured the problem probably comes from two tableViews. However, I have tried to debug this for a few hours, and still no luck. Anyone can help me?
Thanks!!
I think it is something with you UITableViewDelegate or DataSource methods.
Probably it is the reason you crash.
-Suggestion:
try to make your UITableViews as an iVar and in dataSource methods
specify the tableView you want
like:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
{
if(tableView == _tableView1)
return _table1DataSource.count;
else
return _table2DataSource.count;
}
try to do it for other methods.

UITableView doesn't respond to scroll when parent frame is repositioned

I'm building something similar to the Twitter composition panel in their mobile app. The top half of the view has a text area while the bottom half is a table view of images. You can scroll the table view up and it'll push the top view offscreen and only then you can scroll up and down the table view. What I have done is place my table view in a wrapper view and I change the frame of this to move both the tableview and the top view up and down (using a UIPanGestureRecognizer). The problem I have is once the wrapper view has moved up from its original position, only the section of the tableview which was originally visible can be scrolled. The previously offscreen part cannot scroll. Events are still bubbling up a couple view above.
Code below:
CGRect frame = self.tableView.frame;
frame.size.height = self.superview.frame.size.height;
[self.tableView setFrame:frame];
self.tableView.dataSource = dataSourceDelegate;
self.tableView.delegate = dataSourceDelegate;
self.tableView.index = index;
self.panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
self.panGesture.minimumNumberOfTouches = 1.0;
self.panGesture.delegate = self;
self.panGesture.maximumNumberOfTouches = 1;
self.panGesture.delaysTouchesBegan =YES;
self.panGesture.cancelsTouchesInView = YES;
[self.tableView reloadData];
[self.tableView addGestureRecognizer:self.panGesture];
It was a sizing issue for the table view. Although it appeared to be sized correctly, it was not which meant the content size was incorrect and therefore why the scroll didn't function as expected.

UISearchBar hides view in iOS 7

When I initiate a search on UISearchBar which is a child off a UITableView, any other view except the UITableView becomes hidden. This issue only happens on iOS 7. And I dont have any specific code which hides the other views.
To come to the solution I first had to figure out the issue.
When text is input into the UISearchBar, it creates a UITableView which sits on top of the parent view.
To show the hidden parent view, the UITableView created must be offset and re sized to fit within a smaller area.
(void)searchDisplayController:(UISearchDisplayController *)controller didShowSearchResultsTableView:(UITableView *)tableView {
// The tableView the search tableView replaces
CGRect f = self.mainTableView.frame;
CGRect s = self.searchDisplayController.searchBar.frame;
CGRect updatedFrame = CGRectMake(f.origin.x,
f.origin.y + s.size.height,
f.size.width,
f.size.height - s.size.height);
tableView.frame = updatedFrame;
}
Try to add this in the viewDidLoad for the popover UIViewController:
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;

UISearchBar above UICollectionView, how can I get it working with only item in the collection?

I have a UICollectionView that contains a grid of objects. Above it, in a UICollectionView sectionHeader I have a UISearchBar. I want the search bar to be hidden when the view loads. I try to do it with the following code:
- (void)viewDidLoad
{
[super viewDidLoad];
// 44 = height of search bar.
[self.collectionView setContentOffset:CGPointMake(0, 44) animated:YES];
}
This works when the collectionView contains many objects, when the scrollView have scrollIndicators. But when I e.g. only have one item this doesn't work, the searchBar is always visible. I wonder which approach is the best for achieving my goal, display the UISearchBar when the user scrolls down?
Any suggestions?
If you want to display UISearchBar even user scrolling down down then you can do this by:
-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
UISearchBar *tempSearchBar = searchDisplayController.preSetSearchBar;
CGRect rect = tempSearchBar.frame;
rect.origin.y = MIN(0, scrollView.contentOffset.y);
tempsearchBar.frame = rect;
}
And if you want to hide it then you only need to use:
[scrollView alwaysBounceVertical:YES]; // allows always bounce to vertical
It is the default behave if UIScrollbar So by setting value it pretends to collection view that it has some more height then view.
From reference:
If this property is set to YES and bounces is YES, vertical dragging
is allowed even if the content is smaller than the bounds of the
scroll view. The default value is NO.
I think you have this problem because of your content collectionView size. Try to increase it before you set contentOffset:
- (void)viewDidLoad
{
[super viewDidLoad];
self.collectionView.contentSize = CGSizeMake(self.view.frame.size.width, self.view.frame.size.height);
[self.collectionView setContentOffset:CGPointMake(0, 44) animated:YES];
}
You can hide your header view by setting it's size to zero
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
if (headerIsActive == NO)
return CGSizeMake(0, 0);
else
return CGSizeMake(768, 44);
}

Where do you set the a UITableView's height or frame? AwakeFromNib?

I have a tableview in my app that I built in a NIB where I set the height via the Size Inspector to 68.
I also do the following in my code.
- (void) viewDidAppear:(BOOL)animated
{
self.tableView.frame = CGRectMake(0,0,320,68);
self.tableView.scrollEnabled = NO;
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (void)awakeFromNib
{
[self.tableView setBackgroundColor:[UIColor clearColor]];
self.tableView.rowHeight = 68;
}
When I run the app in the simulator or iPhone it looks fine, as the table is only 68px tall. If I close the app (go to the home screen) and reopen it the table is no longer only 68px tall, but it takes up the entire screen.
I can't seem to make it stay 68px all the time?
Besides my question above is there a method (awakeFromNib, ViewDidAppear, etc...) where you should always and only set the size or position of objects?
Use this method to set the height,
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 68;
}
Put your code into viewWillApper, that may work!
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.tableView.frame = CGRectMake(0,0,320,68);
self.tableView.scrollEnabled = NO;
[self.tableView setBackgroundColor:[UIColor clearColor]];
self.tableView.rowHeight = 68;
}
Found my own solution. The solution per Apple is that if you are using a UITableView and other subviews then don't use a uitbalviewcontroller, as the tableview will always try to use the entire screen. The solution is to use a uiview as the base with a uiviewcontroller then put a uitableview in the uiview and give the uiviewcontroller the delegate methods it needs to manage the tableview.
So just remember, if you don't want a full height uitableview then don't use a uitableviewcontroller with menubar.

Resources