insertRowsAtIndexPaths or reloadData doesn't respond - ios

Here is my code. And yesterday it works just fine. But this morning, it doesn't work.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
RSDrug *drug = [[RSDrug alloc]init];
[drugArray insertObject:drug atIndex:0];
NSIndexPath *ip = [NSIndexPath indexPathForRow:1 inSection:0];
[tableView insertRowsAtIndexPaths:#[ip] withRowAnimation:UITableViewRowAnimationAutomatic];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return drugArray.count + 1;
}
I have tried to add some code like beginUpdates/endUpdates, or I delete insertRowsAtIndexPaths, just use reloadData.
But same result. When the app runs to insertRowsAtIndexPaths or reloadData, it stuck, no response.
So I need some help. How to solve this?
Found the problem..........A stupid mistake
There are two UITextFields in the added cell, and they all have the same leftView, my code is like this:
UIImageView *leftImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"img"]];
field_1.leftView = leftImage;
field_2.leftView = leftImage;
I never know that I can't reuse the leftView. If I set the leftImage to field1, I can't set it to field2 anymore.
When I changed to this, it works again.
field_1.leftView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"img"]];
field_2.leftView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"img"]];

Try this sequence...
NSMutableArray *indexPaths=[[NSMutableArray alloc]init];
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tableView beginUpdates];
RSDrug *drug = [[RSDrug alloc]init];
[drugArray insertObject:drug atIndex:0];
if (indexPath.row == 0) {
[indexPaths removeAllObjects];
[indexPaths addObject:[NSIndexPath indexPathForRow:indexPath.row++ inSection:0]]; // here inserting row index=1;
[tableViewMenuList insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
}
[tableView endUpdates];
}

Have you tried this?
RSDrug *drug = [[RSDrug alloc]init];
[drugArray insertObject:drug atIndex:0];
[tableView beginUpdates];
// indexpath inserted is with the index 0 same with the `insertObject: `
NSIndexPath *ip = [NSIndexPath indexPathForRow:0 inSection:0];
[tableView insertRowsAtIndexPaths:#[ip] withRowAnimation:UITableViewRowAnimationAutomatic];
//here is what i use to do instead of #[]
//[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:ip] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];
EDIT
Your code are working fine. i tested it. here..
Code:
Output:
Log:
Check the tested code above if you have omitted something.
I think the problem is the delegates of your table, make sure that your table have the delegate for both UITableViewDataSource & UITableViewDelegate.
Hope this is helpful.. Cheers.. :)

Related

UITableView scrollToRowAtIndexPath:atScrollPosition:animated: lag my app seriously

