Inline date picker crashed on second attempt - ios

I have been struggling for this issue for two week now. but by the help of StackOverflow people I have came up with 95% successful implementation..
Here is my problem.. and now I could load my results with the picker cell [First most cell] when the date is selected.
Now I have another issue...when i run my application at first time, it is works as I expected..but when i tap the first most cell to pick a different date , then the application crashed..
Here is the log output...
below is my codes for the implementation
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSDictionary* reqFdate= [ScheduleView getRequestForDate];
if (reqFdate.count == 0) {
NSInteger numberOfRows = [self.persons count];
if ([self datePickerIsShown]){
numberOfRows++;
}
return numberOfRows;
}
else{
return reqFdate.count + 1;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
NSDate *today = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
// display in 12HR/24HR (i.e. 11:25PM or 23:25) format according to User Settings
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
NSString *currentTime = [dateFormatter stringFromDate:today];
NSDate *date=[dateFormatter dateFromString:currentTime];
if(indexPath.row==0){
VCPerson *person = self.persons[0];
cell = [self createPersonCell:person];
}
else if ([self datePickerIsShown] && (self.datePickerIndexPath.row == 1)){
// VCPerson *person = self.persons[indexPath.row -1];
cell = [self createPickerCell:date];
}
else{
cellForDatePickCell *cell = (cellForDatePickCell*)[self.tableView dequeueReusableCellWithIdentifier:kOtherCellIdentifier];
cell.delegate_Dtepick = self;
return cell;
}
if(indexPath.section!=0 && tapfirstCell) {
UITableViewCell *cell = (UITableViewCell*)[self.tableView dequeueReusableCellWithIdentifier:kOtherCellIdentifier forIndexPath:indexPath];
//cell.delegate_Dtepick = self;
NSDictionary *dictionary = [_dataArray objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"data"];
NSString *cellValue = [array objectAtIndex:indexPath.row];
cell.textLabel.text =cellValue;
}
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView beginUpdates];
if ([self datePickerIsShown] && (self.datePickerIndexPath.row - 1 == indexPath.row)){
[self hideExistingPicker];
// [self.tableView reloadData];
//[self viewDidLoad];
//call the service and take the results
NSString* selecteDate = [ScheduleView getDate];
NSString* prsonID =[LoginView getPersonID];
NSDictionary* parms = [NSDictionary dictionaryWithObjectsAndKeys:prsonID,#"caregiverPersonId",selecteDate,#"selectedDate", nil];
jsonpaser* jp = [[jsonpaser alloc]init];
[jp getWebServiceResponce:#"http://qa.vardle.com/Mobile/WebServices/AppointmentService.asmx/GetAppointments" :parms success:^(NSDictionary *responseObject)
{
requestsF_date = responseObject;
NSLog(#"RESPONSEFORDATE_IN DIDSELECT :%#",requestsF_date);
NSArray* indexpaths = [self getIndexPaths];
NSLog(#"indexPATHS %#",indexpaths);
[self.tableView reloadData];
}];
// cellForDatePickCell *cell = (cellForDatePickCell*)[self.tableView dequeueReusableCellWithIdentifier:kOtherCellIdentifier forIndexPath:indexPath];
// cell.delegate_Dtepick = self;
//tapfirstCell = true;
/*
cellForDatePickCell *cell=(cellForDatePickCell*)[tableView cellForRowAtIndexPath:indexPath];
if(![cell.textLabel.text isEqualToString:#"5/23/14"])
{
return;
}
*/
if (tapfirstCell==false) {
tapfirstCell = true;
}
else{
tapfirstCell = false;
}
}else {
NSIndexPath *newPickerIndexPath = [self calculateIndexPathForNewPicker:indexPath];
if ([self datePickerIsShown]){
[self hideExistingPicker];
}
[self showNewPickerAtIndex:newPickerIndexPath];
self.datePickerIndexPath = [NSIndexPath indexPathForRow:newPickerIndexPath.row + 1 inSection:0];
}
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
[self.tableView endUpdates];
}
please someone tell me where is the issue..why app is crashed when i try to pick a date second time..
please help

i have fix my issue... i didnt deleted the rows before i start to show the date picker again..
here is the full code
here what i did was : i use Inline Datepicker with the table view [date picker will show by selecting the first cell of the table view].according to the date selected from the picker, i am displaying my custom cells below the first cell.[because the first cell always there to pick a date from a date picker].
if someone want to do the same thing which i did i think my code will help you
thank you

Related

Buggy swipe to delete display on one more row after each delete

I'm having a weird issue on UITableView delete action since iOS 11.
Here's the relevant TableView code :
#implementation ChatMessageListViewController(TableView)
#pragma mark - table view datasource/delegate
- (NSArray<UITableViewRowAction *> *) tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(nonnull NSIndexPath *)indexPath{
NSMutableArray *rowActions = [NSMutableArray array];
UITableViewRowAction *delete = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:#"Delete" handler:^(UITableViewRowAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) {
[self deleteMessageAtIndexPath:indexPath];
}];
delete.backgroundColor = [UIColor redColor];
[rowActions addObject:delete];
return [rowActions copy];
}
- (void) deleteMessageAtIndexPath:(NSIndexPath *)indexPath {
NSString *threadID = [[self.messageArray objectAtIndex:indexPath.row] objectForKey:#"threadID"];
[self.tableView beginUpdates];
[self.messageArray removeObjectAtIndex:indexPath.row];
[self.tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self.tableView endUpdates];
#weakify(self);
[UIUtil showLoadingHudWithText:WELocalString(#"message_remove_thread_loading_text", #"Deleting...", #"删除中...")];
[[AsyncUtil sharedInstance] dispatch_background_network:^{
DBManager *db = [[DBManager alloc] init];
[db deletetableData:[NSString stringWithFormat:#"singleChat WHERE threadID = '%#' ",threadID] ];
[[MemChatThreadMessages sharedInstance] removeThread:threadID];
NSDictionary * result = [Network deleteChatThread:threadID forEmail:[WEUtil getEmail]];
[[AsyncUtil sharedInstance] dispatch_main:^{
[UIUtil hideLoadingHuds];
#strongify(self);
if(self == nil) return ;
if([result[#"result"] isEqualToString:#"success"]){
}else{
[UIUtil showErrorMessage:WELocalString(#"message_remove_thread_error", #"Cannot delete this thread", #"不能删除该会话!")];
}
[self.tableView reloadData];
}];
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.messageArray count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *messageInfo = [self.messageArray objectAtIndex:indexPath.row];
if ([(NSString *)[messageInfo objectForKey:#"isAnnouncement"] isEqualToString:#"1"]) {
return 80;
}else if ([[messageInfo objectForKey:#"chatTag"] isValidString]){
return 80;
}else if([self isSpecialMessage:messageInfo]){
return 80;
}else{
return 67;
}
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"message";
if(self.events == nil){
NSDictionary * d = [WEUtil getMyEventListCache];
self.events = [[NSMutableDictionary alloc] init];
for(NSDictionary * eventSummary in d[#"events"]){
NSString * eventID = eventSummary[#"eventid"];
[self.events setObject:eventSummary forKey:eventID];
}
}
UserMessageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[UserMessageTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
if(indexPath.row >= [self.messageArray count]){
TERMINATE_WITH_NIL_CELL;
}
NSDictionary *messageInfo = [self.messageArray objectAtIndex:indexPath.row];
if(![self isSpecialMessage:messageInfo]){
[cell configureCellWithMessageDict:messageInfo];
}else{
[cell configureCellWithNewMessageDict:messageInfo withEvents:self.events];
}
return cell;
}
#pragma mark - Navigation
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSDictionary *msgThreadDict = [self.messageArray objectAtIndex:indexPath.row];
if(![self isSpecialMessage:msgThreadDict]){
[self tableView:tableView didSelectNormalRowAtIndexPath:indexPath];
}else{
NSString * event = msgThreadDict[#"event"];
if([event isValidString]){
if([event isEqualToString:#"no_event_messages"]){
[UIUtil showErrorMessage:#"no event id"];
}else{
[BackendTracking trackingWithAction:#"open_special" withLabel:#"threads_list"];
SpecialTopicListViewController * special = [[SpecialTopicListViewController alloc] init];
special.tracking_src = #"tab";
[self.navigationController pushViewController:special animated:YES];
}
}
}
}
-(void) tableView:(UITableView *)tableView didSelectNormalRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *msgThreadDict = [self.messageArray objectAtIndex:indexPath.row];
NSString *threadID = [msgThreadDict objectForKey:#"threadID"];
NSString *jid = [msgThreadDict objectForKey:#"jid"];
[GATracking trackCategory:#"message" withAction:#"thread_list_item_click" withLabel:threadID];
[[MemChatThreadMessages sharedInstance] setCurrentThreadID:threadID];
PrivateMessageViewController * chatVC = [[PrivateMessageViewController alloc] init];
chatVC.threadID = threadID;
chatVC.targetJID = jid;
chatVC.targetName = [msgThreadDict objectForKey:#"name"];
chatVC.unreadMsgNumber = [[self.messageArray objectAtIndex:indexPath.row][#"unreadCnt"] integerValue];
if ([(NSString *)[msgThreadDict objectForKey:#"isGroup"] isEqualToString:#"1"]) {
chatVC.isGroup = YES;
}else{
chatVC.isGroup = NO;
}
chatVC.src = #"list";
WELogInfo(#"click message");
[self.navigationController pushViewController:chatVC animated:YES];
}
#end
With the update and the changes using those trailing swipe actions there is another View appended before each time I delete an entry (until it doesn't work anymore). I've tried disabling the full trail or implementing iOS 11 trailingSwipeActionsConfigurationForRowAtIndexPath but I can't resolve this issue so far.
Do you see something wrong in the code? The main controller code is in another file.
Try reloading after you delete, after this line
[self.tableView endUpdates];
I think you removed the data from messageArray but as you are not reloading just after that so table view count is still 2 and you are reloading inside the block which might be taking time.
And one more thing you already removing data from messageArray, and then removing from db, So if you fail to remove it from db you are showing its not removed but for user it will be removed, as its no longer in message array

Expand UITableViewCell with smooth animation

I am trying to Animate the transition of a UITableViewCell when its height is changed. For this I am using the following lines of code:
[meetingsTable beginUpdates];
[meetingsTable reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:changedRow inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
[meetingsTable endUpdates];
but it is not showing the row height change animation. It just displays the expanded cell. However, if I remove the line
[meetingsTable reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:changedRow inSection:0]] withRowAnimation:UITableViewRowAnimationNone];
it shows the expected animated height change but the cell is not reloaded. I have tried all the available UITableViewRowAnimationoptions but with no success. I have also tried
[meetingsTable reloadData];
but it is also not helpful.
Please suggest what can be the possible solution.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
BMeetingsTableCell *cell;
cell = [tableView dequeueReusableCellWithIdentifier:#"MEETINGS"];
if (!cell) {
cell = [[BMeetingsTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MEETINGS"];
}
[self customizeCell:cell atIndexPath:indexPath forTable:tableView];
return cell;
}
- (void)customizeCell:(BMeetingsTableCell *)cell atIndexPath:(NSIndexPath *)indexPath forTable:(UITableView*)tableView shouldReload:(BOOL)shouldReload{
NSDictionary *event;
if (isSearching) {
event = [NSDictionary dictionaryWithDictionary:[searchedData objectAtIndex:indexPath.row]];
}else if ([tableView isEqual:_activeMeetingsTable])
event = [NSDictionary dictionaryWithDictionary:[activeEvents objectAtIndex:indexPath.row]];
else if ([tableView isEqual:_completedMeetingTable])
event = [NSDictionary dictionaryWithDictionary:[completedEvents objectAtIndex:indexPath.row]];
NSArray *partArr;
UILabel *showTimeLbl = (UILabel *)[cell viewWithTag:9];
UIImageView *showNewMeetingIcon = (UIImageView *)[cell viewWithTag:8];
[showTimeLbl setHidden:YES];
[showNewMeetingIcon setHidden:YES];
cell.delegate = self;
cell.tag = indexPath.row;
NSMutableArray* foundConts = [[NSMutableArray alloc]init];
NSMutableArray *tempPartArr = [[NSMutableArray alloc]init];
for (NSDictionary *dict in [event valueForKey:#"users"]) {
[tempPartArr addObject:dict];
}
partArr = [NSArray arrayWithArray:tempPartArr];
if ([displayName length]==0) displayName = numberString;
NSDictionary *participant = [[NSDictionary alloc]initWithObjectsAndKeys:inviteStat, #"inviteStatus", displayName, #"displayName", nil];
[foundConts addObject:participant];
}
}
if ([allParticipants count]> indexPath.row) {
[allParticipants replaceObjectAtIndex:indexPath.row withObject:invitedConts];
}else
[allParticipants addObject:invitedConts];
if ([tableView isEqual:_meetingsTable] && selectedRow == indexPath.row) {
cell.participants = [NSArray arrayWithArray:foundConts];
[cell.contsTable setHidden:NO];
// [cell.arrowButton setSelected:YES];
[cell.userImage setImage:[UIImage imageNamed:#"expandedProfilePic.png"]];
}else{
[cell.userImage setImage:[UIImage imageNamed:#"ProfileImage.png"]];
[cell.contsTable setHidden:YES];
// [cell.arrowButton setSelected:NO];
}
[cell.tapProfileBtn addTarget:self action:#selector(expandDetails:) forControlEvents:UIControlEventTouchUpInside];
cell.tapProfileBtn.tag = indexPath.row;
[cell.title setText:[event valueForKey:#"subject"]];
NSString* location;
if ([[event valueForKey:#"address"] isKindOfClass:[NSNull class]]) {
location = #"";
}else
location = [event valueForKey:#"location"];
long long startDateMilliSec = [[event valueForKey:#"start_time_milliseconds"] longLongValue];
NSDate *capturedStartDate = [NSDate dateWithTimeIntervalSince1970:startDateMilliSec];
//
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateStyle:NSDateFormatterFullStyle];
NSDateComponents *comps1 = [[NSCalendar currentCalendar] components:NSYearCalendarUnit|NSHourCalendarUnit|NSMinuteCalendarUnit fromDate:capturedStartDate];
NSString *theYear = [NSString stringWithFormat:#", %ld", (long)comps1.year];
[dateFormatter setDoesRelativeDateFormatting:YES];
[dateFormatter setLocale:[NSLocale currentLocale]];
NSString *dateString = [dateFormatter stringFromDate:capturedStartDate];
if ([dateString isEqualToString:#"Today"]||[dateString isEqualToString:#"Tomorrow"]) {
}else{
[dateFormatter setDateFormat:#"dd MMMM yyyy"];
[dateFormatter setDoesRelativeDateFormatting:NO];
dateString = [dateFormatter stringFromDate:capturedStartDate];
}
NSString *amPM = (comps1.hour>=12)?#"PM":#"AM";
NSString *hourStr = [NSString stringWithFormat:#"%02d",(comps1.hour%12)];
dateString = [dateString stringByReplacingOccurrencesOfString:theYear withString:#""];
NSString *timeString = [NSString stringWithFormat:#"%#:%02d %#",hourStr, comps1.minute, amPM];
NSString *displayString = [NSString stringWithFormat:#"%# | %#",dateString, timeString];
[cell.date setText:[NSString stringWithFormat:#"%# | %#", displayString, location]];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row == selectedRow) {
NSDictionary* event = [activeEvents objectAtIndex:indexPath.row];
NSArray *contacts = [event valueForKey:#"users"];
int height = ([contacts count]*50)+70;
return height;
}
else return 50
}
- (IBAction)expandDetails:(id)sender{
UIButton *btn = (UIButton*)sender;
selectedRow = btn.tag;
BMeetingsTableCell *changedCell = (BMeetingsTableCell*)[_activeMeetingsTable cellForRowAtIndexPath:[NSIndexPath indexPathForRow:btn.tag inSection:0]];
[self customizeCell:changedCell atIndexPath:[NSIndexPath indexPathForRow:btn.tag inSection:0] forTable:_meetingsTable];
[_meetingsTable beginUpdates];
[_meetingsTable endUpdates];
}
You have to update the cell without reloading the table view.
I imagine you have your cell customization code in cellForRowAtIndexPath.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//dequeue cell
//customize cell at index path
return cell;
}
Move your customization into its own method that takes a cell.
- (void)customizeCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
//customize cell
}
Now when you need to update a cell you can do this...
- (void)rowWasChanged:(NSInteger)changedRow {
NSIndexPath *changedIndex = [NSIndexPath indexPathForRow:changedRow inSection:0];
UITableViewCell *changedCell = [self.meetingsTable cellForRowAtIndexPath:changedIndex];
[self customizeCell:changedCell atIndexPath:changedIndex];
[self.meetingsTable beginUpdates];
[self.meetingsTable endUpdates];
}
// Cell animation
if(sender.tag == 0) {
if(sender.on){
rowHeight1 = 250;
}else{
rowHeight1 = 55;
}
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:sender.tag inSection:0];
NSArray* rowsToReload = [NSArray arrayWithObjects:indexPath, nil];
[tblHealthQuestion reloadRowsAtIndexPaths:rowsToReload withRowAnimation:UITableViewRowAnimationAutomatic];
}
// for Section animation
NSRange range = NSMakeRange(senctionIndex, 1);//NSMakeRange(0, 1);
NSIndexSet *section = [NSIndexSet indexSetWithIndexesInRange:range];
[tblHealthQuestion reloadSections:section withRowAnimation:UITableViewRowAnimationAutomatic];
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation{
[self reloadSections:sections withRowAnimation:animation];
}

Using NSSortDescriptor to sort UITableview title with setDateFomat:#"dd.MMMM-EEEE

I have a title in UITableView with different dates with the formate of dd.MMMM-EEEE. How can I sort them according to time from old to new? Should I use NSSortDescriptor?
Here is my code:
#synthesize managedObjectContext, pictureListData;
#synthesize scroll;
-(IBAction)scrolldown:(id)sender{
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *today = [NSDate date];
NSInteger index = NSNotFound;
if ([pictureListData containsObject:today]) {
index = [pictureListData indexOfObject:today];
}
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionNone
animated:YES];
}
-(void)viewDidLoad{
NSSortDescriptor * sortDesc = [[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES];
[pictureListData sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
[self.tableView reloadData];
}
- (void)viewWillAppear:(BOOL)animated
{
// Repopulate the array with new table data
[self readDataForTable];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"dd.MMMM - EEEE"];
NSDate *today = [NSDate date];
[pictureListData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
Pictures *picture = (Pictures *)obj;
NSDate *date = [dateFormatter dateFromString:picture.title];
NSDateComponents *components = [cal components:NSDayCalendarUnit
fromDate:date
toDate:today
options:0];
if ([components day]==0) {
*stop = TRUE;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:idx inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionTop
animated:YES];
}
}];
}
// When the view reappears, read new data for table
// Grab data for table - this will be used whenever the list appears or reappears after an add/edit
- (void)readDataForTable
{
// Grab the data
pictureListData = [CoreDataHelper getObjectsForEntity:#"Pictures" withSortKey:#"title" andSortAscending:YES andContext:managedObjectContext];
// Force table refresh
[self.tableView reloadData];
}
#pragma mark - Actions
// Button to log out of app (dismiss the modal view!)
#pragma mark - Segue methods
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get a reference to our detail view
PictureListDetail *pld = (PictureListDetail *)[segue destinationViewController];
// Pass the managed object context to the destination view controller
pld.managedObjectContext = managedObjectContext;
// If we are editing a picture we need to pass some stuff, so check the segue title first
if ([[segue identifier] isEqualToString:#"EditPicture"])
{
// Get the row we selected to view
NSInteger selectedIndex = [[self.tableView indexPathForSelectedRow] row];
// Pass the picture object from the table that we want to view
pld.currentPicture = [pictureListData objectAtIndex:selectedIndex];
}
}
#pragma mark - Table view data source
// Return the number of sections in the table
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
// Return the number of rows in the section (the amount of items in our array)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [pictureListData count];
}
// Create / reuse a table cell and configure it for display
- (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];
}
// Get the core data object we need to use to populate this table cell
Pictures *currentCell = [pictureListData objectAtIndex:indexPath.row];
// Fill in the cell contents
cell.textLabel.text = [currentCell title];
cell.detailTextLabel.text = [currentCell desc];
// If a picture exists then use it
if ([currentCell smallPicture])
{
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
cell.imageView.image = [UIImage imageWithData:[currentCell smallPicture]];
}
return cell;
}
// Swipe to delete has been used. Remove the table item
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Get a reference to the table item in our data array
Pictures *itemToDelete = [self.pictureListData objectAtIndex:indexPath.row];
// Delete the item in Core Data
[self.managedObjectContext deleteObject:itemToDelete];
// Remove the item from our array
[pictureListData removeObjectAtIndex:indexPath.row];
// Commit the deletion in core data
NSError *error;
if (![self.managedObjectContext save:&error])
NSLog(#"Failed to delete picture item with error: %#", [error domain]);
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
#end
Modify your dataSource initializing method. Regular sortDescriptor is not sufficient as you need to change the dateString to date for comparison.
- (void)readDataForTable
{
// Grab the data
pictureListData = [CoreDataHelper getObjectsForEntity:#"Pictures" withSortKey:#"title" andSortAscending:YES andContext:managedObjectContext];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"dd.MMMM - EEEE"];
[pictureListData sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
Pictures *picture1 = (Pictures *)obj1;
Pictures *picture2 = (Pictures *)obj2;
NSDate *date1 = [dateFormatter dateFromString:picture1.title];
NSDate *date2 = [dateFormatter dateFromString:picture2.title];
return [date1 compare:date2];
}];
// Force table refresh
[self.tableView reloadData];
}

UITableView crashes when it scrolls to non-top side and saying index 2 beyond bounds [0..1]

Now I meet a strange situation, I need your help, and forgive my poor English.
When a UITableView, filled with NSArray, on the top, really reload data when I use [UITableView reloadData]. But, the table doesn't reload data if it's not on the top side. In fact, the app crashed. The strange thing is that the indexPath.section isn't the right value, bigger than real value. So the console said: index 2 beyond bounds [0..1].
Does anybody know why? Please give me a hand or a tips.
Below are some codes:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (pageCount == 0) {
[[NSNotificationCenter defaultCenter] postNotificationName:#"IPOCalendarTableTitle" object:nil];
return 0;
} else {
NSMutableArray *arrayMonths = [stockArray objectAtIndex:pageIndex];
NSMutableArray *arrayDays = [arrayMonths objectAtIndex:0];
IPOListing *listing = [arrayDays objectAtIndex:0];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = #"yyyy/MM/dd";
NSDate *date = [formatter dateFromString:listing.date];
NSString *s = nil;
NSArray *arrayMonthEN = [NSArray arrayWithObjects:#"Jan", #"Feb", #"Mar", #"Apr", #"May", #"Jun", #"Jul", #"Aug", #"Sep", #"Oct", #"Nov", #"Dec", nil];
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
if ([delegate.currentLanguage isEqualToString:#"SC"]) {
formatter.dateFormat = #"yyyy年M月";
s = [formatter stringFromDate:date];
} else if ([delegate.currentLanguage isEqualToString:#"TC"]) {
formatter.dateFormat = #"yyyy年M月";
s = [formatter stringFromDate:date];
} else if ([delegate.currentLanguage isEqualToString:#"EN"]) {
int year = [[listing.date substringWithRange:NSMakeRange(0, 4)] intValue];
int month = [[listing.date substringWithRange:NSMakeRange(5, 2)] intValue];
s = [NSString stringWithFormat:#"%#, %d", [arrayMonthEN objectAtIndex:month - 1], year];
}
[formatter release];
NSArray *array = [NSArray arrayWithObjects:s, [NSNumber numberWithInt:pageCount], [NSNumber numberWithInt:pageIndex], nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"IPOCalendarTableTitle" object:array];
NSLog(#"%d", [arrayMonths count]);
return [arrayMonths count];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSMutableArray *arrayMonths = [stockArray objectAtIndex:pageIndex];
NSMutableArray *arrayDays = [arrayMonths objectAtIndex:section];
return [arrayDays count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 36.0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"IPOCalendarCellIdentifier";
IPOCalendarCell *cell = (IPOCalendarCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"IPOCalendarCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.lineLabel.backgroundColor = [UIColor colorWithRed:240/255.0 green:240/255.0 blue:240/255.0 alpha:1.0];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSLog(#"%d, %d", indexPath.section, indexPath.row);
NSMutableArray *arrayMonths = [self.stockArray objectAtIndex:pageIndex];
NSMutableArray *arrayDays = [arrayMonths objectAtIndex:indexPath.section];
IPOListing *listing = [arrayDays objectAtIndex:indexPath.row];
// configuration the cell...
return cell;
}
If indexPath.section isn't the right value, I'm pretty sure it has something to do with the value you return in - (NSInteger) numberOfRowsInSection:(UITableView *)tableView
Check this first, because If the size of your array is two, so as the value return by numberOfRowsInSection:, indexPath.section can't be equal or greater than this value.
Fixed. The problem is not here, it is about that two gang tables. When I use [UITableView setContentOffset] to table A, B will refresh too. In this case table A will reloadData twice, and when contentOffset of table is zero, it will reloadData only once. When table reloadData twice in quick time, it crashes. Thank all of you and I feel so sorry for my mistake.

Custom TableViewCell not updating

I want to set the checkmark in front of the cell. When I click on the checkmark icon the correct function is called and the datasource is changed.
I call [table reloadData] and after that even cellForRowAtIndexPath is also called but it is always dequeing the old table cell and not reloading it with the new data source..
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"CheckboxCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
NSLog(#"cellForRowAtIndexPath row: %d", indexPath.row);
// use CustomCell layout
CheckboxCell *checkboxCell;
if(cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"CheckboxCell" owner:self options:nil];
for (id currentObject in topLevelObjects){
if ([currentObject isKindOfClass:[UITableViewCell class]]){
checkboxCell = (CheckboxCell *)currentObject;
break;
}
}
} else {
checkboxCell = (CheckboxCell *)cell; // return cell;
}
Observation *observation = [observations objectAtIndex:indexPath.row];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"dd.MM.yyyy";
[dateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
NSString *nowString = [dateFormatter stringFromDate:observation.date];
[dateFormatter release];
NSString *amountString = [[NSString alloc] initWithFormat:#"%d", observation.amount];
checkboxCell.name.text = [observation.organism getNameDe];
checkboxCell.date.text = nowString;
checkboxCell.amount.text = amountString;
checkboxCell.latName.text = [observation.organism getLatName];
// Define the action on the button and the current row index as tag
[checkboxCell.checkbox addTarget:self action:#selector(checkboxEvent:) forControlEvents:UIControlEventTouchUpInside];
[checkboxCell.checkbox setTag:observation.observationId];
// Define the action on the button and the current row index as tag
[checkboxCell.remove addTarget:self action:#selector(removeEvent:) forControlEvents:UIControlEventTouchUpInside];
[checkboxCell.remove setTag:observation.observationId];
// Set checkbox icon
if(observation.submitToServer) {
NSLog(#"CHECKED");
checkboxCell.checkbox.imageView.image = [UIImage imageNamed:#"check_icon.png"];
} else {
NSLog(#"UNCHECKED");
checkboxCell.checkbox.imageView.image = [UIImage imageNamed:#"checkbox.gif"];
}
[amountString release];
[observation release];
return checkboxCell;
// Set checkbox icon
if(observation.submitToServer) {
NSLog(#"CHECKED");
checkboxCell.checkbox.imageView.image = [UIImage imageNamed:#"check_icon.png"];
} else {
NSLog(#"UNCHECKED");
checkboxCell.checkbox.imageView.image = [UIImage imageNamed:#"checkbox.gif"];
}
[amountString release];
[observation release];
return checkboxCell;
}
I think I'm doing something in the cellForRowAtIndexPath wrong.. Can anybody help me?
Edit:
The first problem could be fixed (Thanks to Maggie). Now the checkmark is changing the first time correctly. But somehow if I change it on another cell its crashing on the following line:
- (void) checkboxEvent:(UIButton *)sender
{
UIButton *button = (UIButton *)sender;
NSNumber *number = [NSNumber numberWithInt:button.tag];
for(Observation *ob in observations) {
if(ob.observationId == [number intValue]) { // <---- IT'S CRASHING HERE
ob.submitToServer = !ob.submitToServer;
NSLog(#"New value: %#", (ob.submitToServer) ? #"YES" : #"NO");
}
}
[table reloadData];
}
But the observation object isn't nil. Any ideas?
Replace
else {
return cell;
}
part with
else {
checkboxCell = (CheckboxCell *)cell;
}
and fill your checkboxCell with apropriate data.

Resources