Tableview is not visible on UIViewController - ios

UITableView is not visible on the UIViewController Class.
On Storyboard added a new UIViewController set to related SlideViewcontroller class to it, Add a new UITableView (tbl_Slide), set the datasource and delegate to UIViewController in storyboard for the added UITableView.
And also included the related datasource and delegate methods to the UIViewController class.
- (void)viewDidLoad {
[super viewDidLoad];
self.tbl_SlideMenu = [[UITableView alloc]
initWithFrame:CGRectMake(0, 80, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain];
self.tbl_SlideMenu.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
self.tbl_SlideMenu.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.tbl_SlideMenu.separatorColor = [UIColor lightGrayColor];
self.tbl_SlideMenu.dataSource=self;
self.tbl_SlideMenu.delegate=self;
[self.view addSubview:self.tbl_SlideMenu];
}
Since added the UITableView to the UIViewController for UIView, need not to induced above two lines of code
self.tbl_SlideMenu = [[UITableView alloc]
initWithFrame:CGRectMake(0, 80, self.view.frame.size.width,self.view.frame.size.height) style:UITableViewStylePlain];
[self.view addSubview:self.tbl_SlideMenu];
Once I included the allocation and added to subview its showing the data with tableview.
Once I removed allocation and frame added to subview is not visible.
So what is need of storyboard where I added UITableView to UIViewController for UIView (view default.) once Component added to storyboard and framed need not to allocate and frame in code.
Advance Thanks
Hope for best posible answers

If u added the tableview in storyboard there is no need to initialise the view components in the code in this case u don't need below lines as u mentioned
self.tbl_SlideMenu = [[UITableView alloc]
initWithFrame:CGRectMake(0, 80, self.view.frame.size.width,self.view.frame.size.height) style:UITableViewStylePlain];
however u need to create a outlet for your tableview to access the tableview in code that means as soon as view is loaded all your view components are initialised in your case tableview is initialised and u can ready to use it and also u don't need below lines of code if u set datasource and delegate in storyboard
self.tbl_SlideMenu.dataSource=self;
self.tbl_SlideMenu.delegate=self;
since u configured your tableview datasource and delegate and also added tableview to view controller's view there is no need of below line also
[self.view addSubview:self.tbl_SlideMenu];
and second way is as u mentioned creating the view in pure code, in this case u have to do all things by your self from initialising to adding the view component to controller's view as u mentioned like below
self.tbl_SlideMenu = [[UITableView alloc]
initWithFrame:CGRectMake(0, 80, self.view.frame.size.width, self.view.frame.size.height) style:UITableViewStylePlain]; //creating the tableview
self.tbl_SlideMenu.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
self.tbl_SlideMenu.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; //configuring the view
self.tbl_SlideMenu.separatorColor = [UIColor lightGrayColor];
self.tbl_SlideMenu.dataSource=self; //setting the datasource and delegate
self.tbl_SlideMenu.delegate=self;
[self.view addSubview:self.tbl_SlideMenu]; //adding it to tableview
hope u get this
Edit
it is working fine for me, i crossed checked it with some dummy values, for example as i mentioned , dragged and dropped a tableview, set its datasource and delegate to View Controller in storyboard and connected a outlet in ViewController.h file, like below,
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UITableView *tbl_SlideMenu;
#end
and in ViewController.m file
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.tbl_SlideMenu.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
self.tbl_SlideMenu.separatorColor = [UIColor lightGrayColor];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CELL"];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CELL"];
}
cell.textLabel.text = #"Hello";
return cell;
}
#end
and i got output showing the tableview with 5 "Hello" on each row

Related

iOS multiple viewcontrollers

