UITableView is adding empty rows and disabling scrolling - ios

Utilizing the method of populating a UITableView from this answer, and setting the table to edit mode via:
tableView.editing = true;
And adding these methods:
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
}
I am seeing that a user can accidentally(or intentionally) double tab the ordering handle and insert an empty row. This will also kill the scrolling for the table view. Here is an image:
Between "Logs" and "Settings" there is an empty row. I have looped through all rows on the table view via the answers found here, and the empty rows are skipped over as if they don't exist.
I was able to remove the empty rows via [tableView reload] each time a row is moved, which unfortunately results in a kind of jarring snap. However, I haven't been able to re-enabled the scrolling. I am trying to avoid having to make the user close and redisplay the view.
Any one run across this issue and find a suitable work around?
EDIT:
Row deletion is irrelevant - this happens as a result of moving rows around
This is Xcode 6.1 on ios 8/7 - have also seen this Xcode 5.x -> ios 7/8.
We are targeting ipads, so not sure if this is an issue on iphone
Also, better description of how to reproduce:
double tap cell and hold on second tap for a second
drag cell up or down
Posted on Apple forums and submitted bug to Apple. Here was the example project I submitted to them (in which I was able to reproduce said issue):
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableData = [NSMutableArray arrayWithObjects:#"One",#"Two",#"Three",#"Four",#"Five",
#"One",#"Two",#"Three",#"Four",#"Five",
#"One",#"Two",#"Three",#"Four",#"Five",
#"One",#"Two",#"Three",#"Four",#"Five",
#"One",#"Two",#"Three",#"Four",#"Five",
#"One",#"Two",#"Three",#"Four",#"Five", nil];
self.tableView.editing = true;
[self.tableView setTableFooterView:[UIView new]];
self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
self.tableView.rowHeight = 20.0;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"ScrollingDisplayCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if( cell == nil )
{
cell = [[[UITableViewCellNoPadding alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease]; // MEMCHK: Autorelease so no ownership implications
cell.textLabel.font = [UIFont fontWithName:#"Courier New" size:17.0];
cell.textLabel.frame = cell.contentView.bounds;
}
// Configure the cell...
cell.textLabel.text = [self.tableData objectAtIndex:indexPath.row];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
NSString *stringToMove = self.tableData[sourceIndexPath.row];
[self.tableData removeObjectAtIndex:sourceIndexPath.row];
[self.tableData insertObject:stringToMove atIndex:destinationIndexPath.row];
}
And here is UITableViewCellNoPadding : UITableViewCell:
// https://stackoverflow.com/questions/3467288/center-align-text-in-uitableviewcell-problem
-(void)layoutSubviews
{
[super layoutSubviews];
self.textLabel.frame = CGRectMake(0, self.textLabel.frame.origin.y, self.frame.size.width, self.textLabel.frame.size.height);
}
NOTE: It was more difficult to reproduce here than in my own app

Since you specified that users should not be able to delete rows, I added editingStyleForRowAtIndexPath to always return UITableViewCellEditingStyleNone. Without this implementation, UITableViewCellEditingStyleDelete is returned by default.
With the implementation posted below, everything seems to behave well, and I've checked that all edits commit successfully to the table model.
I hope this helps!
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.tableModel = [NSMutableArray new];
for (int i = 0; i < 30; i++) {
[self addTableObject];
}
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.editing = true;
}
- (void) addTableObject
{
NSString *rowValue = [NSString stringWithFormat:#"%i", _tableModel.count+1];
[_tableModel addObject:rowValue];
}
#pragma mark - Table view delegate methods
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [_tableModel objectAtIndex:indexPath.row];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _tableModel.count;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
//Make change in data model
id selectedValue = [_tableModel objectAtIndex:sourceIndexPath.row];
[_tableModel removeObjectAtIndex:sourceIndexPath.row];
[_tableModel insertObject:selectedValue atIndex:destinationIndexPath.row];
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleNone;
}

Related

I have created a table view programmatically as follows-

- (void)viewDidLoad {
[super viewDidLoad];
menuArray=[[NSMutableArray alloc]initWithObjects:#"Address",#"Restaurants",#"Deals",#"Orders",#"Account",#"Address Book",#"Settings",#"Live Chat",#"Info",nil];
tableView=[[UITableView alloc]initWithFrame:CGRectMake(0, menuSubView.frame.size.height, self.view.frame.size.width-80, self.view.frame.size.height-menuSubView.frame.size.height)];
tableView.delegate=self;
tableView.dataSource=self;
[self.view addSubview:tableView];
}
and other methods as follows-
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return menuArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *reusableIdentifier=#"Cell4";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reusableIdentifier];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reusableIdentifier];
}
cell.textLabel.text=[menuArray objectAtIndex:indexPath.row];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 70;
}
However when I run the program i am able to see the table view as desired. But when I scroll through it, table's data disappear and only blank table view remains. Can anyone help me? Thanks in advance.
--> I appreciate above answer.
--> Please try this line in "cellForRowAtIndexPath" Method...!
--> Sometimes it happens. I have solved this issue with this line in past. I hope it's useful for you.
UITableViewCell *cell = [self.tblView dequeueReusableCellWithIdentifier:#"Cell4" forIndexPath:indexPath];

adding table cells to table in a specific section in iOS

Please if you are going to add the link of the documentation, please don't do that
I have a problem her and i don't know how to solve it and need a clear answer
I have build a table view from xcode UI and add 5 sections each section contains some cells except section2, what I want to do is to add cells to section2 in viewDidLoaded is that possible or not
this is the header file
#interface Menu : UITableViewController;
this is the implementation file
#implementation Menu
#synthesize drawerTableView;
- (void) viewDidLoad {
NSDictionary *object = [drawerTableView dataSource];
KhawaterDataManager *sharedManager = [KhawaterDataManager instance];
CategoriesResponse *categories = [sharedManager categories];
[categories printObject];
}
/*- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"%d", section);
switch (section) {
case 1:
return 5;
break;
}
return [tableView.dataSource[section] count];
}*/
/*- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
[cell setBackgroundColor:[UIColor colorWithRed:.8 green:.8 blue:1 alpha:1]];
cell.textLabel.text = #"hello";
return cell;
}*/
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)newIndexPath{
// my logic
}
#end
I think you are using static cells in your UITableView. What you can do is make use of dynamic tableview cells. You have to uncomment and use both methods to create your cell:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

Pass array of images from multiple UITableView selected cells

I am having such an issue right now. I have a UIViewController that has a UITableView, I have it set up so that when the UITableView is in editing mode it returns 3 - circles with the check marks. My UITableView has custom cells with in image and text. When I put the UITableView in edit mode, I am trying to pass an array of the images from multiple selected rows to a second view controller to use those images in a collection view, but I am just having a hard time passing the array of images. Any suggestions would be appreciated.
here is my TableView code:
-(void)didTapEditBUtton:(id)sender{
if ([self.ribbonTableView isEditing]) {
viewButton.hidden = YES;
headerLabel.hidden = NO;
[ribbonTableView setEditing:NO animated:YES];
[selectButton setTitle:#"select"];
}
else {
[selectButton setTitle:#"Cancel"];
// Turn on edit mode
headerLabel.hidden = YES;
viewButton.hidden = NO;
[ribbonTableView setEditing:YES animated:YES];
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection (NSInteger)section{
return [ribbonsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
RibbonCustomCell *cell = (RibbonCustomCell *) [ribbonTableView dequeueReusableCellWithIdentifier:#"RibbonDetail"];
if (cell != nil)
{
RibbonsInfo *ribbonsInfo = [ribbonsArray objectAtIndex:indexPath.row];
//NSLog(#"%#", ribbonsInfo);
//Ribbon Image
cell.ribbonImageView.image = ribbonsInfo.ribbonImage;
cell.ribbonLabel.text = ribbonsInfo.ribbonName;
}
return cell;
}
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return 3;
}
-(void)tableView:(UITableView *)tableView didSelectRowsAtIndexPath:(NSIndexPath *)indexPath{
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath{
}
You should take the property of NSMutableArray...
#property (nonatomic, strong) NSMutableArray *selectedImages;
- (void)viewDidLoad {
[super viewDidLoad];
self.selectedImages = [NSMutableArray new];
}
now when you select or deselect the cell the delegates are called -
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%#",indexPath);
RibbonsInfo *ribbonsInfo = [ribbonsArray objectAtIndex:indexPath.row];
[self.selectedImages addObject:ribbonsInfo.ribbonImage];
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%#",indexPath);
if (self.selectedImages.count > 0) {
[self.selectedImages removeObjectAtIndex:indexPath.row];
}
}
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{
return 3;
}
Now the selectedImages array contains the selected cell images and you can pass this array.
Hope it will solve your problem.

Can't reorder rows in UITableView

I have encountered an issue when trying to reorder rows in UITableView.
I have the function tableView:moveRowAtIndexPath:toIndexPath: triggered, but fromIndexPath is equal to toIndexPath (i.e. source == destination).
I saw the same issue here: uitableview re-order won't work, source always equal to destination
But the solution was - to use different library. That is not a variant for me.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
//fromIndexPath is equal to toIndexPath, so nothing is exchaned
[self.table_data exchangeObjectAtIndex:fromIndexPath.row withObjectAtIndex:toIndexPath.row];
}
My table is in editable mode, I have canMoveRowAtIndexPath: returning YES. My it does not help.
How come? What am I doing wrong?
The problem was in custom pan gesture recognizer.
It somehow was in conflict with rows drag-drop behavior
Setting myGestureRecognizer.cancelsTouchesInView = NO; fixed the issue
Try this. It works.
- (void)viewDidLoad {
[super viewDidLoad];
arr = [NSMutableArray arrayWithObjects:#"First",#"Second",#"Third",#"Fourth", nil];
self.tableView.editing = YES;
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return arr.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellIdentifier" forIndexPath:indexPath];
UILabel *label = (UILabel *)[cell.contentView viewWithTag:100];
[label setText:[arr objectAtIndex:indexPath.row]];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
NSString *stringToMove = arr[sourceIndexPath.row];
[arr removeObjectAtIndex:sourceIndexPath.row];
[arr insertObject:stringToMove atIndex:destinationIndexPath.row];
}
Check the screenshot -

UITableview tries to scrollToTop but doesn't (Indicator tries to go up, strange.) - video

So I've been working on a UITableView and I can't hit the statusbar to scroll up, however it seems like it's trying to scroll up, but it doesn't.
Here you can see a video of it (Decided to use mp4 instead of GIF since it was so laggy)
http://i.gyazo.com/4c7be7437116e420411ac879b6d0d784.mp4
If you look at the video you can see that you indicator on the right side tries to scroll up but doesn't ? Has anyone experienced something similar ?
I'm also using ECSlidingViewController
My current code
Called upon -viewDidLoad
-(void)setTableViewStuff {
[self.myTableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
[self.myTableView registerNib:[UINib nibWithNibName:#"YouTubeTableCell" bundle:nil] forCellReuseIdentifier:CellIdentifier];
self.myScrollView.scrollsToTop = NO;
self.myTableView.scrollsToTop = YES;
}
Table View Code
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 256;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return myVideoTitles.count;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
YouTubeTableCell *cell = (YouTubeTableCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
//cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
//cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if (indexPath.section == 0) {
NSString* thumbnailURL = myVideoThumbnails[indexPath.row];
[cell.myThumbnail setImageWithURL:[NSURL URLWithString:[thumbnailURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] placeholderImage:nil];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return NO;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
EDIT:
Found a solution to this!!, Apperiantely if you're using ECSlidingViewController you must have yourtableview.scrollstotop = NO; inside the "drawer"
Found a solution to this!!, Apperiantely if you're using ECSlidingViewController you must have yourtableview.scrollstotop = NO; inside the "drawer"

Resources