I am developing an apps for data management system for iOS 6. This is my code:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationItem.title = #"Detail";
if (self.student.thumbnailImage != nil) {
[self.imageButton setImage:[UIImage imageWithData:self.student.thumbnailImage] forState:UIControlStateNormal];
} else {
[self.imageButton setImage:[UIImage imageNamed:#"Default_photo3.png"] forState:UIControlStateNormal];
}
NSLog(#"Student First = %#", self.student.firstname);
self.firstNameTF.text = self.student.firstname;
NSLog(#"Student Last = %#", self.student.lastname);
self.lastNameTF.text = self.student.lastname;
NSLog(#"Student IC = %#", self.student.ic);
self.icTF.text = self.student.ic;
NSLog(#"Student Form = %#", self.student.form);
self.formTF.text = self.student.form;
NSLog(#"Student Gender = %#", self.student.gender);
self.genderTF.text = self.student.gender;
NSLog(#"Student Birthday = %#", self.student.birthday);
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd/MM/yyyy"];
NSString *date = [dateFormatter stringFromDate:self.student.birthday];
self.birthdateTF.text = date;;
self.dateButton.titleLabel.text =date;
NSLog(#"Address = %#", self.student.address.street);
NSLog(#"Zip = %#", self.student.address.zip);
NSLog(#"City = %#", self.student.address.city);
NSLog(#"State = %#", self.student.address.state);
[self updateImageButton];
//Create a mutable array for guardians
NSSortDescriptor *sortDEscriptors = [[NSSortDescriptor alloc]initWithKey:#"firstname" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDEscriptors, nil];
NSMutableArray *sortedGuardians = [[NSMutableArray alloc] initWithArray:[self.student.guardians allObjects]];
[sortedGuardians sortUsingDescriptors:sortDescriptors];
self.guardiansArray= sortedGuardians;
[self.tableView reloadData];
}
I found out that my tableview didn't scroll at the beginning. But when i remove the [self.tableView reloadData] in this part, it did scroll normally. Does anyone know why? I need to put the [self.tableView reloadData] here so the data is updated after editing.
Put the reloadData in ViewDidAppear method, so you will set your data before the view appear and request the reload after it appears.
You can set offset as it was before data reload
CGPoint offset = self.tableView.contentOffset;
[self.tableView reloadData];
[self.view layoutIfNeeded];
[self.tableView setContentOffset:offset animated:NO];
Hope this will help someone
Related
I have a screen which shows favourite locations and if a user wants to add new location he can search using uisearchcontroller and add it to favourite location's list.
The problem is that once i make the api call for autocomplete the list of searched locations is visible but i cannot select or scroll the table.
I know that the problem is where i set the uisearchcontroller. but i do not know the right way to do it.
I am newbie in iOS so ur suggestions will be welcome.
the following is the GithubRepository for the project(incase ul want to try out the app and make suggestions)
and heres the related code where i beleive the problem exists.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
favList = [[NSMutableArray alloc] init];
searchList = [[NSMutableArray alloc]init];
self.table.dataSource = self;
self.table.delegate = self;
[self initSearch];
}
#pragma mark UI Search methods
-(void) initSearch
{
FavouriteViewController *searchResultsController = [[FavouriteViewController alloc] init];
searchResultsController.table.dataSource = self;
searchResultsController.table.delegate = self;
searchResultsController.table.allowsSelectionDuringEditing = YES;
searchResultsController.table.allowsSelection = YES;
self.search = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
self.definesPresentationContext = NO;
self.table.tableHeaderView = self.search.searchBar;
self.search.searchResultsUpdater = self;
self.search.searchBar.delegate = self;
self.search.dimsBackgroundDuringPresentation = NO;
}
didSelectRowAtIndex method
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (self.search.active) {
NSManagedObjectContext *context = [self managedObjectContext];
NSManagedObjectModel *place = [NSEntityDescription insertNewObjectForEntityForName:#"Place" inManagedObjectContext:context];
NSString *places =[searchList[indexPath.row] valueForKey:#"name"];
if (![favList containsObject:places])
{
NSString *lati = [searchList[indexPath.row] valueForKey:#"lat"];
NSString *longi = [searchList[indexPath.row] valueForKey:#"lon"];
if (places != NULL && lati != NULL && longi != NULL)
{
[place setValue:places forKey:#"placeName"];
[place setValue:lati forKey:#"latitude"];
[place setValue:longi forKey:#"longitude"];
}
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
}
[self.search setActive:NO];
filtered = NO;
[self getalldata];
[self.table reloadData];
}
else
{
NSManagedObject *device = [favList objectAtIndex:indexPath.row];
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.SJI.Weather-App"];
[defaults setObject:[device valueForKey:#"placeName"] forKey:#"favSet"];
[[self navigationController] popToRootViewControllerAnimated:YES];
}
}
I have a method in ViewController.m called getData which is called inside viewDidLoad:
-(void)getData {
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *context = [appDelegate managedObjectContext];
NSEntityDescription *entityDesc = [NSEntityDescription entityForName:#"WorkoutHasExercise" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDesc];
request.resultType = NSDictionaryResultType;
request.propertiesToFetch = [NSArray arrayWithObjects:#"exerciseName", #"reps", #"sets", nil];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(workoutName = %#)", _workoutName];
[request setPredicate:pred];
NSManagedObject *matches = nil;
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if ([objects count] == 0) {
} else {
[_exercises removeAllObjects];
for (int x = 0; x < [objects count]; x++) {
matches = objects[x];
[_exercises addObject:[matches valueForKey:#"exerciseName"]];
[_totalSets addObject:[matches valueForKey:#"sets"]];
[_totalReps addObject:[matches valueForKey:#"reps"]];
[_currentSets addObject:[NSNumber numberWithInteger:0]];
}
}
[_exercisesTableView reloadData];
}
I also have a custom UITableViewCell with two buttons initiated in cellForRowAtIndexPath:
ActiveWorkoutCell *cell = (ActiveWorkoutCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ActiveWorkoutCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.increaseButton.tag = indexPath.row;
cell.decreaseButton.tag = indexPath.row;
In ActiveWorkoutCell.m I have 2 IBActions for the buttons:
- (IBAction)decreaseSets:(id)sender {
ActiveWorkoutViewController *vc = [[ActiveWorkoutViewController alloc] init];
[vc decreaseSets:[sender tag]];
}
- (IBAction)increaseSets:(id)sender {
ActiveWorkoutViewController *vc = [[ActiveWorkoutViewController alloc] init];
[vc increaseSets:[sender tag]];
}
The IBActions call these 2 methods back in ViewController.m
-(void)increaseSets:(NSInteger)row {
[self getData];
//There will be code here to increase the value of currentSets[row]
}
-(void)decreaseSets:(NSInteger)row {
[self getData]
//Code to decrease value...
}
PROBLEM:
When getData is called from viewDidLoad, it works fine.
The problem occurs when returning to ViewController.m from the IBAction in ActiveWorkoutCell.m.
When I call [self getData] in increaseSets the fetch request returns an empty array. This is what is confusing me - the code works fine when it is first called but not at all when called the second time after the custom cell Action has been triggered.
Here is my viewDidLoad if it helps:
- (void)viewDidLoad {
[super viewDidLoad];
_exercises = [NSMutableArray array];
_totalSets = [NSMutableArray array];
_currentSets = [NSMutableArray array];
_totalReps = [NSMutableArray array];
_titleLabel.text = _workoutName;
_exercisesTableView.allowsSelection = NO;
[self getData];
}
_workoutName is given a value in prepareForSegue in the previous view controller.
I think I found the issue. You are instantiating the "ActivityWorkOutViewController" when the IBAction methods called and it will be a new instance and then in those methods you are calling [self getData] which pointing to the new instance which has no variables instantiated or viewDidLoad happened, so your mutable arrays are not allocated and hence they are empty.
Just use the old instance of the class to get the data.
I am not sure how you are referencing those classes. I am just in a confusion about that. But, you might check the allocations and calling the right class to get the data
Currently I've a Tableview that when it loads it makes a request to Core-Data and grabs the first 10 Messages of the newer ones.
// Initialize Fetch Request
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Chat"];
// Add Sort Descriptors
fetchRequest.fetchLimit = 10;
fetchRequest.predicate = [NSPredicate predicateWithFormat:#"room = %#", _roomid];
[fetchRequest setSortDescriptors:#[[NSSortDescriptor sortDescriptorWithKey:#"date_message" ascending:NO]]]; // YES;
// Initialize Fetched Results Controller
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self;
// Perform Fetch
NSError *error = nil;
[self.fetchedResultsController performFetch:&error];
if (error) {
NSLog(#"Unable to perform fetch.");
NSLog(#"%#, %#", error, error.localizedDescription);
}
After I call them. Messages are shown properly under. But When I load (fetch older messages on demand) I use the following.
- (void)fetchOldMessages {
[self.fetchedResultsController.fetchRequest setSortDescriptors:#[[NSSortDescriptor sortDescriptorWithKey:#"date_message" ascending:NO]]];
_fetchedResultsController.fetchRequest.fetchLimit +=10;
NSError *error = nil;
[self.fetchedResultsController performFetch:&error];
if (error) {
NSLog(#"Unable to perform fetch.");
NSLog(#"%#, %#", error, error.localizedDescription);
}
[self.tableView reloadData];
}
The issue is that the Old messages are now being shown below instead of above the new messages. Also new inserted messages are shown at the top of the tableView instead of the bottom.
this is my IndexPath:
- (UITableViewCell*)tableView:(UITableView*)table cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Chat *messageInfo = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString *CellIdentifier = #"fromMe";
FromMeTableViewCell *cell = [table dequeueReusableCellWithIdentifier:CellIdentifier];
cell.message_me.clipsToBounds = YES;
cell.message_me.layer.cornerRadius = 15;
cell.message_me.textContainerInset = UIEdgeInsetsMake(8.0, 8.0, 8.0, 8.0);
cell.message_me.text = messageInfo.message;
cell.message_date_me.text = [NSString stringWithFormat:#"%#", messageInfo.date_message];
cell.avatar_message_me.clipsToBounds = YES;
cell.avatar_message_me.layer.cornerRadius = cell.avatar_message_me.frame.size.width / 2;
cell.avatar_message_me.image = user_images[#"me"];
cell.message_me.backgroundColor = [UIColor colorWithRed:0.098 green:0.737 blue:0.611 alpha:1];
cell.message_me.textColor = [UIColor whiteColor]; //[UIColor whiteColor];
// Date Settings
NSDate *today = [[NSDate alloc]init];
NSDate *message_date = messageInfo.date_message;
NSDateFormatter *formatDate = [[NSDateFormatter alloc]init];
[formatDate setDateFormat:#"yyyy-MM-dd"];
NSString *today_string = [formatDate stringFromDate:today];
NSString *message_date_string = [formatDate stringFromDate:message_date];
// Make Date validation case is older display full date
if([today_string isEqualToString:message_date_string]){
NSDateFormatter *timeformat = [[NSDateFormatter alloc] init];
[timeformat setDateFormat:#"hh:mm a"];
NSDate *message_date = messageInfo.date_message;
NSString *string_date = [timeformat stringFromDate:message_date];
cell.message_date_me.text = [NSString stringWithFormat:#"Today at %#",[NSString stringWithFormat:#"%#",string_date]];
}
else {
NSDateFormatter *timeformat = [[NSDateFormatter alloc] init];
[timeformat setDateFormat:#"EEEE d hh:mm a"];
NSDate *message_date = messageInfo.date_message;
NSString *string_date = [timeformat stringFromDate:message_date];
cell.message_date_me.text = [NSString stringWithFormat:#"%#",[NSString stringWithFormat:#"%#",string_date]];
}
return cell;
}
This is when It first loads shows 5 Messages But the last message should be down ant not Above as you can see on the DATE
When I load more Data it shows the Messages in the right Order from new to older but the issue is that I want to show newer messages Below and Older messages Above.
Make your fetch request controller sorting ASCENDING to YES
[self.fetchedResultsController.fetchRequest
setSortDescriptors:#[[NSSortDescriptor
sortDescriptorWithKey:#"date_message" ascending:YES]]];
Im using GCD to download a plist file from the internet then enter the data into an array then load it into a tableView.
The data is being downloaded and converted alright but the table view is taking ages to update. I have the app Logging something when it calls [self.tableView reloadData] but the table view updates about 10 seconds later.
I don't think this is about the table view because I tried changing the title of the Navigation Bar inside the GCD and there was also a delay. So it might be a delay updating the user interface?
This is my GCD code:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
Thanks for you help
EDIT:
This is my code:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UERootArray = [[NSArray alloc] initWithContentsOfURL:[NSURL URLWithString:#"url to file"]];
NSLog(#"Array: %#", UERootArray);
//NSLog(#"count %#",count);
NSString *currentName;
NSString *currentLoaction;
NSString *currentDate;
int currentEventInt = 0;
NSArray *currentEventArr = [UERootArray objectAtIndex:0];
while (currentEventArr.count > currentEventInt)
{
currentName = [currentEventArr objectAtIndex:0];
currentLoaction = [currentEventArr objectAtIndex:1];
currentDate = #"7pm 17/11"; //[currentEventArr objectAtIndex:2];
NSLog (#"Title: %#", currentName);
NSLog (#"News: %#", currentLoaction);
NSLog (#"Date: %#", currentDate);
UEEvent *currentTask = [[UEEvent alloc] initWithName:currentName location:currentLoaction date:currentDate];
[self.upcommingEvents addObject:currentTask];
currentEventInt = currentEventInt + 1;
}
UEDownloaded = YES;
[self.tableView reloadData];
Edit 2:
- (void)downloadUEData
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UERootArray = [[NSArray alloc] initWithContentsOfURL:[NSURL URLWithString:#"url to file"]];
[self processUEData];
});
}
- (void)processUEData
{
NSLog(#"Array: %#", UERootArray);
//NSLog(#"count %#",count);
NSString *currentName;
NSString *currentLoaction;
NSString *currentDate;
int currentEventInt = 0;
NSArray *currentEventArr = [UERootArray objectAtIndex:0];
while (currentEventArr.count > currentEventInt)
{
currentName = [currentEventArr objectAtIndex:0];
currentLoaction = [currentEventArr objectAtIndex:1];
currentDate = #"7pm 17/11"; //[currentEventArr objectAtIndex:2];
NSLog (#"Title: %#", currentName);
NSLog (#"News: %#", currentLoaction);
NSLog (#"Date: %#", currentDate);
UEEvent *currentTask = [[UEEvent alloc] initWithName:currentName location:currentLoaction date:currentDate];
[self.upcommingEvents addObject:currentTask];
currentEventInt = currentEventInt + 1;
}
UEDownloaded = YES;
[self.tableView reloadData];
}
i think following code will solve your problem ...
- (void)downloadUEData
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UERootArray = [[NSArray alloc] initWithContentsOfURL:[NSURL URLWithString:#"http://www.nytrex.webs.com/Linx/upcommingEvents.plist"]];
[self processUEData];
});
}
- (void)processUEData
{
NSLog(#"Array: %#", UERootArray);
//NSLog(#"count %#",count);
NSString *currentName;
NSString *currentLoaction;
NSString *currentDate;
int currentEventInt = 0;
NSArray *currentEventArr = [UERootArray objectAtIndex:0];
while (currentEventArr.count > currentEventInt)
{
currentName = [currentEventArr objectAtIndex:0];
currentLoaction = [currentEventArr objectAtIndex:1];
currentDate = #"7pm 17/11"; //[currentEventArr objectAtIndex:2];
NSLog (#"Title: %#", currentName);
NSLog (#"News: %#", currentLoaction);
NSLog (#"Date: %#", currentDate);
UEEvent *currentTask = [[UEEvent alloc] initWithName:currentName location:currentLoaction date:currentDate];
[self.upcommingEvents addObject:currentTask];
currentEventInt = currentEventInt + 1;
}
UEDownloaded = YES;
dispatch_async(dispatch_get_main_queue(), ^{ // update your UI in main thread
[self.tableView reloadData];
});
}
I've almost finished my app and everything seems to work but the main view.
It's an UIViewController with an embedded UITableView.
I'm using Parse as the backend, and I get an array of the objects I need in my viewDidLoad method.
Each cell contains some data that I'm fetching in the tableView:cellForRowAtIndexPath and I'm afraid that this is the reason why my table view is so laggy, but I don't know how to fetch the data I need for each object in my array without having the indexPath.row number.
I've already made each cell element "opaque" as suggested in other answers.
This is my code, any help would be greatly appreciated:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"cellHT";
CellHT *cell = (CellHT *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[CellHT alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// self.hH is an NSArray containing all the objects
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
cell.lblTitle.text = [self.hH[indexPath.row] objectForKey:#"title"];
cell.lblVenueName.text = [self.hH[indexPath.row] objectForKey:#"venueName"];
cell.lblDistance.text = NSLocalizedString(#"Distance from you", nil);
self.geo = [self.hH[indexPath.row] objectForKey:#"coordinates"];
// the formatters are initialized in the viewDidLoad: method
self.formatData = [NSDateFormatter dateFormatFromTemplate:#"dd/MM" options:0 locale:[NSLocale currentLocale]];
[self.formatterData setDateFormat:self.formatData];
self.formatOra = [NSDateFormatter dateFormatFromTemplate:#"j:mm" options:0 locale:[NSLocale currentLocale]];
[self.formatterOra setDateFormat:self.formatOra];
self.dal = NSLocalizedString(#"from", nil);
self.ore = NSLocalizedString(#"at", nil);
CLLocation *vLoc = [[CLLocation alloc] initWithLatitude:self.geo.latitude longitude:self.geo.longitude];
CLLocation *user = [[CLLocation alloc] initWithLatitude:self.userGeo.latitude longitude:self.userGeo.longitude];
CLLocationDistance distance = [user distanceFromLocation:venueLoc];
if ([[prefs objectForKey:#"unit"] isEqualToString:#"km"]) {
cell.lblDist.text = [NSString stringWithFormat:#"%.1f Km", distance /1000];
} else {
cell.lblDist.text = [NSString stringWithFormat:#"%.1f Miles", distance /1609];
}
// compare the object's starting date with the current date to set some images in the cell
NSComparisonResult startCompare = [[self.hH[indexPath.row] objectForKey:#"startDate"] compare: [NSDate date]];
if (startCompare == NSOrderedDescending) {
cell.quad.image = [UIImage imageNamed:#"no_HT"];
cell.lblStartTime.textColor = [UIColor redColor];
} else {
cell.quad.image = [UIImage imageNamed:#"yes_HT"];
cell.lblStartTime.textColor = [UIColor colorWithRed:104.0/255.0 green:166.0/255.0 blue:66.0/255.0 alpha:1.0];
}
NSString *dataInizio = [NSString stringWithFormat:#"%# %# %# %#", self.dal, [self.formatterData stringFromDate:[self.hH[indexPath.row] objectForKey:#"startDate"]], self.ore, [self.formatterOra stringFromDate:[self.hH[indexPath.row] objectForKey:#"endDate"]]];
cell.lblStartTime.text = dataInizio;
PFObject *cat = [self.hH[indexPath.row] objectForKey:#"catParent"];
NSString *languageCode = [[NSLocale preferredLanguages] objectAtIndex:0];
if ([languageCode isEqualToString:#"it"]) {
cell.lblCategory.text = [cat objectForKey:#"nome_it"];
} else if ([languageCode isEqualToString:#"es"]) {
cell.lblCategory.text = [cat objectForKey:#"nome_es"];
} else {
cell.lblCategory.text = [cat objectForKey:#"nome_en"];
}
//getting the image data from the Parse PFFile
PFFile *theImage = [self.hH[indexPath.row] objectForKey:#"photo"];
[theImage getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
cell.cellImageView.image = [UIImage imageWithData:data];
}
}];
//getting the cell object's owner and his profile
PFUser *usr = [self.hH[indexPath.row] objectForKey:#"parent"];
PFQuery *prof = [PFQuery queryWithClassName:#"Profile"];
prof.cachePolicy = kPFCachePolicyCacheThenNetwork;
[prof whereKey:#"parent" equalTo:usr];
[prof getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!error) {
//getting the object's rating and the number of votes
PFQuery *rateQuery = [PFQuery queryWithClassName:#"Rating"];
[rateQuery whereKey:#"parent" equalTo:object];
[rateQuery getFirstObjectInBackgroundWithBlock:^(PFObject *object, NSError *error) {
if (!error) {
float vote = [[object objectForKey:#"rate"] floatValue];
float temp = ((vote * 2) + 0.5);
int tempvote = (int)temp;
float roundedVote = (float)tempvote / 2;
// drawing the stars number, depending on the rating obtained
UIImage *starsImage = [UIImage imageNamed:#"stars"];
UIGraphicsBeginImageContextWithOptions(cell.imgVoto.frame.size, NO, 0);
CGPoint starPoint = (CGPoint) {
.y = (cell.imgVoto.frame.size.height * (2 * roundedVote + 1)) - (starsImage.size.height)
};
[starsImage drawAtPoint:starPoint];
cell.imgVoto.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
cell.lblVoto.text = [NSString stringWithFormat:#"(%d)", [[object objectForKey:#"voters"] intValue]];
}
}];
}
}];
return cell;
}
EDIT: this is the cell code:
+ (void)initialize {
if (self != [HH class]) {
return;
}
}
-(id)initWithCoder:(NSCoder *)aDecoder {
if ( !(self = [super initWithCoder:aDecoder]) ) return nil;
self.cellImageView.image = [UIImage imageNamed:#"icona_foto"];
self.cellImageView.contentMode = UIViewContentModeScaleToFill;
self.formatterData = [[NSDateFormatter alloc] init];
self.formatData = [[NSString alloc] init];
self.formatterOra = [[NSDateFormatter alloc] init];
self.formatOra = [[NSString alloc] init];
self.formatData = [NSDateFormatter dateFormatFromTemplate:#"dd/MM" options:0 locale:[NSLocale currentLocale]];
[self.formatterData setDateFormat:self.formatData];
self.formatOra = [NSDateFormatter dateFormatFromTemplate:#"j:mm" options:0 locale:[NSLocale currentLocale]];
[self.formatterOra setDateFormat:self.formatOra];
self.lblVoto.text = #"(0)";
return self;
}
SECOND EDIT: this is the code in the viewDidLoad method:
PFQuery *hours = [PFQuery queryWithClassName:#"HH"];
hours.cachePolicy = kPFCachePolicyCacheThenNetwork;
// here I'm making lots of query constraints that I'll not include
[hours findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
self.objectsNumber = objects.count;
self.hH = [[NSArray alloc] initWithArray:objects];
}
}];
[self.tableView reloadData];
}
I would move as much of the logic out of cellForRowAtIndexPath: as you can, it needs to be very light-weight to get good scrolling performance. You're doing a lot of work on the main thread, and I would do a lot more of this work when you get your model objects back from Parse (if you could post viewDidLoad I can give you more specific help) and update the table view when these calls are done:
[UIImage imageWithData:data]
anything to do with NSDateFormatter
CLLocation's initWithLatitude:longitude:
creating the rating stars image
None of these depend on the state of the table view, so they can be effectively precomputed and cached in a model object. If you simply scroll up and down the table, you're doing allo f the same work over and over, killing your performance.
Updated for the questioner's newest code:
I won't include all of your functionality here but this should give you an idea:
// create a single shared formatter instead of one per object
NSDateFormatter *dateFormatter = [NSDateFormatter dateFormatFromTemplate:#"dd/MM" options:0 locale:[NSLocale currentLocale]];
NSDateFormatter *timeFormatter = [NSDateFormatter dateFormatFromTemplate:#"j:mm" options:0 locale:[NSLocale currentLocale]];
[hours findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
self.objectsNumber = objects.count;
for (SomeObject *modelObj in objects) {
// if you can add properties to your model object directly, do that
// otherwise write a category on the Parse object to add the ones you need
modelObj.dateString = [NSString stringWithFormat:#"%# %# %# %#", modelObj.dal, [self.dateFormatter stringFromDate:[modelObj objectForKey:#"startDate"]], modelObj.ore, [self.timeFormatter stringFromDate:[modelObj objectForKey:#"endDate"]]];
// create your locations, images, etc in here too
}
self.hH = [[NSArray alloc] initWithArray:objects];
}
}];]
Then in cellForRowAtIndexPath:, take the precomputed properties and simply assign them to the appropriate labels, image views, etc.
It would be even better to do most of this processing off the main thread via GCD, but that is most likely out of scope for this question. See Using GCD and Blocks Effectively for more information. Just remember do only interact with UIKit from the main thread!
have a try by removing
CLLocation *vLoc = [[CLLocation alloc] initWithLatitude:self.geo.latitude longitude:self.geo.longitude];
CLLocation *user = [[CLLocation alloc] initWithLatitude:self.userGeo.latitude long itude:self.userGeo.longitude];
CLLocationDistance distance = [user distanceFromLocation:venueLoc];
This was at first sight , then I see your all your code and I realize a lot of image are used
Because UITableView takes some time to layout cells.
Solution:
step1. Set section number and row number to 0.
step2. Reload tableView in viewDidAppear.
Then your view controller cloud response quickly and then show cells.