UITableView cellForRowAtIndexPath not getting called - ios

I know that the cellForRowAtIndexPath method isn't being called because I never see the NSLog messages inside of it. I have set the dataSource and delegate attributes of the UITableView and I also have declared UITableViewDelegate and UITableViewDataSource in the header file. What am I missing?
- (void)viewDidLoad {
[self.view setBackgroundColor:[UIColor grayColor]];
tableData = [[NSMutableArray alloc] init];
matchesForUser = [[NSMutableArray alloc] init];
sortedFirstArray = [[NSArray alloc] init];
sortedSecondArray = [[NSArray alloc] init];
_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 20, self.view.frame.size.width, self.view.frame.size.height - 20) style:UITableViewStylePlain];
_tableView.dataSource = self;
_tableView.delegate = self;
[self.view addSubview:_tableView];
countUsers = 0;
PFQuery *query = [PFQuery queryWithClassName:#"_User"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
tableData[countUsers] = [object valueForKey:#"username"];
matchesForUser[countUsers] = [object valueForKey:#"matches"];
}
}else{
NSLog([error description]);
}
NSLog(#"***tabledata***");
NSLog([NSString stringWithFormat:#"%lu", (unsigned long)[tableData count]]);
NSLog(#"***matchesdata***");
NSLog([NSString stringWithFormat:#"%lu", (unsigned long)[matchesForUser count]]);
}];
dictionary = [NSDictionary dictionaryWithObjects:matchesForUser forKeys:tableData];
sortedFirstArray = [[dictionary allKeys] sortedArrayUsingSelector:#selector(compare:)];
sortedSecondArray = [dictionary objectsForKeys:sortedFirstArray notFoundMarker:[NSNull null]];
backToMap = [[UIButton alloc] initWithFrame:CGRectMake(80, 518, 160, 30)];
backToMap.backgroundColor = [UIColor colorWithRed:33.0f/255.0f green:156.0f/255.0f blue:41.0f/255.0f alpha:1.0f];
[backToMap addTarget:self action:#selector(dismiss) forControlEvents:UIControlEventTouchUpInside];
[backToMap setTitle:#"BACK TO MAP" forState:UIControlStateNormal];
[self.view addSubview:backToMap];
}
- (void)dismiss {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tableData count];
}
- (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];
}
NSString *username = [[sortedFirstArray objectAtIndex:indexPath.row] stringByAppendingString:#" "];
NSString *matchAmount = [sortedSecondArray objectAtIndex:indexPath.row];
NSLog(#"***username***");
NSLog(username);
NSLog(#"***matchamount***");
NSLog(matchAmount);
cell.textLabel.text = [username stringByAppendingString:matchAmount];
return cell;
}

Try doing the following things
1.) Register your tableView like
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"SimpleTableItem"];
2.) Then Add [_tableView reloadData]; just below
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
tableData[countUsers] = [object valueForKey:#"username"];
matchesForUser[countUsers] = [object valueForKey:#"matches"];
}
Inside if (!error) part..
So your Updated Code must look like
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
tableData[countUsers] = [object valueForKey:#"username"];
matchesForUser[countUsers] = [object valueForKey:#"matches"];
}
[_tableView reloadData];
}else{
NSLog([error description]);
}
NSLog(#"***tabledata***");
NSLog([NSString stringWithFormat:#"%lu", (unsigned long)[tableData count]]);
NSLog(#"***matchesdata***");
NSLog([NSString stringWithFormat:#"%lu", (unsigned long)[matchesForUser count]]);
}];

1) Here you do need to use countUsers = 0;If you need than you need to increment the value inside for loop by 1.Otherwise it will overwrite the value at index 0 every time.
2) You are using background calling method to fetch data.So it will take time to fetch data and control will go further and execute following code.But At that time matchesForUser array is empty, and dictionary is also empty.So in cell it won't display anything and you will not see NSLOG from cell.
Instead of this
ini
dictionary = [NSDictionary dictionaryWithObjects:matchesForUser forKeys:tableData];
sortedFirstArray = [[dictionary allKeys] sortedArrayUsingSelector:#selector(compare:)];
sortedSecondArray = [dictionary objectsForKeys:sortedFirstArray notFoundMarker:[NSNull null]];
3) Try with this,
PFQuery *query = [PFQuery queryWithClassName:#"_User"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (!error) {
for (PFObject *object in objects) {
NSLog(#"%#", object.objectId);
[tableData addObject:[object valueForKey:#"username"]];
[matchesForUser addObject:[object valueForKey:#"matches"]];
}
dictionary = [NSDictionary dictionaryWithObjects:matchesForUser forKeys:tableData];
sortedFirstArray = [[dictionary allKeys] sortedArrayUsingSelector:#selector(compare:)];
sortedSecondArray = [dictionary objectsForKeys:sortedFirstArray notFoundMarker:[NSNull null]];
[_tableView reloadData];
}else{
NSLog([error description]);
}
NSLog(#"***tabledata***");
NSLog([NSString stringWithFormat:#"%lu", (unsigned long)[tableData count]]);
NSLog(#"***matchesdata***");
NSLog([NSString stringWithFormat:#"%lu", (unsigned long)[matchesForUser count]]);
});
}];

Did you reload the Tableview in ViewDidLoad? like
[_tableView reloadData];

Reload the table again after
dictionary = [NSDictionary dictionaryWithObjects:matchesForUser forKeys:tableData];
sortedFirstArray = [[dictionary allKeys] sortedArrayUsingSelector:#selector(compare:)];
sortedSecondArray = [dictionary objectsForKeys:sortedFirstArray notFoundMarker:[NSNull null]];
[_tableView reloadData];

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tableData count];
}
The count is 0? you can type NSLog("%#", #(tableData.count)); or just return 1; for test.
UITableView send the tableView:numberOfRowsInSection: first, if the method return 0. it will not call the cellForRowAtIndexPath.
And as #PiyushSharma mentioned, you should Register your tableView.

Related

Getting crash when try to delete row from UITableView when I have multiple sections. Section values are in Dynamic NSMutableDictionary

Let me describe what I actually want. I have a dictionary where keys are Alphabets and it's values are starting with that alphabet.
Something like this :
key value
---------------------------------------------------------
A (Apple, Aim, Arise, Attempt, Airplane, Absolute)
B (Bubble, Bite, Borrow, Basket)
C (Cat, Correct)
D (Dog, Direction, Distribute)
My NSMutableDictionary call wordDic have all data Alphabetically. Just like the above table. I pull all data from my ManagedObject and show them in that dictionary.
- (void)dataStructure
{
NSManagedObjectContext *moc = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Words"];
self.wordListArray = [[NSMutableArray alloc] init];
self.wordListArray = [[moc executeFetchRequest:fetchRequest error:nil] mutableCopy];
self.wordInWordListArray = [[NSMutableArray alloc] init];
for (int i = 0; i < [self.wordListArray count]; i++)
{
self.words = [self.wordListArray objectAtIndex:i];
[self.wordInWordListArray addObject:self.words.word];
}
if ([self.wordListArray count] != 0)
{
self.wordDic = [self sortedDictionary:self.wordInWordListArray];
// Sorted key array
self.keyArray = [[NSArray alloc] init];
NSArray *key = [[NSArray alloc] init];
key = [self.wordDic allKeys];
self.keyArray = [key sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
[self.homeTableView reloadData];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self viewRelatedChange];
[self dataStructure];
}
These data are showing in tableView perfectly. But when I try to delete a particular row, it got crash. The message is something like -[__NSArrayM objectAtIndex:]: index 2 beyond bounds [0 .. 0]', which means in my numberOfRowsInSection, tableView try to access a row, which is not exist. So I have to handle that according to my data structure. What I did is in commitEditingStyle after delete object from my mangedObject and my tableView array, I call the above method [self dataStructure];
- (void)tableView:(UITableView *) tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
// NSString *secTitle = [self.keyArray objectAtIndex:indexPath.section];
NSString *selectedString = [secData objectAtIndex:indexPath.row];
NSString *key = [self.keyArray objectAtIndex:indexPath.section];
NSMutableArray *words = [self.wordDic objectForKey:key];
[words sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSManagedObjectContext *context = [self managedObjectContext];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"Words" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"word like %#", [secData objectAtIndex:indexPath.row]];
[request setPredicate:predicate];
if (editingStyle == UITableViewCellEditingStyleDelete)
{
NSError *error;
NSArray *matchingData = [context executeFetchRequest:request error:&error];
for (NSManagedObject *obj in matchingData)
{
[context deleteObject:obj];
}
[context save:&error];
// remove info from tableView array
int coreDataIndex = 0;
for (int i = 0; i < [self.wordInWordListArray count]; i++)
{
NSString *dataString = [self.wordInWordListArray objectAtIndex:i];
if ([dataString isEqualToString:selectedString])
{
coreDataIndex = i;
}
}
[self.wordListArray removeObjectAtIndex:coreDataIndex];
[words removeObjectAtIndex:indexPath.row];
//[self.homeTableView beginUpdates];
[self.homeTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
//[self.homeTableView endUpdates];
}
[self dataStructure];
}
But it is not working. And my apps still getting crash with same message. I also notice that in numberOfRowsInSection the value of section is not always start with 0. (like indexPath.row did). So what's the problem of my structure and what will be the solution of it?
Below I am giving the full code, of my tableView. If any one have an answer, please share that with me. It would be very appreciable. A lot of thanks in advance. Good day to all.
- (void)dataStructure
{
NSManagedObjectContext *moc = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Words"];
self.wordListArray = [[NSMutableArray alloc] init];
self.wordListArray = [[moc executeFetchRequest:fetchRequest error:nil] mutableCopy];
self.wordInWordListArray = [[NSMutableArray alloc] init];
for (int i = 0; i < [self.wordListArray count]; i++)
{
self.words = [self.wordListArray objectAtIndex:i];
[self.wordInWordListArray addObject:self.words.word];
}
if ([self.wordListArray count] != 0)
{
self.wordDic = [self sortedDictionary:self.wordInWordListArray];
// Sorted key array
self.keyArray = [[NSArray alloc] init];
NSArray *key = [[NSArray alloc] init];
key = [self.wordDic allKeys];
self.keyArray = [key sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
[self.homeTableView reloadData];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self viewRelatedChange];
[self dataStructure];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.keyArray count];
}
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 28;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"section %ld", (long)section);
NSString *key = [self.keyArray objectAtIndex:section];
NSMutableArray *value = [self.wordDic objectForKey:key];
// NSLog(#"keys %#", key);
NSLog(#"values %#", value);
return [value count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([selectedIndex isEqual:indexPath]) {
return kHomeTableViewExpandedCellHeight;
} else {
return kHomeTableViewCellHeight;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = kHomeTableViewCellID;
HomeTableViewCell *cell = (HomeTableViewCell *)[self.homeTableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell)
{
cell = [[HomeTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSString *secTitle = [self.keyArray objectAtIndex:indexPath.section];
secData = [self.wordDic objectForKey:secTitle];
[secData sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSString *data = [secData objectAtIndex:indexPath.row];
[cell.wordLabel setText:data];
// NSManagedObject *words = [self.wordListArray objectAtIndex:indexPath.row];
// [cell.wordLabel setText:[NSString stringWithFormat:#"%#", [words valueForKey:#"word"]]];
return cell;
}
- (void)tableView:(UITableView *) tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
// NSString *secTitle = [self.keyArray objectAtIndex:indexPath.section];
NSString *selectedString = [secData objectAtIndex:indexPath.row];
NSString *key = [self.keyArray objectAtIndex:indexPath.section];
NSMutableArray *words = [self.wordDic objectForKey:key];
[words sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSManagedObjectContext *context = [self managedObjectContext];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"Words" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"word like %#", [secData objectAtIndex:indexPath.row]];
[request setPredicate:predicate];
if (editingStyle == UITableViewCellEditingStyleDelete)
{
NSError *error;
NSArray *matchingData = [context executeFetchRequest:request error:&error];
for (NSManagedObject *obj in matchingData)
{
[context deleteObject:obj];
}
[context save:&error];
// remove info from tableView array
int coreDataIndex = 0;
for (int i = 0; i < [self.wordInWordListArray count]; i++)
{
NSString *dataString = [self.wordInWordListArray objectAtIndex:i];
if ([dataString isEqualToString:selectedString])
{
coreDataIndex = i;
}
}
[self.wordListArray removeObjectAtIndex:coreDataIndex];
[words removeObjectAtIndex:indexPath.row];
//[self.homeTableView beginUpdates];
[self.homeTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
//[self.homeTableView endUpdates];
}
[self dataStructure];
}
Just try calling the dataStructure method before deleting the appropriate row
- (void)tableView:(UITableView *) tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *selectedString = [secData objectAtIndex:indexPath.row];
NSString *key = [self.keyArray objectAtIndex:indexPath.section];
NSMutableArray *words = [self.wordDic objectForKey:key];
[words sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
NSManagedObjectContext *context = [self managedObjectContext];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"Words" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"word like %#", [secData objectAtIndex:indexPath.row]];
[request setPredicate:predicate];
if (editingStyle == UITableViewCellEditingStyleDelete)
{
NSError *error;
NSArray *matchingData = [context executeFetchRequest:request error:&error];
for (NSManagedObject *obj in matchingData)
{
[context deleteObject:obj];
}
[context save:&error];
// remove info from tableView array
int coreDataIndex = 0;
for (int i = 0; i < [self.wordInWordListArray count]; i++)
{
NSString *dataString = [self.wordInWordListArray objectAtIndex:i];
if ([dataString isEqualToString:selectedString])
{
coreDataIndex = i;
}
}
[self.wordListArray removeObjectAtIndex:coreDataIndex];
[words removeObjectAtIndex:indexPath.row];
[self dataStructure];
//[self.homeTableView beginUpdates];
[self.homeTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
//[self.homeTableView endUpdates];
}
}
deleteRowsAtIndexPaths will basically reload the tableView which in turn calls numberOfRowsInSection method. So before control reaches numberOfRowsInSection, your data source should be updated
I got my problem. In commitEditingStyle when I was removing my tableView data I was used secData which is basically hold the selected indexPath.row. Instead of it, I have to use the
[words objectAtIndex:indexPath.row];
in predicate. It's now working perfectly. :)

How to implement search option with webservice url in ios, using objective C

I'm getting data from a web service.If we pass any string through service url, then it will returns data according to it.I have implemented and display data in a tableview . now what I want is to implement search option for it. so I used uisearchcontroller and to do that.but it is not working well.I mean if we send letter 'y' for the web service, it will return all the results that starts from y. this is my code.
- (void)viewDidLoad {
[super viewDidLoad];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil];
self.searchController.searchResultsUpdater = self;
self.searchController.dimsBackgroundDuringPresentation = NO;
self.searchController.searchBar.scopeButtonTitles = #[NSLocalizedString(#"ScopeButtonCountry", #"Airport"), NSLocalizedString(#"ScopeButtonCapital", #"AirportCode")];
self.searchController.searchBar.delegate = self;
//self.searchController.searchBar.frame = CGRectMake(self.searchController.searchBar.frame.origin.x, self.searchController.searchBar.frame.origin.y, self.searchController.searchBar.frame.size.width, 44.0);
self.mtableView.tableHeaderView = self.searchController.searchBar;
self.definesPresentationContext = YES;
[self.searchController.searchBar sizeToFit];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)getAirports:(NSString *)needeedString
{
airportList = nil;
needeedString = [NSString stringWithFormat:#""];
NSString *apiKey = [NSString stringWithFormat:#"some api"];
NSString *fullUrl = [NSString stringWithFormat:#"someurl%#%#",apiKey,needeedString];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:fullUrl parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSArray *result = (NSArray *)responseObject;
airportList = [NSMutableArray array];
for (NSDictionary *all in result)
{
Details *d1 = [Details new];
d1.airport = [all objectForKey:#"Airport"];
[airportList addObject:d1];
[self.mtableView reloadData];
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchString = searchController.searchBar.text;
if (searchString == nil || [searchString isEqual: #""]) {
[self getAirports:#""];
[self.mtableView reloadData];
}
[self getAirports:searchString];
[self.mtableView reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [airportList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ci"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"ci"];
}
Details *newDetails = [airportList objectAtIndex:indexPath.row];
cell.textLabel.text = newDetails.airport;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Details *newDetails = [airportList objectAtIndex:indexPath.row];
NSString *selectedText = newDetails.airport;
[[NSUserDefaults standardUserDefaults] setObject:selectedText forKey:#"st"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self dismissViewControllerAnimated:YES completion:nil];
}
Please find the below changes I have made ,hope it will work
- (void)getAirports:(NSString *)needeedString
{
airportList = nil;
needeedString = [NSString stringWithFormat:#""];
NSString *apiKey = [NSString stringWithFormat:#"some api"];
NSString *fullUrl = [NSString stringWithFormat:#"someurl%#%#",apiKey,needeedString];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:fullUrl parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSArray *result = (NSArray *)responseObject;
airportList = [NSMutableArray array];
for (NSDictionary *all in result)
{
Details *d1 = [Details new];
d1.airport = [all objectForKey:#"Airport"];
[airportList addObject:d1];
//remove reload data method from here because it will reload your table on each iteration
}
dispatch_async(dispatch_get_main_queue(), ^{
//reload on main thread
[self.mtableView reloadData];
});
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchString = searchController.searchBar.text;
if (searchString != nil && ![searchString isEqual: #""]) {
[self getAirports:searchString];
}
//here there is no need to reload
//also changed condition
}
Call reload in dispatch main queue:
dispatch_async(dispatch_get_main_queue(), ^{
[self.mtableView reloadData];
});
I guess In method
- (void)getAirports:(NSString *)needeedString
remove
[self.mtableView reloadData];
outside the for loop
and you can call reloadData like
self.mtableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES

tableview reloadData not working after successful login / AFNetworking

I'm using the below code in my ViewController.m to log a user in to my app. However on the following ViewController (AccountViewController), I have a tableView. Upon successful login, I want to reload/populate the data in the tableView, but instead after a successful login, I get an empty table. I've put reloadData in viewWillAppear at the top of MyAccountViewController. See below. Not sure why it's doing this, as when I navigate from AccountViewController to another screen and back, the table is populated. Is my AFNetworking bit causing the table not to populate for some reason?
ViewController.m
[DIOSUser userLoginWithUsername:_userField.text
andPassword:_passField.text
success:^(AFHTTPRequestOperation *op, id response) {
// Saving to keychain/NSUserDefaults
NSDictionary *diosSession = [[DIOSSession sharedSession] user];
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:diosSession] forKey:#"diosSession"];
[[NSUserDefaults standardUserDefaults] synchronize];
[[DIOSSession sharedSession] getCSRFTokenWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *csrfToken = [NSString stringWithUTF8String:[responseObject bytes]];
[[NSUserDefaults standardUserDefaults] setObject:csrfToken forKey:#"diosToken"];
[[NSUserDefaults standardUserDefaults] synchronize];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// failure handler
}];
wrongLogin.hidden = YES;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
MyAccountViewController *yourViewController = (MyAccountViewController *)[storyboard instantiateViewControllerWithIdentifier:#"MyAccount"];
[self.navigationController pushViewController:yourViewController animated:YES];
[self.activityIndicatorViewOne stopAnimating];
self.activityIndicatorViewOne.hidden = YES;
NSLog(#"Success!");}
failure:^(AFHTTPRequestOperation *op, NSError *err) { NSLog(#"Fail!"); wrongLogin.hidden = NO; }
];
AccountViewController.m
- (void)viewWillAppear:(BOOL)animated {
[self.tableView reloadData];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView reloadData];
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(ReloadDataFunction:)
name:#"refresh"
object:nil];
[self.tableView reloadData];
self.descripData = [[NSMutableArray alloc] init];
UIBarButtonItem *flipButton = [[UIBarButtonItem alloc] initWithImage: [UIImage imageNamed:#"logouticon4.png"]
// initWithTitle:#"Logout"
style:UIBarButtonItemStylePlain
target:self
action:#selector(flipView)];
self.navigationItem.rightBarButtonItem = flipButton;
[flipButton release];
self.navigationController.navigationBar.tintColor = [UIColor whiteColor];
[self.navigationItem setHidesBackButton:YES animated:YES];
refreshControl = [[UIRefreshControl alloc]init];
[self.tableView addSubview:refreshControl];
[refreshControl addTarget:self action:#selector(refreshTable) forControlEvents:UIControlEventValueChanged];
// Do any additional setup after loading the view.
self.storageData = [[NSMutableDictionary alloc] init];
userName.text = [[[DIOSSession sharedSession] user] objectForKey:#"name"];
//emailAddress.text = [[[DIOSSession sharedSession] user] objectForKey:#"mail"];
NSLog(#"%#", [[DIOSSession sharedSession] user]);
// DIOSView *view = [[DIOSView alloc] init];
NSMutableDictionary *viewParams = [NSMutableDictionary new];
[viewParams setValue:#"storeditems" forKey:#"view_name"];
[DIOSView viewGet:viewParams success:^(AFHTTPRequestOperation *operation, id responseObject) {
self.descripData = [responseObject mutableCopy];
NSLog(#"%#",self.descripData);
// [self.tableView reloadData];
// [HUD hide:YES];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", [error localizedDescription]);
}];
[DIOSNode nodeIndexWithPage:#"0" fields:#"title" parameters:[NSArray arrayWithObjects:#"storage_item", nil] pageSize:#"20" success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Nodes retrieved!");
__block int iCount = 0;
for (id object in responseObject) {
// NSLog(#"adding object!");
[self.storageData setObject:(NSDictionary *)object forKey:[NSString stringWithFormat:#"%d",iCount]];
iCount++;
[self.tableView reloadData];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//failure
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self.storageData count] > 0 && self.descripData.count > 0)
{
return [self.descripData count];
}
else
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *DoctorsTableIdentifier = #"StorageItemTableViewCell";
StorageItemTableViewCell *cell = (StorageItemTableViewCell *)[tableView dequeueReusableCellWithIdentifier:DoctorsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"StorageItemTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if (self.storageData.count > 0 && self.descripData.count > 0) {
noitemsView.hidden = YES;
cell.cellCountLabel.text = [NSString stringWithFormat:#"%i", indexPath.row+1];
NSDictionary *title = [self.descripData objectAtIndex:indexPath.row];
[[cell itemName] setText:[title objectForKey:#"node_title"]];
NSDictionary *node = [self.descripData objectAtIndex:indexPath.row];
[[cell itemDescrip] setText:[node objectForKey:#"body"]];
NSDictionary *value = [self.descripData objectAtIndex:indexPath.row];
[[cell valueLabel] setText:[value objectForKey:#"storeditemvalue"]];
NSLog(#"%#", self.descripData);
NSDictionary *quantity = [self.descripData objectAtIndex:indexPath.row];
[[cell quantityLabel] setText:[quantity objectForKey:#"numberofitemstored"]];
NSLog(#"%#", self.descripData);
NSString *secondLink = [[self.descripData objectAtIndex:indexPath.row] objectForKey:#"photo"];
[cell.itemPhoto sd_setImageWithURL:[NSURL URLWithString:secondLink]];
NSLog(#"%#",secondLink);
}
else {
noitemsView.hidden = NO;
}
return cell;
}
You have a "refresh" observer, but it calls a function you haven't shown here. You set your data it looks like with this:
for (id object in responseObject) {
// NSLog(#"adding object!");
[self.storageData setObject:(NSDictionary *)object forKey:[NSString stringWithFormat:#"%d",iCount]];
iCount++;
[self.tableView reloadData];
}
but because that is in viewDidLoad, it is only called once, BEFORE viewWillAppear. You need to fill self.storageData and self.descripData in a separate function, then call THAT function from viewWillAppear, or using your NSNotificationCenter notification from the previous VC.

Wrong PFUser objectId when selecting recipients in didSelectRowAtIndexPath Parse.com

I'm currently building a photo messaging app where users can send photos to each other. When the photo is taken, you select recipients from a UITableView in a new View Controller.
But every time I select a person from the list and send the photo, it gets the wrong user.objectId. It seems to take the Friendship objectId which is another class named Friendship, when it should take the objectId of the user. Here's how I'm doing it:
#implementation PickRecipientsViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.recipients = [[NSMutableArray alloc] init];
[_selectedImage setImage:_image];
self.tableView.delegate = self;
[self refreshFriends];
}
- (void)refreshFriends {
[__acceptedRequests removeAllObjects];
PFQuery *friendsQuery = [self queryForFriends];
PFQuery *acceptedRequestQuery = [self queryForAcceptedFriendRequests];
PFQuery *friendRequestsQuery = [self queryForRequests];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// Find friends
NSArray *objects = [friendsQuery findObjects];
for (PFObject * obj in objects) {
[obj[#"user1"] fetchIfNeeded];
[obj[#"user2"] fetchIfNeeded];
}
_friends = [objects mutableCopy];
// Find pending requests
objects = [friendRequestsQuery findObjects];
for (PFObject *obj in objects) {
[obj[#"fromUser"] fetchIfNeeded];
}
__friendRequests = [objects mutableCopy];
// Find accepted requests
objects = [acceptedRequestQuery findObjects];
for (PFObject *obj in objects) {
PFUser *to = (PFUser*)[obj[#"toUser"] fetchIfNeeded];
[obj deleteEventually];
[__acceptedRequests addObject:to[#"username"]];
}
// show accepted requests
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
if (__acceptedRequests.count > 0) {
NSString *friends = __acceptedRequests[0];
for (int i = 1; i < __acceptedRequests.count; ++i) {
friends = [friends stringByAppendingFormat:#", %#", __acceptedRequests[i]];
}
friends = [friends stringByAppendingString:#" accepted your friend request"];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"New Friends" message:friends delegate:self cancelButtonTitle:#"Wuhu" otherButtonTitles:nil, nil];
alert.tag = kAlertTagAcceptedRequest;
[alert show];
}
});
});
}
- (PFQuery *)queryForAcceptedFriendRequests {
PFUser *user = [PFUser currentUser];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"status = %# AND (fromUser = %# AND toUser != %#)", #"approved", user, user];
PFQuery *acceptedRequestQuery = [PFQuery queryWithClassName:#"FriendRequest" predicate:predicate];
return acceptedRequestQuery;
}
- (PFQuery *)queryForFriends {
PFUser *user = [PFUser currentUser];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"user1 = %# AND user2 != %# OR user1 != %# AND user2 = %#", user, user, user, user];
PFQuery *friendsQuery = [PFQuery queryWithClassName:#"Friendship" predicate:predicate];
return friendsQuery;
}
- (PFQuery *)queryForRequests {
PFUser *user = [PFUser currentUser];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"status = %# AND (toUser = %# AND fromUser != %#)", #"pending", user, user];
PFQuery *friendRequests = [PFQuery queryWithClassName:#"FriendRequest" predicate:predicate];
return friendRequests;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RecipientsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"RecipientsTableViewCell" forIndexPath:indexPath];
PFUser *user = [self.friends objectAtIndex:indexPath.row];
if([self.recipients containsObject:user.objectId]){
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}else{
cell.accessoryType = UITableViewCellAccessoryNone;
}
PFObject *friendRequest = [_friends objectAtIndex:indexPath.row];
PFUser *user1 = (PFUser *)friendRequest[#"user1"];
PFUser *user2 = (PFUser *)friendRequest[#"user2"];
if ([user1.username isEqualToString:[PFUser currentUser].username]) {
cell.nameL.text = user2[#"username"];
[(PFFile*)user2[#"profilePic"] getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (error) {return;}
cell.profilePic.image = [UIImage imageWithData:data];
}];
} else if ([user2.username isEqualToString:[PFUser currentUser].username]) {
cell.nameL.text = user1[#"username"];
[(PFFile*)user1[#"profilePic"] getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (error) {return;}
cell.profilePic.image = [UIImage imageWithData:data];
}];
}
return cell;
}
- (BOOL)isFriend:(PFUser *)user {
for (PFUser *friend in self.friends) {
if ([friend.objectId isEqualToString:user.objectId]) {
return YES;
}
}
return NO;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _friends.count;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 68;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
PFUser *user = [self.friends objectAtIndex:indexPath.row];
if (cell.accessoryType == UITableViewCellAccessoryNone){
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self.recipients addObject:user.objectId];
} else{
cell.accessoryType = UITableViewCellAccessoryNone;
[self.recipients removeObject:user.objectId];
}
}
- (IBAction)sendImage {
PFObject *message = [PFObject objectWithClassName:#"Messages"];
[message setObject:[PFUser currentUser] forKey:#"fromUser"];
[message setObject:[PFUser currentUser] forKey:#"toUser"];
[message setObject:#"image" forKey:#"fileType"];
[message setObject:self.recipients forKey:#"recipientIds"];
[message setObject:[[PFUser currentUser] objectId] forKey:#"senderId"];
// Image
NSData *imageData = UIImageJPEGRepresentation(_image, 1.0);
NSString *filename = [NSString stringWithFormat:#"image.png"];
PFFile *imageFile = [PFFile fileWithName:filename data:imageData];
[message setObject:imageFile forKey:#"file"];
[message saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
// Dismiss the controller
[[[self presentingViewController] presentingViewController] dismissViewControllerAnimated:YES completion:nil];
} else {
[SVProgressHUD showErrorWithStatus:#"Oh darn! Something went wrong :("];
}
}];
}
#end
Because _friends is an array of Friendship objects and when a row is tapped you just directly get it out of the array and don't then get the appropriate user from it (like you do when you configure the cell labels).
So in tableView:didSelectRowAtIndexPath: you should have something like:
BOOL adding = NO;
if (cell.accessoryType == UITableViewCellAccessoryNone){
cell.accessoryType = UITableViewCellAccessoryCheckmark;
adding = YES;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
PFObject *friendRequest = [_friends objectAtIndex:indexPath.row];
PFUser *user1 = (PFUser *)friendRequest[#"user1"];
PFUser *user2 = (PFUser *)friendRequest[#"user2"];
PFUser *recipient = nil;
if ([user1.username isEqualToString:[PFUser currentUser].username]) {
recipient = user2;
} else if ([user2.username isEqualToString:[PFUser currentUser].username]) {
recipient = user1;
}
if (adding) {
[self.recipients addObject:recipient.objectId];
} else {
[self.recipients removeObject:recipient.objectId];
}

problems with the UITableView - please advice

I have this piece of code and it should bring a ActivityIndicator (thats fine), then go out a query databases twice (looking at the logs it brings in all the correct info). I just STILL does not show up on the tableview and it is driving me crazy!! Can you if possible have a look over the code and see whats wrong - I have been on this for days now - please help!
[super viewDidLoad];
// create the activity indicator in the main queue
self.MainTableView.hidden = YES;
UIActivityIndicatorView *ac = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[self.view addSubview:ac];
[ac startAnimating];
self.client = [MSClient clientWithApplicationURLString:#"https://outnight-mobile.azure-mobile.net/" applicationKey:#"okYeRGfBagYrsbkaqWIRObeDtktjkF10"];
self.table = [self.client tableWithName:#"notifications"];
self.rowitems = [[NSMutableArray alloc] init];
MSQuery *query = [self.table query];
query.fetchLimit = 3;
[query readWithCompletion:^(NSArray *items, NSInteger totalCount, NSError *error)
{
self.rowitems = [items mutableCopy];
// we have the notifications and the barID in ROWITEMS array
// so lets make this into a dictionary so we can query it
// we need to run this next block of code 3 times, for the 3 bar ids we have got in ROWITEMS
//[self.TableView reloadData];
int a;
for (a = 0; a < 3; a++)
{
NSDictionary *apt = [self.rowitems objectAtIndex:a];
NSLog(#"%#", apt[#"barID"]);
NSDictionary *barIDDictionary = #{ #"myParam": apt[#"barID"]};
self.client = [MSClient clientWithApplicationURLString:#"https://outnight-mobile.azure-mobile.net/" applicationKey:#"okYeRGfBagYrsbkaqWIRObeDtktjkF10"];
[self.client invokeAPI:#"photos" body:barIDDictionary HTTPMethod:#"POST" parameters:nil headers:nil completion:^(id result, NSHTTPURLResponse *response, NSError *error) {
if (error) {
NSLog(#"Error %#", error );
}
else {
NSString *string = [NSString stringWithFormat:#"%#", [result objectForKey:#"rows"]];
NSString *stringWithoutbracketsend = [string stringByReplacingOccurrencesOfString:#")" withString:#""];
NSString *stringWithoutbracketsfront = [stringWithoutbracketsend stringByReplacingOccurrencesOfString:#"(" withString:#""];
NSString *completion = [stringWithoutbracketsfront stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *newStr = [completion substringFromIndex:1];
NSString *finalstring = [newStr substringToIndex:newStr.length-(newStr.length>0)];
[self.logoURL addObject:finalstring];
NSLog(#"%#",finalstring);
}
}];
}
}];
[self.MainTableView reloadData];
self.MainTableView.hidden = YES;
}
THIS IS ALL MY CODE THANKS
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) MSTable *table;
#property (nonatomic, strong) NSMutableArray *items;
#property (nonatomic, strong) NSMutableArray *logoURL;
#property (weak, nonatomic) IBOutlet UITableView *MainTableView;
#end
#implementation ViewController {
dispatch_queue_t MyQueue;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// create the activity indicator in the main queue
self.MainTableView.hidden = YES;
UIActivityIndicatorView *ac = [[UIActivityIndicatorView alloc]
initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[self.view addSubview:ac];
[ac startAnimating];
self.client = [MSClient clientWithApplicationURLString:#"https://outnight-mobile.azure-mobile.net/" applicationKey:#"okYeRGfBagYrsbkaqWIRObeDtktjkF10"];
self.table = [self.client tableWithName:#"notifications"];
self.rowitems = [[NSMutableArray alloc] init];
MSQuery *query = [self.table query];
query.fetchLimit = 3;
[query readWithCompletion:^(NSArray *items, NSInteger totalCount, NSError *error)
{
self.rowitems = [items mutableCopy];
// we have the notifications and the barID in ROWITEMS array
// so lets make this into a dictionary so we can query it
// we need to run this next block of code 3 times, for the 3 bar ids we have got in ROWITEMS
[self.MainTableView reloadData];
int a;
for (a = 0; a < 3; a++)
{
NSDictionary *apt = [self.rowitems objectAtIndex:a];
NSLog(#"%#", apt[#"barID"]);
NSDictionary *barIDDictionary = #{ #"myParam": apt[#"barID"]};
self.client = [MSClient clientWithApplicationURLString:#"https://outnight-mobile.azure-mobile.net/" applicationKey:#"okYeRGfBagYrsbkaqWIRObeDtktjkF10"];
[self.client invokeAPI:#"photos" body:barIDDictionary HTTPMethod:#"POST" parameters:nil headers:nil completion:^(id result, NSHTTPURLResponse *response, NSError *error) {
if (error) {
NSLog(#"Error %#", error );
}
else {
NSString *string = [NSString stringWithFormat:#"%#", [result objectForKey:#"rows"]];
NSString *stringWithoutbracketsend = [string stringByReplacingOccurrencesOfString:#")" withString:#""];
NSString *stringWithoutbracketsfront = [stringWithoutbracketsend stringByReplacingOccurrencesOfString:#"(" withString:#""];
NSString *completion = [stringWithoutbracketsfront stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *newStr = [completion substringFromIndex:1];
NSString *finalstring = [newStr substringToIndex:newStr.length-(newStr.length>0)];
[self.logoURL addObject:finalstring];
NSLog(#"%#",finalstring);
[ac stopAnimating];
[self.MainTableView reloadData];
self.MainTableView.hidden = NO;
}
}];
}
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
NSDictionary *stress = [self.rowitems objectAtIndex:indexPath.row];
cell.textLabel.text = stress[#"content"];
// putting an image on a row
switch (indexPath.row) {
case 0:
[cell.imageView setImageWithURL:[NSURL URLWithString:[self.logoURL objectAtIndex:(0)]] placeholderImage:[UIImage imageNamed:#"greybox40.png"]];
break;
case 1:
[cell.imageView setImageWithURL:[NSURL URLWithString:[self.logoURL objectAtIndex:(1)]] placeholderImage:[UIImage imageNamed:#"greybox40.png"]];
break;
case 2:
[cell.imageView setImageWithURL:[NSURL URLWithString:[self.logoURL objectAtIndex:(2)]] placeholderImage:[UIImage imageNamed:#"greybox40.png"]];
break;
}
return cell;
}
#end
Looks like you need to call
[self.MainTableView reloadData];
self.MainTableView.hidden = NO;
inside Completion block
I think your Query is running asynchronously. All you need to do is to put your [tableView reloadData] in the block that runs after completion of the Query Block and make sure that you put the reloadData call inside a dispatch_async block.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Background work
dispatch_async(dispatch_get_main_queue(), ^{
// Update UI
[tableView reloadData];
}); });
Did you implement UITableViewDatasource and UITableViewDelegate protocols?
Implement required methods of this 2 protocols and link your MainTableView.
Programmatically:
MainTableView.datasource = self;
MainTableView.delegate = self;
Via storyboard:
UPD:
Try this code:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSDictionary *stress = [self.rowitems objectAtIndex:indexPath.row];
cell.textLabel.text = [stress objectForKey:#"content"];

Resources