Hi when I do for loop to get all documents from a collection. I add the car object to the NSMutablearray and when I debug i can see that the objects are being added to the array but when i want it to display in the table and get the count of the array I call the [self.mycars count] to get the count but the count is nil and i cant get information from the cell.textLabel.text = vehicle.name; so what am i doing wrong.
#import "TableViewController.h"
#import "Car.h"
#import "Vehicle.h"
#interface TableViewController ()
#end
#implementation TableViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 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;
self.db = [FIRFirestore firestore];
self.myCars = [[NSMutableArray alloc] init];
[[[[self.db collectionWithPath:#"users"] documentWithPath:[FIRAuth auth].currentUser.uid]
collectionWithPath:#"cars"] getDocumentsWithCompletion:^(FIRQuerySnapshot *snapshot, NSError *error) {
if (error != nil) {
NSLog(#"Error getting documents: %#", error);
} else {
for (FIRDocumentSnapshot *document in snapshot.documents) {
NSLog(#"%# => %#", document.documentID, document.data);
Car *car = [[Car alloc] initWithCarName:[document valueForField:#"carname"] andCarStyle:[document valueForField:#"carstyle"]
andCarColour:[document valueForField:#"colour"] andCarYear:[document valueForField:#"caryear"]
andCarDoors:[document valueForField:#"doors"] andCarSeat:[document valueForField:#"seat"] andCarWheels:[document valueForField:#"wheels"]
andCarTankCapacity:[document valueForField:#"tankcapacity"] andCarHorsePower:[document valueForField:#"horsepower"] andCarModelName:[document valueForField:#"modelname"]];
NSLog(#"Car name:%#", car.name);
[self.myCars addObject:car];
}
}
}];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.myCars count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellidentifier" forIndexPath:indexPath];
// Configure the cell...'
Vehicle *vehicle = [self.myCars objectAtIndex:indexPath.row];
cell.textLabel.text = vehicle.name;
return cell;
}
#end
You need to reload data manually after changing/updating your datasource (self.myCars in this case) which mean you need to add [self.tableView reloadData]; after for loop. If it still is not working, you might want to check if self.myCars is initialized yet.
Related
I had a problem regarding how can I set my NSArray in completionHandler block. I successfully assign a value for NSArray in my completion block, but once I tried to NSLog NSArray value outside completion block it gave 0.
Here is my full code.
//
// HomeTVC.m
// ABOX
//
// Created by Zero on 11/18/15.
// Copyright © 2015 Zero. All rights reserved.
//
#import "HomeTVC.h"
#import "facebook.h"
#interface HomeTVC ()<UITableViewDataSource, UITableViewDelegate>
{
NSDictionary *userPageLikesParams;
NSArray *pagesInfo;
facebook *fb;
}
#end
#implementation HomeTVC
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
fb = [[facebook alloc] init];
userPageLikesParams = #{#"fields": #"about,name,created_time",#"limit": #"5"} ;
[fb getUserPagelikes:userPageLikesParams completionHandler:^(NSDictionary *pagesResult) {
pagesInfo = [[NSArray alloc] init];
pagesInfo = pagesResult[#"data"];
// NSArray *p = pagesResult[#"data"];
// [self pages:p];
}];
}
//- (void)pages:(NSArray*)pageInfo {
//
// self.pagesInfo = pageInfo;
// NSLog(#"fb pages result ayam : %#", self.pagesInfo[0]);
// NSLog(#"array counzz : %d", (int)self.pagesInfo.count);
//}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// here I got 0, how can I solve this problem?
NSLog(#"table count : %d", (int)pagesInfo.count);
return 5;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// Configure the cell...
return cell;
}
#end
Thanks in advance.
Reload your table view when the completion block finishes up and you should see your pagesInfo array populated and returning a count.
As per #michal, you should reload your tableView below like this:
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.delegate = self;
self.tableView.dataSource = self;
fb = [[facebook alloc] init];
userPageLikesParams = #{#"fields": #"about,name,created_time",#"limit": #"5"} ;
[fb getUserPagelikes:userPageLikesParams completionHandler:^(NSDictionary *pagesResult)
{
pagesInfo = pagesResult[#"data"];
[yourTableViewObj reloadData];
// NSArray *p = pagesResult[#"data"];
// [self pages:p];
}];
}
Hope it will help.
I've been stuck on this problem for a while now. Basically i've been trying to pull a list of results from parse and then get information from a relational pointer.
I have got to the point where i can set the cells label to the title but it seems to have the same title for as many rows are returned.
I know i need to utilize the indexPath.row somewhere but i can't for the life of me think how.
Any help would be gratefully appreciated :)
//
// DEMOWatchedGamesTableViewController.m
// ShoutOutz
//
// Created by Craig Turner on 05/08/2014.
// Copyright (c) 2014 Roman Efimov. All rights reserved.
//
#import "DEMOWatchedGamesTableViewController.h"
#import <Parse/Parse.h>
#interface DEMOWatchedGamesTableViewController ()
#end
NSMutableArray *arrayGames;
#implementation DEMOWatchedGamesTableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// 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;
//PFUser *currentUser = [PFUser currentUser];
PFQuery *query = [PFQuery queryWithClassName:#"watched_games"];
// Include the user data with each post
[query includeKey:#"game_id"];
[query findObjectsInBackgroundWithBlock:^(NSArray *postObjects, NSError *error)
{
if(!error){
NSLog(#"myArray: %#", postObjects);
self.myArray = postObjects;
[self.tableView reloadData];
} else {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
- (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 [self.myArray count];
//return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
NSLog(#"Array: %#", self.myArray);
for (PFObject * postObject in self.myArray) {
[postObject fetchIfNeededInBackgroundWithBlock:^(PFObject *object, NSError *error){
PFObject *postAuthor = [object objectForKey:#"game_id"];
NSLog(#"retrieved related Post Author: %#", postAuthor);
cell.textLabel.text = [postAuthor objectForKey:#"gameTitle"];
}];
}
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
Rememer that the tableView:cellForRowAtIndexPath: method is called once for every cell that needs to be displayed, and that's determined by the value you supply in the tableView:numberOfRowsInSection data source method, in this case - the size of your myArray array.
So based on that principle you dont need to go through your array for every iteration of the cellForRowAtIndexPath method. What's helpful with this method is that it lets you know which cell index it is going to create by supplying you the indexPath. So you can use this indexPath value supplied by the method as an index to then grab the appropriate instance in your array like so:
This is just an example based on your existing code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
/**
Why are you printing the array? youll end up printing it as many times as there are instances
in your myArray array. You dont want to do that ;)
NSLog(#"Array: %#", self.myArray);
*/
//Using the indexpath's row value we can go ahead and grab that from your myArray array
PFObject * postObject = [self.myArray objectAtIndex:indexPath.row];
[postObject fetchIfNeededInBackgroundWithBlock:^(PFObject *object, NSError *error){
PFObject *postAuthor = [object objectForKey:#"game_id"];
NSLog(#"retrieved related Post Author: %#", postAuthor);
cell.textLabel.text = [postAuthor objectForKey:#"gameTitle"];
}];
return cell;
}
I am using MapKit and I'm trying to retrieve a list of nearby places based on the users current location and after that, I am trying to display them in a TableView. However, when using the iOS simulator, no places show up. I went to simulator->debug->location->Apple so shouldn't results pertaining to THAT location show up? I'm confused. Here is my code:
- (void)viewDidLoad
{
[super viewDidLoad];
//[self CurrentLocationIdentifier];
[self performSearch];
_m= [MKMapItem mapItemForCurrentLocation];
}
- (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 _places.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"placeCell";
PlaceTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
long row = [indexPath row];
cell.placeLabel.text = _places[row];
return cell;
}
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[super tableView:tableView didDeselectRowAtIndexPath:indexPath];
int rowNo = indexPath.row;
_place = [_places objectAtIndex:rowNo];
}
- (void) performSearch {
MKLocalSearchRequest *request =
[[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = _m.name;
_places = [[NSMutableArray alloc] init];
MKLocalSearch *search =
[[MKLocalSearch alloc]initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse
*response, NSError *error) {
if (response.mapItems.count == 0)
NSLog(#"No Matches");
else
for (MKMapItem *item in response.mapItems)
{
NSString *n = item.name;
[_places addObject:n];
}
}];
}
#end
You need to add a bunch of log statements and look at what is displayed in the console (or add breakpoints and use the debugger, but I'm guessing you don't know how to do that.
Add a log statement at the beginning of your performSearch that displays the _m.name that you are using as your search string. Add a log to the top of your completion handler so you know that it's called.
Okay so for some reason the results started appearing after I changed the type of "row" in cellForRowAtIndexPath from long to int and instead of [indexPath row], I changed it to indexPath.row
This question already has an answer here:
ios - why does my UITableView not get populated with comments
(1 answer)
Closed 9 years ago.
I am getting a list of some ShoppingLists through a WCF call.
My code:
#import "ListTableViewController.h"
#import "ListServiceSvc.h"
#interface ListTableViewController (){
// NSMutableArray *shoppingLists;
}
#property (nonatomic, retain) NSMutableArray *shoppingList;
#end
#implementation ListTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
_shoppingList = [NSMutableArray array];
[self loadListsFromRemoteServer];
[super viewDidLoad];
}
-(void) loadListsFromRemoteServer
{
NSString *uname = #"Test4";
NemListBinding *binding = [[ListServiceSvc NemListBinding]initWithAddress:#"http://balder.ucn.dk/dm76_gr5/WCF.ListService.svc/custom?singleWsdl"];
binding.logXMLInOut=YES;
ListServiceSvc_GetShoppingListsWithUname *parms = [[ListServiceSvc_GetShoppingListsWithUname alloc]init];
parms.uname = uname;
[binding GetShoppingListsWithUnameAsyncUsingParameters:parms delegate:self];
}
- (void) operation:(NemListBindingOperation *)operation completedWithResponse:(NemListBindingResponse *)response
{
NSArray *responseHeaders = response.headers;
NSArray *responseBodyParts = response.bodyParts;
//[NSThread sleepForTimeInterval:5.0];
NSMutableArray *shoppingListFromWebserver = [[NSMutableArray alloc] init];
// step 1 fill in the blanks.
for(id header in responseHeaders) {
// here do what you want with the headers, if there's anything of value in them
}
for (id mine in responseBodyParts)
{
if ([mine isKindOfClass:[ListServiceSvc_GetShoppingListsWithUnameResponse class]])
{
for (id slist in [[mine GetShoppingListsWithUnameResult] ShoppingList])
{
[shoppingListFromWebserver addObject:slist];
NSLog(#"new list :: RESPONSE FROM SERVER :: nList %#", [slist ShoppingListName]);
//self.result.text = [self.result.text stringByAppendingString:[slist shoppingListName]];
}
}
}
[self performSelectorOnMainThread:#selector(updateNewView:) withObject:shoppingListFromWebserver waitUntilDone:NO];
}
-(void) updateNewView:(NSMutableArray*) result
{
_shoppingList = result;
NSLog( #"new list - number of news :: %u", [_shoppingList count]);
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
//- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
//{
// return _shoppingList.count;
//}
//- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
//{
// // Return the number of rows in the section.
// return 10;
//}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cellforrow");
static NSString *CellIdentifier = #"ListCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
//cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// Configure the cell...
id shopList = [_shoppingList objectAtIndex:indexPath.row];
cell.textLabel.text = [shopList ShoppingListName];
return cell;
}
Nothing happens when i run the app in Xcode. I can see in the log window that the log
NSLog( #"new list - number of news :: %u", [_shoppingList count]);
does return a value (4), but the NSLog i have made in the CellForRowAtIndexPath method does not get printed. I also have a breakpoint in there, that isn't reached. Why is it not getting to the method?
These methods, numberOfSectionsInTableView and numberOfRowsInSection are important to determine what number of data the TableView should show.. it should look something like this:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1; // the number of different sections in your table view
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [_shoppingList count]; // the number of data in your shopping list
}
You should not comment out these methods: numberOfSectionsInTableView and numberOfRowsInSection.
At least numberOfRowsInSection is required and must return the number of rows you want/need.
As far as I got it, this should be _shoppingList.count in your case.
because you commented out these methods: numberOfSectionsInTableView and numberOfRowsInSection, your tableView would be 0 section and 0 row,so the method
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
did not be accessed.
C/xcode geeks!
I have been struggling with this error for hours now, and I don't seem to find the solution, although it seems as many people have had the exact same problem.
See code:
//
// ListViewController.m
// Puns
//
// Created by Amit Bijlani on 12/13/11.
// Copyright (c) 2011 Treehouse Island Inc. All rights reserved.
//
#import "ListViewController.h"
#import "BlogPost.h"
//#import "Pun.h"
#import "PunsTableViewCell.h"
#import "DetailViewController.h"
#implementation ListViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
#pragma mark - Segue
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSLog(#"0");
if ( [[segue identifier] isEqualToString:#"ShowMenu"] ){
NSLog(#"1");
DetailViewController *dvc = (DetailViewController *)[segue destinationViewController];
dvc.menu = [self.blogPosts objectAtIndex:[[self.tableView indexPathForSelectedRow] row]];
}
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// GET WEB DATA SOURCE (JSON)
// The url
NSURL *blogURL = [NSURL URLWithString:#"http://constantsolutions.dk/json.html"];
// The data
NSData *jsonData = [NSData dataWithContentsOfURL:blogURL];
// Error variable
NSError *error = nil;
// jsonData to serialization
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
// Get array 'posts'
self.blogPosts = [NSMutableArray array];
NSArray *blogPostsArray = [dataDictionary objectForKey:#"posts"];
for (NSDictionary *bpDictionary in blogPostsArray) {
// Get title
// Will only retrieve data, if TITLE exists
BlogPost *blogPost = [BlogPost blogPostWithTitle:[bpDictionary objectForKey:#"title"]];
// Get the content
blogPost.content = [bpDictionary objectForKey:#"content"];
// Get thumbnail
blogPost.thumbnail = [bpDictionary objectForKey:#"thumbnail"];
// Get date
blogPost.date = [bpDictionary objectForKey:#"date"];
// Get price
blogPost.price = [bpDictionary objectForKey:#"price"];
// Add the object to blogPosts array
[self.blogPosts addObject:blogPost];
}
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#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.blogPosts count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"PunTableViewCell";
PunsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[PunsTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
BlogPost *blogPost = [self.blogPosts objectAtIndex:indexPath.row];
cell.menuTitle.text = blogPost.title;
cell.menuContent.text = blogPost.content;
if([blogPost.price length] == 0) {
[cell.menuPrice setHidden:YES];
} else {
cell.menuPrice.text = blogPost.price;
}
return cell;
}
#end
As you can see, I have implented NSLog() inside the prepareForSegue, but it is not triggered.
Do you guys have any idea what I am doing wrong? I am pretty new to this, so I still haven't found out this whole iPhone development thing. So bare over with me if the solution is simple :o).
Thanks in advance!
You have a name for the segue, so does that mean you created it by dragging from a button or table view cell to the other view controller and then selected it and named it in xcode? if you are programmatically changing the view it wont be called but you can manually call a method before swapping views to prepare
I had a similar issue in going about sharing information in ios between views where the answer may be helpful.
In particular from the answer on that post where he says:
"in your .m file you would trigger you segue - maybe on a button or some action. sounds like you already have this:"
[self performSegueWithIdentifier:#"viewB" sender:self];
--
Swapping your segue name in of course.