I have an issue with reloading a UITableView when calling from other viewcontroller. I have called a service from viewcontroller.m and the results are displayed in tableviewcontroller.m. Here is my problem, I have a button in UITableViewCell, when clicked on a button, the table should be reloaded or refreshed.
Below is my code:
viewController.m
NSString * post = [[NSString alloc]initWithFormat:#"country=%#&state=%#&userId=%#",_txtSearchField.text,UserId];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"url"]];
tableviewcontroller.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
customCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if(!cell)
{
cell = [[customCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSArray *arr=[[profileArr objectAtIndex:indexPath.row] allKeys];
cell.lblAge.text = [[[profileArr objectAtIndex:indexPath.row] valueForKey:key] valueForKey:#"Age"];
cell.lblLocation.text = [[[profileArr objectAtIndex:indexPath.row] valueForKey:key] valueForKey:#"Address"];
cell.lblProfession.text = [[[profileArr objectAtIndex:indexPath.row] valueForKey:key] valueForKey:#"Occupation"];
}
-(void)buttonclick:(id)sender
{
UIButton *btn = sender;
NSArray *arr=[[profileArr objectAtIndex:btn.tag] allKeys];
NSString *key=[arr objectAtIndex:0];
NSMutableDictionary *userDict=[[profileArr objectAtIndex:btn.tag] objectForKey:key];
NSString *str = [userDict objectForKey:#"UserId"];
[self callbuttonService:str];
}
-(void)callbuttonService:(NSString *)OtherUserId
{
//service is called
}
#pragma mark - MRConnection Delegate Methods
- (void)jsonData:(NSDictionary *)jsonDict
{
[SVProgressHUD dismiss];
NSMutableArray *jsonArr1;
jsonArr1=[jsonDict objectForKey:#"DataTable"];
if (![jsonArr1 isEqual:[NSNull null]]) {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:#"Employee" message:#"Sucess" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* ok = [UIAlertAction actionWithTitle:#"OK" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:ok];
[self presentViewController:alertController animated:YES completion:nil];
[alertController.view setTintColor:[UIColor blackColor]];
}
else{
[SVProgressHUD showErrorWithStatus:#"Something went wrong!"];
}
}
According to your question, you have call service in viewcontroller.m file and you want to reload tableview in tableviewcontroller.m file. Please try this. keep coding.
viewController.m
-(void)callbuttonService:(NSString *)OtherUserId
{
//service is called
}
#pragma mark - MRConnection Delegate Methods
- (void)jsonData:(NSDictionary *)jsonDict
{
[SVProgressHUD dismiss];
NSMutableArray *jsonArr1;
jsonArr1=[jsonDict objectForKey:#"DataTable"];
if (![jsonArr1 isEqual:[NSNull null]]) {
NSDictionary *DictionaryData = [[NSDictionary alloc]init];
[DictionaryData setValue:jsonArr1 forKey:#"data"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"tableReload" object:nil userInfo:DictionaryData];
}
else{
[SVProgressHUD showErrorWithStatus:#"Something went wrong!"];
}
}
tableviewcontroller.m
-(void)viewDidLoad() {
super.viewDidLoad()
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(tableReloadNotification:) name:#"tableReload" object:nil];
}
- (void) tableReloadNotification:(NSNotification *) notification {
NSDictionary *info = notification.userInfo;
if (info != nil) {
NSMutableArray *jsonArr1 = [info valueForKey:#"data"];
tableview.reloadData();
}
}
You can use NSNotificationCenter for reload table view from another class. When your web service respond successfully then post your local notification.
Have you tried just calling [tableView reloadData]?
Also I fail to see how you add a button to your default UITableViewCell. Maybe you want this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
// check if correct cell was tapped
if (indexPath.section == 0 && indexPath.row == 0)
{
[tableView reloadData];
}
}
When you implement this method, it will be called whenever you tap a UITableViewCell, you won't need a button or something.
Of course, you're free to bind the [tableView reloadData] to any other action in your app, e. g. a button in the toolbar or something.
Related
this question had been mentioned many time here but my case is slightly different what i am doing that there is a two UITableViewController inside UITabBarController when i switch to second UITableViewController the cellForRowAtIndextPath method is not fired to fill the UITableViewController with the data that are pulled from my server using AFNetworking after searching for many solution over the internet all the question that i found does not include UITabBarController such as
question 1 , question 2, question 3, question 4, question 5,
here is the code that i am trying to use :
#import "newsAndEventTableViewController.h"
#import "SplashViewController.h"
#import "sharedVariables.h"
#import"AFNetworking.h"
#import "UIWebView+AFNetworking.h"
#import "SDWebImageCompat.h"
#import "SDWebImageDownloaderOperation.h"
#import "SDWebImageDownloader.h"
#import "MyGeeksTableViewController.h"
#import "geeksEvent.h"
#interface newsAndEventTableViewController ()
{
NSMutableArray *events;
geeksEvent *eventObject;
NSMutableArray *listOfEventsObjects;
}
#end
#implementation newsAndEventTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.delegate = self;
UIImage *image = [UIImage imageNamed:#"image.png"];
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:image];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [events count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:#"http://myserver.com/get.php" parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
// NSArray *products = [jsonDict objectForKey:#"images"];
// [products enumerateObjectsUsingBlock:^(id obj,NSUInteger idx, BOOL *stop){
// // NSString *productIconUrl = [obj objectForKey:#"imageUrl"];
//
// }];
//
NSLog(#"the response is: %#",responseObject);
events = [responseObject objectForKey:#"events"];
for (int i = 0; i < [events count];i++) {
eventObject = [events objectAtIndex:i];
[listOfEventsObjects addObject:eventObject];
}
}
failure:^(NSURLSessionTask *operation, NSError *error) {
NSLog(#"Error: %#", error);
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:#"Error"
message:#"pls check your internet connection"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* yesButton = [UIAlertAction
actionWithTitle:#"retry"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
//Handel your yes please button action here
}];
UIAlertAction* noButton = [UIAlertAction
actionWithTitle:#"No, Cancel"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
//Handel no, thanks button
}];
[alert addAction:yesButton];
[alert addAction:noButton];
[self presentViewController:alert animated:YES completion:nil];
}];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Display recipe in the table cell
geeksEvent *event = [events objectAtIndex:indexPath.row];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = [UIImage imageNamed:#"placeholderimage"];
UILabel *eventTitle = (UILabel *)[cell viewWithTag:200];
eventTitle.text = event.eventTitle;
NSLog(#"the event title is: %#",event.eventTitle);
UILabel *eventDesc = (UILabel *)[cell viewWithTag:300];
eventDesc.text = event.eventShortDiscription;
// Assign our own background image for the cell
// UIImage *background = [self cellBackgroundForRowAtIndexPath:indexPath];
// UIImageView *cellBackgroundView = [[UIImageView alloc] initWithImage:background];
// cellBackgroundView.image = background;
// cell.backgroundView = cellBackgroundView;
return cell;
}
/*
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:<##"reuseIdentifier"#> forIndexPath:indexPath];
// Configure the cell...
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
The code inside the success block of the AFNetworking request is called asynchronously and that's why there's no data when displaying the tableView.
As a suggestion, you may want to move the AFNetworking request outside the tableView:cellForRowAtIndexPath: method (ex.: viewDidLoad) because this will trigger a request every time the app wants to display a cell, making the app unresponsive and consume the user bandwidth.
So using the suggestions above, the code will be:
#import "newsAndEventTableViewController.h"
#import "SplashViewController.h"
#import "sharedVariables.h"
#import"AFNetworking.h"
#import "UIWebView+AFNetworking.h"
#import "SDWebImageCompat.h"
#import "SDWebImageDownloaderOperation.h"
#import "SDWebImageDownloader.h"
#import "MyGeeksTableViewController.h"
#import "geeksEvent.h"
#interface newsAndEventTableViewController ()
{
NSMutableArray *events;
geeksEvent *eventObject;
NSMutableArray *listOfEventsObjects;
}
#end
#implementation newsAndEventTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.delegate = self;
UIImage *image = [UIImage imageNamed:#"image.png"];
self.navigationItem.titleView = [[UIImageView alloc] initWithImage:image];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:#"http://myserver.com/get.php" parameters:nil progress:nil success:^(NSURLSessionTask *task, id responseObject) {
NSLog(#"the response is: %#",responseObject);
events = [responseObject objectForKey:#"events"];
for (int i = 0; i < [events count];i++) {
eventObject = [events objectAtIndex:i];
[listOfEventsObjects addObject:eventObject];
}
// Calling reload data after request is done
[self.tableView reloadData];
}
failure:^(NSURLSessionTask *operation, NSError *error) {
NSLog(#"Error: %#", error);
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:#"Error"
message:#"pls check your internet connection"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* yesButton = [UIAlertAction
actionWithTitle:#"retry"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
//Handel your yes please button action here
}];
UIAlertAction* noButton = [UIAlertAction
actionWithTitle:#"No, Cancel"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
//Handel no, thanks button
}];
[alert addAction:yesButton];
[alert addAction:noButton];
[self presentViewController:alert animated:YES completion:nil];
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [events count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Display recipe in the table cell
geeksEvent *event = [events objectAtIndex:indexPath.row];
UIImageView *recipeImageView = (UIImageView *)[cell viewWithTag:100];
recipeImageView.image = [UIImage imageNamed:#"placeholderimage"];
UILabel *eventTitle = (UILabel *)[cell viewWithTag:200];
eventTitle.text = event.eventTitle;
NSLog(#"the event title is: %#",event.eventTitle);
UILabel *eventDesc = (UILabel *)[cell viewWithTag:300];
eventDesc.text = event.eventShortDiscription;
// Assign our own background image for the cell
// UIImage *background = [self cellBackgroundForRowAtIndexPath:indexPath];
// UIImageView *cellBackgroundView = [[UIImageView alloc] initWithImage:background];
// cellBackgroundView.image = background;
// cell.backgroundView = cellBackgroundView;
return cell;
}
#end
I am doing JSON parsing, but my data is only shown in log and not in Tableview.
I am showing the main method of JSON parsing below. I would like to show the whole code but Stack Overflow doesn't allow me.
- (void)viewDidLoad
{
[super viewDidLoad];
[_CenterTableview setHidden:NO];
[_CenterTableview reloadData];
NSString *str=#"http://www.vallesoft.com/vlcc_api/getservicenames.php?centrename=";
NSURL * url=[NSURL URLWithString:str];
NSURLRequest *req=[[NSURLRequest alloc]initWithURL:url];
Connection1=[[NSURLConnection alloc]initWithRequest:req delegate:self];
if (Connection1) {
WebData1=[[NSMutableData alloc]init];
}
// [self.CenterTableview reloadData];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSDictionary *json=[NSJSONSerialization JSONObjectWithData:WebData1 options:0 error:0];
NSArray *city_info =[json objectForKey:#"city_info"];
for(NSDictionary *dic in city_info)
{
NSArray *vlcc_service_name=[dic objectForKey:#"vlcc_service_name"];
Centers=[[NSMutableArray alloc]initWithObjects:vlcc_service_name, nil];
//This Nslog showing service name //
NSLog(#"%#",vlcc_service_name);
}
}
But in Tableview, it is not showing:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableItem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [Centers objectAtIndex:indexPath.row];
return cell;
}
You need to reload the tableview once you get the centers array filled in didFinishLoading
///Your code......
Centers=[[NSMutableArray alloc]initWithObjects:vlcc_service_name, nil];
[_CenterTableview reloadData];
////Your code.....
I am aware this question has been asked previously, but the answers provided have not solved my issue.
For instance, I have a very simple array of objects outlined in viewDidLoad:
#implementation MyViewController {
NSArray *tableData;
}
- (void)viewDidLoad
{
[super viewDidLoad];
tableData = [NSArray arrayWithObjects:#"Hello", #"My", #"Name", #"Is"];
NSLog(#"My Data: %#", tableData);
which is called in a tableView using cellForRowAtIndexPath
cell.nameLabel.text = [tableData objectAtIndex:indexPath.row];
This works fine and the NSLog shows my array. However, when i outline tableData outside of viewDidLoad, my array is (null).
My question is, how do I make my array available for the tableView when it is specified outside of ViewDidLoad?
edit: Here is my specific code:
#import <UIKit/UIKit.h>
#import "PhotoView.h"
#interface FrontViewController : UIViewController
#property (nonatomic, retain) UITableView *tableView;
#end
#import "FrontViewController.h"
#import "StreamScreen.h"
#import "API.h"
#import "PhotoView.h"
#import "StreamPhotoScreen.h"
#import "PrivateViewController.h"
#import "SWRevealViewController.h"
#import "PhotoScreen.h"
#import "RearViewController.h"
#import "SimpleTableCell.h"
#interface FrontViewController()
// Private Methods:
- (IBAction)pushExample:(id)sender;
#end
#implementation FrontViewController{
NSArray *tableData;
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = NSLocalizedString(#"Front View", nil);
SWRevealViewController *revealController = [self revealViewController];
[self.navigationController.navigationBar addGestureRecognizer:revealController.panGestureRecognizer];
UIBarButtonItem *revealButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"reveal-icon.png"]
style:UIBarButtonItemStyleBordered target:revealController action:#selector(revealToggle:)];
self.navigationItem.leftBarButtonItem = revealButtonItem;
// This works if I uncomment
//tableData = [NSArray arrayWithObjects:#"Hello", #"My", #"Name", #"Is", nil];
[self refreshStream];
}
-(void)refreshStream {
// call the "stream" command from the web API
[[API sharedInstance] commandWithParams:
[NSMutableDictionary dictionaryWithObjectsAndKeys:#"stream", #"command", nil]
onCompletion:^(NSDictionary *json) {
//got stream
[self showStream:[json objectForKey:#"result"]];
NSMutableArray *myData = [[NSMutableArray alloc] init];
myData = [json objectForKey:#"result"];
NSArray *userNameData = [myData valueForKey:#"username"];
[self loadData];
tableData = userNameData;
[self.tableView reloadData];
// I can see my json array in NSLog
NSLog(#"here's the results: %#", tableData);
}];
}
//This doesn't work either
//-(void)loadData {
// Add the data to your array.
//tableData = [NSArray arrayWithObjects:#"Hello", #"My", #"Name", #"Is", nil];
//NSLog(#"My Data: %#", tableData);
// Now load the table view.
// [self.tableView reloadData];
//}
-(void)showStream:(NSArray*)stream {
for (int i=0;i<[stream count];i++) {
NSDictionary* photo = [stream objectAtIndex:i];
}
NSArray *checkData = [stream valueForKey:#"username"];
//I can see my data in NSLog
NSLog(#"here's the results: %#", checkData);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tableData count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 78;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = (SimpleTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.nameLabel.text = [tableData objectAtIndex:indexPath.row];
cell.thumbnailImageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];
cell.prepTimeLabel.text = [prepTime objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"didSelectRowAtIndexPath");
/*UIAlertView *messageAlert = [[UIAlertView alloc]
initWithTitle:#"Row Selected" message:#"You've selected a row" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];*/
UIAlertView *messageAlert = [[UIAlertView alloc]
initWithTitle:#"Row Selected" message:[tableData objectAtIndex:indexPath.row] delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
// Display the Hello World Message
[messageAlert show];
// Checked the selected row
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"willSelectRowAtIndexPath");
if (indexPath.row == 0) {
return nil;
}
return indexPath;
}
#end
-(void)refreshStream {
// call the "stream" command from the web API
[[API sharedInstance] commandWithParams:
[NSMutableDictionary dictionaryWithObjectsAndKeys:#"stream", #"command", nil]
onCompletion:^(NSDictionary *json) {
//got stream
[self showStream:[json objectForKey:#"result"]];
NSMutableArray *myData = [json objectForKey:#"result"];
NSArray *userNameData = [myData valueForKey:#"username"];
}];
tableData = userNameData;
[self.tableView reloadData];
}
You're falling into a very common trap with asynchronous programming here.
commandWithParams takes a completion block, which is where you are getting the data out of the JSON. This block is not executed until the API call has returned. The sequence of events that happens when you run this code is:
commandWithParams is called
tableData is assigned to the contents of userNameData (which presumably you've also declared somewhere else otherwise this would not even compile)
reloadData is called
.... time passes
The completion block is executed and the JSON is read out into local variables, which are then instantly destroyed.
You need to move the two lines (points 2 and 3 in the list above) inside the completion block. There will be no data for your table until the block returns.
Ok my understanding of your question is that you want to assign variables to your NSArray in another method (not viewDidLoad) and then load the table view.
This is simple, just make a method which is in charge of adding the data to your array and then reload your table view like so:
-(void)viewDidLoad {
[super viewDidLoad];
// Call your method.
[self loadData];
}
-(void)loadData {
// Add the data to your array.
tableData = [NSArray arrayWithObjects:#"Hello", #"My", #"Name", #"Is"];
NSLog(#"My Data: %#", tableData);
// Now load the table view.
[myTableView reloadData];
}
Update 1
It would be much more helpful if you could share your code with us. How your and setting up your tableview, when its being called/etc....
Update 2
Ok well it seems obvious what yoru issue is. Your table view will never load like that. You need to call the tableview reloadData method outside the cellForRowAtIndexPath method.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *simpleTableIdentifier = #"SimpleTableCell";
SimpleTableCell *cell = (SimpleTableCell *)[self.tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SimpleTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.nameLabel.text = [tableData objectAtIndex:indexPath.row];
cell.thumbnailImageView.image = [UIImage imageNamed:[thumbnails objectAtIndex:indexPath.row]];
cell.prepTimeLabel.text = [prepTime objectAtIndex:indexPath.row];
return cell;
}
So the method call [self.tableView reloadData]; should only be called in your refreshStream method.
Update 3
You need to initialize your NSMutableArray before you can add data to it. initialize it in your refreshStrem method like so:
-(void)refreshStream {
// call the "stream" command from the web API
[[API sharedInstance] commandWithParams:[NSMutableDictionary dictionaryWithObjectsAndKeys:#"stream", #"command", nil] onCompletion:^(NSDictionary *json) {
//got stream
[self showStream:[json objectForKey:#"result"]];
NSMutableArray *myData = [[NSMutableArray alloc] init];
myData = [json objectForKey:#"result"];
NSArray *userNameData = [myData valueForKey:#"username"];
}];
tableData = userNameData;
[self.tableView reloadData];
}
Update 4
Ok well after reading #jrturton answer, I think its safe to assume that my answer is rubbish. To anyone reading my answer, please view #jrturton post.
Well I feel pretty sheepish. The answer was simple. I was so hung up on Json and API that all I didn't check the basics. All I need was in my .h file:
#property (strong, nonatomic) IBOutlet UITableView *tableView;
I had originally had:
#property (nonatomic, retain) UITableView *tableView;
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 8 years ago.
I have done for parsing data from JSON and put it show in Table view.
So I want to pass data (catID and catName )to another Page it's DetailPageController
how can I do like that? the below is my code.
Thanks in advance!
#import "ViewController.h"
#interface ViewController ()
{
NSMutableArray *myObject;
// A dictionary object
NSDictionary *dictionary;
// Define keys
NSString *catName;
NSString *catID;
}
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
catName =#"Category Name";
catID=#"Category ID";
myObject = [[NSMutableArray alloc] init];
NSData *jsonSource = [NSData dataWithContentsOfURL:
[NSURL URLWithString:#"MY_URL"]];
id jsonObjects = [NSJSONSerialization JSONObjectWithData:
jsonSource options:NSJSONReadingMutableContainers error:nil];
for (NSDictionary *dataDict in jsonObjects) {
NSString *TheCatName = [dataDict objectForKey:#"cat_name"];
NSString *TheCatID = [dataDict objectForKey:#"cat_id"];
NSLog(#"cat_name: %#",TheCatName);
NSLog(#"cat_id: %#",TheCatID);
dictionary = [NSDictionary dictionaryWithObjectsAndKeys:
TheCatName, catName,
TheCatID, catID,
nil];
[myObject addObject:dictionary];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return myObject.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Item";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell=[[UITableViewCell alloc]initWithStyle:
UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
NSDictionary *tmpDict = [myObject objectAtIndex:indexPath.row];
NSMutableString *textcat;
textcat = [NSMutableString stringWithFormat:#"%#",
[tmpDict objectForKeyedSubscript:catName]];
NSMutableString *catid;
catid = [NSMutableString stringWithFormat:#"ID: %# ",
[tmpDict objectForKey:catID]];
cell.textLabel.text = textcat;
cell.detailTextLabel.text= catid;
return cell;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *tmpDict = [myObject objectAtIndex:indexPath.row];
NSMutableString *catID;
catID = [NSMutableString stringWithFormat:#"%#",
[tmpDict objectForKeyedSubscript:cat_id]];
NSLog(#"didSelectRowAtIndexPath");
/*UIAlertView *messageAlert = [[UIAlertView alloc]
initWithTitle:#"Row Selected" message:#"You've selected a row" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];*/
UIAlertView *messageAlert = [[UIAlertView alloc]
initWithTitle:#"Row Selected" message:catID delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
// Display the Hello World Message
[messageAlert show];
// Checked the selected row
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
First import DetailPageController in TableviewController Class with help of following line.
#import "DetailPageController.h"
Now implement following method in your TableViewController Class
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailPageController * detailPageControllerOBJ_ = [[ImageOptionViewController alloc]initWithNibName:#“XIBName bundle:nil];
detailPageControllerOBJ_.dicSelectedData = [self.arrayData objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailPageControllerOBJ_ animated:YES];
}
And in DetailPageController.h put following code.
#property (nonatomic,strong) NSDictionary * dicSelectedData;
You will get your selected data in dicSelectedData Dictionary
I'm working on a sharing extension to simply grab a link, choose a few names to share it to, and Share. The data layer isn't added yet, only the UI to display some names in a tableview (using a custom cell) and I'm pulling in the shared URL from the extension context. All of the code in the VC is below. All views are set up in the Storyboard. Two UIButtons, Two UILabels, One TableView and a UIView to hold it all, so I can easily round the corners.
The issue I'm having is that the _linkLabel that I'm using the display the URL doesn't visually update for nearly 10 seconds! What.In.The.World. What I'm a doing here that's causing this?
I'm logging out the URL in the callback from hasItemConformingToTypeIdentifier and it happens as soon as the extension appears, but doesn't update the label??!! Helps. Please.
#import "ShareViewController.h"
#import "UserCell.h"
#interface ShareViewController ()
#end
#implementation ShareViewController
- (void)viewDidLoad{
self.view.alpha = 0;
_friends = [#[#"Ronnie",#"Bobby",#"Ricky",#"Mike"] mutableCopy];
_containerView.layer.cornerRadius = 6.f;
_selectedIndexPaths = [[NSMutableArray alloc] init];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[UIView animateWithDuration:0.5 animations:^{
self.view.alpha = 1;
}];
}
- (void)viewDidAppear:(BOOL)animated{
//pull the URL out
NSExtensionItem *item = self.extensionContext.inputItems[0];
NSItemProvider *provider = item.attachments[0];
if ([provider hasItemConformingToTypeIdentifier:#"public.url"]) {
[provider loadItemForTypeIdentifier:#"public.url" options:nil completionHandler:^(id<NSSecureCoding> item, NSError *error) {
NSURL *url = (NSURL*)item;
_linkLabel.text = url.absoluteString;
NSLog(#"Link: %#", url.absoluteString);
}];
}
else{
NSLog(#"No Link");
}
}
#pragma mark - UITableView Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UserCell *cell = (UserCell*)[tableView cellForRowAtIndexPath:indexPath];
if([_selectedIndexPaths containsObject:indexPath]){
[_selectedIndexPaths removeObject:indexPath];
cell.selected = NO;
}
else{
cell.selected = YES;
[_selectedIndexPaths addObject:indexPath];
}
NSLog(#"Share to %i friends", (int)[_selectedIndexPaths count]);
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
//Later, calc height based on text in comment
return 44;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [_friends count];
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"UserCell";
UserCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil){
cell = [[UserCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.selected = ([_selectedIndexPaths containsObject:indexPath]) ? YES : NO;
cell.nameLabel.text = [_friends objectAtIndex:indexPath.row];
return cell;
}
- (IBAction)dismiss {
[UIView animateWithDuration:0.34 animations:^{
self.view.alpha = 0;
} completion:^(BOOL finished) {
[self.extensionContext completeRequestReturningItems:nil completionHandler:nil];
}];
}
#end
Delays in updates to UI elements is a classic sign of trying to update the UI from outside the main queue. Which is what is happening here. You have this:
[provider loadItemForTypeIdentifier:#"public.url" options:nil completionHandler:^(id<NSSecureCoding> item, NSError *error) {
NSURL *url = (NSURL*)item;
_linkLabel.text = url.absoluteString;
NSLog(#"Link: %#", url.absoluteString);
}];
Except that NSItemProvider does not guarantee that the completion handler will be called on the same queue that you started on. You're almost guaranteed to be on a different queue here, so you're getting this weird delay. You need to dispatch back to the main queue to perform the update:
[provider loadItemForTypeIdentifier:#"public.url" options:nil completionHandler:^(id<NSSecureCoding> item, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
NSURL *url = (NSURL*)item;
_linkLabel.text = url.absoluteString;
NSLog(#"Link: %#", url.absoluteString);
});
}];