Objective-C array issues - objective-c

I have this NSArray and each item returns a POIndex and PONumber and I am putting each item of the array inside another Array and the other array is returning like this:
POIndex
PONumber
POIndex
PONumber
Here is my code:
- (void)GetRequest
{
NSArray *tableData = [dataSource.areaData GetPurchaseOrderItems:[NSString stringWithFormat:#"%#%#",areaPickerSelectionString,unitPickerSelectionString]];
if(!self.objects){
self.objects = [[NSMutableArray alloc]init];
}
for(int i = 0; i < [tableData count]; i++){
[self.objects addObjectsFromArray:[tableData objectAtIndex:i]];
}
[self.tableView reloadData];
}
Here is a screenshot of what tableData is returning:
What I am looking to do is have have the PONumber as the key and POIndex as the display value, how would I do this?
I have tried the following:
NSMutableDictionary *subDict=[[NSMutableDictionary alloc]init];
for (NSDictionary *dict in tableData) {
[subDict setValue:[dict objectForKey:#"POIndex"] forKey:[dict objectForKey:#"PONumber"]];
[self.objects addObject:subDict];
}
but this displays like so:
{
{
{
{
Here is what is displaying it:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSString *object = self.objects[indexPath.row];
cell.textLabel.text = [object description];
return cell;
}

Your tableData array contains NSDictionary at each index. So you can use the same array in your cellForRowIndexPath method like as follows,
#property(nonatomic, retain) NSArray * tableData;
- (void)GetRequest
{
self.tableData = [dataSource.areaData GetPurchaseOrderItems:[NSString stringWithFormat:#"%#%#",areaPickerSelectionString,unitPickerSelectionString]];
[self.yourTableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSString *strPOIndex = [self.tableData[indexPath.row] valueForKey:#"POIndex"];
cell.textLabel.text = strPOIndex;
return cell;
}

Related

Delete Firebase Data located at indexPath.row

Been trying to figure this out for a while and I cannot understand why this keeps crashing. I swipe the cell and the delete button shows up, but when pressed it crashes at:
[[[_datRef child:#"posts"]child:index] removeValue];
Crash code is this:
***** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[FIRDataSnapshot length]: unrecognized selector sent to instance 0x61800002a080**
I'm trying to delete the Firebase content at the row that was selected for deletion. Anyone know what I am missing? Please only Objective-C.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return finalArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UpdatesTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"updateCell" forIndexPath:indexPath];
FIRDataSnapshot *snapshot = (self.finalArray)[indexPath.row];
NSString *title = snapshot.value[#"title"];
NSString *description = snapshot.value[#"description"];
NSString *date = snapshot.value[#"date"];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
cell.titleLabel.text = title;
cell.updateTextView.text = description;
NSString *timeAgoFormattedDate = [NSDate mysqlDatetimeFormattedAsTimeAgo:date];
cell.dateLabel.text = timeAgoFormattedDate;
cell.updateTextView.delegate = self;
cell.clipsToBounds = YES;
return cell;
}
- (void)getUpdates {
posts = [_datRef child:#"posts"];
[[posts queryOrderedByChild:#"date"] observeEventType:FIRDataEventTypeValue
withBlock:^(FIRDataSnapshot *snapshot) {
self.updatesArray = [NSMutableArray array];
for (snapshot in snapshot.children) {
[self.updatesArray addObject:snapshot];
_sortArray = [updatesArray reverseObjectEnumerator].allObjects;
self.finalArray = [NSMutableArray array];
[self.finalArray addObjectsFromArray:_sortArray];
}
[self.tableView reloadData];
}];
[self.tableView reloadData];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[[_datRef child:#"posts"] removeValue];
[finalArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
I found an easier way of doing this. In your post method:
//Create a random string for you child:
NSString *uuid = [NSUUID UUID].UUIDString;
//Put the random string as one of your childs:
[[[_alertRef child:#"posts"] child:uuid] setValue:#{
//create a key called childID and assign it the same value:
#"childID" : uuid,
#"date" : _date,
#"description" : _descriptionTextView.text,
#"title" : _alertTitle.text }];
Now when you go to retrieve your firebase data in your tableView put the data in a dictionary:
- (void)getUpdates {
posts = [_datRef child:#"posts"];
[[posts queryOrderedByChild:#"date"] observeEventType:FIRDataEventTypeValue
withBlock:^(FIRDataSnapshot *snapshot) {
self.updatesArray = [NSMutableArray array];
for (snapshot in snapshot.children) {
[self.updatesArray addObject:snapshot];
_firebaseDict = [[NSDictionary alloc] init];
_firebaseDict = snapshot.value;
_sortArray = [updatesArray reverseObjectEnumerator].allObjects;
self.finalArray = [NSMutableArray array];
[self.finalArray addObjectsFromArray:_sortArray];
}
[self.tableView reloadData];
}];
[self.tableView reloadData];
}
Then in your tableView editing method:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSString *childID = [_firebaseDict valueForKey:#"childID"];
[[[_datRef child:#"posts"] child:childID] removeValue];
[finalArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
}

Insert Cells and Sections from Table Views

Help me ! I can not able to insert cells in section tableviews !
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
NSInteger result = 0;
result = [[_dictionoryOfDay allKeys] count];
return result;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
NSInteger result = 0;
NSString *sectionNameInDictionary = [[_dictionoryOfDay allKeys]
objectAtIndex:section];
NSArray *sectionArray = [_dictionoryOfDay objectForKey:
sectionNameInDictionary];
result = [sectionArray count];
return result;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UICustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellMain" forIndexPath:indexPath];
[cell.btnAddMore addTarget:self action:#selector(actionAddMore:)forControlEvents:UIControlEventTouchUpInside];
cell.btnAddMore.tag = indexPath.section;
return cell;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
TableHeaderAvailabel *header;
if(!header){
header = [tableView dequeueReusableHeaderFooterViewWithIdentifier:#"TableHeaderAvailabel"];
}
NSString *result = nil;
result = [[self.dictionoryOfDay allKeys] objectAtIndex:section];
header.lbTitle.text = result;
return header;
}
-(void)actionAddMore:(UIButton *)sender{
}
My guess is that you want to add a row to your section when you tap on a cell's btnAddMore. If that's the case, then the implementation of actionAddMore() should look like
NSString *sectionNameInDictionary = [[_dictionoryOfDay allKeys]
objectAtIndex:section];
NSArray *sectionArray = [_dictionoryOfDay objectForKey:
sectionNameInDictionary];
// Create whatever you use to populate rows
[sectionArray addObject: <your new object>];
_dictionaryOfDay[sectionNameInDictionary] = sectionArray;
[self.tableView reloadData]; // Or just load the new cell, but this is easier

multiple checkmarks from

Tutorial I am following: http://www.appcoda.com/ios-programming-tutorial-create-a-simple-table-view-app/
I have created a tableview with 16 cells. When I select a row, it will show checkmark on it.
But when I scroll the tableview, there is also a checkmark showing on another cell further down the list. This repeats for any cell selected.
#import "FlightChecklistViewController.h"
#interface FlightChecklistViewController ()
#end
#implementation FlightChecklistViewController
{
NSArray *tableData;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Initialize table data
tableData = [NSArray arrayWithObjects:#"Egg Benedict", #"Mushroom Risotto", #"Full Breakfast", #"Hamburger", #"Ham and Egg Sandwich", #"Creme Brelee", #"White Chocolate Donut", #"Starbucks Coffee", #"Vegetable Curry", #"Instant Noodle with Egg", #"Noodle with BBQ Pork", #"Japanese Noodle with Pork", #"Green Tea", #"Thai Shrimp Cake", #"Angry Birds Cake", #"Ham and Cheese Panini", nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tableData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIAlertView *messageAlert = [[UIAlertView alloc]
initWithTitle:#"Row Selected" message:#"You've selected a row" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
// Display Alert Message
[messageAlert show];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#end
Any suggestions?
You need to store the information about the rows indexpaths, that were selected, somehow.
And populate your cell according to it.
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) NSMutableArray *selectedCells;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.selectedCells = [NSMutableArray array];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 100;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *unifiedID = #"aCellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:unifiedID];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:unifiedID];
}
cell.textLabel.text = [NSString stringWithFormat:#"%u", indexPath.row];
//if the indexPath was found among the selected ones, set the checkmark on the cell
cell.accessoryType = ([self isRowSelectedOnTableView:tableView atIndexPath:indexPath]) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
}
//if a row gets selected, toggle checkmark
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if([self isRowSelectedOnTableView:tableView atIndexPath:indexPath]){
[self.selectedCells removeObject:indexPath];
cell.accessoryType = UITableViewCellAccessoryNone;
} else {
[self.selectedCells addObject:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
-(BOOL)isRowSelectedOnTableView:(UITableView *)tableView atIndexPath:(NSIndexPath *)indexPath
{
return ([self.selectedCells containsObject:indexPath]) ? YES : NO;
}
#end
you will find the complete example code on github
The problem is that cells are reused. So, if you add a checkmark accessory view to a cell further up it'll appear again when the cell is reused further down. You should save which ones are checkmarked in an array somewhere that correlates to the rows of the table when you add/remove a checkmark. Then, when you give the table view a new cell you can determine whether or not it needs a checkmark and set that up.
I had the same issue recently with one of my apps, and I fixed it by doing this:
#property (nonatomic, strong) NSArray *list;
- (void)viewDidLoad
{
[super viewDidLoad];
self.list = [[NSArray alloc] initWithObjects:#"foo", #"bar", nil];
}
- (NSString *)SettingsPlist
{
NSString *paths = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *PlistPath = [paths stringByAppendingPathComponent:#"Settings.plist"];
return PlistPath;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [[self list] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *contentForThisRow = [[self list] objectAtIndex:[indexPath row]];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:[self SettingsPlist]];
NSString *row = [NSString stringWithFormat:#"%d",indexPath.row];
if([[dict objectForKey:row]isEqualToString:#"0"])
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
else
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
[[cell textLabel] setText:contentForThisRow];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableDictionary *plist = [NSMutableDictionary dictionaryWithContentsOfFile:[self SettingsPlist]];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *row = [NSString stringWithFormat:#"%d",indexPath.row];
if(cell.accessoryType == UITableViewCellAccessoryNone)
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
NSString *on = #"1";
[plist setObject:on forKey:row];
[plist writeToFile:[self SettingsPlist] atomically:YES];
}
else if(cell.accessoryType == UITableViewCellAccessoryCheckmark)
{
cell.accessoryType = UITableViewCellAccessoryNone;
NSString *off = #"0";
[plist setObject:off forKey:row];
[plist writeToFile:[self SettingsPlist] atomically:YES];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

How to add multiple Objects to Array - Objective C / iOS

I'm new to programming in Objective C
Here is my Dilemma: I'm pulling in a JSON file from the web and I'm able to display one of the elements (currDate) to my tableView but now I want to display more. From the code below I would I get it to display both currDate and prevDate
The logic needs to be changed here:
for (NSDictionary *diction in arrayOfEntry) {
NSString *currDate = [diction objectForKey:#"Current Date"];
a = currDate;
NSString *prevDate = [diction objectForKey:#"Previous Date"];
b = prevDate;
[array addObject:a];
}
[[self myTableView]reloadData];
I'm not sure if I need to change anything here but I'm attaching it to show how I'm displaying the array to my viewTable:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [array count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [array objectAtIndex:indexPath.row];
//cell.textLabel.text = [array objectsAtIndexes:indexPath.row];
return cell;
}
just add another line:
[array addObject:a];
[array addObject:b];
make arrayOfEntry global. in .h file
NSArray *arrayOfEntry;
In numberOfRowsInSection
[arrayOfEntry count]
In tableView: cellForRowAtIndexPath
NSString *currDate = [[arrayOfEntry objectAtIndex:indexPath.row] objectForKey:#"Current Date"]
NSString *prevDate = [[arrayOfEntry objectAtIndex:indexPath.row] objectForKey:#"Previous Date"]
cell.textLabel.text = [NSString stringWithFormat:#"%# %#", currDate, prevDate];
To add multiple elements to an Array in objective c you need to use:
NSMutableArray *newArr = [NSMutableArray new];
Then:
[newArr addObject:dict1];
If you want, you can then set your NSArray you were using to the NSMutuableArray after the addition of objects is complete.

Howto fill UITableView with sections and rows dynamically?

I have some problems with UITableView and sections/rows.
Iam parsing the section names, all row names and row count per section from a xml.
I have 3 NSMutableArrays:
nameArray (with all row names)
sectionArray (all section names)
secCountArray (row count per section)
For the cellForRowAtindexPath to work, do I have to return the rows for the displayed section?
The next step I would do is to build an 2d Array with sections and all rows for each section.
Does anyone knows any better solution?
Here comes the code:
// Customize the appearance of table view cells.
- (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] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Set up the cell
int xmlEntryIndex = [indexPath indexAtPosition: [indexPath length] -1];
//???
cell.textLabel.text = [[theParser.nameArray objectAtIndex: 1]valueForKey:#"name"];
return cell;
}
Thanks!
You could have one _section array and one _row array for the whole tableview.
like your view controller.h file declare array
NSMutableArray *arrSection, *arrRow;
then your view controller.m file paste below code..
- (void)viewDidLoad
{
[super viewDidLoad];
arrSection = [[NSMutableArray alloc] initWithObjects:#"section1", #"section2", #"section3", #"section4", nil];
arrRow = [[NSMutableArray alloc] init];
[arrSection enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSMutableArray *tempSection = [[NSMutableArray alloc] init];
[arrSection enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[tempSection addObject:[NSString stringWithFormat:#"row%d", idx]];
}];
[arrRow addObject:tempSection];
}];
NSLog(#"arrRow:%#", arrRow);
}
#pragma mark - Table view data source
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [arrSection count];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [arrSection objectAtIndex:section];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[arrRow objectAtIndex:section] count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:nil];
if(!cell)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil];
cell.textLabel.text = [[arrRow objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];
return cell;
}
This method does not involve defining and creating your own custom view. In iOS 6 and up, you can easily change the background color and the text color by defining the
- (void)tableView:(UITableView *)tableView
willDisplayHeaderView:(UIView *)view
forSection:(NSInteger)section
delegate method.
For example:
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section
{
// Background color
view.tintColor = [UIColor blackColor];
// Text Color
UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view;
[header.textLabel setTextColor:[UIColor whiteColor]];
// Another way to set the background color
// Note: does not preserve gradient effect of original header
// header.contentView.backgroundColor = [UIColor blackColor];
}
you can see display dynamic section and row
May be helpful for you..
You could have one array for the whole table view. The array contains arrays for every section. Then the cellForRowAtIndexPath could look like:
- (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] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
[[cell textLabel] setText: [[[myArray objectAtIndex: indexPath.section] objectAtIndex: indexPath.row]];
return cell;
}
I hope this help you in your problem.
Edit: With the modern Objective-C and ARC I would write this as
- (void)viewDidLoad {
....
[self.tableView registerClass:[MyCellClass class] forCellReuseIdentifier:kMyCellIdentifier];
}
...
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
MyCellClass *cell = [tableView dequeueReusableCellWithIdentifier:kMyCellIdentifier forIndexPath:indexPath];
cell.textLabel.text = myArray[indexPath.section][indexPath.row];
return cell;
}