Reputation: 15
I've been able to get data from a local JSON file to display in a tableview
but it's displaying like this:
.......................cell1...............................
Biscuits
3 cups All-purpose Flour
2 Tablespoons Baking Powder
1/2 teaspoon Salt
.......................cell2...............................
12 whole Dinner Rolls Or Small Sandwich Buns (I Used Whole Wheat)
1 pound Thinly Shaved Roast Beef Or Ham (or Both!)
......................................................
And I need it to display each ingredient separated into its own cell like this:
.......................cell1...............................
Biscuits
.......................cell2...............................
3 cups All-purpose Flour
.......................cell3...............................
2 Tablespoons Baking Powder
.......................cell4...............................
1/2 teaspoon Salt
.......................cell5...............................
12 whole Dinner Rolls Or Small Sandwich Buns (I Used Whole Wheat)
.......................cell6...............................
1 pound Thinly Shaved Roast Beef Or Ham (or Both!)
...........................................................
What code would I need to display the data correctly? Heres my current code:
/////////locations.json/////////////////////////////
{
"locations": [
{ "ingredients" : "Biscuits\n3 cups All-purpose Flour\n2 Tablespoons Baking Powder\n1/2 teaspoon Salt\nShortened for example” },
{ "ingredients" : "12 whole Dinner Rolls Or Small Sandwich Buns (I Used Whole Wheat)\n1 pound Thinly Shaved Roast Beef Or Ham (or Both!)\nShortened for example” },
//many more records. only included 2 for example
]
}
/////////Location.h/////////////////////////////////////////
#import <Foundation/Foundation.h>
@interface Location : NSObject
- (id)initWithJSONDictionary:(NSDictionary *)jsonDictionary;
@property (readonly) NSString *ingredients;
@end
////////Location.m////////////////////////////////////
#import "Location.h"
@implementation Location
// Init the object with information from a dictionary
- (id)initWithJSONDictionary:(NSDictionary *)jsonDictionary {
if(self = [self init]) {
// Assign all properties with keyed values from the dictionary
_ingredients = [jsonDictionary objectForKey:@"ingredients"];
}
return self;
}
@end
////////JSONLoader.h////////////////////////////////////
#import <Foundation/Foundation.h>
@interface JSONLoader : NSObject
// Return an array of Location objects from the json file at location given by url
- (NSArray *)locationsFromJSONFile:(NSURL *)url;
@end
////////JSONLoader.m////////////////////////////////////
#import "JSONLoader.h"
#import "Location.h"
@implementation JSONLoader
- (NSArray *)locationsFromJSONFile:(NSURL *)url {
// Create a NSURLRequest with the given URL
NSURLRequest *request = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:30.0];
// Get the data
NSURLResponse *response;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
// Now create a NSDictionary from the JSON data
NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
// Create a new array to hold the locations
NSMutableArray *locations = [[NSMutableArray alloc] init];
// Get an array of dictionaries with the key "locations"
NSArray *array = [jsonDictionary objectForKey:@"locations"];
// Iterate through the array of dictionaries
for(NSDictionary *dict in array) {
// Create a new Location object for each one and initialize it with information in the dictionary
Location *location = [[Location alloc] initWithJSONDictionary:dict];
// Add the Location object to the array
[locations addObject:location];
}
// Return the array of Location objects
return locations;
}
@end
////////TableViewController.h////////////////////////////////////
#import <UIKit/UIKit.h>
#import "Location.h"
@interface FilterViewController : UITableViewController
@property (weak, nonatomic) Location *location;
@end
////////TableViewController.m////////////////////////////////////
#import "FilterViewController.h"
#import "LocationsViewController.h"
#import "Location.h"
#import "JSONLoader.h"
@implementation FilterViewController {
NSArray *_locations;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Create a new JSONLoader with a local file URL
JSONLoader *jsonLoader = [[JSONLoader alloc] init];
NSURL *url = [[NSBundle mainBundle] URLForResource:@"locations" withExtension:@"json"];
// Load the data on a background queue...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
_locations = [jsonLoader locationsFromJSONFile:url];
// Now that we have the data, reload the table data on the main UI thread
[self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES];
});
}
// Just before showing the LocationDetailViewController, set the selected Location object
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
LocationsViewController *vc = segue.destinationViewController;
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
vc.location = [_locations objectAtIndex:indexPath.row];
}
#pragma mark - Table View Controller Methods
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"FilterCell"];
Location *location = [_locations objectAtIndex:indexPath.row];
cell.textLabel.text = location.ingredients;
cell.imageView.image = [UIImage imageNamed:@"ingredientsicon3232.png"];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_locations count];
}
@end
Note: I'm unable to change the JSON data format as it's from an outside source and there's a lot more "ingredients" keys than I posted in the example.
Upvotes: 0
Views: 117
Reputation: 1790
Edit:
Some sample code for you to get a working.
// JSONLoader.m
- (NSArray *)locationsFromJSONFile:(NSURL *)url {
// Existing code .......
// Get an array of dictionaries with the key "locations"
NSArray *array = [jsonDictionary objectForKey:@"locations"];
// Iterate through the array of dictionaries
for(NSDictionary *dict in array) {
NSString *string = [dict objectForKey:@"ingredients"];
NSArray *brokenIntoParts = [string componentsSeparatedByString:@"\n"];
for (NSString *ingredient in brokenIntoParts) {
[locations addObject:ingredient];
}
}
// Return the array of Location objects
return locations;
}
// FilterViewController.m
#pragma mark - Table View Controller Methods
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"FilterCell"];
cell.textLabel.text = [_locations objectAtIndex:indexPath.row];
cell.imageView.image = [UIImage imageNamed:@"ingredientsicon3232.png"];
return cell;
}
Original:
Your code looks fine, actually just change your data,
{
"locations": [ { "ingredients" : "Biscuits"},
{ "ingredients" : "3 cups All-purpose Flour"},
{ "ingredients" : "Tablespoons Baking Powder"}
.
.
.
]}
This should solve your problem, basically you want key:value of "keyword":ingredient, please comment if it does not, good luck.
Upvotes: 1
Reputation: 285069
This code extracts the ingredients
from the dictionary using the key-value coding method valueForKey
and converts the newline separated strings to an array.
NSDictionary *jsonDictionary = @{@"locations" : @[@{ @"ingredients" : @"Biscuits\n3 cups All-purpose Flour\n2 Tablespoons Baking Powder\n1/2 teaspoon Salt\nShortened for example" },
@{ @"ingredients" : @"12 whole Dinner Rolls Or Small Sandwich Buns (I Used Whole Wheat)\n1 pound Thinly Shaved Roast Beef Or Ham (or Both!)\nShortened for example" }]};
NSArray* locations = jsonDictionary[@"locations"];
NSMutableArray *ingredients = [NSMutableArray array];
NSArray *jsonIngredients = [locations valueForKey:@"ingredients"];
for (NSString *ingredient in jsonIngredients) {
[ingredients addObjectsFromArray:[ingredient componentsSeparatedByString:@"\n"]];
}
NSLog(@"%@", ingredients);
The result ingredients
can be used directly as the data source array.
Edit:
Your model class Location
is actually incompatible with the JSON data format
To try the code you have to assign the result ingredients
to your data source array _locations
_locations = ingredients;
Then in cellForRowAtIndexPath
replace the lines
Location *location = [_locations objectAtIndex:indexPath.row];
cell.textLabel.text = location.ingredients;
with
NSString *ingredient = _locations[indexPath.row];
cell.textLabel.text = ingredient;
PS: If you are also responsible for the JSON on the server side consider to use a more convenient data format.
Upvotes: 0