I have a tableview. It will receive mess of data from server. Every time tableview receive data I wanna it show the latest one at bottom.I called scrollToRowAtIndexPath:atScrollPosition:animated: but it lag my app i can do nothing else in my screen when scroll to bottom of tableview.
Here is my main code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"tableViewCell";
DLtestCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
NSDictionary* dict = arr[indexPath.row];
cell.myLabel.attributedText = dict[#"content"];
[cell.myImageview sd_setImageWithURL:dict[#"imageUrl"] placeholderImage:[UIImage imageNamed:#"transparentPlaceHolder"]];
return cell;
}
and here is scrolling to the bottom main code
- (void)reloadTableView
{
dispatch_async(dispatch_get_main_queue(), ^{
NSIndexPath *lastRow = [NSIndexPath indexPathForRow:row inSection:0];
[self.tableView insertRowsAtIndexPaths:#[lastRow] withRowAnimation:UITableViewRowAnimationLeft];
});
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:row inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:NO];
}
You should use scrollToRowAtIndexPath method.
And in viewWillAppear write below code.
[theTableView reloadData];
NSIndexPath* ip = [NSIndexPath indexPathForRow:rowNumber inSection:sectionNumberHere];
[theTableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:NO];
here 'rowNumber' is the row number in the data source you want to scroll to.
or you can calculate 'rowNumber' as follows:
int lastRowNumber = [tableView numberOfRowsInSection:0] - 1;
and pass this lastRowNumber to indexPathForRow.
NOTE : numberOfRowsInSection returns row count, not the last row number (which is row count - 1).

UITableview Insert/Delete

I am having one number of section base tableview in that plus button which will add new item in tableview.
While i try add or delete the section from tableview and reload that tableview it will blink old record many times and then add or delete the section. Here is the code.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SymbolTableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectIndexPath containsObject:[NSNumber numberWithInt:(int)indexPath.section]])
{
[selectSymbol removeObject:cell.lblsymbol.text];
[selectIndexPath removeObject:[NSNumber numberWithInt:(int)indexPath.section]];
}
else
{
NSString *strr = cell.lblsymbol.text;
[selectSymbol addObject:strr];
[selectIndexPath addObject:[NSNumber numberWithInt:(int)indexPath.section]];
}
[tblDetail reloadData];
}
what is the issue?
try following code it may helps you
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath
{
SymbolTableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectIndexPath containsObject:[NSNumber numberWithInt:(int)indexPath.section]])
{
[tblDetail beginUpdates];
[selectSymbol removeObject:cell.lblsymbol.text];
[selectIndexPath removeObject:[NSNumber numberWithInt:(int)indexPath.section]];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
else
{
NSString *strr = cell.lblsymbol.text;
[tblDetail beginUpdates];
[selectSymbol addObject:strr];
[selectIndexPath addObject:[NSNumber numberWithInt:(int)indexPath.section]];
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
}
You can reload cell which you removed/added
You will not reload all table.
Try the following code please
[self.tableView deleteRowsAtIndexPaths:#[ indexPath ] withRowAnimation:UITableViewRowAnimationFade];
or
[self.tableView insertRowsAtIndexPaths:#[ indexPath ] withRowAnimation:UITableViewRowAnimationFade];
for inserting row in tableview
- (void)insertNewObject:(id)sender
{
if (!arrayForTableContent) {
arrayForTableContent = [[NSMutableArray alloc] init];
}
NSInteger count = [arrayForTableContent count];
NSString *strTobeAdded = [NSString stringWithFormat:#"%d",count+1];
[arrayForTableContent insertObject:strTobeAdded atIndex:count];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:count inSection:0];
[self.tableViewForScreen insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
I'm not writing all the code nor test it in the debugger, but I will give you an advice of how to proper implement this. Let's say you have a datasource, like this:
NSMutableArray *data = #[#"First", #"Second", #"Third"];
Datasource: In numberOfRowsInSection, you return data.count; in cellForRowAtIndexPath, you will configure the cell with the respective index from the array;
Delegate: In didSelectRowAtIndexPath, remove the object from the data array, say you will need something like this: [data removeObjectAtIndex(indexPath.row)]; then call reloadData on the table view. The table view will smoothly return now just two items.

UITableView insert row at top crashes

I'm trying to insert a row at the top of UITableView, but it crashes in the last line where I declare the endUpdating. This is the code I'm using and I'm using a button outside the table to insert row.
[comments insertObject:comment atIndex:0];
[self.commentsTableView beginUpdates];
NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.commentsTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.commentsTableView endUpdates]; //here crashes with "assertion failure"
I know I can just do insert in array and reload, but I want to do it with animation.
Thank you in advance.
This is my cell for row method
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"CommentCell";
// Similar to UITableViewCell, but
ListingCommentTableViewCell *cell = (ListingCommentTableViewCell *)[theTableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[ListingCommentTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.commenterLabel.text = [[comments objectAtIndex:indexPath.row] objectForKey:#"user"];
[cell.commenterLabel sizeToFit];
cell.commentLabel.text = [[comments objectAtIndex:indexPath.row] objectForKey:#"text"];
[cell.commentLabel sizeToFit];
cell.lineView.frame = CGRectMake(5 , cell.commentLabel.frame.origin.y + cell.commentLabel.frame.size.height+ 5, cell.frame.size.width-20, 1);
cell.dateLabel.text = [Utils formatCommentDate:[[comments objectAtIndex:indexPath.row] objectForKey:#"createdOn"]];
return cell;
}
THis is my cell height method
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
int height = [Utils findHeightForText:[[comments objectAtIndex:indexPath.row] objectForKey:#"teksti"] havingWidth:screenWidth - 40 andFont:[UIFont fontWithName:#"Ubuntu" size:14]];
height += 25;
return height + 5;
}
and my number of rows method
- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section
{
return [comments count];
}
This is how I insert objects to UITableView with animation.
-(void)updateMethod {
[self.commentsTableView beginUpdates];
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:0];
NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[comments insertObjects:[NSArray arrayWithObjects:comment, nil] atIndexes:indexSet];
[self.commentsTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.commentsTableView endUpdates];
}
You should check numberOfRowsInSection and be sure it reflect your comments.count
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return comments.count;
}
Also all UI updates must be done on the main thread, if you call your update method in different thread there is a change you can see that error.
You should update data source array inside animation block:
[self.commentsTableView beginUpdates];
[comments insertObject:comment atIndex:0];
NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.commentsTableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.commentsTableView endUpdates];

Push row to top in UItableview in iOS

I have uitableview and it has 1 button "TOP" in each row. I want to when user click on this button, this row has been push on top in Uitableview ( with animation). Can i reuse BVReorderTableView to do that? How can i do that? Thanks much
i am assuming your -cellForRowAtIndexPath loads cell contents from an array such as the one i named arrObjects which:
is an NSMutableArray object
has many NSString objects
something like:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//...
[cell.textLabel setText:[arrObjects objectAtIndex:indexPath.row]];
UIButton *btnUp = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btnUp setFrame:CGRectMake(0, 0, 30, 30)];
//[btnUp setTag:100];
[btnUp setTitle:#"\u261D" forState:UIControlStateNormal];
[btnUp addTarget:self
action:#selector(moveToTop:)
forControlEvents:UIControlEventTouchUpInside];
[cell setAccessoryView:btnUp];
return cell;
}
- (void)moveToTop:(UIButton *)sender
{
UITableViewCell *cell = (UITableViewCell *)sender.superview; //iOS6 prior
//UITableViewCell *cell = (UITableViewCell *)sender.superview.superview; //iOS7
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
//uncomment lines for safety, incase indexPath ever comes nil... prevent the crash
//if (indexPath == nil) {
// return;
//}
//1. move and animate row to top
[self.tableView moveRowAtIndexPath:[NSIndexPath indexPathForItem:indexPath.row
inSection:indexPath.section]
toIndexPath:[NSIndexPath indexPathForItem:0
inSection:indexPath.section]];
//2. make appropriate changes to the datasource
//so that it reflects logically and is not just an aestehtical change
//PRE-NOTE:
//arrObjects is an object of a category on NSMutableArray
//with a custom instance method named -moveObjectFromIndexPath:toIndex:
//uncomment the following line when you are ready with the category
//[arrObjects moveObjectFromIndex:indexPath.row toIndex:0];
}
the category is easy to create, follow:
http://www.icab.de/blog/2009/11/15/moving-objects-within-an-nsmutablearray/
other links to try:
http://adeem.me/blog/2009/05/29/iphone-sdk-tutorial-add-delete-reorder-uitableview-row/
http://learn-iphone-app-development.com/2011/01/31/tables-part-iii-%E2%80%94-re-ordering-moving-cells-and-swipe-to-delete/
have you tried
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath;
you can use animations if you want so..
You can easy do that like this:
[self.tableView setContentOffset:CGPointMake(0, 0) animated:YES];
or:
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES];
or:
[self.tableView scrollRectToVisible:CGRectMake(0.f, 0.f, CGRectGetWidth(self.tableView.frame), CGRectGetHeight(self.tableView.frame)) animated:YES];
Edit
Sorry, I misunderstood what you meant.
You should do that like this:
[tableView moveRowAtIndexPath:indexPath toIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
If you want to tableView scroll to the top immediately after move the cell, you can try the above code.
Edit
// A more detailed description
- (void)buttonHandle:(UIButton *)sender {
// Assuming button is added directly on the cell.
UITableViewCell *cell = (UITableViewCell *)sender.superview;
NSIndexPath *indexPath = [tableView indexPathForCell:cell];
[tableView moveRowAtIndexPath:indexPath toIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
}

Add cell/data to the top of UITableView

I'm trying to create a simple chat application for iOS. It currently looks like this:
I want to change the order that the messages is displayed, i.e. display the latest message over the older messages. My current implementation looks like this:
// Datasource for the tableView
messages = [[NSMutableArray alloc] init];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
[...]
// messageTextView is a contentView subView.
messageTextView.text = [messages objectAtIndex:indexPath.row];
[...]
- (IBAction)sendMessage:(id)sender
{
[messages addObject:messageField.text];
messageField.text = #"";
[self.tableView reloadData];
/*
I have tried the implementation below, but I always got an exception.
[self.tableView beginUpdates];
NSIndexPath *path1 = [NSIndexPath indexPathForRow:1 inSection:0];
NSArray * indexArray = [NSArray arrayWithObjects:path1,nil];
[self.tableView insertRowsAtIndexPaths:indexArray
withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
*/
}
Any tips on how to do this would be great.
Thanks.
Simple you need to insert the new UITableViewCell at the 0 index. Also modify your Datasource otherwise your app will crash. Below I show how to modify your UITableView. Modifying your datasource is easy.
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[tableView beginUpdates];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
[tableView endUpdates];
What you are essentially doing here is inserting the new chat message cell at the 0th index position. You could use a nice animation effect to make it appear or fade in.
There are various animations that you can use here-
UITableViewRowAnimationBottom
UITableViewRowAnimationFade
UITableViewRowAnimationMiddle
UITableViewRowAnimationNone
UITableViewRowAnimationRight
UITableViewRowAnimationTop
You can try.
[messages insertObject:messageField.text atIndex:0];
instead of [messages addObject:messageField.text];.
Swift Solution
Define array like this
var arrMessage = [AnyObject]()
and Button Action
#IBAction func btnSendMessageTapped(sender: AnyObject) {
arrMessage.insert(txtTypeMessage.text!, atIndex: 0)
txtTypeMessage.text = ""
self.tblMessage.reloadData()
}

Resources