I am new to iOS programming.
I have to implement a location search based on the third party map API, but I think I have messed up multiple view controllers.
Scenario:
I have a mapviewController for displaying the mapview. And I have a searchController for searchbar. There is a resultviewController property in searchController for display the search suggestions.
I have tried to add search VC as child VC to map VC, but once I click to the search bar it returns "Application tried to present modally an active controller".
So then I remove search VC from map VC & the search bar is not activated.
Therefore I want to ask how to handle these VCs, and avoid the case that map view covers the search bar and suggestion lists.
Thank you so much.
UPDATE:
I'm building a search bar in code. My aim is to build the following style in iOS.
like this http://i1.tietuku.com/cd4efa23d97af75ft.jpg
I pushed the map viewController to the navigation controller from menu.
[self.navigationController pushViewController:mapviewController animated:YES];
And trying to add a searchController to it.
- (void)viewDidLoad {
[super viewDidLoad];
_resultsTableController = [[UITableViewController alloc] init];
_searchController = [[UISearchController alloc] initWithSearchResultsController:self.resultsTableController];
_searchController.searchResultsUpdater = self;
[_searchController.searchBar sizeToFit];
_resultsTableController.tableView.tableHeaderView = _searchController.searchBar;
self.searchController.searchBar.delegate = self;
_resultsTableController.tableView.delegate = self;
_searchController.delegate = self;
_searchController.dimsBackgroundDuringPresentation = NO;
_searchController.searchBar.delegate = self;
mapView = [[BMKMapView alloc]initWithFrame:CGRectMake(0, kHeight(100), kScreen_Width , kScreen_Height-kHeight(100))];
[self addChildViewController:_searchController];
[self.view addSubview: _searchController.view];
[self.view addSubview:mapView];
}
for UISearchController you no need to add it as child view controller and and instant of using UITableViewController uses UITableView it make easy for you and
here below is code that is .m file
free to run that code and without uses storyboard.
#interface ViewController ()
{
UITableView *tableview;
UISearchController *searchcontroller;
NSMutableArray *array;}
#end
#implementation ViewController
(void)viewDidLoad
{
[super viewDidLoad];
array = [[NSMutableArray alloc]initWithObjects:#"one",#"two",#"three",#"four", nil];
tableview = [[UITableView alloc]initWithFrame:CGRectMake(0, 50, CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame)/2)];
[self.view addSubview:tableview];
tableview.dataSource = self;
tableview.delegate =self;
searchcontroller = [[UISearchController alloc]initWithSearchResultsController:nil]; // Create Reference of searchController
searchcontroller.searchResultsUpdater = self;
searchcontroller.searchBar.backgroundColor = [UIColor redColor];
searchcontroller.searchBar.barStyle = UIBarStyleBlack;
searchcontroller.searchBar.barTintColor = [UIColor whiteColor];
searchcontroller.dimsBackgroundDuringPresentation = false;
[searchcontroller.searchBar sizeToFit];
tableview.tableHeaderView = searchcontroller.searchBar;
MKMapView *mapview = [[MKMapView alloc]initWithFrame:CGRectMake(0, CGRectGetMaxY(tableview.frame), CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame)/2)];
[self.view addSubview:mapview];
}
(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController;
{
NSLog(#"update ");
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
// Default is 1 if not implemented
{
return 1;
}
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return array.count;
}
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
}
cell.textLabel.text = array[indexPath.row];
return cell;
}
According to me you should use only one view controller which has a map on it. Over the map you can simply add custom search view and on typing/ taping search you can show search results using UITableview with some dropping animation keeping some max frame fixed, And finally on taping any result remove this UITableView and show location of map. If time permits I will create a sample for you, cant give assurance but will try. Mean while you can also go through Maps reference may be helpful

UIView vs UITableCellView to show user posts

