When I run the application, the header view container space is there, and is visible. I'm trying to display the username inside the header view, but nothing is showing up. Here is my code so far in the tableView:
#import "HomeView.h"
#interface HomeView () <UIActionSheetDelegate, UIImagePickerControllerDelegate>
#end
#implementation HomeView
- (void)viewDidLoad {
[super viewDidLoad];
if ([PFUser currentUser]) {
NSLog(#"Welcome to the App, %#", [self.user objectForKey:#"username"]);
} else {
LoginView *loginView = [[LoginView alloc] init];
[loginView setHidesBottomBarWhenPushed:YES];
[loginView.navigationItem setHidesBackButton:YES];
[self.navigationController pushViewController:loginView animated:NO];
}
UIBarButtonItem *takePhoto = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:#selector(takePhoto:)];
self.navigationItem.rightBarButtonItem = takePhoto;
// [self.tableView registerClass:[HomeViewCell class] forCellReuseIdentifier:#"cellIdentifier"];
// [self.tableView registerNib:[UINib nibWithNibName:#"HomeViewCell" bundle:nil]
// forCellReuseIdentifier:#"cellIdentifier"];
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
- (id)initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self) {
self.reusableSectionHeaderViews = [NSMutableSet setWithCapacity:3];
}
return self;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PFQuery *query = [PFQuery queryWithClassName:#"UserPhotos"];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
} else {
self.userPhotos = objects;
NSLog(#"Retrieved objects: %#", self.userPhotos);
[self.tableView reloadData];
}
}];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSInteger sections = self.userPhotos.count;
// Return the number of sections.
return sections;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return 1;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
if (section == self.userPhotos.count) {
// Load More section
return nil;
}
HomeHeaderView *headerView = [self dequeueReusableSectionHeaderView];
if (!headerView) {
headerView = [[HomeHeaderView alloc] initWithFrame:CGRectMake( 0.0f, 0.0f, self.view.bounds.size.width, 44.0f) buttons:HomePhotoHeaderButtonsDefault];
headerView.delegate = self;
[self.reusableSectionHeaderViews addObject:headerView];
}
//Setting the username display.
PFObject *owner = [self.userPhotos objectAtIndex:section];
PFUser *user = [owner objectForKey:#"user"];
[user fetchIfNeededInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!error) {
NSString *username = user.username;
[headerView.userButton setTitle:username forState:UIControlStateNormal];
}
}];
return headerView;
}
- (HomeHeaderView *)dequeueReusableSectionHeaderView {
for (HomeHeaderView *sectionHeaderView in self.reusableSectionHeaderViews) {
if (!sectionHeaderView.superview) {
// we found a section header that is no longer visible
return sectionHeaderView;
}
}
return nil;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"cellIdentifier";
HomeViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil)
{
cell = [[HomeViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//Setting the image in the cell.
PFObject *carPhoto = [self.userPhotos objectAtIndex:indexPath.row];
PFFile *imageFile = [carPhoto objectForKey:#"imageFile"];
NSURL *imageFileUrl = [[NSURL alloc] initWithString:imageFile.url];
NSData *imageData = [NSData dataWithContentsOfURL:imageFileUrl];
cell.carImage.contentMode = UIViewContentModeScaleAspectFit;
cell.carImage.image = [UIImage imageWithData:imageData];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 269;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
if (section == self.userPhotos.count) {
return 0.0f;
}
return 44.0f;
}
[user fetchIfNeededInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!error) {
NSString *username = user.username;
[headerView.userButton setTitle:username forState:UIControlStateNormal];
}
}];
The code above, you are updating the headerview UI from a background thread. You need to wrap the UI part so it performs on the main thread.
dispatch_async(dispatch_get_main_queue(), ^{
[headerView.userButton setTitle:username forState:UIControlStateNormal];
};
You need to be careful though, you are performing a background operation and then updating the header which you are reusing. There is a chance that the header is reused for a new section before the operation finishes and it is then set with the wrong username for that section. You can take care of this by not reusing the header or canceling the network operation if the header scrolls off screen before the operation finishes.
Related
I'm using Parse to populate a table view which works fine. I'm trying to delete a row from the table view but get this error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI length]: unrecognized selector sent to instance 0x7fd3f0f20f60'
Here is the code:
#import "CompletedJobs.h"
#import <Parse/Parse.h>
#interface CompletedJobs ()
#property (nonatomic, strong) NSMutableArray *jobs;
#property (nonatomic, strong) NSMutableArray *objectIds;
#property (nonatomic, strong) UIActivityIndicatorView *loadingIndicator;
#property (nonatomic, strong) UIRefreshControl *refresh;
#end
#implementation CompletedJobs
- (void)viewDidLoad {
[super viewDidLoad];
[self.tableView setDataSource:self];
[self.tableView setDelegate:self];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
CGFloat width = CGRectGetWidth(self.view.bounds);
CGFloat height = CGRectGetHeight(self.view.bounds);
self.loadingIndicator = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(width / 2, height / 2, 37, 37)];
self.loadingIndicator.center = CGPointMake(width / 2, height / 2 - 37);
self.loadingIndicator.autoresizingMask = (UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin);
self.loadingIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
self.loadingIndicator.hidesWhenStopped = YES;
[self.view addSubview:self.loadingIndicator];
[self.loadingIndicator startAnimating];
[self getJobs];
self.refresh = [[UIRefreshControl alloc]init];
self.refresh.tintColor = [UIColor blackColor];
[self.refresh addTarget:self action:#selector(refreshData) forControlEvents:UIControlEventValueChanged];
self.refreshControl = self.refresh;
}
- (void)viewDidAppear:(BOOL)animated {
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)getJobs {
self.jobs = [[NSMutableArray alloc]init];
self.objectIds = [[NSMutableArray alloc]init];
PFQuery *query = [PFQuery queryWithClassName:#"Completed"];
[query setLimit:1000];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
for (NSDictionary *objectDictionary in objects) {
[self.jobs addObject:objectDictionary];
for (int i = 0; i < self.jobs.count; i++) {
[self.objectIds addObject:[self.jobs valueForKeyPath:#"objectId"]];
}
}
dispatch_async(dispatch_get_main_queue(), ^ {
[self.tableView reloadData];
[self.loadingIndicator stopAnimating];
});
}
else {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
- (void)refreshData {
[self getJobs];
[self.refresh endRefreshing];
}
#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.jobs.count;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
NSString *objectId = [self.objectIds objectAtIndex:indexPath.row];
PFQuery *query = [PFQuery queryWithClassName:#"Completed"];
[query getObjectInBackgroundWithId:objectId block:^(PFObject *job, NSError *error) {
[job deleteInBackground];
}];
[self getJobs];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
NSDictionary *jobDictionary = [self.jobs objectAtIndex:[indexPath row]];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"UITableViewCell"];
}
if (cell) {
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.text = [jobDictionary objectForKey:#"job"];
NSString *completedBy = [jobDictionary objectForKey:#"completedBy"];
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
formatter.dateStyle = NSDateFormatterLongStyle;
formatter.timeStyle = NSDateFormatterShortStyle;
NSString *completedDate = [formatter stringFromDate:[jobDictionary objectForKey:#"date"]];
NSString *detailString = [NSString stringWithFormat:#"Completed by: %# on %#", completedBy, completedDate];
cell.detailTextLabel.text = detailString;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
}
#end
I'm trying to do a search function in my table view, to return objects from my Parse.com class.
I'm getting this error when I try to make a search in the UISearchBar:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier FeaturedTableViewCell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
Here's how I'm doing it:
#interface DiscoverViewController () <UISearchBarDelegate, UISearchDisplayDelegate>
#property (nonatomic, retain) PFQuery *query;
#property (nonatomic, retain) PFObject *category;
#end
#implementation DailyDiscoverViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.searchController = [[UISearchDisplayController alloc] initWithSearchBar:self.searchBar contentsController:self];
self.searchController.searchResultsDataSource = self;
self.searchController.searchResultsDelegate = self;
self.searchController.delegate = self;
self.searchResults = [NSMutableArray array];
_categories = [[NSMutableArray alloc] initWithCapacity:100];
}
- (void)filterResults:(NSString *)searchTerm {
[self.searchResults removeAllObjects];
PFQuery *query = [PFQuery queryWithClassName:#"Projects"];
[query whereKeyExists:#"name"];
[query whereKey:#"name" containsString:searchTerm];
NSArray *results = [query findObjects];
[self.searchResults addObjectsFromArray:results];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterResults:searchString];
return YES;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[searchBar resignFirstResponder];
}
- (void)refresh {
PFQuery *query = [PFQuery queryWithClassName:#"Categories"];
[query orderByDescending:#"name"];
[query findObjectsInBackgroundWithBlock:^(NSArray *posts, NSError *error) {
if (!error) {
//NSLog(#"%#", posts);
} else {
}
[_categories setArray:posts];
[self.tableView reloadData];
[_loadingView stopAnimating];
[_refreshControl endRefreshing];
}];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tableView) {
if (section == 0) {
return 1;
} else {
return self.categories.count;
}
} else {
return self.searchResults.count;
}
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
return 320;
} else {
return 52;
}
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
_featuredObject = [_featured objectAtIndex:indexPath.row];
DiscoverFeaturedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DiscoverFeaturedTableViewCell" forIndexPath:indexPath];
[(PFFile*)_featuredObject[#"picture"] getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
cell.image1.image = [UIImage imageWithData:data];
}];
return cell;
} else {
_category = [_categories objectAtIndex:indexPath.row];
DiscoverTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"DiscoverTableViewCell" forIndexPath:indexPath];
cell.name.text = _category[#"name"];
if ([tableView isEqual:self.searchDisplayController.searchResultsTableView]) {
PFUser *obj2 = [self.searchResults objectAtIndex:indexPath.row];
PFQuery *query = [PFQuery queryWithClassName:#"Projects"];
PFObject *searchedUser = [query getObjectWithId:obj2.objectId];
NSString *first = [searchedUser objectForKey:#"name"];
cell.name.text = [first substringToIndex:1];
cell.name.text = first;
return cell;
}
return cell;
}
}
#end
I think you can look this stack over flow post : POST
K.
Ok,
Try it on viewDidLoad:
YourCustomCell *yourCustomCell = [UINib
nibWithNibName:#"YourCustomCell" bundle:nil]; [self.tableView
registerNib:cellNib forCellReuseIdentifier:#"cell"];
Note: Your custom cell must have a .xib of course.
You could try this, I remember running into this exact issue and this was one of the solutions I tried:
[self.tableView registerClass:[DiscoverTableViewCell class] forCellReuseIdentifier:#"DiscoverTableViewCell"];
However, I distinctly remember that this didn't work. It turned out I hadn't correctly connected the cells in the storyboard. Furthermore, make sure that the class of your storyboard cell has been changed to represent your cell's custom class.
Problem: I have read in values from Windows Azure. Through NSLogs I am able to see that my application does indeed read in from the table on the Azure Server. However Displaying the values has become a problem.
Situation: So far I have an NSMutableArray object in the ViewController.m file. I have accessed the array and been able to assign the values from the results of the read from the table (in windows azure) to the mutableArray. My problem is that I am trying to display it through a tableview however nothing displays, and when I move down the table view, the application crashes.
I believe the main problem is this line:
cell.textLabel.text = [clubs objectAtIndex:indexPath.row];
Here is the ViewController.m code:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController{
NSDictionary *courseDetails;
NSArray *justCourseNames;
NSDictionary *webcourseDetails;
NSArray *webjustCourseNames;
NSDictionary *clubNames;
NSArray *location;
NSMutableArray *clubs;
NSInteger amount;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 2;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
if (section == 0)
{
return #"Milton Keynes";
}
else{
return #"Stafford";
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (section == 0)
{
return clubs.count;
}
else{
return webcourseDetails.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
UIImage *image = [UIImage imageNamed:#"ClubCellImage"];
[cell.imageView setImage:image];
//removing the line of code below seems to fix the crash. this is the line of code to display the details
cell.textLabel.text = [clubs objectAtIndex:indexPath.row];
/*if (indexPath.section == 0)
{
//cell.textLabel.text = justCourseNames[indexPath.row];
//cell.detailTextLabel.text = courseDetails[justCourseNames[indexPath.row]];
}
else
{
cell.textLabel.text = clubs[indexPath.row];
//cell.textLabel.text = webjustCourseNames[indexPath.row];
//cell.detailTextLabel.text = webcourseDetails[webjustCourseNames[indexPath.row]];
}*/
return cell;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.client = [MSClient clientWithApplicationURLString:#"https://clublocatortimogunmakin.azure-mobile.net/"
applicationKey:#"ecxnaXEfNpeOvwYYgcViJJoumZlZng45"];
// Do any additional setup after loading the view.
NSURL *url = [[NSBundle mainBundle] URLForResource:#"courses" withExtension:#"plist"];
MSTable *itemTable = [_client tableWithName:#"Item"];
courseDetails = [NSDictionary dictionaryWithContentsOfURL:url];
justCourseNames = courseDetails.allKeys;
NSURL *weburl = [[NSBundle mainBundle] URLForResource:#"courses_web" withExtension:#"plist"];
webcourseDetails = [NSDictionary dictionaryWithContentsOfURL:weburl];
webjustCourseNames = courseDetails.allKeys;
[itemTable readWithCompletion:^(NSArray *results, NSInteger totalCount, NSError *error) {
clubs = [results mutableCopy];
amount = totalCount;
if (error) {
NSLog(#"Error: %#", error);
} else {
//NSLog(#"Item read, id: %#", [results objectAtIndex:1]);
for (int i = 0; i < results.count; i++)
{
NSLog(#"Item read, id: %#", [results objectAtIndex:i]);
}
}
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You are contradicting yourself when you implement the required tableview datasource methods (i.e. the numberOfRowsInSection and the cellForRowAtIndexPath methods)
You provide the count of cells here:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (section == 0)
{
return clubs.count;
}
else{
return webcourseDetails.count;
}
}
So, your cellForRowAtIndexPath method should look something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// cell init/dequeuing
if (indexPath.section == 0) {
cell.textLabel.text = clubs[indexPath.row]; //Assuming that is an NSString instance
} else {
cell.textLabel.text = webcourseDetails[indexPath.row]; //Assuming that is an NSString instance
}
return cell;
}
Please, try to do the following (I think you're not re-loading table after all items are read):
[itemTable readWithCompletion:^(NSArray *results, NSInteger totalCount, NSError *error) {
clubs = [results mutableCopy];
amount = totalCount;
if (error) {
NSLog(#"Error: %#", error);
} else {
//NSLog(#"Item read, id: %#", [results objectAtIndex:1]);
for (int i = 0; i < results.count; i++)
{
NSLog(#"Item read, id: %#", [results objectAtIndex:i]);
}
[YOURTABLENAMEHERE reloadData];
}
}];
Replace YOURTABLENAMEHERE with a reference to your table.
in my app I'm using Parse.com as the holder of the data on a database and SearchBarDisplayController for research. I have prepared a following to prepare for my table in order to send the data cells in another view controller and works perfectly ... Now I am having a problem ...
How can I create a "prepareforsegue" for the SearchDisplayController, to activate the cells of the search results?
In here you can see the code for "Prepare for Segue" (or another Method) that I made and the data to be passed ...
Some Ideas on this? Thanks so much!
#import "Ricerca.h"
#import "Custom.h"
#import "DettagliProfilo.h"
#interface Ricerca () <UISearchDisplayDelegate, UISearchBarDelegate>
#property (nonatomic, strong) NSMutableArray *searchResults;
#end
#implementation Ricerca
#synthesize searchResults;
- (void)viewDidLoad {
[super viewDidLoad];
[self loadObjects];
self.searchResults = [NSMutableArray array];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
// The className to query on
self.parseClassName = #"_User";
self.pullToRefreshEnabled = YES;
self.paginationEnabled = YES;
self.objectsPerPage = 10;
}
return self;
}
- (PFQuery *)queryForTable {
PFQuery *query = [PFQuery queryWithClassName:self.parseClassName];
//[query whereKeyExists:#"username"];
//[query whereKeyExists:#"email"];
[query orderByAscending:#"username"];
if ([self.objects count] == 0) {
query.cachePolicy = kPFCachePolicyCacheThenNetwork;
}
return query;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait || UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
UITableViewCell *cell = (UITableViewCell *)[self.tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
// Configure the cell
UIColor *color = [[UIColor alloc] initWithRed:0.0 green:0.0 blue:0.0 alpha:0.0];
cell.detailTextLabel.backgroundColor = color;
cell.textLabel.backgroundColor = color;
if (tableView == self.tableView) {
cell.textLabel.text = [object objectForKey:#"username"];
cell.detailTextLabel.text = [object objectForKey:#"email"];
cell.imageView.image = [UIImage imageNamed:#"unknown"];
PFFile *imageFile = [object objectForKey:#"foto"];
[imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
cell.imageView.image =[UIImage imageWithData:data];
}];
}
else if(tableView == self.searchDisplayController.searchResultsTableView) {
PFObject *searchedUser = [self.searchResults objectAtIndex:indexPath.row];
NSString *content = [searchedUser objectForKey:#"username"];
NSString *email = [searchedUser objectForKey:#"email"];
cell.detailTextLabel.text = email;
cell.textLabel.text = content;
cell.imageView.image = [UIImage imageNamed:#"unknown"];
PFFile *imageFile = [searchedUser objectForKey:#"foto"];
[imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
cell.imageView.image =[UIImage imageWithData:data];
}];
NSLog(#"Content: %#", content);
}
return cell;
}
- (void)callbackLoadObjectsFromParse:(NSArray *)result error:(NSError *)error {
if (!error) {
[self.searchResults removeAllObjects];
NSLog(#"Successfully fetched %d entries", result.count);
[self.searchResults addObjectsFromArray:result];
[self.searchDisplayController.searchResultsTableView reloadData];
} else {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}
-(void)filterResults:(NSString *)searchTerm {
[self.searchResults removeAllObjects];
PFQuery *query = [PFUser query];
[query orderByAscending:#"username"];
[query whereKeyExists:#"email"];
[query whereKey:#"username" containsString:searchTerm];
query.cachePolicy = kPFCachePolicyNetworkOnly;
[query findObjectsInBackgroundWithTarget:self selector:#selector(callbackLoadObjectsFromParse:error:)];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterResults:searchString];
return YES;
}
- (void)searchDisplayController:(UISearchDisplayController *)controller didLoadSearchResultsTableView:(UITableView *)tableView
{
tableView.rowHeight = 80.0f; // or some other height
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tableView) {
return self.objects.count;
} else {
return self.searchResults.count;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
} else {
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
}
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Check that a new transition has been requested to the DetailViewController and prepares for it
/*if ([segue.identifier isEqualToString:#"Dettaglio"]){
// Capture the object (e.g. exam) the user has selected from the list
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
PFObject *object = [self.objects objectAtIndex:indexPath.row];
DettagliProfilo *detailViewController = [segue destinationViewController];
detailViewController.Dettaglio = object;*/
if ([[segue identifier]isEqualToString:#"Dettaglio"])
{
DettagliProfilo *sdvc = (DettagliProfilo *)[segue destinationViewController];
if(self.searchDisplayController.active) {
NSIndexPath *indexPath = [[self tableView] indexPathForSelectedRow];
PFObject *object = [self.objects objectAtIndex:indexPath.row];
object = (PFObject *)[[self searchResults]objectAtIndex:[[[[self searchDisplayController]searchResultsTableView]indexPathForSelectedRow]row]];
sdvc.Dettaglio = object;
} else {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
PFObject *object = [self.objects objectAtIndex:indexPath.row];
DettagliProfilo *detailViewController = [segue destinationViewController];
detailViewController.Dettaglio = object;
}
}
}
#end
Hey together I am using Parse SDK for my App - the interface is build in Storyboard...
I am having a table view which get's his data from Parse, now I want to make it searchable.
I found this post and followed it but not came to a running result! :/
The search results are load but I having problems to display them...
I get the following errors:
... myApp[..] *** Assertion failure in -[UISearchResultsTableView _configureCellForDisplay:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2380.17/UITableView.m:5471
... myApp[...] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'
I tried a lot around but don't come to a result, here is my code - can anybody help:
Sorry for my bad english! ;)
#import "FirstLaunchViewController.h"
#interface FirstLaunchViewController ()
#end
#implementation FirstLaunchViewController
#pragma mark - UIViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self loadObjects];
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"navbar_background.png"] forBarMetrics:UIBarMetricsDefault];
self.searchResults = [NSMutableArray array];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithClassName:#"teams"];
self = [super initWithCoder:aDecoder];
if (self) {
// The className to query on
self.parseClassName = #"teams";
self.textKey = #"verein";
// The key of the PFObject to display in the label of the default cell style
// self.keyToDisplay = #"text";
// Whether the built-in pull-to-refresh is enabled
self.pullToRefreshEnabled = NO;
// Whether the built-in pagination is enabled
self.paginationEnabled = YES;
self.loadingViewEnabled = NO;
// The number of objects to show per page
self.objectsPerPage = 50;
}
return self;
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait || UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object {
PFTableViewCell *cell = (PFTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
// Configure the cell
UIColor *color = [[UIColor alloc] initWithRed:0.0 green:0.0 blue:0.0 alpha:0.0];
cell.detailTextLabel.backgroundColor = color;
cell.textLabel.backgroundColor = color;
cell.backgroundView = [ [UIImageView alloc] initWithImage:[ [UIImage imageNamed:#"cellbackground_n.png"] stretchableImageWithLeftCapWidth:0.0 topCapHeight:5.0]];
cell.selectedBackgroundView = [ [UIImageView alloc] initWithImage:[ [UIImage imageNamed:#"cellbackground_down_n.png"] stretchableImageWithLeftCapWidth:0.0 topCapHeight:5.0]];
cell.accessoryView = [[ UIImageView alloc ] initWithImage:[UIImage imageNamed:#"cellarrows.png" ]];
if (tableView == self.tableView) {
cell.textLabel.text = [object objectForKey:#"verein"];
} else {
PFUser *obj2 = [self.searchResults objectAtIndex:indexPath.row];
PFQuery *query = [PFQuery queryWithClassName:#"teams"];
PFObject *searchedUser = [query getObjectWithId:obj2.objectId];
NSString *content = [searchedUser objectForKey:#"verein"];
cell.textLabel.text = content;
NSLog(#"Content: %#", content);
}
return cell;
}
-(void)filterResults:(NSString *)searchTerm {
[self.searchResults removeAllObjects];
PFQuery *query = [PFQuery queryWithClassName: self.parseClassName];
[query whereKeyExists:#"verein"]; //this is based on whatever query you are trying to accomplish
[query whereKey:#"verein" containsString:searchTerm];
NSArray *results = [query findObjects];
NSLog(#"%#", results);
NSLog(#"%u", results.count);
[self.searchResults addObjectsFromArray:results];
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterResults:searchString];
return YES;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (tableView == self.tableView) {
return self.objects.count;
} else {
return self.searchResults.count;
}
}
#end
The issue is that your tableView initially has no reusable cells to dequeue. You need to check whether the cell returned by dequeueReusableCellWithIdentifier: is nil, and create a cell if it is.
PFTableViewCell *cell = (PFTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!cell)
{
cell = [[PFTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
// Configure the cell
...
This way, you are guaranteeing that cell has a value, so you can avoid returning nil from this method.
To handle tableView:didSelectRowAtIndexPath: correctly, you'll need to first check which tableView triggered the event, and handle it accordingly. Below is an example of how this could work - you'd need to substitute your own detail view controller.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.tableView) {
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
}
else {
PFUser *user = PFUser *obj2 = [self.searchResults objectAtIndex:indexPath.row];
MyDetailViewController *detailController = [[MyDetailViewController alloc] initWithObject:user];
[self.navigationController pushViewController:datailController animated:YES];
}
}