I'm implementing in my PFQueryTableViewController ( Use Parse.com ) the works Swipe to Delete . When I go to perform the action of cancellation of the cell gives me this error and the app crashes.
Unigo 10/08/2013 15:40:50.683 [ 29142 : a0b ] User Online : between
Unigo 10/08/2013 15:40:54.495 [ 29142 : a0b ] * Assertion failure in
- [ UITableView _endCellAnimationsWithContext : ] , / SourceCache/UIKit_Sim/UIKit-2903.2/UITableView.m 1330 Unigo 10/08/2013
15:40:54.499 [ 29142 : a0b ] * Terminating app two to uncaught
exception ' NSInternalInconsistencyException ' , reason : 'Invalid
update : invalid number of rows in section 0 . The number of rows
contained in an existing section after the update ( 5 ) must be equal
to the number of rows contained in That section before the update ( 5
) , plus or minus the number of rows inserted or deleted from That
section (0 inserted , 1 deleted ) and plus or minus the number of rows
moved into or out of That section (0 moved in , 0 moved out). '
Can you help me figure out where I'm wrong ?
#implementation FFEsami
#synthesize FFNewLabelEsameInAttesa,FFViewEsameInAttesaAvviso,clock,ShowPanel,ArrayMutable;
-(id)initWithCoder:(NSCoder *)FFaDecoder {
self = [super initWithCoder:FFaDecoder];
if (self) {
self.parseClassName = FF_ESAMI_CLASS;
self.pullToRefreshEnabled = YES;
}
return self;
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
[self SetGraphSectionView];
[self queryForTable];
self.tableView.allowsSelectionDuringEditing = YES;
self.tableView.allowsMultipleSelectionDuringEditing = YES;
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
[self.navigationItem.leftBarButtonItem setTintColor:[UIColor whiteColor]];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
[self loadObjects];
}
#pragma mark - Parse
- (void)objectsDidLoad:(NSError *)error {
[super objectsDidLoad:error];
// This method is called every time objects are loaded from Parse via the PFQuery
}
- (void)objectsWillLoad {
[super objectsWillLoad];
// This method is called before a PFQuery is fired to get more objects
}
- (PFQuery *)queryForTable {
PFQuery *FFQueryPerTableView = [PFQuery queryWithClassName:FF_ESAMI_CLASS ];
[FFQueryPerTableView whereKey: FF_ESAMI_USER equalTo: [PFUser currentUser]];
[FFQueryPerTableView orderByDescending:FF_ESAMI_DATA_STRING];
if ([self.objects count] == 0) {
}
return FFQueryPerTableView;
}
-(void)SetGraphSectionView {
FFViewEsameInAttesaAvviso =[[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 50)] ;
FFNewLabelEsameInAttesa = [[UILabel alloc]initWithFrame:CGRectMake(60, -1, 200, 50)];
FFNewLabelEsameInAttesa.numberOfLines = 2;
FFNewLabelEsameInAttesa.textAlignment = NSTextAlignmentLeft;
FFNewLabelEsameInAttesa.textAlignment = NSTextAlignmentLeft;
FFNewLabelEsameInAttesa.lineBreakMode = NSLineBreakByTruncatingTail;
clock = [[UIImageView alloc] initWithFrame:CGRectMake(17, 11, 25, 25)];
// ShowPanel = [[UIImageView alloc] initWithFrame:CGRectMake(280, 27, 20, 20)];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 50.0;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
if(section==0){
PFQuery *query = [PFQuery queryWithClassName:FF_ESAMI_CLASS];
[query whereKey:FF_ESAMI_USER equalTo:[PFUser currentUser]];
[query whereKey:FF_ESAMI_STATUS equalTo:[NSNumber numberWithBool:YES]];
[query orderByAscending:FF_ESAMI_DATA_STRING];
[query getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!object) {
NSString *titolo = [NSString stringWithFormat:#"Nessun esame imminente"];
FFNewLabelEsameInAttesa.text = titolo;
FFNewLabelEsameInAttesa.font = [UIFont fontWithName:#"HelveticaNeue" size:13];
FFNewLabelEsameInAttesa.textColor = [UIColor grayColor];
FFNewLabelEsameInAttesa.numberOfLines = 2;
FFViewEsameInAttesaAvviso.backgroundColor = [UIColor clearColor];
clock.image= [UIImage imageNamed:#"FFIMG_InAttesa"];
} else {
NSString *titolo = [NSString stringWithFormat:#"%#", [object objectForKey:FF_ESAMI_TITOLO]];
FFNewLabelEsameInAttesa.text = titolo;
FFNewLabelEsameInAttesa.font = [UIFont fontWithName:#"HelveticaNeue" size:13];
FFNewLabelEsameInAttesa.textColor = [UIColor whiteColor];
FFViewEsameInAttesaAvviso.backgroundColor = [UIColor colorWithRed:(203/255.0) green:(162/255.0) blue:(86/255.0) alpha:(0.90)];
clock.image= [UIImage imageNamed:#"FFIMG_InAttesaBianco"]; }
}];
ShowPanel.image= [UIImage imageNamed:#"FFDownView"];
[FFViewEsameInAttesaAvviso addSubview:FFNewLabelEsameInAttesa];
[FFViewEsameInAttesaAvviso addSubview:clock];
[FFViewEsameInAttesaAvviso addSubview:ShowPanel];
}
return FFViewEsameInAttesaAvviso;
}
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 0;
}
- (FFCustomListaEsamiCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
FFCustomListaEsamiCell *cell = (FFCustomListaEsamiCell * )[self.tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if (!cell) {
cell = [[FFCustomListaEsamiCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
NSString *text = [object objectForKey:FF_ESAMI_TITOLO];
cell.FFTitoloEsameLabel.numberOfLines = 2;
cell.FFTitoloEsameLabel.text = text;
NSDateFormatter *FFDataFormattata = [[NSDateFormatter alloc] init];
[FFDataFormattata setDateFormat:FF_DATE_FORMATTER];
cell.FFDataEsameLabel.text = [NSString stringWithFormat: #"%#",[FFDataFormattata stringFromDate:[object objectForKey:FF_ESAMI_DATA_STRING]]];
PFObject *rowObject = [self.objects objectAtIndex:indexPath.row];
if([[rowObject objectForKey:FF_ESAMI_STATUS] boolValue])
{
//DATO CONVALIDATO
cell.last.image = [UIImage imageNamed:#"FFIMG_InAttesa"];
/*UIImage *btn = [UIImage imageNamed:#"FF_ChechOk"];
[cell.FFInserisciConvalida setImage:btn forState:UIControlStateNormal];
[cell.FFInserisciConvalida addTarget:self
action:#selector(FFConvalidaDato)
forControlEvents:UIControlEventTouchUpInside];
[cell.FFAltreAzioni addTarget:self
action:#selector(ActionSheetForStateInAttesa)
forControlEvents:UIControlEventTouchUpInside];*/
} else {
//DATO NON CONVALIDATO
//UIImage *btn = [UIImage imageNamed:#"FFIMG_ClockTAG"];
/* [cell.FFInserisciConvalida setImage:btn forState:UIControlStateNormal];
[cell.FFInserisciConvalida addTarget:self
action:#selector(FFMettiInAttesa)
forControlEvents:UIControlEventTouchUpInside];
[cell.FFAltreAzioni addTarget:self
action:#selector(ActionSheetForStateConvalidato)
forControlEvents:UIControlEventTouchUpInside];*/
}
return cell;
}
/*
// Override if you need to change the ordering of objects in the table.
- (PFObject *)objectAtIndex:(NSIndexPath *)indexPath {
return [objects objectAtIndex:indexPath.row];
}
*/
/*
// Override to customize the look of the cell that allows the user to load the next page of objects.
// The default implementation is a UITableViewCellStyleDefault cell with simple labels.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForNextPageAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"NextPage";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.text = #"Load more...";
return cell;
}
*/
#pragma mark - Table view data source
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
PFObject *object = [self.objects objectAtIndex:indexPath.row];
[object deleteInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
[self loadObjects];
}];[tableView reloadRowsAtIndexPaths:[tableView indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationFade];
// [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
}
#end
You have this code:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 0;
}
which is telling the table to have 0 cells in it after the update when the table is expecting 4. If you are using static cells in the storyboard then you should not implement the numberOfRowsInSection function.
If you remove that code then you should have no problems.
EDIT:
Or if you do want the numberOfRowsInSection function then you need to hook up a datasource to the tableview. This would allow you to return the count of the datasource. Then, when you delete a row you would remove the corresponding object in your datasource so that the count is 1 less than it previously was.
Related
So i have been trying for a little while now to create a table view with expandable sections and one non expandable section. One of the expandable sections should have 3 text fields inside them in which you can edit the test inside the text field. I was able to get that working bt the moment you collapse the section and expand it again the textfield suddenly duplicates itself above and sometimes swaps itself out with the above cell. Ihavent been able to figure out why or how to make it not do that.
The idea is when the user enters text in the field and selects enter the text is stored into an array.
the code:
- (void)viewDidLoad{
[super viewDidLoad];
if (!expandedSections){
expandedSections = [[NSMutableIndexSet alloc] init];
}
manualSensorName = [[NSMutableArray alloc]initWithObjects: #"Sensor",#"",#"2",#"T", nil];
}
- (void)didReceiveMemoryWarning{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Expanding
- (BOOL)tableView:(UITableView *)tableView canCollapseSection:(NSInteger)section{
if (section>0) return YES;
return NO;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if ([self tableView:tableView canCollapseSection:section])
{
if ([expandedSections containsIndex:section])
{
return 5; // return rows when expanded
}
return 1; // only top row showing
}
// Return the number of rows in the section.
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
if ([self tableView:tableView canCollapseSection:indexPath.section]){
if (!indexPath.row){
// first row
cell.textLabel.text = #"Expandable"; // only top row showing
if ([expandedSections containsIndex:indexPath.section])
{
UIImageView *arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrowUP.png"]];
cell.accessoryView = arrow;
}
else
{
UIImageView *arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrowDOWN.png"]];
cell.accessoryView = arrow;
}
}
else {
if (indexPath.row == 1){
NSString *flightNumText = [manualSensorName objectAtIndex:indexPath.row];
cell.textLabel.text = flightNumText;
}
else if (indexPath.row == 2){
txtManualSensor = [[UITextField alloc] initWithFrame:CGRectMake(180, 5, 120, 30)];
txtManualSensor.placeholder = #"Select";
txtManualSensor.delegate = self;
txtManualSensor.autocorrectionType = UITextAutocorrectionTypeNo;
txtManualSensor.backgroundColor = [UIColor whiteColor];
[txtManualSensor setBorderStyle:UITextBorderStyleBezel];
[txtManualSensor setTextAlignment:NSTextAlignmentCenter];
[txtManualSensor setReturnKeyType:UIReturnKeyDone];
// UITextField *playerTextField = [[UITextField alloc] initWithFrame:CGRectMake(180, 5, 120, 30)];
// playerTextField.adjustsFontSizeToFitWidth = YES;
// playerTextField.textColor = [UIColor blackColor];
// playerTextField.placeholder = #"SAMPLE";
// playerTextField.tag = 200;
// playerTextField.delegate = self;
// [cell.contentView addSubview:playerTextField];
cell.textLabel.text = #"Sensor Name";
[cell addSubview:txtManualSensor];
}
else if (indexPath.row == 3){
cell.textLabel.text = #"Some Detail";
cell.accessoryView = nil;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
}
}
else {
cell.accessoryView = nil;
cell.textLabel.text = #"Normal Cell";
}
return cell;
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
[manualSensorName replaceObjectAtIndex:2 withObject:textField.text];
return YES;
}
-(BOOL) textFieldShouldReturn:(UITextField *)textField{
[textField resignFirstResponder];
return YES;
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if ([self tableView:tableView canCollapseSection:indexPath.section]){
if (!indexPath.row){
[tableView beginUpdates];
// only first row toggles exapand/collapse
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSInteger section = indexPath.section;
BOOL currentlyExpanded = [expandedSections containsIndex:section];
NSInteger rows;
NSMutableArray *tmpArray = [NSMutableArray array];
if (currentlyExpanded) {
rows = [self tableView:tableView numberOfRowsInSection:section];
[expandedSections removeIndex:section];
}
else {
[expandedSections addIndex:section];
rows = [self tableView:tableView numberOfRowsInSection:section];
}
for (int i=1; i<rows; i++) {
NSIndexPath *tmpIndexPath = [NSIndexPath indexPathForRow:i inSection:section];
[tmpArray addObject:tmpIndexPath];
}
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (currentlyExpanded) {
UIImageView *arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrowDOWN.png"]];
[tableView deleteRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationFade];
cell.accessoryView = arrow;
}
else {
UIImageView *arrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrowUP.png"]];
[tableView insertRowsAtIndexPaths:tmpArray
withRowAnimation:UITableViewRowAnimationFade];
cell.accessoryView = arrow;
}
NSLog(#"tableview row is %ld in section %ld",(long)indexPath.row,(long)indexPath.section);
[tableView endUpdates];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog(#"selected row is %ld in section %ld",(long)indexPath.row,(long)indexPath.section);
if (indexPath.row == 1) {
// update text fields in cell table view
}
}
}
It may be as simple as replacing UITableViewRowAnimationTop by UITableViewRowAnimationFade:
When changing indexes in didSelectRowAtIndexPath, UITableViewCells change physical location (remember that the UITableView is a UIScrollView), and the scroller can't keep track of what your intent is.
UITableViewRowAnimationTop attempts to adjust the scrolling location, but fails.
Other design considerations:
Do not mix the model (the array of data to be displayed) with your view model (the UI displaying the model). In didSelectRowAtIndexPath, you should first re-order your model, then apply it to the cells
Consider not changing indexes on the fly: you may prefer a model that actually reflects the view structure, i.e. a tree.
Have you noticed you are not respecting - (void)tableView:(UITableView *)tableView and sometimes using self tableView:tableView or self.customTableView in the same method? You should use the tableView passed to you.
what I am trying to do is inserting data from Core Data inside UITableView everything is going to be fine except one trick if there is no data inside Core Data I only display a label message that said no data is inserted yet I already made many researches about this topic and how to implemented.
I found this
iOS Programming 101: Implementing Pull-to-Refresh and Handling Empty Table which not a complete tutorial and also i search on stack for some examples i just found How can I call numberOfSectionsInTableView multiple times?
here is my full implementation of code:
- (IBAction)refresh:(id)sender {
[self getAllReservationHistory];
[sender endRefreshing];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
EntryCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
ReservationEntity *reservationEntry = [self.fetchedResultController objectAtIndexPath:indexPath];
[cell configureCellForEntry:reservationEntry];
return cell;
}
-(NSFetchRequest *) entryListFetchRequest {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:#"Reservations"];
[fetchRequest setFetchLimit:10];
[self.tableView reloadData];
fetchRequest.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"reservationID" ascending:NO]];
return fetchRequest;
}
// this method is used to fetch the data //
-(NSFetchedResultsController *) fetchedResultController {
if(_fetchedResultController != nil)
return _fetchedResultController;
CoreData *coreDataStack = [CoreData defaultStack];
NSFetchRequest *fechtRequest = [self entryListFetchRequest];
_fetchedResultController = [[NSFetchedResultsController alloc] initWithFetchRequest:fechtRequest managedObjectContext:coreDataStack.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
_fetchedResultController.delegate = self;
return _fetchedResultController;
}
//- (CGFloat)tableView:(UITableView *)tableView
//heightForFooterInSection:(NSInteger)section {
// //differ between your sections or if you
// //have only on section return a static value
// return 50;
//}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"details"])
{
UITableViewCell *cell = sender;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
UINavigationController *naviagationController = segue.destinationViewController;
DetailedHistoryViewController *detailedHisotryViewController = (DetailedHistoryViewController *) naviagationController.topViewController;
detailedHisotryViewController.entry = [self.fetchedResultController objectAtIndexPath:indexPath];
}
}
-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
switch (type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:#[newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
if ([self.tableView numberOfRowsInSection:0] > 10) {
[self.tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
break;
default:
break;
}
}
/*****************************************************************************************/
- (void)viewDidLoad {
[super viewDidLoad];
[self.fetchedResultController performFetch:nil];
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
if (section == tableView.numberOfSections - 1) {
return [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
}
return nil;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
if (section == tableView.numberOfSections - 1) {
return 1;
}
return 0;
}
//
//- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
// if(footerView == nil) {
// footerView = [[UIView alloc] init];
// UIButton *button = [UIButton buttonWithType:UIButtonTypeContactAdd];
// button.layer.cornerRadius = (button.frame.size.width + button.frame.size.height)/ 2.0f;
// [button setBackgroundColor:[UIColor colorWithRed:234.0/255.0 green:76.0/255.0 blue:136.0/255.0 alpha:1.0f]];
// //the button should be as big as a table view cell
// [button setFrame:CGRectMake(300, 0, 50, 50)];
//
// //set title, font size and font color
//// [button setTitle:#"+" forState:UIControlStateNormal];
// [button.titleLabel setFont:[UIFont boldSystemFontOfSize:20]];
// [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
//
// //set action of the button
// [button addTarget:self action:#selector(AddReservation)
// forControlEvents:UIControlEventTouchUpInside];
//
// //add the button to the view
// [footerView addSubview:button];
// }
//
// //return the view for the footer
// return footerView;
//}
//-(void) AddReservation {
// NSLog(#"Bla");
//}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
CoreData *ch = [CoreData defaultStack];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:#"Reservations" inManagedObjectContext:ch.managedObjectContext]];
[request setIncludesSubentities:NO]; //Omit subentities. Default is YES (i.e. include subentities)
NSError *err;
NSUInteger count = [ch countForFetchRequest:request error:&err];
NSLog(#"%lu",(unsigned long)count);
if(count != 0)
{
return self.fetchedResultController.sections.count;
// return 10;
}
UILabel *messageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height)];
messageLabel.text = #"No data is currently available. Please pull down to refresh.";
messageLabel.textColor = [UIColor blackColor];
messageLabel.numberOfLines = 0;
messageLabel.textAlignment = NSTextAlignmentCenter;
messageLabel.font = [UIFont fontWithName:#"Palatino-Italic" size:20];
[messageLabel sizeToFit];
self.tableView.backgroundView = messageLabel;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
id< NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultController sections][section];
return [sectionInfo numberOfObjects];
// return 10;
}
Full Description:
Here is in details what I am trying to do is :
If there is no data inside the core data the UITableView display a label message " that there is no data" or whatever the message is and
After inserting the first reservation this label message should disappear and displaying the reservation data
Thanks in advance
In your numberOfSectionsInTableView after your if condition
if(count != 0)
{
return self.fetchedResultController.sections.count;
// return 10;
}
else {
return 1;
}
and in your numberOfRowsInTableView return 1 similarly
and in cellForRowAtIndexPath check if
id< NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultController sections][section];
if([sectionInfo objects]>0)
{// display cell
}
else
{
UITableViewCell *cell = [tableView dequeueCellUsingResusableIdentifier:#"cell" atIndexPath:indexPath];
UILabel *label;
if(!cell)
{
cell = [[UITableviewCell alloc]initWithCellIdentifier:#"cell"];
label =[UILabel alloc]initWithFrame:CGRectMake(0,0,100,50)];
}
label.text = #"No data is currently available. Please pull down to refresh.";
}
}
I was trying to create a custom viewForHeaderInSection for my tableview.Tableview itself
works fine, but for some reason, compiler skips,
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{}
Delegate method, and I tried what is written on the reference , and this .But for some reason it just doesn't read these methods. Obviously, I am doing something wrong. If someone can point my mistake out, I would appreciate. Thank you in advance.
#import "TableViewController.h"
#interface TableViewController ()
#end
#implementation TableViewController
#synthesize settingTableView,audioPlayer,labelSwitch,descriptiveSwitch,autoPlaySwitch;;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.settingTableView.tableFooterView = [[UIView alloc]init];
self.settingTableView.scrollEnabled = NO;
settings = #{#"Animation Sets" : #[#"Set1",#"Set2",#"Set3"],#"Settings" : #[#"Label",#"Sound",#"Autoplay"]};
values = [[settings allKeys]sortedArrayUsingSelector:#selector(localizedStandardCompare:)];
[settingTableView setRowHeight:44];
[settingTableView reloadData];
}
-(void)close:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
[self.delegate closeView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [values count];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [values objectAtIndex:section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSString *sectionTitle = [values objectAtIndex:section];
NSArray *sectionValue = [settings objectForKey:sectionTitle];
return [sectionValue count];
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
CGRect frame = tableView.frame;
NSString *value = [values objectAtIndex:section];
UILabel *title = [[UILabel alloc]init];
UIView *headerView = [[UIView alloc]init];
//if (section == 0 && section == 1) {
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
title.frame = CGRectMake(10,10,150,30);
}
else
{
title.frame = CGRectMake(10,5,100,30);
}
title.backgroundColor = [UIColor clearColor];
title.text = value;
headerView.frame = CGRectMake(0,0,frame.size.width,frame.size.height);
headerView.backgroundColor = [UIColor clearColor];
[headerView addSubview:title];
[headerView setBackgroundColor:[UIColor blueColor]];
//}
return headerView;
[settingTableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = nil;
static NSString *MyCellIdentifier = #"Cell";
cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyCellIdentifier];
cell.textLabel.numberOfLines = 2;
cell.textLabel.font = [UIFont fontWithName:#"Helvetica" size:17.0];
NSString *sectionTitle = [values objectAtIndex:indexPath.section];
NSArray *sectionValue= [settings objectForKey:sectionTitle];
NSString *settingValues = [sectionValue objectAtIndex:indexPath.row];
cell.textLabel.text = settingValues;
return cell;
}
}
You need to make sure that the class that implements that delegate method is the delegate and dataSource of your table view.
I have a UITableView in which I need to programmatically select a cell if the data model says that the cell represents the selected choice in a list of items. I do this when I'm configuring the UITableViewCell:
if (group == self.theCase.assignedGroup) {
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
self.selectedIndexPath = indexPath;
} else {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
I am seeing very odd behavior with this. If the first row of the tableview is the one that should be selected, the cell doesn't highlight its background properly. However, if the second row is the one that should be selected, it works as it's supposed to (screenshots at the end).
UPDATE: It could have something to do with the fact that I am loading data for the table asynchronously, and while the data is loading I show a different kind of cell with a progress indicator in that first row. Here's the table view data source code that's handling this:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
if (self.hasMorePages) {
return self.groups.count + 1;
}
return self.groups.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
if (indexPath.row < self.groups.count) {
cell = [tableView dequeueReusableCellWithIdentifier:#"DSAssignCell" forIndexPath:indexPath];
[self configureCell:cell forRowAtIndexPath:indexPath];
} else {
cell = [tableView dequeueReusableCellWithIdentifier:#"DSLoadingCell" forIndexPath:indexPath];
[self configureLoadingCell:cell forRowAtIndexPath:indexPath];
}
return cell;
}
- (void)configureCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
{
DSGroup *group = self.groups[indexPath.row];
if (group == self.theCase.assignedGroup) {
[self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
self.selectedIndexPath = indexPath;
} else {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
cell.textLabel.text = group.name;
cell.tag = kDataCellTag;
}
- (void)configureLoadingCell:(UITableViewCell *)cell
forRowAtIndexPath:(NSIndexPath *)indexPath
{
UIActivityIndicatorView *activityIndicator;
if ([cell viewWithTag:kActivityIndicatorTag]) {
activityIndicator = (UIActivityIndicatorView *)[cell viewWithTag:kActivityIndicatorTag];
} else {
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.center = cell.center;
activityIndicator.tag = kActivityIndicatorTag;
[cell.contentView addSubview:activityIndicator];
}
[activityIndicator startAnimating];
cell.tag = kLoadingCellTag;
}
UPDATE As requested, here is the code that handles the asynchronous loading of the group & agent data from the web service:
- (void)viewDidLoad
{
[super viewDidLoad];
[self resetData];
[self loadData];
}
- (void)resetData
{
self.currentPage = 0;
self.hasMorePages = YES;
self.groups = [[NSMutableArray alloc] initWithCapacity:kGroupsPerPage];
self.agents = [[NSMutableArray alloc] initWithCapacity:kAgentsPerPage];
}
- (void)loadData
{
if (self.showingGroups) {
[DSGroup fetchGroupsOnPage:self.currentPage + 1 perPage:kGroupsPerPage success:^(NSArray *groups, NSDictionary *links, NSNumber *totalEntries) {
[self.groups addObjectsFromArray:groups];
[self didLoadDataPage:(links[#"next"] != [NSNull null])];
} failure:^(NSError *error) {
[self showAlert:#"Could not load groups. Please try again later." withError:error];
}];
} else {
[DSUser fetchUsersOnPage:self.currentPage + 1 perPage:kAgentsPerPage success:^(NSArray *users, NSDictionary *links, NSNumber *totalEntries) {
[self.agents addObjectsFromArray:users];
[self didLoadDataPage:(links[#"next"] != [NSNull null])];
} failure:^(NSError *error) {
[self showAlert:#"Could not load users. Please try again later." withError:error];
}];
}
}
- (void)didLoadDataPage:(BOOL)hasMorePages
{
self.hasMorePages = hasMorePages;
self.currentPage++;
[self.tableView reloadData];
}
Here's a screenshot of trying to select (and highlight) the first row, which is wrong (no gray background):
Here's a screenshot of trying to select (and highlight) the second row, which is correct:
Any idea what might be going on here?
I wasn't able to fix this using the built-in selection styles of UITableViewCell, but subclassing it and overriding setSelected:animated fixed it:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
self.contentView.backgroundColor = selected ? [UIColor grayColor] : [UIColor whiteColor];
}
I have a view with a tabBar at the bottom and a tableview. When a barButtonItem is pressed, the array that holds the data for the tableview changes.
With NSLogs, it is clear that the array is really changing, as the [NSArray count] displays different values. However, when I use [UITableview reloadData], the cells stay the same.
If I scroll a up a bit however and then scroll back down, whatever went offscreen gets updating. I'm guessing this is because when it goes offscreen it is dequeued and when it comes back it is redrawn with the new data. Is there a way to just have it redraw everything?
#import "TableViewController.h"
#interface TableViewController ()
#end
#implementation TableViewController
#synthesize listBar,selectedTab , linkTableView, barButton5, barButton4, barButton3, barButton2, barButton1, Lists, imageID, titleID, linkID, cells;
- (void)viewDidLoad
{
[super viewDidLoad];
linkTableView = [[UITableView alloc] init];
Lists = [[NSArray alloc] init];
imageID = [[NSMutableArray alloc] init];
titleID = [[NSMutableArray alloc] init];
linkID = [[NSMutableArray alloc] init];
linkTableView.delegate = self;
linkTableView.dataSource = self;
}
-(void)viewWillAppear:(BOOL)animated{
NSArray *barItems = [[NSArray alloc] initWithObjects:barButton1, barButton2, barButton3, barButton4, barButton5, nil];
listBar.selectedItem = [barItems objectAtIndex:selectedTab];
//when view will appear load data dependent on selectedTab
[self performSelector:#selector(updateTable)];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)tabBar:(UITabBar *)tabBar didSelectItem:(UITabBarItem *)item{
selectedTab = item.tag;
[self performSelector:#selector(updateTable)];
}
-(void)updateTable{
[imageID removeAllObjects];
[titleID removeAllObjects];
[linkID removeAllObjects];
//load from the xml file
RXMLElement *rxml = [RXMLElement elementFromXMLFile:#"Lists.xml"];
//makes an array from the list children
Lists = [rxml children:#"List"];
cells = [[Lists objectAtIndex:selectedTab] children:#"Cell"];
[rxml iterateElements:cells usingBlock:^(RXMLElement *cellElement) {
[imageID addObject:[cellElement child:#"ImageName"]];
[titleID addObject:[cellElement child:#"CellText" ]];
[linkID addObject:[cellElement child:#"Link" ]];
}];
NSLog(#"Count is %i", [cells count]);
[linkTableView reloadData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [cells count];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 60;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"LinkCell";
linkCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[linkCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSString *imageName = [NSString stringWithFormat:#"%#", [imageID objectAtIndex:indexPath.row]];
cell.image.image = [UIImage imageNamed:imageName];
NSString *labelText = [NSString stringWithFormat:#"%#", [titleID objectAtIndex:indexPath.row]];
cell.linkCellLabel.text = labelText;
return cell;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
#end
remove this line from your code:
linkTableView = [[UITableView alloc] init];
or any other initializers for your uitableview
and use this code to update the Sections
[self.tableView beginUpdates];
NSMutableIndexSet* index = [[NSMutableIndexSet alloc]init];
[index addIndex:0];
[self.tableView reloadSections:index withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];