I am inserting NSMutableArray(self.tablePdfListArray) in tableview textlabel and NSMutableArray(self.dateListArray) in detailtextlabel at same index. It got added correctly at first place but when I am opening the TableView again the detailTextlabel becoming textlabel and textlabel is becoming detailTextlabel.
I have NSLog both the NSMutabelArray and come to know that both array value are getting swap. How to retain its original values? Thanks in advance for any suggestion.
Edited With tableView code
- (void)viewDidLoad
{
if([[NSUserDefaults standardUserDefaults] objectForKey:#"children"] != nil )
{
self.tablePdfListArray = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"children"]];
}
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"dates"] != nil)
{
self.dateListArray = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"dates"]];
}
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0)
{
self.myPDFName = [NSString stringWithFormat:#"%#", [alertView textFieldAtIndex:0].text];
firstDayInYear = [NSDate date];
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *currentTime = [dateFormatter stringFromDate:firstDayInYear];
NSLog(#"User's current time in their preference format:%#",currentTime);
if(!self. tablePdfListArray)
{
self.tablePdfListArray = [[NSMutableArray alloc]init];
}
if(!self.dateListArray)
{
self.dateListArray = [[NSMutableArray alloc]init];
}
[self.dateListArray insertObject:currentTime atIndex:0];
NSLog(#"mhy date dateListArray %#",dateListArray);
//the below if condition will not allow repeatative string array in tableList and textfield lenth.
if ([[alertView textFieldAtIndex:0].text length] != 0 && ![self.tablePdfListArray containsObject:self.myPDFName])
{
[self.tablePdfListArray insertObject:[NSString stringWithFormat:#"%#", [alertView textFieldAtIndex:0].text] atIndex:0];
NSLog(#"mhy date tablePdfListArray %#",tablePdfListArray);
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.pdfListnameTable insertRowsAtIndexPaths:#[indexPath]withRowAnimation:UITableViewRowAnimationAutomatic];
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
[defaults setObject:self.dateListArray forKey:[NSString stringWithFormat:#"children"]];
[defaults setObject:self.tablePdfListArray forKey:[NSString stringWithFormat:#"dates"]];
[defaults synchronize];
}
}}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if( tableView == pdfListnameTable)
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone; //cell bg
//self.myChklist.backgroundColor = [UIColor clearColor];
}
NSString *tablePdfname = [self.tablePdfListArray objectAtIndex:indexPath.row];
cell.textLabel.text = tablePdfname;
NSString *tablePdfdate = [self.dateListArray objectAtIndex:indexPath.row];
//[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
cell.detailTextLabel.text = tablePdfdate;
return cell;
}
}
Why are you checking tableView == pdfListnameTable ?
That should be tableView isEqual:self. pdfListnameTable. Not sure that is relevant here, but if you have more than one tableView - i'd guess that you aren't switching to it as there seems to be a lack of an else statement for that.
Well, I'm not sure but I did a little refactoring of your code. You have some places where it looks like you're trying to access a property, but then you're also trying to access it as an instance value.
So, here is what I did. It may not be correct. but it should be close (or at least will help you figure this out)
#interface someTableViewController()
#property(nonatomic, strong) NSMutableArray *tablePdfListArray;
#property(nonatomic, strong) NSMutableArray *dateListArray;
#property(nonatomic, copy) NSString *myPDFName;
#property(nonatomic, strong) NSDate *firstDayInYear;
#property(nonatomic, strong) NSDateFormatter *dateFormatter;
#property(nonatomic, weak) IBOutlet UITableView *pdfListnameTable;
#end
#implementation someTableViewController
-(void)viewDidLoad {
self.tablePdfListArray = [NSMutableArray new];
self.dateListArray = [NSMutableArray new];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
if([userDefaults objectForKey:#"children"] != nil ) {
self.tablePdfListArray = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"children"]];
}
if([userDefaults objectForKey:#"dates"] != nil) {
self.dateListArray = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"dates"]];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone; //cell bg
NSInteger currentRow = indexPath.row;
NSString *tablePdfname = [self.tablePdfListArray objectAtIndex:currentRow];
cell.textLabel.text = tablePdfname;
NSString *tablePdfdate = [self.dateListArray objectAtIndex:currentRow];
cell.detailTextLabel.text = tablePdfdate;
UIButton *someButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
[someButton setTitle:#"CLICK" forState:UIControlStateNormal];
[someButton addTarget:self action:#selector(testButtonClickIndexPath:) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:someButton];
return cell;
}
-(void)testButtonClickIndexPath:(id)sender {
CGPoint touchPoint = [sender convertPoint:CGPointZero toView:self.pdfListnameTable];
NSIndexPath *indexPath = [self.pdfListnameTable indexPathForRowAtPoint:touchPoint];
if(indexPath != nil) {
// show alert message, call it, or whatever. just using a silly one for now..
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"RAR"
message:#"Mamma Say..my..my mamma say"
delegate:self
cancelButtonTitle:#"Medulla Oblongata"
otherButtonTitles:#[ #"h2o", #"Gatorade"]];
[alert show];
}
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if(buttonIndex == 0) {
self.myPDFName = [NSString stringWithFormat:#"%#", [alertView textFieldAtIndex:0].text];
self.firstDayInYear = [NSDate date];
self.dateFormatter = [[NSDateFormatter alloc] init];
[self.dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[self.dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *currentTime = [self.dateFormatter stringFromDate:self.firstDayInYear];
NSLog(#"User's current time in their preference format:%#",currentTime);
[self.dateListArray insertObject:currentTime atIndex:0];
NSLog(#"mhy date dateListArray %#",self.dateListArray);
//the below if condition will not allow repeatative string array in tableList and textfield lenth.
if([[alertView textFieldAtIndex:0].text length] != 0 && ![self.tablePdfListArray containsObject:self.myPDFName]) {
[self.tablePdfListArray insertObject:[NSString stringWithFormat:#"%#", [alertView textFieldAtIndex:0].text] atIndex:0];
NSLog(#"mhy date tablePdfListArray %#",self.tablePdfListArray);
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.pdfListnameTable insertRowsAtIndexPaths:#[indexPath]withRowAnimation:UITableViewRowAnimationAutomatic];
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
[defaults setObject:self.dateListArray forKey:[NSString stringWithFormat:#"dates"]];
[defaults setObject:self.tablePdfListArray forKey:[NSString stringWithFormat:#"children"]];
[defaults synchronize];
}
}
}
#end
Related
I've created an UITableView with cells and i am trying to add a person's phone and name information into a cell via some functions. The problem is when i try to add a person's info, it is being added into my data array but, i cannot see the new info on UITableView cell. I tried to use reloadData function to reload UITableView, it was no use.
I have arrays for people's numbers and names. Also, i have a button which adds a person via ABPeoplePickerNavigationController.
addedContacts.h :
#import <UIKit/UIKit.h>
#import AddressBook;
#import AddressBookUI;
#interface addedContacts : UIViewController <UITextFieldDelegate, ABPeoplePickerNavigationControllerDelegate, UITableViewDelegate,
UITableViewDataSource>{
NSMutableArray* people;
NSMutableArray* numbers;
IBOutlet UITableView *tableview;
}
- (IBAction)addPerson:(id)sender;
#end
I use commitEditingStyle function to delete a person's information from the tableview. In addition, I keep people's information in defaults of application.
addedContacts.m :
#import "addedContacts.h"
#implementation addedContacts
-(void)viewDidLoad{
[super viewDidLoad];
}
- (IBAction)addPerson:(id)sender {
ABPeoplePickerNavigationController* picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
[self presentViewController:picker animated:YES completion:nil];
}
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
[self dismissViewControllerAnimated:YES completion:nil];
}
-(BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person{
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
numbers = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:#"numbers"]];
people = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:#"people"]];
if(numbers.count == 0 && numbers.count == 0){
numbers = [[NSMutableArray alloc] init];
people = [[NSMutableArray alloc] init];
}
NSString *contactName = CFBridgingRelease(ABRecordCopyCompositeName(person));
NSString* nameField = [NSString stringWithFormat:#"%#", contactName ? contactName : #"No Name"];
ABMultiValueRef phoneRecord = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFStringRef phoneNumber = ABMultiValueCopyValueAtIndex(phoneRecord, 0);
NSString* phoneField = (__bridge_transfer NSString *)phoneNumber;
CFRelease(phoneRecord);
[people addObject:nameField];
[numbers addObject:phoneField];
[defaults setObject:people forKey:#"people"];;
[defaults setObject:numbers forKey:#"numbers"];
[self dismissViewControllerAnimated:YES completion:nil];
return NO;
}
-(void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
// Remove the row from data model
[people removeObjectAtIndex:indexPath.row];
[numbers removeObjectAtIndex:indexPath.row];
// Request table view to reload
[tableView reloadData];
}
-(NSInteger) numberOfSectionsInTableView: (UITableView*) tableView{
return 1;
}
-(NSInteger) tableView:(UITableView*) tableView numberOfRowsInSection:(NSInteger)section{
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
numbers = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:#"numbers"]];
return [numbers count];
}
-(UITableViewCell*) tableView: (UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
numbers = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:#"numbers"]];
people = [[NSMutableArray alloc] initWithArray:[defaults objectForKey:#"people"]];
NSLog(#"%#",numbers);
NSLog(#"%#",people);
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
cell.accessoryType = UITableViewCellAccessoryDetailButton;
}
NSLog(#"%ld", (long)indexPath.row);
NSLog(#"%ld", (long)people.count);
NSString* Tname = [people objectAtIndex:indexPath.row];
NSString* Tnumber = [numbers objectAtIndex:indexPath.row];
cell.textLabel.text = Tname;
cell.detailTextLabel.text = Tnumber;
return cell;
}
#end
Any suggestions?
1) this is something strange:
if(numbers.count == 0 && numbers.count == 0){
numbers = [[NSMutableArray alloc] init];
people = [[NSMutableArray alloc] init];
}
i think you mean
if(numbers.count == 0 && people.count == 0)
2) i think you mast insert reload of table after you add your new object into people and numbers arrays
[people addObject:nameField];
[numbers addObject:phoneField];
[tableView reloadData];
My hunch is that, there this a bug in the tableView:numberOfRowsInSection code. You need to return count of people or numbers. Not get the value from the user defaults. Since they don't have the newly added person and number.
-(NSInteger) tableView:(UITableView*) tableView numberOfRowsInSection:(NSInteger)section{
return [numbers count];
}
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];
}
I cannot seem to wrap my head around population of different sections in a single uitableview. Is there any way I can do it with my current setup? I am willing to change the way my arrays are set up if I need to. I have a lot of useless code in here that I am going to remove later, but basically all of it works. The issue is that all sections are being loaded with all of the data stored in the NSMutableDictionary.
- (void)viewDidLoad
{
bannerIsVisible = NO;
bannerView.hidden = YES;
[super viewDidLoad];
//NSDate Info
self.secondsPerDay = 86400;
self.todayDate = [[NSUserDefaults standardUserDefaults]objectForKey:#"todayDate"];
self.dateFormat = [[NSDateFormatter alloc] init];
[self.dateFormat setDateFormat:#"MMMM dd, yyyy"];
self.todayString = [self.dateFormat stringFromDate:self.todayDate];
//change to string and set to the string properties
todaysDate.text = self.todayString;
//initialize the arrays and the state
self.mainArray = [[NSMutableArray alloc] init];
self.subjectArray = [[NSMutableArray alloc]init];
self.mainDictionary = [[NSMutableDictionary alloc]init];
/*The UITapGestureRecognizer will make it so the program can dismiss
the keyboard at will. */
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]
initWithTarget:self
action:#selector(hideKeyboard)];
[self.view addGestureRecognizer:tapGesture];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"HasLaunchedOnce"])
{
// app already launched
[self.subjectArray addObjectsFromArray:[[NSUserDefaults standardUserDefaults]arrayForKey:[NSString stringWithFormat:#"%#sections",self.todayString]]];
[[NSUserDefaults standardUserDefaults]synchronize];
}
else
{
self.counter++;
// This is the first launch ever
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"HasLaunchedOnce"];
[[NSUserDefaults standardUserDefaults] synchronize];
AG_Storage *store = [[AG_Storage alloc] init];
store.itemName = #"Swipe to Delete";
NSString *storeString = store.itemName;
self.counter++;
NSLog(#"counter%d",self.counter);
AG_Storage *store2 = [[AG_Storage alloc] init];
store2.itemName = #"+ Button to Add";
NSString *store2String = store2.itemName;
self.counter++;
NSString *stringStuff = #"Tap this area to add notes for the day!";
[[NSUserDefaults standardUserDefaults]setObject:stringStuff forKey:[NSString stringWithFormat:#"%#textView",self.todayString]];
[[NSUserDefaults standardUserDefaults]synchronize];
[self.subjectArray addObject:#"Test"];
[[NSUserDefaults standardUserDefaults]setObject:self.subjectArray forKey:[NSString stringWithFormat:#"%#sections",self.todayString]];
[[NSUserDefaults standardUserDefaults]synchronize];
//allocates tempDic and gives it tasks and keys
NSMutableDictionary *tempDic = [[NSMutableDictionary alloc] initWithObjectsAndKeys: storeString, [NSString stringWithFormat:#"%d",0], store2String, [NSString stringWithFormat:#"%d",1], nil];
//Sets tempDic in mainDictionary with the key Test
[self.mainDictionary setObject:tempDic forKey:[NSString stringWithFormat:#"%#",[self.subjectArray objectAtIndex:0]]];
//Saves mainDictionary
[[NSUserDefaults standardUserDefaults] setObject:self.mainDictionary forKey:[NSString stringWithFormat:#"mainDictionary%#",self.todayString ]];
[[NSUserDefaults standardUserDefaults]synchronize];
}
[self loadInitialData];
}
- (void)loadInitialData
{
// Do any additional setup after loading the view, typically from a nib.
//call my custom class and store today's date.
AG_Storage *theDateToday = [[AG_Storage alloc]init];
theDateToday.todaysDate = self.todayDate;
NSLog(#"tried loadinitialdata");
NSMutableDictionary *mutDic = [[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:#"mainDictionary%#",self.todayString ]];
NSLog(#"%#",mutDic);
//Populate mainArray
for (int x= 0; x < self.subjectArray.count; x++) {
for (int y = 0; y != -99; y++) {
NSDictionary *tempDir = [mutDic valueForKey:[NSString stringWithFormat:#"%#",[self.subjectArray objectAtIndex:x]]];
[[NSUserDefaults standardUserDefaults] synchronize];
NSLog(#"tempDir %#",tempDir);
NSString *tempString = [tempDir valueForKey:[NSString stringWithFormat:#"%d",y]];
NSLog(#"tempString %#",tempString);
if ([tempString length] != 0) {
//add the data to the mainArray and update counter
[self.mainArray addObject:tempString];
NSLog(#"added to array%#", self.mainArray);
}
else
y = -100;
}
NSLog(#"SHOULD EXIT LOOP RIGHT NOW");
}
NSLog(#"LOOP ENDED PROPERLY");
/*Populate textviews which hold the user's notes. Populates
based on the state of the program.*/
todayTextView.text = [[NSUserDefaults standardUserDefaults]stringForKey:[NSString stringWithFormat:#"%#textView",self.todayString]];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.subjectArray.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.mainArray.count;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [self.subjectArray objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableViewer cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//populates the table based on which view is selected.
UITableViewCell *cell = [tableViewer dequeueReusableCellWithIdentifier:#"todayCell"];
NSString *toDoItem = [self.mainArray objectAtIndex:indexPath.row];
cell.textLabel.text = toDoItem;
cell.textLabel.adjustsFontSizeToFitWidth = YES;
cell.textLabel.minimumScaleFactor = 0.5;
return cell;
}
In order to reuse sections and try to preserve your code setup, I would recommend using a [NSMutableArray] of [NSMutableArray]s. Each NSMutableArray would represent a section of your table, where the index corresponds to the section
Then in tableView:numberOfRowsInSection: you grab the array from the index using the NSInteger param.
Inside (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath you access section via indexPath.section and use that on your NSMutableArray of sections to pull out your data. From there, you then have access to data only for that section to create your rows.
Example:
self.sectionArrays = [NSMutableArray new];
....
(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.sectionArrays count];
}
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [[self.sectionArrays objectAtIndex:section] count];
}
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *currentSectionArray = [self.sectionArrays objectAtIndex:indexPath.section];
...
NSString *toDoItem = [currentSectionArray objectAtIndex:indexPath.row];
...
configure cell
}
Okay I have three UITableViews that I need to all originate from the same viewcontroller code. I need to populate them all from the .m file of AG_ViewController.
AG_ViewController.h
#import <UIKit/UIKit.h>
#interface AG_ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>{
IBOutlet UITableView *yesterdayTableView;
IBOutlet UITableView *tomorrowTableView;
IBOutlet UITableView *tableView;
IBOutlet UILabel *todaysDate;
IBOutlet UILabel *subtractDate;
IBOutlet UILabel *addDate;
}
#end
AG_ViewController.m
#import "AG_ViewController.h"
#import "AG_Storage.h"
#import "AG_AddItemViewController.h"
#interface AG_ViewController ()
#property NSMutableArray *mainArray;
#property NSMutableArray *yesterdayArray;
#property NSMutableArray *tomorrowArray;
#property NSDate *todayDate;
#property NSDate *tomorrowsDate;
#property NSDate *yesterdaysDate;
#property int counter;
#property(weak,nonatomic)IBOutlet UIButton *yesterdayButton;
#property(weak,nonatomic)IBOutlet UIButton *tomorrowButton;
#property(weak,nonatomic)IBOutlet UIButton *backButton;
#end
#implementation AG_ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.mainArray = [[NSMutableArray alloc] init];
self.yesterdayArray = [[NSMutableArray alloc]init];
self.tomorrowArray = [[NSMutableArray alloc]init];
[self loadInitialData];
}
- (void)loadInitialData
{
// Do any additional setup after loading the view, typically from a nib.
//NSDate Info
NSTimeInterval secondsPerDay = 24 * 60 * 60;
NSDate *today = [[NSDate alloc]init];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"MMMM dd, yyyy"];
self.todayDate = today;
self.tomorrowsDate = [today dateByAddingTimeInterval: secondsPerDay];
self.yesterdaysDate = [today dateByAddingTimeInterval: -secondsPerDay];
NSString *todayString = [dateFormat stringFromDate:self.todayDate];
NSString *tomorrowString = [dateFormat stringFromDate:self.tomorrowsDate];
NSString *yesterdayString = [dateFormat stringFromDate:self.yesterdaysDate];
todaysDate.text = todayString;
addDate.text = tomorrowString;
subtractDate.text = yesterdayString;
AG_Storage *theDateToday = [[AG_Storage alloc]init];
theDateToday.todaysDate = self.todayDate;
//Populate mainArray
for (int x= 0; x!=-99; x++) {
//get ready to call the NSUserDefaults
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:#"%#%d",todayString,x]];
AG_Storage *someStorageObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];
AG_Storage *storeToArray = [[AG_Storage alloc]init];
storeToArray.itemName = someStorageObject;
if (someStorageObject != nil) {
//add the data to the mainArray and update counter
[self.mainArray addObject:storeToArray];
self.counter++;
}
else if ((someStorageObject == nil) && (x==99)){
//exit when done
x=-100;
}
}
//Populate yesterdayArray
for (int x= 0; x!=-99; x++) {
//get ready to call the NSUserDefaults
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:#"%#%d",yesterdayString,x]];
AG_Storage *someStorageObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];
AG_Storage *storeToArray = [[AG_Storage alloc]init];
storeToArray.itemName = someStorageObject;
if (someStorageObject != nil) {
//add the data to the mainArray and update counter
[self.yesterdayArray addObject:storeToArray];
self.counter++;
}
else if ((someStorageObject == nil) && (x==99)){
//exit when done
x=-100;
}
}
//Populate tomorrowArray
for (int x= 0; x!=-99; x++) {
//get ready to call the NSUserDefaults
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:#"%#%d",tomorrowString,x]];
AG_Storage *someStorageObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];
AG_Storage *storeToArray = [[AG_Storage alloc]init];
storeToArray.itemName = someStorageObject;
if (someStorageObject != nil) {
//add the data to the mainArray and update counter
[self.tomorrowArray addObject:storeToArray];
self.counter++;
}
else if ((someStorageObject == nil) && (x==99)){
//exit when done
x=-100;
}
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if(tableView == tomorrowTableView){
return [self.tomorrowArray count];
}
else if(tableView == yesterdayTableView)
return [self.yesterdayArray count];
else
return [self.mainArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableViewer cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableViewer dequeueReusableCellWithIdentifier:#"thisCell"];
AG_Storage *toDoItem = [self.mainArray objectAtIndex:indexPath.row];
cell.textLabel.text = toDoItem.itemName;
if (toDoItem.completed) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (IBAction)unwindToList:(UIStoryboardSegue *)segue
{
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"MMMM dd, yyyy"];
AG_AddItemViewController *source = [segue sourceViewController];
AG_Storage *item = source.store;
NSDate *dateCreated = item.creationDate;
NSString *todayString = [dateFormat stringFromDate:self.todayDate];
NSString *dateCreatedString = [dateFormat stringFromDate:dateCreated];
NSString *tomorrowString = [dateFormat stringFromDate:self.tomorrowsDate];
NSString *yesterdayString = [dateFormat stringFromDate:self.yesterdaysDate];
//Set up file storage!
if (item != nil) {
if ([dateCreatedString isEqualToString:todayString]) {
[self.mainArray addObject:item];
[tableView reloadData];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:item.itemName];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:[NSString stringWithFormat:#"%#%d",todayString,self.counter]];
[[NSUserDefaults standardUserDefaults] synchronize];
}
else if ([dateCreatedString isEqualToString:tomorrowString]){
[self.tomorrowArray addObject:item];
[tableView reloadData];
NSLog(#"THIS WORKED TOO :D");
}
else if ([dateCreatedString isEqualToString:yesterdayString]){
[self.yesterdayArray addObject:item];
[tableView reloadData];
NSLog(#"THIS WORKED");
}
else{
}
}
self.counter++;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableViewer didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableViewer deselectRowAtIndexPath:indexPath animated:NO];
AG_Storage *tappedItem = [self.mainArray objectAtIndex:indexPath.row];
tappedItem.completed = !tappedItem.completed;
[tableViewer reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationNone];
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return YES if you want the specified item to be editable.
return YES;
}
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableViews commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"MMMM dd, yyyy"];
NSString *todayString = [dateFormat stringFromDate:self.todayDate];
if (editingStyle == UITableViewCellEditingStyleDelete) {
//Delete from storage
for (int x = 0; x!=-99; x++) {
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:#"%#%d",todayString,x]];
AG_Storage *someStorageObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];
AG_Storage *storeToArray = [[AG_Storage alloc]init];
storeToArray.itemName = someStorageObject;
AG_Storage *toDoItem = [self.mainArray objectAtIndex:indexPath.row];
NSString *compare = toDoItem.itemName;
//If they equal then delete from NSUserDefaults
if ([compare isEqualToString:someStorageObject]) {
[[NSUserDefaults standardUserDefaults]removeObjectForKey:[NSString stringWithFormat:#"%#%d",todayString,x]];
[[NSUserDefaults standardUserDefaults]synchronize];
x=-100;
}
else
{
}
if (x>10) {
x=-100;
}
}
[self.mainArray removeObjectAtIndex:indexPath.row];
[tableViews deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
#end
I've only ever set up one table at a time, so how do I make yesterdayTableView become populated by yesterdayArray for instance?
You can keep one tableView around.
Steps for,One tableView multiple cell as per your need
1) Design seperate cell for yesterday and tomorrow nibs/storyboard
2) swap cell on click of some button tableView:cellForRowAtIndexPath via if else conditions.
or else go for viewController containment
Several ways to do so,
If you only need to display one tableView at a time you could do something like this in your tableView:cellForRowAtIndexPath: data source method:
The stupid way
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (kAppState_Yesterday) { // Set the controllerstate so that it knows that the arrayDatasource should be yesterday
// create and return cell corresponding to yesterdayArray.
}
}
If all your cells look the same, you could have a NSArray *dataSource and just assign it to the different arrays.
The "a bit smarter way"
if userClicksButton `display yesterday array`
self.dataSource = self.yesterdayArray
end
In this way, your tableView:cellForRowAtIndexPath: will be more consistent since if won't be full of conditionals.
If things get more complicated, I would recommend to use Controller Containment.
I have a problem. At the moment I'm polishing my app and debug it and so on. Something weird happened. Here is how it works: User enters data and gets to the TableView and the data gets displayed. Simple. But as soon as he switches to another view and then back to the TableView, the data is gone! The weird thing is that it didnt happen before. (I redid some codelines, maybe I changed something unknowingly). I have a hinch what it might be, but it would be weird because it worked before. The problem I think lies at the buttonTag line:
- (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];
}
// cell.image = selectedImage;
cell.textLabel.font = [UIFont fontWithName:#"Georgia" size:14.0];
if (buttonTag == 9001) {
cell.textLabel.text = [NSString stringWithFormat:#"%# %# %#, %#.", [self.userData objectAtIndex:0], [self.userData objectAtIndex:1], [self.userData objectAtIndex:2], [self.userData objectAtIndex:3]];
}
if (buttonTag == 9002) {
cell.textLabel.text = [NSString stringWithFormat:#"%# %# %#, %#.", [self.userData objectAtIndex:0], [self.userData objectAtIndex:1], [self.userData objectAtIndex:2], [self.userData objectAtIndex:3]];
}
if (buttonTag == 9003) {
cell.textLabel.text = [NSString stringWithFormat:#"%# %# %#,%#.", [self.userData objectAtIndex:0], [self.userData objectAtIndex:1], [self.userData objectAtIndex:2], [self.userData objectAtIndex:3]];
}
return cell;
}
Because he just displays the data when a particular button is pressed. If you change to the TableView without pressing one of those buttons (From a Tabbar e.g.) it doesnt show anything. My question is now: How can I tell the TableView to maintan the data from the last button pressed? (I was thinking NSUserDefaults?)
Here is another ViewController, the one from where you get to the TableView:
- (IBAction)savePressed:(id)sender
{
if (buttonTag == 9001) {
button.tag = 9001;
NSUserDefaults *savetext = [NSUserDefaults standardUserDefaults];
[savetext setObject:Antwort.text forKey:#"hallo"];
[savetext setObject:Antwort2.text forKey:#"hallo2"];
[savetext setObject:Antwort3.text forKey:#"hallo3"];
UIButton *buttonPressed = (UIButton *)sender;
TV *second =[[TV alloc] initWithNibName:nil bundle:nil];
second.buttonTag = buttonPressed.tag;
[self.navigationController pushViewController:second animated:YES];
}
if (buttonTag == 9002) {
button.tag = 9002;
NSUserDefaults *savetext = [NSUserDefaults standardUserDefaults];
[savetext setObject:Antwort.text forKey:#"hallo"];
[savetext setObject:Antwort2.text forKey:#"hallo2"];
[savetext setObject:Antwort3.text forKey:#"hallo3"];
UIButton *buttonPressed = (UIButton *)sender;
TV *second =[[TV alloc] initWithNibName:nil bundle:nil];
second.buttonTag = buttonPressed.tag;
[self.navigationController pushViewController:second animated:YES];
}
if (buttonTag == 9003) {
button.tag = 9003;
NSUserDefaults *savetext = [NSUserDefaults standardUserDefaults];
[savetext setObject:Antwort.text forKey:#"hallo"];
[savetext setObject:Antwort2.text forKey:#"hallo2"];
[savetext setObject:Antwort3.text forKey:#"hallo3"];
UIButton *buttonPressed = (UIButton *)sender;
TV *second =[[TV alloc] initWithNibName:nil bundle:nil];
second.buttonTag = buttonPressed.tag;
[self.navigationController pushViewController:second animated:YES];
}
}
If the data is read & saved in NSUSerDefaults, try
[savetext synchronize]
before pushing to new view.