In my case i have two views in tab bar controller (categories and Home), one with collection view and one with table view.
In the table view, It starts to load data when only user taps(Home) on its tab bar item.I want to load data , when app launch. I am using AFNetworking, and I have called to my data loading method in viewDidLoad. same thing happen with collection view.please help me with this.hope your help thank you. I have attached part of my code, which I used to load data to table view.
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.homeTableView];
// [self homeviewData];
SWRevealViewController *revealController = self.revealViewController;
if (revealController) {
[self.sidebarButton setTarget:self.revealViewController];
[self.sidebarButton setAction:#selector(revealToggle:)];
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}
// Do any additional setup after loading the view.
}
- (void)viewWillAppear:(BOOL)animated
{
[self homeTableView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)homeviewData
{
homepost = nil;
NSString *mogohomeWebserviceUrl = [NSString stringWithFormat:#"some url"];
AFHTTPRequestOperationManager *homeManager = [AFHTTPRequestOperationManager manager];
[homeManager GET:mogohomeWebserviceUrl parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
homeposts = (NSDictionary *)responseObject;
homepost = [NSMutableArray array];
NSArray *results = [homeposts objectForKey:#"posts"];
for (NSDictionary *all in results)
{
Home *sweetHome = [Home new];
sweetHome.homeImage = [NSString stringWithFormat:#"%#", [all objectForKey:#"thumbnail"]];
sweetHome.homeTitle = [NSString stringWithFormat:#"%#", [all objectForKey:#"title"]];
sweetHome.homewebUrl = [NSString stringWithFormat:#"%#", [all objectForKey:#"url"]];
sweetHome.modifiedTime = [NSString stringWithFormat:#"%#", [all objectForKey:#"modified"]];
[homepost addObject:sweetHome];
[self.homeTableView reloadData];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [homepost count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
HomeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"homereuseIdentifier"];
Home *mogoHome = [homepost objectAtIndex:indexPath.row];
NSString *homeimageurlname = [NSString stringWithFormat:#"%#", mogoHome.homeImage];
NSURL *homeimageurl = [NSURL URLWithString:homeimageurlname];
cell.hometitleLabel.text = mogoHome.homeTitle;
[cell.homeimageView setImageWithURL:homeimageurl placeholderImage:nil];
cell.timeLabel.text = [[mogoHome.modifiedTime componentsSeparatedByString:#" "] objectAtIndex:1];
return cell;
}
You got to understand that the data will only be loaded and displayed after the API request to fetch the data is completed...
This implies you should either be ready with data before the screen appears. This is possible only if the data is independent of user action or Master Data, and you can fetch it right at App Launch. If user action is responsible for the fetched data, you have no option but to wait, and show an Activity Indicator. If you decide to do this, you will find a relevant answers how to do that..
All the best...
Related
I am using RestKit to pull a news feed and it works for pulling the feed. I have used a Master Detail view and it shows multiple feeds in the console but only displays 1 feed in the UITableView (Only 1 cell)
here is my code
#interface MasterViewController (){
NSArray *feedObjects;
NSMutableArray *feedArray;
}
#property NSMutableArray *objects;
#end
#implementation MasterViewController
- (void)awakeFromNib {
[super awakeFromNib];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
self.clearsSelectionOnViewWillAppear = NO;
self.preferredContentSize = CGSizeMake(320.0, 600.0);
}
}
- (void)viewDidLoad {
[super viewDidLoad];
feedArray = [[NSMutableArray alloc]init];
[self configureRestKit];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(insertNewObject:)];
self.navigationItem.rightBarButtonItem = addButton;
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(RKResponseDescriptor *)responseDescriptor {
RKObjectMapping *bodyMapping = [RKObjectMapping mappingForClass:[BaseClass class]];
[bodyMapping addAttributeMappingsFromArray:#[#"body",#"title"]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:bodyMapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
return responseDescriptor;
}
-(void)configureRestKit{
NSURL *baseURL = [NSURL URLWithString:#"http://urlExample"];
NSURLRequest *request = [NSURLRequest requestWithURL:baseURL];
RKObjectRequestOperation *objectRequestOperation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:#[[self responseDescriptor]]];
[objectRequestOperation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
feedObjects = mappingResult.array;
[feedArray addObject:feedObjects];
[self.tableView reloadData];
RKLogInfo(#"Load collection of Feeds: %#", mappingResult.array);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
RKLogError(#"Operation failed with error: %#", error);
}];
[objectRequestOperation start];
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return feedArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSMutableArray *feedarray = feedArray[indexPath.row];
BaseClass *feedO = feedarray[0];
cell.textLabel.text = [NSString stringWithFormat:#"%#",feedO.title];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return YES;
}
}
If anyone could help me that would be great, i've tried adding the mappingResults to a NSArray instead of NSMutableArray but this breaks the program the way i have tried.
Thanks
Of course it does - you are adding only one object to your array here:
[feedArray addObject:feedObjects];
Which means that your function returning number of rows:
feedArray.count == 1
What you want to do is to add all results separately to your NSMutableArray or even use NSArray you got from response directly as data source - so you have an NSArray with only 1 depth level.
[feedArray addObjectsFromArray:feedObjects]
Actually in your case I don't see a reason to keep both feedObjects and feedArray, you can throw away feedArray and use feedObjects instead everywhere.
I’m building an article reading app.I’m using AFNetworking third party library to fetch JSON data into the UITableView.
Let say Json link is www.example.com&page=1 gives 1-10 articles and www.example.com&page=2 gives11-20 articles and so on.
I have implemented pagination and scrollViewDidScroll method means when user scroll it gives next ten article.
I’m facing an issue when app launch and UITableView load scrollViewDidScroll method called three times but expected call once.
I’m using increment variable for pagination in scrollViewDidScroll method as i say it call three time and x value goes to 3 and give 30 articles.
When user scroll again it gives next 30 articles.i’m unable to figure out why scrollViewDidScroll method called three times when app is launched.
this is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
tempJson = [[NSMutableArray alloc] init];
[self loadNinjas];
}
- (void)loadNinjas {
NSString *jsonLink=[NSString stringWithFormat:#"www.example.com&page=%d",x];
NSURL *url = [[NSURL alloc] initWithString:jsonLink];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSArray *jsonArray = (NSArray *)responseObject;
for (NSDictionary *dic in jsonArray) {
Json *json = [[Json alloc] initWithDictionary:dic];
[tempJson addObject:json];
}
self.jsons = [[NSArray alloc] initWithArray:tempJson];
[self.tableView reloadData];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
}];
[operation start];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.jsons.count ;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *Cellidentifier1 = #"ysTableViewCell";
ysTableViewCell *cell1 = [tableView
dequeueReusableCellWithIdentifier:Cellidentifier1 forIndexPath:indexPath];
cell1.TitleLabel1.text = [self.jsons[indexPath.row] title];
cell1.AuthorLabel1.text = [self.jsons[indexPath.row] author];
[cell1.ThumbImage1 setImageWithURL:[NSURL URLWithString:
[self.jsons[indexPath.row] a_image]]];
return cell1;}
- (void)scrollViewDidScroll: (UIScrollView*)scroll {
CGFloat currentOffset = scroll.contentOffset.y;
CGFloat maximumOffset = scroll.contentSize.height - scroll.frame.size.height;
self.tableView.contentInset = UIEdgeInsetsMake(65, 0, 0, 0);
if (maximumOffset - currentOffset <= -60.0) {
x++;
[self loadNinjas];
[self.tableView addInfiniteScrollingWithActionHandler:^{
}];
[self.tableView reloadData];
}
}
This is a simple code that initializes the tableView with 50 cells and as the user scrolls down the page, adds 20 new cells to the tableView every time it reaches the cell which is 10 cells above the end of the table.
int i;
int lastSeen;
- (void)viewDidLoad {
[super viewDidLoad];
i = 50;
lastSeen = 0;
}
#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 i;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"myCell" forIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:#"%ld", (long)indexPath.row];
lastSeen = (lastSeen < indexPath.row) ? indexPath.row : lastSeen;
return cell;
}
- (void)scrollViewDidScroll: (UIScrollView*)scroll {
if (lastSeen >= (i - 10)) {
i += 20;
//load new data here.
[self.tableView reloadData];
}
}
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.
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
I have an app where you can add comments to a post. I'm using [sender tag] to get the index but it's always returning the same post. So no matter what post cell I click the comment button on it always adds it to the same cell and not the one I clicked on.
Any help is super appreciated.
Here is my code(note I've stripped my code to only the parts I think will matter to make reading easier as some functions have a lot of code. If you need to see some more just let me know):
Setting the comment button on each cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
[cell.commentButton addTarget:self action:#selector(commentButtonClick:) forControlEvents:(UIControlEvents)UIControlEventTouchDown];
return cell;
}
Comment button. Just performing a segue:
- (void)commentButtonClick:(id)sender {
[self performSegueWithIdentifier:#"addCommentSegue" sender:sender];
}
Prepare for segue(I send them to a basic view controller with a text field and a save button):
else if ([segue.identifier isEqualToString:#"addCommentSegue"]) {
GFAddCommentViewController *secondDestViewController = [[segue destinationViewController] topViewController];
NSInteger index = [sender tag];
NSDictionary *rootObject = self.posts[index];
NSDictionary *post = rootObject[#"post"];
NSDictionary *group = post[#"group"];
secondDestViewController.postId = [post[#"id"] copy];
secondDestViewController.groupName = [group[#"name"] copy];
secondDestViewController.postBody =[post[#"body"] copy];
}
When they click send on the new view controller this is the function:
-(void)addComment:(id)sender {
GFCredentialStore *credentialStore = [[GFCredentialStore alloc] init];
NSString * authToken = [credentialStore authToken];
NSString * addCommentURL = [NSString stringWithFormat:#"%s%s/%#/%s", kBaseURL, kPostURL, self.postId, kCommentURL];
NSString * commentBody = self.commentTextField.text;
NSMutableDictionary *mutableParams = [NSMutableDictionary dictionary];
if (commentBody) {
[mutableParams setObject:commentBody forKey:#"comment[body]"];
}
[SVProgressHUD showWithStatus:#"Adding Comment"];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setValue:authToken forHTTPHeaderField:#"auth_token"];
[manager POST:addCommentURL parameters:mutableParams success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
[SVProgressHUD showSuccessWithStatus:#"Comment Added"];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
Just to clarify it's successfully adding comments to the database just the post.id is incorrect.
Are you sure you set buttons tag correctly? It seem that you should set like that
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
[cell.commentButton addTarget:self
action:#selector(commentButtonClick:)
forControlEvents:(UIControlEvents)UIControlEventTouchDown];
cell.commentButton.tag = indexPath.row;
return cell;
}