My app has a home screen where I show user posts loaded from the server. My problem is that I use UIView for each post, but it takes up a lot of space (also the user keeps on scrolling making it more memory consuming). Ex:
UIView* box=[[UIView alloc]initWithFrame:CGRectMake(0, postY, maxWidth, 500)];
[box setTag:(NSInteger)[post_id[i] integerValue]];
[box setBackgroundColor:[UIColor whiteColor]];
//Profile pic+++
UIImageView* profile_img=[[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)];
profile_img.layer.cornerRadius=profile_img.frame.size.width/2; //Make it round
profile_img.layer.masksToBounds=YES; //Make it round
profile_img.layer.borderWidth=0.5;
profile_img.layer.borderColor=[rgb(214, 222, 231) CGColor];
[box addSubview:profile_img];
And so on...
Does anyone know a better way of doing this? I tough of UITableCellView but it seems to be odd doing this task this way
I recommend you use a UITableViewController and then subclass UITableViewCell to create a custom cell for you to display the data. A UITableViewController instance contains a UITableView and you display the data by setting it in your custom UITableViewCell subclass. So basically, a UITableView contains various UITableViewCell and use the delegate methods to respond to events and actions on your table.
// YourCustomTableViewCell.h
#import <UIKit/UIKit.h>
#interface YourCustomTableViewCell : UITableViewCell
// Setup the properties for the cell, e.g
#property (strong, nonatomic) IBOutlet UIImageView *profileImageView; // Connect to outlet in storyboard file
#end
// YourCustomTableViewCell.m
#import "YourCustomTableViewCell.h"
#implementation YourCustomTableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.profileImageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)];
}
return self;
}
- (void)awakeFromNib
{
// Use this method to setup frames and sizes of your properties
self.profileImageView.layer.cornerRadius = profileImageView.frame.size.width/2; //Make it round
self.profileImageView.layer.masksToBounds = YES; //Make it round
self.profileImageView.layer.borderWidth=0.5;
self.profileImageView.layer.borderColor = [rgb(214, 222, 231) CGColor];
}
#end
// YourTableViewController.h
#import <UIKit/UIKit.h>
#interface YourTableViewController : UITableViewController
#end
// YourTableViewController.m
#import "YourTableViewController.h"
#import "YourCustomTableViewCell.h"
#interface YourTableViewController ()
#end
#implementation YourTableViewController
- (void)viewDidLoad
{
// Setup your data source for the table
self.tableView.dataSource = self;
// Setup other stuff after loading the view
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1; // Return the number of sections you want in the table view
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows for each section, in your case this would be something like this
return self.posts.count; // If your data is stored in an array
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"YourCustomCell";
YourCustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
if (!cell){
cell = [[YourCustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
// Configure the cell...
// Here you add the code to display the data in the cell e.g.
[cell.profileImageView setImage:yourImageToDisplay];
return cell;
}
#end
As the comment said, you'd better choose UITableView as the posts' container and inherit from UITableViewCell as your box view.
Detailedly speaking much more, suppose the class inherited from UITableViewCell named MyTableViewCell, and you treat its contentView as your UIView *box. After that, you could tell the UITableView to use your MyTableViewCell as the Cell by sending him registerClass:forCellReuseIdentifier:.
Then, you can get MyTableViewCell instance by sending UITableView the
dequeueReusableCellWithIdentifier:forIndexPath: message. After being bound data (telling him display what posts), this instance can be returned to UITableView, which will arrange everything for you. Besides, these usually should be done in the UITableView's dataSource method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath.

Reveal view when swiping a prototype table view cell

What I am trying to do is reveal a hidden menu when swiping on a UITableViewCell.
I have no idea how to do it, any guidance will be appreciated.
Here is an image so that you get an idea:
Image http://imageshack.com/a/img855/9134/j6k8.png
u can do it by using custom cell i give the ruff idea and sample code how to achieve this,
first create a new file objective-c, and name it as CustomCell subclass of UITableViewCell and in CustomCell.h file
i took some dummy views and labels
#import <UIKit/UIKit.h>
#interface CustomCell : UITableViewCell
{
}
#property (nonatomic, retain) UIView *optionsView; //this is your options to show when swiped
#property (nonatomic, retain) UIView *mainVIew; //this is your view by default present on top of options view
#property (nonatomic, retain) UILabel *messageLabel;
#property (nonatomic, retain) UILabel *optionsLabel;
#end
in CustomCell.m
#import "CustomCell.h"
#implementation CustomCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
//since we are not using the xib we hav to initilise hear
_optionsView = [[UIView alloc]init];
_mainVIew = [[UIView alloc]init];
_optionsView.backgroundColor = [UIColor greenColor];
_mainVIew.backgroundColor = [UIColor redColor];
_optionsView.alpha = 0.0f;
_mainVIew.alpha = 1.0f;
_messageLabel = [[UILabel alloc]init];
_optionsLabel = [[UILabel alloc] init];
[_optionsView addSubview:_optionsLabel]; //hear u can add image view or buttons to options view i just added the label
[_mainVIew addSubview:_messageLabel];
//add the gesture to main view
UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(whenSwiped:)];
swipeGesture.direction = UISwipeGestureRecognizerDirectionRight;
[_mainVIew addGestureRecognizer:swipeGesture];//add it to main view
UISwipeGestureRecognizer *swipeReverse = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:#selector(whenSwipedReversed:)];
swipeReverse.direction = UISwipeGestureRecognizerDirectionLeft;
[_optionsView addGestureRecognizer:swipeReverse]; //add it to options view so that user can swipe back
[self.contentView addSubview:_optionsView]; //first add the optionsVIew
[self.contentView addSubview:_mainVIew]; //then main view
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)layoutSubviews
{
[super layoutSubviews];
_optionsView.frame = self.bounds;
_mainVIew.frame = self.bounds;
_messageLabel.frame = _mainVIew.bounds;
_optionsLabel.frame = _optionsView.bounds;
_optionsView.alpha = 0.0f;
_mainVIew.alpha = 1.0f;
}
//handle swipe call backs in cell only and make a delegate to controller about the button actions of options view
- (void)whenSwiped:(id)sender
{
CGRect frameRect = _mainVIew.frame;
frameRect.origin.x = 300.0f;
[UIView animateWithDuration:0.5 animations:^{
_mainVIew.frame = frameRect;
_optionsView.alpha = 1.0f;
}];
}
- (void)whenSwipedReversed:(id)sender
{
CGRect frameRect = _mainVIew.frame;
frameRect.origin.x = 0.0f;
[UIView animateWithDuration:0.5 animations:^{
_mainVIew.frame = frameRect;
_optionsView.alpha = 0.0f;
}];
}
#end
in view controller import #import "CustomCell.h"
in datasource method of tableview
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *Cell = [tableView dequeueReusableCellWithIdentifier:#"CELL"];
if(Cell == nil)
{
Cell = [[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CELL"];
}
Cell.selectionStyle = UITableViewCellSelectionStyleNone;
Cell.optionsLabel.text = #"options";
Cell.messageLabel.text = #"swipe me";
return Cell;
}
above is example, hope this helps u .. :)
and comment if don't get
Here is some guidance:
Each UITableViewCell could have two views, one on top of the other. The top-most view is what is shown by default, and the bottom-most view is what you call the "hidden menu."
You will need to register a UISwipeGestureRecognizer in your storyboard that manages the table cells you are showing above. You will create an IBAction for that gesture recognizer in your custom UITableViewCell class. In that action, you will handle the swipes that occur and then displace the top-most view of the cell by your desire amount, up to a maximum displacement (in the x-direction).
If you need more than this, let me know and I'll provide more info. I can't tell from your original question just how experienced you are, e.g., do you know how to create UITableViews with custom UITableViewCells?
UPDATE:
Make sure that you are creating a XIB file that houses your custom UITableViewCell. Then you can easily add the UISwipeGestureRecognizer to the XIB, and connect it to an IBAction in your cell class. In your UIViewController, you will register the XIB with a reuse identifier and populate your UITableView this way.

Unrecognized selector sent to instance when adding a UITableView as SubView

When i've created a UITableView in the code en add it as a subview in the code it is all working fine. There is green tableview visible.
Example of the code i've created for that.
- (void)getOverviewTable
{
// Adding the TableView
OverviewTableViewController *overviewTableViewController = [[OverviewTableViewController alloc] init];
UITableView *overviewTableView = [[UITableView alloc] initWithFrame:(CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height))];
// Set the datasource and delegete will come here
[overviewTableView setBackgroundColor:[UIColor greenColor]];
[self.view addSubview:overviewTableView];
}
But after i've set the DataSource and the Delegete for the TableView i will receive a warning.
The code in total for reaching it is as follows:
- (void)getOverviewTable
{
// Adding the TableView
OverviewTableViewController *overviewTableViewController = [[OverviewTableViewController alloc] init];
UITableView *overviewTableView = [[UITableView alloc] initWithFrame:(CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height))];
// Set the datasource and delegete will come here
[overviewTableView setDataSource:overviewTableViewController];
[overviewTableView setDelegate:overviewTableViewController];
[overviewTableView setBackgroundColor:[UIColor greenColor]];
[self.view addSubview:overviewTableView];
}
The most of the time it is just an EXC_BAD_ACCESS error, but sometimes it shows me the following error.
[UITransitionView numberOfRowsInSection:]: unrecognized selector sent to instance
The 'OverViewTableViewController' is replaced by just an empty UITableViewController class but the error is still showing up.
(Point of the application is an fullscreen takeover which has to be swiped away to see the tableview underneath it)
Edit:
The function is called from the viewDidLoad function
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.view setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"bg.jpg"]]];
// Setting the home takeover
[self setHomeTakeOver];
// Wait one seconde before we load the tableview
[self getOverviewTable];
//[self performSelector:#selector(getOverviewTable) withObject:nil afterDelay:1.0];
}
What I think is you have your project ARC enabled and from your code segment what i understand is that overviewTableViewController is released through ARC as soon as it leaves the scope of the function getOverviewTable. So, better declare the overviewTableViewController in .h file(#property (nonatomic, strong) OverviewTableViewController *overviewTableViewController; ).
If you do this then the code will look like this
in .h file
#property (nonatomic, strong) OverviewTableViewController *overviewTableViewController;
//// I have strong reference rather than assign
in .m file
- (void)getOverviewTable
{
// Adding the TableView
overviewTableViewController = [[OverviewTableViewController alloc] init]; //// I have made overviewTableViewController as member variable.
UITableView *overviewTableView = [[UITableView alloc] initWithFrame:(CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height))];
// Set the datasource and delegete will come here
[overviewTableView setDataSource:overviewTableViewController];
[overviewTableView setDelegate:overviewTableViewController];
[overviewTableView setBackgroundColor:[UIColor greenColor]];
[self.view addSubview:overviewTableView];
[overviewTableView reloadData];
}
Also be sure that OverviewTableViewController has implemented the datasource methods like
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
Try this.
[overviewTableView setDataSource:self];
[overviewTableView setDelegate:self];
Also confirm to tableviewDelegate and datasource and implement following methods.
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier=#"CellIdentifier";
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell==nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
return cell;
}
You might have forgotten to implement this method.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
}
Try setting the table view controller's tableView property to overviewTableView. I don't know off hand if the UITableViewController must have that property set.
- (void)getOverviewTable
{
// Adding the TableView
OverviewTableViewController *overviewTableViewController = [[OverviewTableViewController alloc] init];
UITableView *overviewTableView = [[UITableView alloc] initWithFrame:(CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height))];
// Set the datasource and delegete will come here
[overviewTableView setDataSource:overviewTableViewController];
[overviewTableView setDelegate:overviewTableViewController];
//THIS IS THE NEW LINE
//a UITableViewController needs to know UITableView that it's managing
[overviewTableViewController setTableView:overviewTableView];
[overviewTableView setBackgroundColor:[UIColor greenColor]];
[self.view addSubview:overviewTableView];
}

