I am quite new to Objective-C and this is the first time I have attempted to implement MVC. I have a model class where l have an NSArray
which will be populated with data from a JSON object. I want to populate my UITableView
(in my view controller class), with objects from this array.
Please review my code:
Droplets.h
@interface Droplets : NSObject {
NSArray *dropletsArray;
}
// Get droplets data
- (void) getDropletsList;
//Object initilization
- (id) init;
//Public properties
@property (strong, nonatomic) NSArray *dropletsArray; // Used to store the selected JSON data objects
@end
Droplets.m
#define kBgQueue dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define kDigialOceanApiURL [NSURL URLWithString:@"http://inspiredwd.com/api-test.php"] //Droplets API call
#import "Droplets.h"
@interface Droplets ()
//Private Properties
@property (strong, nonatomic) NSMutableData *data; // Used to store all JSON data objects
@end
@implementation Droplets;
@synthesize dropletsArray;
@synthesize data;
- (id)init
{
self = [super init];
if (self) {
}
return self;
}
- (void) getDropletsList {
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = kDigialOceanApiURL; // Predefined Digital Ocean URL API http request
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection connectionWithRequest:request delegate:self]; //Should be: [[NSURLConnection alloc]initiWithRequest:request delegate:self]; ...however the instance of NSURLConnection is never used, which results in an "entity unsed" error.
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
data = [[NSMutableData alloc]init]; // mutable data dictionary is allocated and initilized
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData {
[data appendData:theData]; // append 'theData' to the mutable data dictionary
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
//JSON foundation object returns JSON data from a foundation object. Assigned returned data to a dictionary 'json'.
NSDictionary* jsonData = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions error:0];
self.dropletsArray = [jsonData objectForKey:@"droplets"]; //dictionary of arrays
NSLog(@"Droplets %@", self.dropletsArray);
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// If the application is unable to connect to The Digital Ocean Server, then display an UIAlertView
UIAlertView *errorView = [[UIAlertView alloc]initWithTitle:@"Error" message:@"Unable to connect to The Digital Ocean Server, please ensure that you are connected via either WIFI or 3G." delegate:nil cancelButtonTitle:@"Dismiss" otherButtonTitles:nil];
[errorView show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO; // Turn of the network activity indicator
}
@end
DropletsList.h
@class Droplets;
@interface DropletsList : UITableViewController
- (Droplets *) modelDroplets;
@end
DropletsList.m
#define RGB(r, g, b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1]
@interface DropletsList ()
//Private properties
@property (strong, nonatomic) Droplets *modelDroplets;
@property (strong, nonatomic) NSArray *tableData;
@end
@implementation DropletsList
@synthesize tableData;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
NSLog(@"get my data from model");
}
return self;
}
- (Droplets *) modelDroplets
{
if (!_modelDroplets) _modelDroplets = [[Droplets alloc]init];
return _modelDroplets;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_modelDroplets = [[Droplets alloc]init];
self.tableData = [_modelDroplets dropletsArray];
[_modelDroplets getDropletsList];
[self.tableView reloadData]; // reload the droplets table controller
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)aTableView {
return 1; // Return the number of sections.
}
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
return [_modelDroplets.dropletsArray count]; // Return the number of rows in the section.
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// The cell identified by "dropletsList", is assiged as the UITableViewCell
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:@"dropletsList"];
//NSLog(@"Droplets Name: %@",self.dropletsArray);
// The UITableView text label is assigned the contents from 'dropletsArray', with the object key "name"- name of the droplet
cell.textLabel.text=[[tableData objectAtIndex:indexPath.row]objectForKey:@"name"];
// The UITableView text detail label is assigned the contents from 'dropletsArray', with the object key "status"- status of the droplet
cell.detailTextLabel.text=[[tableData objectAtIndex:indexPath.row]objectForKey:@"status"];
//Evalulate the status of each droplet, setting the colour appropriate to the staus
if ([[[tableData objectAtIndex:indexPath.row] objectForKey:@"status"] isEqualToString:@"active"]) {
//Set the detail text label colour
cell.detailTextLabel.textColor = RGB (35,179,0);
}
return cell;
}
@end
Basically my table doesn't populate. Please could someone help?
In this method you are fetching droplets from a webservice. It is asynchronous, by the time tableView reloads the data it might not have completed fetching the data. You need to have a callback which will reload the tableView on completion of webservice.
EDIT :
Create a class method in
Droplets
to fetch all dataDisclaimer : Tested and verified :)