NSMutableArray is empty when reaches numberOfRowsInSection and cellForRowAtIndexPath - ios

I am trying to to pretty standard operation, which is basically, getting all records form my local SQLITE database, then getting additional data form web, merge this data (which is NSMutableArray) and display it in table view. In viewDidLoad, array has all required elements, but in numberOfRowsInSection: it equals to nil. Because of this, I cannot display items in tableview. So where could it get set to nil? Thank you for any help.
Code for InboxViewControler.m
//
// ArticleViewController.m
// ReadLater
//
// Created by Ibragim Gapuraev on 09/06/2014.
// Copyright (c) 2014 Sermilion. All rights reserved.
//
#import "InboxViewController.h"
#import "LoginViewController.h"
#import "SHCTableViewCell.h"
#interface InboxViewController ()
#end
#implementation InboxViewController
#synthesize db, articles, response, jsonData;
- (NSMutableArray* ) articles
{
if (!articles) {
articles = [[NSMutableArray alloc] initWithCapacity:20];
}
return articles;
}
- (Database* ) db
{
if (!db) {
db = [[Database alloc] init];
}
return db;
}
//---------------------------------Getting data from web-------------------------------------------//
/**
The method will connect to a given url and send date of article that has been added at last.
Then, connectionDidFinishLoading will receive json array of all articles, that have been added to server database after that time
**/
#pragma mark Connection to server
- (void) makeConnetion:(id)data
{
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://localhost/nextril/index.php"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15.0];
NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
//send id of article that was added last, to server,
//which will return json arrya of all articles with id greater then the one sent
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[data dataUsingEncoding:NSUTF8StringEncoding]];
if (connection) {
NSLog(#"viewWillAppear: Connecting to server to get data...");
}else{
NSLog(#"viewWillAppear: Error while connecting...");
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData*)data
{
response = [[NSData alloc] initWithData:data];
}
//Check if data been received
- (void) connectionDidFinishLoading:(NSURLConnection *)connection
{
if(sizeof(response)>0){
//NSLog(#"Got response from server %#", response);
NSError* error;
NSArray* json = [NSJSONSerialization
JSONObjectWithData:response //1
options:kNilOptions
error:&error];
self.jsonData = [[NSMutableArray alloc] initWithArray:json];
int count = 0;
[self.db openDatabase];
BOOL added = false;
BOOL addedToUser = false;
NSLog(#"jsonData %d", jsonData.count);
for (int i=0; i<self.jsonData.count; i++) {
NSDictionary *item = [self.jsonData objectAtIndex:i];
NSString* content = [item objectForKey:#"content"];
NSString* author = [item objectForKey:#"author"];
NSString* date = [item objectForKey:#"date"];
NSString* url = [item objectForKey:#"url"];
NSString* tags = [item objectForKey:#"tags"];
NSInteger archived = [[item objectForKey:#"archived"]integerValue];
NSString* title = [item objectForKey:#"title"];
//NSLog(#"",);
Article* article = [[Article alloc]initWithId:0 content:content author:author date:date url:url tags:tags arhived:archived title:title];
added = [self.db addArticleToArticleDB:article];
if (added == true) {
NSInteger last_id = [self.db getLastArticleID];
article.article_id = last_id;
[self.articles addObject:article];
addedToUser = [self.db addArticleToUserArticleDB:article];
}
count++;
}
if (added == true && addedToUser == true) {
NSLog(#"connectionDidFinishLoading: Articles has been imported. Size: %d %lu", jsonData.count, (unsigned long)jsonData.count);
}else{
NSLog(#"connectionDidFinishLoading: Failed to import article.");
}
NSArray *importedArticles = [self.db importAllArticlesForUser:16 archived:0];
[self.articles addObjectsFromArray:importedArticles];
[self.db closeDatabase];
}else{
NSLog(#"connectionDidFinishLoading: Did not get resopnse from server: %#", response);
}
connection = nil;
}
//----------------------------------------------------------------------------------------------------
#pragma mark TODO: work out why data from server loads only after second login
#pragma mark view
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.db openDatabase];
NSString* date_added = [self.db getLastArticleDate];
[self makeConnetion:(id)date_added];
NSLog(#"viewWillAppear: self.articles: %d", self.articles.count);
[self.db closeDatabase];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.tableView.separatorColor = [UIColor clearColor];
self.tableView.backgroundColor = [UIColor blackColor];
[self.tableView registerClass:[SHCTableViewCell class] forCellReuseIdentifier:#"Content"];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSLog(#"numberOfRowsInSection: self.articles: %d", self.articles.count);
return self.articles.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Content";
SHCTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.textLabel.backgroundColor = [UIColor clearColor];
NSMutableArray* safeArticles = self.articles;
// Configure the cell...
Article* article = [safeArticles objectAtIndex:indexPath.row];
NSString *listingKey = article.title;
NSString *listingValues = article.url;
cell.textLabel.text = listingKey;
cell.detailTextLabel.text = listingValues ;
cell.delegate = self;
cell.todoItem = article;
return cell;
}
#pragma mark cell atributes
-(UIColor*)colorForIndex:(NSInteger) index {
NSUInteger itemCount = self.articles.count - 1;
float val = ((float)index / (float)itemCount) * 0.6;
return [UIColor colorWithRed: 1.0 green:val blue: 0.0 alpha:1.0];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 70.0f;
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.backgroundColor = [self colorForIndex:indexPath.row];
}
#pragma mark TODO delete from server database
//method to delete an article form view and to call method to delete from database, as well as form server database
-(void)deleteArticle:(Article*)articleToDelete {
. . .
}
#pragma mark TODO delete from server database
//method to delete an article form view and to call method to delete from database, as well as form server database
-(void)archiveArticle:(Article*)articleToArchive {
. . .
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end

A tableView calls the datasource methods to populate itself just after viewDidLoad. If, at that point, the data source (which is usually an Array) is empty, nothing will appear in the tableView. That is why one has to call reloadData after the data source is brought into existence. This is especially needed in cases the data source is being fetched asyncronously.
According to Apple's documentation about reloadData:
Call this method to reload all the data that is used to construct the
table, including cells, section headers and footers, index arrays, and
so on. For efficiency, the table view redisplays only those rows that
are visible. It adjusts offsets if the table shrinks as a result of
the reload. The table view's delegate or data source calls this
method when it wants the table view to completely reload its data. It
should not be called in the methods that insert or delete rows,
especially within an animation block implemented with calls to
beginUpdates and endUpdates

Took advice of #akashg and added [self.tableView reloadData]; after fetching data. And it worked. Though, I don't know the mechanism of why this happened. At least it works ) Anyone welcome to add their explanation. Thank you.

Related

Grouped Tableview From JSON Data

I've been following a tutorial on YouTube and trying to expand its functionality. I figured out how to send the retrieveData method to a background thread using GCD, figured out how to use Reachability to keep the app from crashing when in Airplane Mode, and now I'm trying to change the tableview to a grouped style. After a couple of weeks I'm at my wit's end.
What I want to do is have the UITableView grouped using the key "country" to establish the groups, and any city within that country appear in the group's cells. The number of countries in the database will change, as will the number of cities.
I'm not even sure it's possible given the data structure, but if it is, I could use some suggestions.
The JSON data is structured like this:
[{"id":"1","cityName":"London","cityState":"London","cityPopulation":"8173194","country":"United Kingdom"}
Here is the .m file:
#import "CitiesViewController.h"
#import "City.h"
#import "DetailViewController.h"
#import "Reachability.h"
#define getDataUrl #"http://www.conkave.com/iosdemos/json.php"
#interface CitiesViewController ()
#end
#implementation CitiesViewController
#synthesize jsonArray, citiesArray;
- (void)viewDidLoad {
[super viewDidLoad];
//Set the title of our VC
self.title = #"Cities of the World";
//Load data
[self retrieveData];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return citiesArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
City * cityObject;
cityObject = [citiesArray objectAtIndex:indexPath.row];
cell.textLabel.text = cityObject.cityName;
cell.detailTextLabel.text = cityObject.cityCountry;
//Accessory
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
#pragma mark - Navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if ([[segue identifier] isEqualToString:#"pushDetailView"])
{
NSIndexPath * indexPath = [self.tableView indexPathForSelectedRow];
//Get the object for the selected row
City * object = [citiesArray objectAtIndex:indexPath.row];
[[segue destinationViewController] getCity:object];
}
}
#pragma mark -
#pragma mark Class Methods
- (void) retrieveData;
{
Reachability *networkReachability = [Reachability reachabilityForInternetConnection];
NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];
if (networkStatus == NotReachable) {
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"No Internet"
message:#"You must have an internet connection for this feature"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[message show];
[self.refreshControl endRefreshing];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
return;
}
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
//Retrieve the data asynchronously
dispatch_async(queue, ^{
NSURL * url = [NSURL URLWithString:getDataUrl];
NSData * data = [NSData dataWithContentsOfURL:url];
jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
//Set up our cities array
citiesArray = [[NSMutableArray alloc] init];
//Loop through our jsonArray
for (int i = 0; i < jsonArray.count; i++)
{
//Create our city object
NSString * cID = [[jsonArray objectAtIndex:i] objectForKey:#"id"];
NSString * cName = [[jsonArray objectAtIndex:i] objectForKey:#"cityName"];
NSString * cState = [[jsonArray objectAtIndex:i] objectForKey:#"cityState"];
NSString * cPopulation = [[jsonArray objectAtIndex:i] objectForKey:#"cityPopulation"];
NSString * cCountry = [[jsonArray objectAtIndex:i] objectForKey:#"country"];
//Add the city object to our cities array
[citiesArray addObject:[[City alloc] initWithCityName:cName andCityState:cState andCityCountry:cCountry andcityPopulation:cPopulation andCityID:cID]];
}
//Back to main thread to update UI.use dispatch_get_main_queue() to get main thread
dispatch_sync(dispatch_get_main_queue(), ^{
//Reload our table view
[self.tableView reloadData];
});
});
}
#end
You can group the data yourself pretty easily in a few ways. One way is by using an array for ordering the countries and a dictionary to group the cities within them.
After you are done creating your City objects, you can do something like this:
// you probably want to save these as instance properties
NSMutableArray *countries = [NSMutableArray new];
NSMutableDictionary *citiesForCountries = [NSMutableDictionary new];
for(City *city in citiesArray)
{
NSString *currentCountry = city.country;
NSMutableArray *citiesInCountry = citiesForCountries[#"currentCountry"];
// first city for this country, so add it to our ordered list and create an array to populate with cities
if(! citiesInCountry)
{
[countries addObject:currentCountry];
citiesInCountry = [NSMutableArray new];
citiesForCountries[#"currentCountry"] = citiesInCountry;
}
[citiesInCountry addObject:city];
}
// Then here are some of the relevant methods on how you would use these data structures
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return countries.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *country = countries[section];
NSArray *cities = citiesForCountries[country];
return cities.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
City * cityObject;
NSString *country = countries[indexPath.section];
NSArray *cities = citiesForCountries[country];
cityObject = cities[indexPath.row];
cell.textLabel.text = cityObject.cityName;
cell.detailTextLabel.text = cityObject.cityCountry;
//Accessory
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}

tableView unable to display data parsed from the web in json format

I created an api using kimono and here is my code.
#import "PlayerRankingsTableViewController.h"
#import "RankingsTableViewCell.h"
#define kBgQueue dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define kPlayerRankingsURL [NSURL URLWithString:#"https://www.kimonolabs.com/api/bg6tcuuq?apikey=xgp4nU6xA9UcBWSe0MIHcBVbAWz5v4wR"]
#interface PlayerRankingsTableViewController () {
}
#property (nonatomic, strong) NSArray *playerRankings;
#end
#implementation PlayerRankingsTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(kBgQueue, ^{
NSData *data = [NSData dataWithContentsOfURL:
kPlayerRankingsURL];
[self performSelectorOnMainThread: #selector(initializePlayerRankingsArray:)
withObject:data waitUntilDone:YES];
});
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be rexrcreated.
}
- (NSArray *)initializePlayerRankingsArray:(NSData *)responseData {
NSError* error;
NSDictionary *json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSArray *myPlayerRankings = [[json objectForKey:#"results"]objectForKey:#"collection1"];
self.playerRankings = myPlayerRankings;
NSLog(#"%#", self.playerRankings);
return self.playerRankings;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.playerRankings count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RankingsTableViewCell *cell = (RankingsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
cell = (RankingsTableViewCell *)[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
NSDictionary *rankings = [self.playerRankings objectAtIndex: indexPath.row];
NSString *rank = [rankings objectForKey:#"rank"];
NSString *name = [rankings objectForKey:#"name"];
NSString *points = [rankings objectForKey:#"points"];
[cell.playerRank setText:rank];
cell.playerName.text = name;
cell.playerPoints.text = points;
return cell;
}
#end
I think there is nothing wrong with data parsing process, because the console displays my data parsed from the web correctly.
However, when I ran the app, I saw nothing but a empty table.
Again, I think this might be something simple and new to programming.
Thank you in advance, and sorry for being such a burden.
In initializePlayerRankingsArray: you shouldn't be returning the array because nothing it there to receive it. You have already set self.playerRankings, so that is enough.
What is missing from this method is [self.tableView reloadData]; (which should be the last line after self.playerRankings is set).

Table View still blank?

I have a problem with my tableview. I'm trying to make a program that downloads job details from my database and lists them. The tableview is still blank, the view is connected to the specific controller and I have checked that the JSON feed and cell identifier are OK. My cell rows are also strange, the row lines continue over the right edge though I have aligned the tableview object correctly. I had similar problems with my previous project but didn't know what was wrong.
Here is a part of the code (Source from: http://codewithchris.com/iphone-app-connect-to-mysql-database/)
JobViewer.m
#interface JobViewer()
{
NSMutableData *_downloadedData;
}
#end
#implementation JobViewer
- (void)downloadItems
{
// Getting json file
NSURL *jsonFileURL = [NSURL URLWithString:#"here is my correct URL"];
//Making request
NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:jsonFileURL];
//Creating NSURLConnection with the request
[NSURLConnection connectionWithRequest:urlRequest delegate:self];
}
#pragma mark NSURLConnectionDataProtocol Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
//Initialize data
_downloadedData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//Append the data that was downloaded
[_downloadedData appendData:data];
}
- (void)connectionDidFinishDownloading:(NSURLConnection *)connection
{
//Creating array for the information
NSMutableArray *_jobs = [[NSMutableArray alloc] init];
// Parsing the JSON file
NSError *error;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:_downloadedData options:NSJSONReadingAllowFragments error:&error];
//Looping through JSON objects and storing them into array
for (int i = 0; i < jsonArray.count; i++)
{
NSDictionary *jsonObject = jsonArray[i];
//Creating a new object and getting data from JSON element
Job *newJob = [[Job alloc] init];
newJob.jobid = jsonObject[#"Job_id"];
newJob.companyid = jsonObject[#"Company_id"];
newJob.customer = jsonObject[#"Customer"];
newJob.phone = jsonObject[#"Phone"];
newJob.email = jsonObject[#"Email"];
newJob.address = jsonObject[#"Address"];
newJob.city = jsonObject[#"City"];
newJob.header = jsonObject[#"Header"];
newJob.notes = jsonObject[#"Notes"];
newJob.date = jsonObject[#"Date"];
newJob.driver = jsonObject[#"Driver"];
//Added question to array
[_jobs addObject:newJob];
}
// Passing the done data and passing items back
if (self.delegate)
{
[self.delegate itemsDownloaded:_jobs];
}
}
#end
MainViewController.m
#interface MainViewController ()
{
JobViewer *_jobViewer;
NSArray *_listObjects;
}
#end
#implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.mainList.delegate = self;
self.mainList.dataSource = self;
_listObjects = [[NSArray alloc] init];
_jobViewer = [[JobViewer alloc] init];
_jobViewer.delegate = self;
[_jobViewer downloadItems];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)itemsDownloaded:(NSArray *)items
{
_listObjects = items;
[self.mainList reloadData];
}
#pragma mark Table View Delegate Methods
// You may remove this method
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _listObjects.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"InfoCell";
UITableViewCell *newCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
Job *item = _listObjects[indexPath.row];
newCell.textLabel.text = item.address;
//[newCell setBackgroundColor:[UIColor blackColor]];
return newCell;
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
You likely need to add "InfoCell" as the reuse identifier in your Storyboard.
Probably your tableView doesn't recognise the cell so you should add the cell at tableView in the storyboard and it is called "InfoCell"
If you don't want to add cell into tableView in the storyboard and you have a xib with your cell. you can call in your viewController this method:
[tableView registerNib:[UINib nibWithNibName:#"IndoCell" bundle:nil] forCellReuseIdentifier:#"IndoCell"];
that if your nib is called "IndoCell.xib"

Pull to refresh UITableView Data

I have a pull to refresh setup. It's currently calling [self.tableView reloadData]; but It's not reloading my parsed Json data from the blogData method. Is theres something I'm missing?
My controller is like this:
//
// ARTableViewController.m
// WorldCupLive
//
// Created by Adam Rais on 14/06/2014.
// Copyright (c) 2014 Adam Rais. All rights reserved.
//
#import "ARTableViewController.h"
#import "ARModal.h"
#interface ARTableViewController ()
#end
#implementation ARTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.blogPost = [[ARModal alloc] init];
self.blogPost.jsonMutable = [NSMutableArray array];
for (NSDictionary *post in self.blogPost.blogData) {
ARModal *bp = [ARModal blogPostWithHome:[[post objectForKey:#"home"] objectForKey:#"text"]];
bp.away = [[post objectForKey:#"away"] objectForKey:#"text"];
bp.result = [[post objectForKey:#"result"] objectForKey:#"text"];
bp.info = [post objectForKey:#"info"];
bp.homeImage = [[post objectForKey:#"homeimage"] objectForKey:#"src"];
[self.blogPost.jsonMutable addObject:bp];
}
[self randomBackgroundImage];
self.tableView.contentInset = UIEdgeInsetsMake(0.0f, -10.0f, 0.0f, 0.0f);
// Initialize Refresh Control
UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
// Configure Refresh Control
[refreshControl addTarget:self action:#selector(refresh:) forControlEvents:UIControlEventValueChanged];
// Configure View Controller
[self setRefreshControl:refreshControl];
}
-(void)randomBackgroundImage {
UIImage *image = self.blogPost.imageUI;
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
self.tableView.backgroundView = imageView;
self.tableView.backgroundView.layer.zPosition -= 1;
}
- (void)refresh:(id)sender
{
NSLog(#"Refreshing");
[self.tableView reloadData];
[self randomBackgroundImage];
// End Refreshing
[(UIRefreshControl *)sender endRefreshing];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.blogPost.jsonMutable count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
// Configure the cell...
ARModal *post = [self.blogPost.jsonMutable objectAtIndex:indexPath.row];
NSData *imageData = [NSData dataWithContentsOfURL:post.jsonURL];
UIImage *image = [UIImage imageWithData:imageData];
cell.textLabel.text = [[[[[post.home stringByAppendingString:#" "]stringByAppendingString:#" "] stringByAppendingString:post.bst] stringByAppendingString:#" "] stringByAppendingString:post.away];
cell.detailTextLabel.text = post.info;
cell.imageView.image = image;
cell.backgroundColor = [UIColor colorWithWhite:1.000 alpha:0.000];
return cell;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
And my modal:
//
// ARModal.m
// WorldCupLive
//
// Created by Adam Rais on 14/06/2014.
// Copyright (c) 2014 Adam Rais. All rights reserved.
//
#import "ARModal.h"
#implementation ARModal
-(id)initWithHome:(NSString *)home {
self = [super init];
if (self) {
_home = home;
_away = nil;
_result = nil;
_info = nil;
_homeImage = nil;
}
return self;
}
+(id)blogPostWithHome:(NSString *)home {
return [[self alloc] initWithHome:home];
}
-(NSArray *)blogData {
NSURL *jsonURL = [NSURL URLWithString:#"http://www.kimonolabs.com/api/2nfgfo2s?apikey=1a1f5f323969d5157af8a8be857026c2"];
NSData *jsonData = [NSData dataWithContentsOfURL:jsonURL];
NSError *jsonError = nil;
NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&jsonError];
NSArray *jsonArray = [[jsonDictionary objectForKey:#"results"] objectForKey:#"collection1"];
if (blogData == nil) {
blogData = jsonArray;
}
return blogData;
}
-(NSURL *)jsonURL {
return [NSURL URLWithString:self.homeImage];
}
-(NSString *)bst {
NSString *sentence = self.result;
NSString *word = #"-";
NSString *wordTwo = #"00.00";
NSString *wordThree = #"01.00";
NSMutableArray *bstArray = [NSMutableArray array];
if ([sentence rangeOfString:word].location != NSNotFound) {
NSLog(#"Found the string");
[bstArray addObject:sentence];
} else if ([sentence rangeOfString:wordTwo].location != NSNotFound) {
NSLog(#"time is 23:00");
[bstArray addObject:#"23:00"];
} else if ([sentence rangeOfString:wordThree].location != NSNotFound) {
NSLog(#"time is 00:00");
[bstArray addObject:#"00:00"];
} else {
float floatOne = [sentence floatValue];
float floatFinal = floatOne - 1.000000;
NSString *str = [NSString stringWithFormat:#"%f", floatFinal];
NSString *bstFinal = [str substringToIndex:[str length] - 4];
[bstArray addObject:bstFinal];
}
return [bstArray objectAtIndex:0];
}
-(UIImage *)imageUI {
NSArray *imageArray = #[[UIImage imageNamed:#"Algeria"],[UIImage imageNamed:#"Argentina"],[UIImage imageNamed:#"Australia"],[UIImage imageNamed:#"Belgium"],[UIImage imageNamed:#"Bosnia-Herzegovina"],[UIImage imageNamed:#"Switzerland"],[UIImage imageNamed:#"Uruguay"],[UIImage imageNamed:#"USA"],[UIImage imageNamed:#"Brazil"],[UIImage imageNamed:#"Cameroon"],[UIImage imageNamed:#"Chile"],[UIImage imageNamed:#"Colombia"],[UIImage imageNamed:#"Costa Rica"],[UIImage imageNamed:#"Côte d'Ivoire"],[UIImage imageNamed:#"Croatia"],[UIImage imageNamed:#"Ecuador"],[UIImage imageNamed:#"England"],[UIImage imageNamed:#"France"],[UIImage imageNamed:#"Germany"],[UIImage imageNamed:#"Ghana"],[UIImage imageNamed:#"Greece"],[UIImage imageNamed:#"Honduras"],[UIImage imageNamed:#"Iran"],[UIImage imageNamed:#"Italy"],[UIImage imageNamed:#"Japan"],[UIImage imageNamed:#"Mexico"],[UIImage imageNamed:#"Netherlands"],[UIImage imageNamed:#"Nigeria"],[UIImage imageNamed:#"Portugal"],[UIImage imageNamed:#"Russia"],[UIImage imageNamed:#"South Korea"],[UIImage imageNamed:#"Spain"]];
int random = arc4random_uniform(imageArray.count);
return [imageArray objectAtIndex:random];
}
#end
When you call the -[UITableView reloadData] method you are telling the tableview to refresh ints content based on the source you already gave him, but he doesnt change the source. In some cases you refresh you datasource and you need to refresh the UITableView so you call the -[UITableView reloadData]. What you need to do is to first refresh you data and the refresh the view, so the view uses your new data.
Use the the same way you got the data from your modal to refresh it.
self.blogPost.jsonMutable = [NSMutableArray array];
for (NSDictionary *post in self.blogPost.blogData) {
ARModal *bp = [ARModal blogPostWithHome:[[post objectForKey:#"home"] objectForKey:#"text"]];
bp.away = [[post objectForKey:#"away"] objectForKey:#"text"];
bp.result = [[post objectForKey:#"result"] objectForKey:#"text"];
bp.info = [post objectForKey:#"info"];
bp.homeImage = [[post objectForKey:#"homeimage"] objectForKey:#"src"];
[self.blogPost.jsonMutable addObject:bp];
}
Then execute the -[UITableView reloadData], but now he is going to refresh using the refreshed data that you got from your modal.
If you need something else, comment.
-[UITableView reloadData] doesn't actually reload your data. It tells the table that you've reloaded the data, and now you need the table view to reload.
So before you call reloadData you should do:
self.blogPost.jsonMutable = [NSMutableArray array];
for (NSDictionary *post in self.blogPost.blogData) {
ARModal *bp = [ARModal blogPostWithHome:[[post objectForKey:#"home"] objectForKey:#"text"]];
bp.away = [[post objectForKey:#"away"] objectForKey:#"text"];
bp.result = [[post objectForKey:#"result"] objectForKey:#"text"];
bp.info = [post objectForKey:#"info"];
bp.homeImage = [[post objectForKey:#"homeimage"] objectForKey:#"src"];
[self.blogPost.jsonMutable addObject:bp];
}
Also as this chunk of code only uses information provided by ARModal, you should probably put it in a method in ARModal

How to add array to a TableViewController?

While I was surfing over the Internet I've found a lot of examples how to load array in the TableViewController, but none of them helped me!
Couldn't you help me to find what is wrong in my code ?
Thank you in advance!!!
#import "Images.h"
#import "AFNetworking.h"
#import "HTMLparser.h"
#interface Images ()
#end
#implementation Images
#synthesize data;
#synthesize textFromVC1;
#synthesize tableView;
#synthesize so2;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.data = [[NSMutableArray alloc]init];
NSError *error = nil;
NSString *so = [#"http://" stringByAppendingString: self.textFromVC1];
NSURL *url = [[NSURL alloc]initWithString:so];
NSString *str=[[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:nil];
HTMLParser *parser = [[HTMLParser alloc] initWithString:str error:&error];
if (error) {
NSLog(#"Error: %#", error);
[parser release];
parser = nil;
return;
}
HTMLNode * body = [parser body];
NSArray *inputs = [body findChildTags:#"img"];
for (HTMLNode *input in inputs) {
NSString *links = [input getAttributeNamed:#"src"];
NSString *so1 = [so stringByAppendingString: #"/"];
so2 = [so1 stringByAppendingString: links];
[self.data addObject:so2];
NSLog(#"%#", data);
NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)
{
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON)
{
}];
[operation start];
}
[self.tableView reloadData];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)viewDidUnload
{
[self setTableView:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.data.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"LinkID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
}
cell.textLabel.text = [self.data objectAtIndex:indexPath.row];
[self.tableView reloadData];
return cell;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
*/
}
- (void)dealloc {
[tableView release];
[super dealloc];
}
#end
well 1) numberOfSections is 0. to see something it should be one IIRC
think thats it but havent double checked
Assuming your data array is built up correctly, your mistake in is your numberOfSections methods. Currently, it returns 0, which tells the UITableView that there are currently no sections to be displayed… ever.
You can either return 1; there or remove the entire method altogether. The default implementation, which you inherit from UITableViewController, also returns 1 by default.
My advice would be to remove the method, as that keeps your own code cleaner. You can always implement it in a later stage, when you might actually need it.

Resources