UIButton inside UITableViewCell steals touch from UITableView

I have a problem similar to this one but answer provided there doesn't help much.
I have UITableView with some custom UITableViewCells, those cells have some nested custom UIViews and finally some UIButtons inside. The problem, as in question specified above, is that when I touch my button touch event won't populate to UITableView and it never scrolls.
Here's some code (it's just fastest way to reproduce, it's not my actual code):
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (strong, nonatomic) IBOutlet UITableView * tableView;
#end
#implementation ViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
{
self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0,
self.view.bounds.size.width,
self.view.bounds.size.height)
style:UITableViewStylePlain];
[self.view addSubview:self.tableView];
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
return self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell * cell = [[UITableViewCell alloc] init];
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
button.backgroundColor = [UIColor redColor];
button.frame = CGRectMake(0, 0, 50, 44);
[cell.contentView addSubview:button];
return cell;
}
#end
Red button in the only cell won't let table view to bounce scroll.
Can anyone help me a bit?
P.S. Don't pay attention to the stupidity of the code I've provided, I'm aware of all issues about it. I just provided it to show what the issue is all about. It's the conflict of buttonView and scrollView.
You can change the behaviour by overriding touchesShouldCancelInContentView: in the UITableView. For this to work you'll need to replace the table view with this subclass, either in loadView or in your xib file.
#interface AutoCancelTableView: UITableView
#end
#implementation AutoCancelTableView
//
// Overriding touchesShouldCanceInContentView changes the behaviour
// of button selection in a table view to act like cell selection -
// dragging while clicking a button will cancel the click and allow
// the scrolling to occur
//
- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
return YES;
}
#end
This is the standard behaviour of UIScrollView which tableviews use. The system doesn't know that you want to scroll until you move your finger, but by that time you have already "pressed" on the button and so it assumes that's what you want to do.
You can play with a couple of properties on your tableview's scrollview to change the behaviour, but you may find they negatively impact the feel of your cells and buttons because of added delays.
self.tableView.delaysContentTouches = YES;
delaysContentTouches
If the value of this property is YES, the scroll view delays handling the touch-down gesture until it can determine if scrolling is the intent...
and
self.tableView.canCancelContentTouches = YES
canCancelContentTouches
If the value of this property is YES and a view in the content has begun tracking a finger touching it, and if the user drags the finger enough to initiate a scroll, the view receives a touchesCancelled:withEvent: message and the scroll view handles the touch as a scroll.
Because all the above answers not working for me. I add a imageView on the button and make the imageView user interface YES, then add a tap gesture on the iamgeView. In the tap gesture related methods I put the button related methods in. so all is well..
may be hack. But it work well..
Below code works for me:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
cell = [tableView dequeueReusableCellWithIdentifier:#"cell_id"];
cell.userInteractionEnabled = YES;
if (cell == nil) {
cell = [[[CustomCell1 alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell_id"]autorelease];
}
[cell.button addTarget:self action:#selector(button_action) forControlEvents:UIControlEventTouchUpInside];}
-(void)button_action{NSLog(#"Hello!");}
This is my custom cell:
#import "CustomCell.h"
#implementation CustomCell
#synthesize button;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
button = [[UIButton alloc]init];
button =[UIColor redColor];
[self.contentView addSubview: button];
}
return self;}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect contentRect = self.contentView.bounds;
CGFloat boundsX = contentRect.origin.x;
CGRect frame;
frame= CGRectMake(boundsX+50 ,+15, 100, 100);
button = frame;}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{ [super setSelected:selected animated:animated];
// Configure the view for the selected state
}

Resources