I have created an array, two dictionaries and a tableview. The tableview should display the contents of array and that array contains the data of dictionaries. When i try to display it using "[mArray addObject:(mDictionary)];" its throwing an exception but if i use "[mArray addObject:[mDictionary objectForKey:#"firstname"]];" its working fine.
Can you help me to understand why is it happening and isn't it possible to display the dictionary value without using "objectForKey"?
Here is my "ViewController.m".
#import "ViewController.h"
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
mArray = [[NSMutableArray alloc]init];
mDictionary = [[NSMutableDictionary alloc]init];
[mDictionary setValue:#"shanu" forKey:#"firstname"];
[mDictionary setValue:#"kumar" forKey:#"lastname"];
mDictionary2 = [[NSMutableDictionary alloc]init];
[mDictionary2 setValue:#"hgjghjgf" forKey:#"firstname1"];
[mDictionary2 setValue:#"ghjgjgfj" forKey:#"lastname1"];
[mArray addObject:mDictionary];
[mArray addObject:mDictionary2];
CGRect frame = self.view.frame;
UITableView *tableView = [[UITableView alloc]initWithFrame:frame style:UITableViewStylePlain];
tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
tableView.backgroundColor = [UIColor cyanColor];
tableView.separatorColor = [UIColor blackColor];
tableView.delegate = self;
tableView.dataSource = self;
[self.view addSubview:tableView];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return #"Array and Tableview";
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return mArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
cell.textLabel.text = [mArray objectAtIndex:indexPath.row];
return cell;
}
- (void)dealloc
{
[mArray release];
[mDictionary release];
[mDictionary2 release];
[super dealloc];
}
#end
Declare an array in .h file:
NSArray *keys
write this in viewDidLoad
keys = [mDictionary allKeys];
This in cellForRowAtIndexPath
cell.textLabel.text = [mDictionary objectForKey:[keys objectAtIndex:indexPath.row];
If you try to assign the some text to the cell's textlabel the object returned from:
[mArray objectAtIndex:indexPath.row];
should be a string and not a whole dictionary.
When you just put the whole dictionary in the array [mArray objectAtIndex:indexPath.row]; will return a dictionary and you cannot assign a dictionary to the textlabel so you get an exception. If you want to store the whole dictionary use objectForKey to get the string you want:
cell.textLabel.text = [[mArray objectAtIndex:indexPath.row] objectForKey:#"WHAT_EVER_KEY_YOU_WANT"];
btw, you are not using ARC zo you probably want to get an autoreleased UITableViewCell so add autorelease to you cell:
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"] autorelease];
or
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
[cell autorelease];
Array contains similar type objects. You can add dictionary objects into array. There is no problem in that case. The problem is when you get an element from array and assign to cell.textLabel.text. Here object is type of dictionary and cell.textLabel.text is type of nsstring. So you should assign a value for key of dictionary object into cell.textLabel.text.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
cell.textLabel.text = [[mArray objectAtIndex:indexPath.row] objectForKey:#"firstname"];
cell.detialTextLabel.text = [[mArray objectAtIndex:indexPath.row] objectForKey:#"lastname"];
return cell;
}
I think it will be helpful to you.
This solved my problem
NSDictionary *cellDict = [self.tableInfoArr objectAtIndex:indexPath.row];
//This is to don't care about what is key and value in that dictionary
NSArray *keyArr = [cellDict allKeys];
//As at each index of array only one dictionary exist.
NSString *keyStr = [keyArr objectAtIndex:0];
cell.titleLabel.text = keyStr;
cell.detailLabel.text = [cellDict valueForKey:keyStr];
Related
maybe somebody can help me. I Have different class objects. They'll get created in the TableView.m file with arrays as properties of these objects. How can I populate the TableView out of these Objects so that every cell contains on object? When I am adding the objects to an array I am getting an error, when I am running the simulator.
Error:
App1[6354:7304461] -[Object1 isEqualToString:]: unrecognized selector sent to instance 0x600000455c00
I think that the TableView doensn't know how to create the cell. But I don't have enough experience to know what is really going on.
Thanks
- (void)viewDidLoad {
[super viewDidLoad];
//creating first Object of NSObject Class Object1
Object1 *object1Class = [[WLAN alloc]init];
object1Class.object1PicsCreated = [[NSMutableArray alloc] init];
object1Class.object1TextsCreated = [[NSMutableArray alloc] init];
[object1Class.object1PicsCreated addObject:object1Class.picsObject1];
[object1Class.object1TextsCreated addObject:object1Class.textsObject1];
//creating second Object of NSObject Class Object2
Object1 *object1Class = [[WLAN alloc]init];
object2Class.object2PicsCreated = [[NSMutableArray alloc] init];
object2Class.object2TextsCreated = [[NSMutableArray alloc] init];
[object1Class.object2PicsCreated addObject:object2Class.picsObject2];
[object1Class.object2TextsCreated addObject:object2Class.textsObject2];
if (!_objects){
_objects = [[NSMutableArray alloc] init];
}
[_objects addObject:object1Class]
[_objects addObject:object2Class]
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _objects.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = [_objects objectAtIndex:indexPath.row];
return cell;
}
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:#"%#",[_objects objectAtIndex:indexPath.row]];
Xcode crashes because you pass an instance of Object1 to the setter which expects NSString. UITableView thinks that object is NSString so calls NSString's methods against it (for you it was -isEqualToString:), which is a reason it crashes.
Whatever you want to show needs to be converted to NSString before you pass it there.
How can I populate the TableView out of these Objects so that every cell contains on object?
This is a very strange question. UITableView's rows are UITableViewCell-s. You may not populate a table with anything else.
Maybe, you should describe your tasks in more details.
I am making tableview with different sections programmatically. I am using this code Please help me where i am wrong.
I have to show different sections with different cells ,sections of years and cells of movies.
in .h file
{
NSDictionary *movieTitles;
NSArray *years;
}
#property (nonatomic, retain) NSDictionary *movieTitles;
#property (nonatomic, retain) NSArray *years;
in .m file
#synthesize movieTitles;
#synthesize years;
- (void)viewDidLoad {
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle]pathForResource:#"about" ofType:#"plist"];
NSDictionary *dic = [[NSDictionary alloc]initWithContentsOfFile:path];
movieTitles = dic;
aboutTable = [[UITableView alloc]initWithFrame:CGRectMake(20, 50, self.view.frame.size.width - 40, self.view.frame.size.height) style:UITableViewStyleGrouped];
aboutTable.delegate = self;
aboutTable.dataSource = self;
UIButton *backButton = [[UIButton alloc]initWithFrame:CGRectMake(20, 20, 50, 20)];
[backButton addTarget:self action:#selector(backdb) forControlEvents:UIControlEventTouchUpInside];
[backButton setTitle:#"Back" forState:UIControlStateNormal];
[self.view addSubview:backButton];
[self.view addSubview:aboutTable];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [years count];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *details = [years objectAtIndex:section];
NSArray *titleSection = [movieTitles objectForKey:details];
return [titleSection count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellidentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellidentifier ];
if(!cell)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellidentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
NSString *details = [years objectAtIndex:[indexPath section]];
NSArray *titleSection = [movieTitles objectForKey:details];
cell.textLabel.text = [titleSection objectAtIndex:[indexPath row]];
return cell;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *details = [years objectAtIndex:section];
return details;
}
You are returning the [years count] for numberOfSectionsInTableView. Where you initialise the years?
And also in viewDidLoad, instead of movieTitles = dic, use the below code:-
movieTitles = [dic copy];
where is your "year" value. It count become Zero. and you have to alloc your value.so first of all add object to array.
e.g.years =[[NSArray alloc]initWithObjects:#"2001",#"2002",#"2003", nil];
Table view don't show beacuse "years is nil" when called
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [years count];
}
as the number of section return 0, so the tableveiw could not add.
resolve this issue.
add this line in viewDidLoad method
years = #[#"2015",#"2015"];
- (void)viewDidLoad {
NSArray *arrYear;
arrYear=[[NSArray alloc]initWithObjects:#"1991",
#"1992",
#"1993",
#"1994",nil]
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdetifier = [NSString stringWithFormat:#"Cell_%#",indexPath];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdetifier ];
if(!cell)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdetifier];
cell.textLabel.text = [arrYear objectAtIndex:[indexPath row]];
}
return cell;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return years.count;
}
arrYear=[[NSArray alloc]initWithObjects:#"1991",
#"abc",
#"xyz",
#"123",nil]
You have to initialise Your Array values in didload
I am developing an ios app..Click on button to Pass The Json Array To other UiViewController TableView To Show The Data In TableView..In TableView Array Data Pass on NSDictionary and to Use Dictionary Object. Error is [__NSCFDictionary objectAtIndex:]: Unrecognised selector sent to instance 0x7b115560']...Thanks In Advance
// Button Click
BBAuthorDetailViewController *BBAuthorDetail =[[UIStoryboard storyboardWithName:#"Main" bundle:nil]instantiateViewControllerWithIdentifier:#"BBAuthorDetail"];
[BBAuthorDetail setSelectionType:BBSelectionAuthorName];
_serverObj = [[Server alloc]init];
[_params setObject:_adDetailsObj.authorDetail forKey:#"author"];
[_serverObj BBAuthorNameWithParams:_params];
// BBAuthorDetail.data=resultsArray;
//NSIndexPath *indexPath = [BBAuthorDetail.tableview indexPathForSelectedRow];
BBAuthorDetail.data = [resultsArray objectAtIndex:indexPath.row];
NSLog(#"%#",resultsArray);
//[BBAuthorDetail setManagedObjectContext:self.managedObjectContext];
[self.navigationController pushViewController:BBAuthorDetail animated:YES];
UIViewController Table TO Show Data
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _data.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = [NSString stringWithFormat:#"Cell-%li", (long)indexPath.row];
BBAdsCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
// AdDetails *_adDetailsObj = (AdDetails *)[_data objectAtIndex:indexPath.row];
// NSDictionary *dic = [_data objectAtIndex:indexPath.row];
//AdDetails *_adDetailsObj = [[AdDetails alloc]init];
if (cell == nil) {
cell = [[BBAdsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.row = indexPath.row;
//[cell setDelegate:self];
}
// Error Part
NSDictionary *dic = [_data objectAtIndex:0];
cell.textLabel.text = [dic objectForKey:#"post_author"];
return cell;
}
i'm trying to create a dynamically fixtures which automatic updates using an API. The problem is it does connect the right sections with the right fixtures and the fixtures seem to duplicate in the different sections. Why is it not connecting the section date with the fixtures?
First i have an fixture array which contain all the fixtures.
[fixtures addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:date,#"date", time, #"time", competition_id,#"competition_id", home, #"home", away, #"away", nil]];
Then i have an array with contain all the dates with no duplicates ordered by date called reversedArray:
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"self" ascending:NO];
NSArray *descriptors = [NSArray arrayWithObject: descriptor];
NSArray *reverseOrder = [dateArray sortedArrayUsingDescriptors:descriptors];
reversedArray = [[reverseOrder reverseObjectEnumerator] allObjects];
Then i have my view where i look
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 22)];
/* Create custom view to display section header... */
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, tableView.frame.size.width, 22)];
[label setFont:[UIFont boldSystemFontOfSize:14]];
[label setTextColor:[UIColor whiteColor]];
NSString *dateString = [NSString stringWithFormat:#"%#",[reversedArray objectAtIndex:section]];
NSString *newString = [dateString substringToIndex:[dateString length]-15];
NSString *string =[NSString stringWithFormat:#"%#",newString];
[label setText:string];
[view addSubview:label];
[view setBackgroundColor:[UIColor colorWithRed:13/255.0f green:78/255.0f blue:102/255.0f alpha:1.0f]];
return view;
}
The numberOfRowsInSection method
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *dateString = [NSString stringWithFormat:#"%#",[reversedArray objectAtIndex:section]];
NSLog(#"%# = %#", [dateString substringToIndex:[dateString length]-15], [[fixtures objectAtIndex:section] valueForKey:#"date"]);
NSArray *filteredArray = [fixtures filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"date == %#",[dateString substringToIndex:[dateString length]-15]]];
return filteredArray.count;
}
cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FixtureCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
cell = [[FixtureCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
cell.homeTeamLabel.text = [[fixtures objectAtIndex:indexPath.row] objectForKey:#"home" ];
cell.awayTeamLabel.text = [[fixtures objectAtIndex:indexPath.row] objectForKey:#"away" ];
}
take out this code from your if sentence
cell.homeTeamLabel.text = [[fixtures objectAtIndex:indexPath.row] objectForKey:#"home" ];
cell.awayTeamLabel.text = [[fixtures objectAtIndex:indexPath.row] objectForKey:#"away" ];
you are reusing cells so the condition cell=nil will no be true always.
Also use indexPath.section for to know which data you should take for fill your cell
Assign label values outside if (cell == nil) reuse cell Identifier not enter the loop after cell creation
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FixtureCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
cell = [[FixtureCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
cell.homeTeamLabel.text = [[fixtures objectAtIndex:indexPath.row] objectForKey:#"home" ];
cell.awayTeamLabel.text = [[fixtures objectAtIndex:indexPath.row] objectForKey:#"away" ];
return cell;
}
Change this method cellForRowAtIndexPath method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
FixtureCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil)
{
cell = [[FixtureCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
cell.homeTeamLabel.text = [[fixtures objectAtIndex:indexPath.row] objectForKey:#"home"];
cell.awayTeamLabel.text = [[fixtures objectAtIndex:indexPath.row] objectForKey:#"away"];
return cell;
}
If you are using custom cell then try this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"FixtureCell";
FixtureCell *cell = (FixtureCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"FixtureCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.homeTeamLabel.text = [[fixtures objectAtIndex:indexPath.row] objectForKey:#"home"];
cell.awayTeamLabel.text = [[fixtures objectAtIndex:indexPath.row] objectForKey:#"away"];
return cell;
}
Im parsing JSON data in an external class (NSObject) class that then put organizes the parsed data into an array. That array is then placed into my Table View. Because it takes longer to parse the info then to finish viewDidLoad the array is always set to nil.
Code:
- (void)viewDidLoad
{
//Fetching Data
[super viewDidLoad];
myClass = [[MyClass alloc] init];
[myClass fetchDataWithTarget:self];
//Initialize the dataArray
dataArray = [[NSMutableArray alloc] init];
//First section data
NSArray *firstItemsArray = myClass.fechedDataArray;
NSDictionary *firstItemsArrayDict = [NSDictionary dictionaryWithObject:firstItemsArray forKey:#"data"];
[dataArray addObject:firstItemsArrayDict];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
NSDictionary *dictionary = [dataArray objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"data"];
NSString *cellValue = [array objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}
How can I insure that firstItemsArray is set after the data is fetched.
Note: There is obviously more to the table view then this, I did all the dictionary stuff to separate sections and what not.
You'll have to load the JSON data into the array BEFORE
- (void) viewDidLoad
or use some type threading (asynchronous method) such as:
performSelectorInBackground:withObject
NSOperation or Grand Central Dispatch