I'd like to create a simple reference app that lists a group of people, their job title, and their portrait. What I have so far is the list of people and their job title. It works alright, but I think I should have done it differently.
From reading other posts, I suppose I should be using dictionaries. This is how my PList currently looks:
And this is how the important bits of my code look:
#implementation RootViewController
#synthesize staffArray, subtitleArray;
- (void)viewDidLoad
{
[super viewDidLoad];
NSString* path = [[NSBundle mainBundle] pathForResource:#"StaffData" ofType:#"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSMutableArray *tmpNameArray = [dict objectForKey:#"Root"];
self.staffArray = [[NSMutableArray alloc] initWithArray:tmpNameArray copyItems:YES];
NSMutableArray* tmpSubtitleArray = [dict objectForKey:#"Subs"];
self.subtitleArray = [[NSMutableArray alloc] initWithArray:tmpSubtitleArray copyItems:YES];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [staffArray count];
}
// 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:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
cell.textLabel.text = [staffArray objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [subtitleArray objectAtIndex:indexPath.row];
return cell;
}
Using two arrays kind of defeats the purpose of OOP, I think, because in this case the people aren't connected to their job titles; they just happen to be in the same order. I'd like to create for example:
Array called Jonas, first value = job title, second value = pathToImage.png.
Another array called Andreas, etc etc etc.
What do I do?
I think that as a start, your design lacks an "Employee" object, that has data members like "Name", "JobTitle", etc... After you have this set up, just create an array of people and take whatever you need from there, by index.
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.
Hi guys I am new to Objective C. I want to make an app where it can read a csv file locally and display the data in a specific column in the tableview.
1)Read csv locally
2)Display csv data (let's say fifth column "ItemName") in the tableview
Thanks for any advice.
- (void)viewDidLoad {
[super viewDidLoad];
NSString *strPath = [[NSBundle mainBundle] pathForResource:#"issues" ofType:#"csv"];
NSString *strFile = [NSString stringWithContentsOfFile:strPath encoding:NSUTF8StringEncoding error:nil];
if (!strFile) {
NSLog(#"Error reading file.");
}
issues = [[NSArray alloc] init];
issues = [strFile componentsSeparatedByString:#","];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return[issues count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [issues objectAtIndex:indexPath.row];
return cell;
}
The way you do the parsing is only making columns of the whole file. First you need to separate by line-breaks (probably '\n'), then you can separate each line by ',' and each time take the 5th element and add it to an NSMutableArray (issues).
[strFile componentsSeparatedByString:#","] is not really CSV-parsing, there are more complex libraries available for that on cocoapods. If you need error-handling, etc. you better go with a library.
I am trying to get my NSdictionary values into a UITableViewCell. Here is my dictionary format:
{
date = "3/4/14, 3:33:01 PM Pacific Standard Time";
weight = 244;
}
Here is the code I'm using to populate my uitableview (which is not working).
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"WeightCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
NSArray* allKeys = [weights allKeys];
NSDictionary *obj = [allKeys objectAtIndex: indexPath.row];
cell.textLabel.text = [obj objectForKey: #"date"];
cell.detailTextLabel.text = [obj objectForKey:#"weight"];
return cell;
}
You should try initialising the array for the tableView outside of the tableView itself... something along the lines of
- (void)viewDidLoad
{
[super viewDidLoad];
_allKeys = [[NSMutableArray alloc] initWithArray:[weights allKeys]];
}
Once you have initialised that data you can access it throughout the process. Also to find out how many rows your tableview needs.
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_allKeys count];
}
Then when you access the array into a dictionary it has retained the row count and can access it properly.
NSDictionary *obj = [_allKeys objectAtIndex: indexPath.row];
cell.textLabel.text = [obj objectForKey: #"date"];
cell.detailTextLabel.text = [obj objectForKey:#"weight"];
From what I can see the dictionary cant access the array at your indexPath.row because you haven't initialised the array anywhere before you use it in your tableView.
Hope that helps, T
Some of the other posters have good suggestions. However, this line:
NSDictionary *obj = [allKeys objectAtIndex: indexPath.row];
Is wrong. allKeys is an array of your dictionary keys, which are presumably strings.
So, you want code like this instead:
NSString *thisKey = allKeys[indexPath.row];
NSDictionary *obj = weights[thisKey];
Note that I am using the new Objective C literal syntax. The expression weights[thisKey] is equivalent to [weights objectForKey: thisKey]
I don't see the definition of the weights object. If you want to keep adding NSDictionary's to an array, you need to use an NSMutableArray, and you'll probably want to do that by setting it as a #property on your class. Let's say you added it like this:
#property (strong, nonatomic) NSMutableArray *weights;
Then in your tableView:cellForRowAtIndexPath: method you'll want to get the NSDictionary corresponding to that line by using self.weights[indexPath.row]. Also don't forget to instantiate weights before using it, otherwise it will return nil and no objects are going to be added to it.
P.S.: the user provided some context here and what he probably needs is Core Data.
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
I have a program that connects to a MAMP server and selects my database and displays the contents in the Xcode simulator. Right now I have 2 tabs and the data is the same for both. I want the tabs to seperate the type of data to display in each tab. (1 tab should display types of wine grape and the other displays wine countries)
I think that I have to make a class (subclass of NSObject) that pulls the data, then another view controller with a mutable array that holds the data needed for each tab but HOW do I do this? How do I create a MutableArray?
Here the code in my TableViewController.m, which connects to my database using JSON:
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:#"http://[localhost]:8888/wine.php"]; // Modify this to match your url.
NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL:url]; // Pulls the URL
NSLog(jsonreturn); // Look at the console and you can see what the restults are
NSData *jsonData = [jsonreturn dataUsingEncoding:NSUTF32BigEndianStringEncoding];
NSError *error = nil;
// In "real" code you should surround this with try and catch
NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
if (dict)
{
rows = [[dict objectForKey:#"wine"] retain];
}
NSLog(#"Array: %#",rows);
[jsonreturn release];
}
Then I created another method for the tableview:
pragma mark - Table view data source
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [rows count];
}
// 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:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
NSDictionary *dict = [rows objectAtIndex: indexPath.row];
//cell.textLabel.text = [dict objectForKey:#"id"];
//cell.textLabel.text = [dict objectForKey:#"wineColor"];
//cell.textLabel.text = [dict objectForKey:#"wineGrape"];
cell.textLabel.text = [dict objectForKey:#"wineCountry"];
cell.detailTextLabel.text = [dict objectForKey:#"id"];
return cell;
}
with this, the same data (the wine countries) is displayed in both Grape & Country tabs. How can I create a Mutable Array that will grab what data should be displayed in each tab?
You need the second (Grape) view controller to implement the tableView datasource and delegate methods for its own tableview, but you don't need another array, you can use your JSON dictionary, but add the proper text to labels within your cells for grapes (in the cellForRowAtIndexPath UITableView datasource method). You would use the lines above that are currently commented out to populate your labels in cells of your "Grape" table view:
//cell.textLabel.text = [dict objectForKey:#"wineColor"];
//cell.textLabel.text = [dict objectForKey:#"wineGrape"];
You could add a custom UITableViewCell or use the subtitle style and set the subtitle to color.