TableView reloadData does not remove images - ios7

I have tableView with multiple types of dynamic prototype cells. When I call reloadData in viewDidLoad most of the data gets reloaded but the images remain and overlap with the new content. Is there another command that I'm missing?
Here's the code snippet (tried to edit it down for simplicity):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
PFObject *question = [self.friendsPosts objectAtIndex:indexPath.row];
...
else if ([[question objectForKey:#"questionType"] isEqualToString:#"PhotoChoice"]) {
static NSString *CellIdentifier = #"PhotoChoiceCell";
PhotoChoiceTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFUser *asker = [question objectForKey:#"asker"];
[asker fetch];
cell.question = question;
cell.usernameLabel.text = asker.username;
cell.questionLabel.text = [question objectForKey:#"questionText"];
cell.delegate = self;
[cell setCellIndexPath:indexPath];
[cell.questionLabel adjustFontSizeToFit];
cell.answered = false;
NSDate *postedTime = [question createdAt];
NSString *postedAgo = [postedTime dateTimeAgo];
cell.timeLabel.text = postedAgo;
[cell.likeButton setTitle:[NSString stringWithFormat:#"Likes (%#)", [question objectForKey:#"likes"]] forState:UIControlStateNormal];
cell.commentButton.text = [NSString stringWithFormat:#"Comments (%lu)", (unsigned long)[[question objectForKey:#"comments" ] count]];
PFRelation *allAnswerers = [question objectForKey:#"answerersRelation"];
PFQuery *answerersQuery = [allAnswerers query];
[answerersQuery whereKey:#"objectId" equalTo:[[PFUser currentUser] objectId]];
[answerersQuery countObjectsInBackgroundWithBlock:^(int number, NSError *error) {
if (error) {
NSLog(#"Error %# %#", error, [error userInfo]);
}
else {
if (number == 0) {
if ( [[question objectForKey:#"numPhotos"] isEqualToString:#"2" ]) {
[cell.photoButtonA1 setImage:allImages[0] forState:UIControlStateNormal];
[cell.photoButtonA2 setImage:allImages[1] forState:UIControlStateNormal];
cell.photoButtonA1.hidden = NO;
cell.photoButtonA2.hidden = NO;
}
else if ( [[question objectForKey:#"numPhotos"] isEqualToString:#"3"] ) {
[cell.photoButtonB1 setImage:allImages[0] forState:UIControlStateNormal];
[cell.photoButtonB2 setImage:allImages[1] forState:UIControlStateNormal];
[cell.photoButtonB3 setImage:allImages[2] forState:UIControlStateNormal];
cell.photoButtonB1.hidden = NO;
cell.photoButtonB2.hidden = NO;
cell.photoButtonB3.hidden = NO;
}
else if ( [[question objectForKey:#"numPhotos"] isEqualToString:#"4"] ) {
[cell.photoButtonC1 setImage:allImages[0] forState:UIControlStateNormal];
[cell.photoButtonC2 setImage:allImages[1] forState:UIControlStateNormal];
[cell.photoButtonC3 setImage:allImages[2] forState:UIControlStateNormal];
[cell.photoButtonC4 setImage:allImages[3] forState:UIControlStateNormal];
cell.photoButtonC1.hidden = NO;
cell.photoButtonC2.hidden = NO;
cell.photoButtonC3.hidden = NO;
cell.photoButtonC4.hidden = NO;
}
}
So, I should have made it clear that the images were set as UIButtons.

OK, here is my guess:
You seem to have three types of cell: one with 2 images, one with 3, and one with 4; but they are all of the same class and use the same cell identifier.
So when you recycle (dequeue) your table cells, you might be reusing a cell that was previously assigned 4 images, but this time using it as a 2-image cell. Thus, you update only 2 images of the previous 4, and the other two remain unchanged. You should set the remaining images to nil when you set less than 4 images to a cell (2 or 3).
Although without further details on the pattern of occurrence of your bug, it is hard to tell.
Try this modification to your code:
// (previous code omitted)
if (number == 0) {
// Reset all cell images, regardless of type
[cell.photoButtonA1 setImage:nil forState:UIControlStateNormal];
[cell.photoButtonA2 setImage:nil forState:UIControlStateNormal];
[cell.photoButtonB1 setImage:nil forState:UIControlStateNormal];
[cell.photoButtonB2 setImage:nil forState:UIControlStateNormal];
[cell.photoButtonB3 setImage:nil forState:UIControlStateNormal];
[cell.photoButtonC1 setImage:nil forState:UIControlStateNormal];
[cell.photoButtonC2 setImage:nil forState:UIControlStateNormal];
[cell.photoButtonC3 setImage:nil forState:UIControlStateNormal];
[cell.photoButtonC4 setImage:nil forState:UIControlStateNormal];
//
if ( [[question objectForKey:#"numPhotos"] isEqualToString:#"2" ]) {
[cell.photoButtonA1 setImage:allImages[0] forState:UIControlStateNormal];
[cell.photoButtonA2 setImage:allImages[1] forState:UIControlStateNormal];
cell.photoButtonA1.hidden = NO;
cell.photoButtonA2.hidden = NO;
}
else if ( [[question objectForKey:#"numPhotos"] isEqualToString:#"3"] ) {
[cell.photoButtonB1 setImage:allImages[0] forState:UIControlStateNormal];
[cell.photoButtonB2 setImage:allImages[1] forState:UIControlStateNormal];
[cell.photoButtonB3 setImage:allImages[2] forState:UIControlStateNormal];
cell.photoButtonB1.hidden = NO;
cell.photoButtonB2.hidden = NO;
cell.photoButtonB3.hidden = NO;
}
else if ( [[question objectForKey:#"numPhotos"] isEqualToString:#"4"] ) {
[cell.photoButtonC1 setImage:allImages[0] forState:UIControlStateNormal];
[cell.photoButtonC2 setImage:allImages[1] forState:UIControlStateNormal];
[cell.photoButtonC3 setImage:allImages[2] forState:UIControlStateNormal];
[cell.photoButtonC4 setImage:allImages[3] forState:UIControlStateNormal];
cell.photoButtonC1.hidden = NO;
cell.photoButtonC2.hidden = NO;
cell.photoButtonC3.hidden = NO;
cell.photoButtonC4.hidden = NO;
}
}
// (following code omitted)

Related

selection of cell is repeating while loading in tableview in objective c

Tick mark button selection of uitableview cell is repeating when scroll the tableview. and the tableview is already loaded with an array of item. but i need to do multi selection of cells in tableview
-(void)checkButtonClicked:(UIButton *)sender{
CGPoint touchPoint = [sender convertPoint:CGPointZero toView:_tableView];
NSIndexPath *indexPath = [_tableView indexPathForRowAtPoint:touchPoint];
sender.tag = indexPath.row;
selectedIndexForPassing = sender.tag;
if([_selectionArray count ] == 0){
_uploadSheetBtn.enabled = NO;
if (sender.selected){
sender.selected = false;
}
else{
TCSTimeSheet * sc = self.timesheetList[selectedIndexForPassing];
_canEdit = sc.canEdit;
if([_canEdit isEqual: #"1"]){
sender.selected = true;
_uploadSheetBtn.enabled = YES;
TCSTimeSheet * sc = self.timesheetList[selectedIndexForPassing];
NSDictionary * detailsDictionary= [NSDictionary dictionaryWithObjectsAndKeys:sc.timesheetDetailId,#"timesheetDetailId",sc.scheduleEmployeeDetailId, #"scheduleDetailId",sc.lastUpdatedTime,#"lastUpdatedTime",sc.timesheetStatus,#"timesheetStatus",sc.shiftDate , #"shiftDate",sc.employeeId ,#"employeeId",nil];
[_storingArray addObject:detailsDictionary];
[_selectionArray addObject:sc.clientId];
}
}
}
here is my cell for at indexpath code
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * reuseIdentifier = #"timeSheetCell" ;
TimeSheetCell * dataCell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
TCSTimeSheet * currentTimeSheet = self.timesheetList[indexPath.row] ;
_statusIndicator = currentTimeSheet.timesheetStatus;
_timesheetDetailId = currentTimeSheet.timesheetDetailId;
_timesheetDocId = currentTimeSheet.timesheetDocId;
_documentType = currentTimeSheet.documentType;
if(![currentTimeSheet.notes isEqual:#""]){
_notes = currentTimeSheet.notes;
}
if (dataCell == nil)
{
dataCell = [[TimeSheetCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:reuseIdentifier];
}
dataCell.clientNameLbl.text = currentTimeSheet.clientName;
dataCell.dayLbl.text = currentTimeSheet.shiftDay;
dataCell.dateLbl.text = currentTimeSheet.shiftDate;
dataCell.shiftTime.text = currentTimeSheet.shiftTime;
dataCell.shiftType.text = currentTimeSheet.shiftType;
[dataCell.checkBtn addTarget:self action:#selector(checkButtonClicked:) forControlEvents:UIControlEventTouchUpInside];
if ([_statusIndicator isEqual: #"D"]) {
if([currentTimeSheet.canEdit isEqual:#"1"]) {
[dataCell.remarkBtn setImage:[UIImage imageNamed:#"selectedMessage_btn"] forState:UIControlStateNormal];
dataCell.containerView.backgroundColor = [UIColor colorWithDisplayP3Red:255.0 green:191.0 blue:0 alpha:0.5];
if(![currentTimeSheet.notes isEqual:#""]){
[dataCell.remarkBtn addTarget:self action:#selector(presentMessagePopUp:) forControlEvents:UIControlEventTouchUpInside];
}
}
}
else if ([_statusIndicator isEqual: #"U"]){
if([currentTimeSheet.canDelete isEqual:#"1"]){
[dataCell.remarkBtn setImage:[UIImage imageNamed:#"selectedDelete_btn"] forState:UIControlStateNormal];
[dataCell.remarkBtn addTarget:self action:#selector(deleteDocument:) forControlEvents:UIControlEventTouchUpInside];
}
}
else{
[dataCell.remarkBtn setImage:[UIImage imageNamed:#"unselectedDelete_btn"] forState:UIControlStateNormal];
dataCell.containerView.backgroundColor = [UIColor colorWithDisplayP3Red:255 green:255 blue:255 alpha:1];
[dataCell.checkBtn setImage:[UIImage imageNamed:#"timesheetUnselectedTick"] forState:UIControlStateNormal];
}
if([_timesheetDocId isEqual: #""] && [_timesheetDetailId isEqual:#""]) {
[dataCell.previewBtn setImage:[UIImage imageNamed:#"unselectedView_btn"] forState:UIControlStateNormal];
}
else {
[dataCell.previewBtn setImage:[UIImage imageNamed:#"selectedView_btn"] forState:UIControlStateNormal];
if([_documentType isEqual:#"image"]){
[dataCell.previewBtn addTarget:self action:#selector(buttonClickedToShowImage:) forControlEvents:UIControlEventTouchUpInside];
}
else {
[dataCell.previewBtn addTarget:self action:#selector(buttonClickedToShowDocuments:) forControlEvents:UIControlEventTouchUpInside];
}
}
return dataCell ;
}
**button action of the tick mark**
-(void)checkButtonClicked:(UIButton *)sender{
CGPoint touchPoint = [sender convertPoint:CGPointZero toView:_tableView];
NSIndexPath *indexPath = [_tableView indexPathForRowAtPoint:touchPoint];
sender.tag = indexPath.row;
selectedIndexForPassing = sender.tag;
if([_selectionArray count ] == 0){
_uploadSheetBtn.enabled = NO;
if (sender.selected){
sender.selected = false;
}
else{
TCSTimeSheet * sc = self.timesheetList[selectedIndexForPassing];
_canEdit = sc.canEdit;
if([_canEdit isEqual: #"1"]){
sender.selected = true;
_uploadSheetBtn.enabled = YES;
TCSTimeSheet * sc = self.timesheetList[selectedIndexForPassing];
NSDictionary * detailsDictionary= [NSDictionary dictionaryWithObjectsAndKeys:sc.timesheetDetailId,#"timesheetDetailId",sc.scheduleEmployeeDetailId, #"scheduleDetailId",sc.lastUpdatedTime,#"lastUpdatedTime",sc.timesheetStatus,#"timesheetStatus",sc.shiftDate , #"shiftDate",sc.employeeId ,#"employeeId",nil];
[_storingArray addObject:detailsDictionary];
[_selectionArray addObject:sc.clientId];
}
}
}
else{
TCSTimeSheet * sc = self.timesheetList[selectedIndexForPassing];
if (sender.selected){
NSDictionary * detailsDictionary= [NSDictionary dictionaryWithObjectsAndKeys:sc.timesheetDetailId,#"timesheetDetailId",sc.scheduleEmployeeDetailId, #"scheduleDetailId",sc.lastUpdatedTime,#"lastUpdatedTime",sc.timesheetStatus,#"timesheetStatus",sc.shiftDate,#"shiftDate",sc.employeeId,#"employeeId",nil];
sender.selected = false;
[_storingArray removeObject:detailsDictionary];
//[_selectionArray removeAllObjects];
if([_storingArray count] == 0){
_uploadSheetBtn.enabled = NO;
[_selectionArray removeAllObjects];
}
}
else{
if([_selectionArray firstObject] == sc.clientId){
_uploadSheetBtn.enabled = YES;
sender.selected = true;
NSDictionary * detailsDictionary= [NSDictionary dictionaryWithObjectsAndKeys:sc.timesheetDetailId,#"timesheetDetailId",sc.scheduleEmployeeDetailId, #"scheduleDetailId",sc.lastUpdatedTime,#"lastUpdatedTime",sc.timesheetStatus,#"timesheetStatus",sc.shiftDate , #"shiftDate",sc.employeeId ,#"employeeId",nil];
[_storingArray addObject:detailsDictionary];
}
else{
sender.selected = false;
UIAlertView *alertCantDisply=[[UIAlertView alloc]initWithTitle:#"Can't Select" message:#"Can choose same client only" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alertCantDisply show];
}
}
}
}
The cell will reuse, but the model will not, and the state of the view should be recorded in the model

Reload Section does not handle properly

I have the following implementation where I have title, and two buttons(titles are half and full) on the tablecell. When user selects and close the section and open it again, he only sees the default values of button title which is full rather than his selection.
I could able to see the following method (setHalfButton :indexPath
) is getting called during the reloading, but it does not have any effect.
Code and screenshots are follows.
- (void)selectItemAtIndexPath:(NSIndexPath *)indexPath setQuantity :(double) quantity {
NSMutableArray* array = [selectedRowsInSectionDictionary objectForKey:#(indexPath.section)];
if(array){
[array addObject:indexPath];
} else {
array = [NSMutableArray array];
[array addObject:indexPath];
[selectedRowsInSectionDictionary setObject:array forKey:#(indexPath.section)];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"ComboCell";
ComboTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[ComboTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
if([selectedRowsInSectionDictionary[#(indexPath.section)] containsObject: indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
if(
comboItemsArray[indexPath.section].allComboItems[indexPath.row].pQuantity == 0.5)
{
// it comes here after reloading
[self setHalfButton:indexPath];
}
else
{
[self setFullButton:indexPath];
}
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
cell.halfBtnOutlet.hidden = YES;
cell.fullBtnOutlet.hidden = YES;
}
cell.comboTitle.text =comboItemsArray[indexPath.section].allComboItems[indexPath.row].pName;
[cell.halfBtnOutlet addTarget:self action:#selector(halfBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.fullBtnOutlet addTarget:self action:#selector(fullBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
-(void) setHalfButton : (NSIndexPath*)indexPath
{
ComboTableViewCell* cell = [comboTableView cellForRowAtIndexPath:indexPath];
[cell.halfBtnOutlet setTitleColor:[UIColor colorWithRed:0 green:102.0f/255.0f blue:0 alpha:1] forState:UIControlStateNormal];
[cell.fullBtnOutlet setTitleColor:[UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1] forState:UIControlStateNormal];
[cell.halfBtnOutlet.titleLabel setFont:[UIFont boldSystemFontOfSize:15.f]];
[cell.fullBtnOutlet.titleLabel setFont:[UIFont systemFontOfSize:15.f]];
}
-(void) setFullButton : (NSIndexPath*)indexPath
{
ComboTableViewCell* cell = [comboTableView cellForRowAtIndexPath:indexPath];
[cell.fullBtnOutlet setTitleColor:[UIColor colorWithRed:0 green:102.0f/255.0f blue:0 alpha:1] forState:UIControlStateNormal];
[cell.halfBtnOutlet setTitleColor:[UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1] forState:UIControlStateNormal];
[cell.fullBtnOutlet.titleLabel setFont:[UIFont boldSystemFontOfSize:15.f]];
[cell.halfBtnOutlet.titleLabel setFont:[UIFont systemFontOfSize:15.f]];
}
Your setHalfButton and setFullButton functions are being called from the cellForRowAtIndexPath: datasource method, but they are calling the cellForRowAtIndexPath: tableview method. Since you have not yet returned the cell from the former method, the latter method will return nil to cell, resulting in no visible update.
The setHalfButton and setFullButton methods should be in your ComboTableViewCell class:
-(void) setHalfButton
{
[self.halfBtnOutlet setTitleColor:[UIColor colorWithRed:0 green:102.0f/255.0f blue:0 alpha:1] forState:UIControlStateNormal];
[self.fullBtnOutlet setTitleColor:[UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1] forState:UIControlStateNormal];
[self.halfBtnOutlet.titleLabel setFont:[UIFont boldSystemFontOfSize:15.f]];
[self.fullBtnOutlet.titleLabel setFont:[UIFont systemFontOfSize:15.f]];
}
-(void) setFullButton
{
[self.fullBtnOutlet setTitleColor:[UIColor colorWithRed:0 green:102.0f/255.0f blue:0 alpha:1] forState:UIControlStateNormal];
[self.halfBtnOutlet setTitleColor:[UIColor colorWithRed:0.5f green:0.5f blue:0.5f alpha:1] forState:UIControlStateNormal];
[self.fullBtnOutlet.titleLabel setFont:[UIFont boldSystemFontOfSize:15.f]];
[self.halfBtnOutlet.titleLabel setFont:[UIFont systemFontOfSize:15.f]];
}
Also, you are adding the button action handlers each time you dequeue a cell, but you should only do this when you allocate a new cell. From a design point-of-view these button tap handlers should also be in your ComboTableViewCell class with a delegation pattern to notify the view controller that the half/full was changed.
At the very least it should look something like this:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"ComboCell";
ComboTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[ComboTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
[cell.halfBtnOutlet addTarget:self action:#selector(halfBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell.fullBtnOutlet addTarget:self action:#selector(fullBtnClicked:) forControlEvents:UIControlEventTouchUpInside];
}
if([selectedRowsInSectionDictionary[#(indexPath.section)] containsObject: indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
if(
comboItemsArray[indexPath.section].allComboItems[indexPath.row].pQuantity == 0.5)
{
// it comes here after reloading
[cell setHalfButton];
}
else
{
[cell setFullButton];
}
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
cell.halfBtnOutlet.hidden = YES;
cell.fullBtnOutlet.hidden = YES;
}
cell.comboTitle.text =comboItemsArray[indexPath.section].allComboItems[indexPath.row].pName;
return cell;
}

Make UITableView Smoother

I have a UITableView that displays both images and text. Its a social app so I have to retrieve all data from the database, I'm using Parse. Heres the code. I know its long but if you could just skim through it that would be great. I have three different custom cells(nibs) that will be loaded depending on the content. A cell - just a string post, groupPost - also a string post, and a imageCell - for image posts. Im confused on how to make a smoother scroll such as facebooks, or instagrams. How I should load the images, and retrieve the data? Ive looked through posts and seen the recommendation of caching it but not exactly sure how to do that. Thanks for the help
postCell *cell = (postCell *)[tableView dequeueReusableCellWithIdentifier:#"postCell"];
groupPostCell *groupPost = (groupPostCell *) [self.tableView dequeueReusableCellWithIdentifier:#"groupPostCell"];
pictureCell *imageCell = (pictureCell *) [self.tableView dequeueReusableCellWithIdentifier:#"imageCell"];
PFObject *object = [self.friendPosts objectAtIndex:indexPath.row];
if ([object objectForKey:#"Image"] != nil) {
if (imageCell == nil) {
imageCell = [[pictureCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"imageCell"];
}
PFFile *file = [object objectForKey:#"Image"];
NSData *data = [file getData];
imageCell.imagePost.image = [UIImage imageWithData:data];
imageCell.caption.text = [object objectForKey:#"stringPost"];
PFFile *profileFile = [object objectForKey:#"profileImage"];
NSData *profileData = [profileFile getData];
imageCell.profileImage.image = [UIImage imageWithData:profileData];
[imageCell.name setTitle:[object objectForKey:#"User_Name"] forState:UIControlStateNormal];
[imageCell.eventButton setTitle:[object objectForKey:#"Event"] forState:UIControlStateNormal];
imageCell.name.hidden = false;
imageCell.eventButton.hidden = false;
imageCell.name.tag = indexPath.row;
imageCell.profileImageButton.tag = indexPath.row;
imageCell.eventButton.tag = indexPath.row;
[imageCell.name addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[imageCell.profileImageButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[imageCell.eventButton addTarget:self action:#selector(eventPage:) forControlEvents:UIControlEventTouchUpInside];
NSArray *likesArray = [object objectForKey:#"likes"];
NSString *likeString = [NSString stringWithFormat:#"%lu Likes", (unsigned long)likesArray.count];
if ([likesArray containsObject:[PFUser currentUser].objectId]) {
imageCell.rateButton.hidden = true;
}
else{
imageCell.rateButton.hidden = false;
}
NSArray *commentArray = [object objectForKey:#"Comments"];
NSString *commentString = [NSString stringWithFormat:#"%lu Comments", (unsigned long)commentArray.count];
[imageCell.likesButton setTitle:likeString forState:UIControlStateNormal];
[imageCell.commentsButton setTitle:commentString forState:UIControlStateNormal];
imageCell.rateButton.tag = indexPath.row;
imageCell.likesButton.tag = indexPath.row;
imageCell.commentsButton.tag = indexPath.row;
imageCell.flagButton.tag = indexPath.row;
[imageCell.rateButton addTarget:self action:#selector(like:) forControlEvents:UIControlEventTouchUpInside];
[imageCell.likesButton addTarget:self action:#selector(likesPage:) forControlEvents:UIControlEventTouchUpInside];
[imageCell.commentsButton addTarget:self action:#selector(imageComment:) forControlEvents:UIControlEventTouchUpInside];
[imageCell.flagButton addTarget:self action:#selector(flagPost:) forControlEvents:UIControlEventTouchUpInside];
[imageCell.timeButton setTitle:[self getDaysBetween:object.createdAt] forState:UIControlStateNormal];
return imageCell;
}
if ([object objectForKey:#"Group"] == nil) {
if (cell == nil) {
cell = [[postCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"postCell"];
}
cell.personStringPost.text = [object objectForKey:#"stringPost"];
if ([object objectForKey:#"Event"] == nil) {
[cell.noEventNameButton setTitle:[object objectForKey:#"User_Name"] forState:UIControlStateNormal];
cell.noEventNameButton.tag = indexPath.row;
[cell.noEventNameButton addTarget:self action:#selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];
cell.nameLabel.hidden = true;
cell.eventLabel.hidden = true;
cell.noEventNameButton.hidden = false;
}
else{
[cell.nameLabel setTitle:[object objectForKey:#"User_Name"] forState:UIControlStateNormal];
cell.nameLabel.tag = indexPath.row;
[cell.nameLabel addTarget:self action:#selector(buttonPressed:) forControlEvents: UIControlEventTouchUpInside];
cell.noEventNameButton.hidden = true;
cell.nameLabel.hidden = false;
cell.eventLabel.hidden = false;
[cell.eventLabel setTitle:[object objectForKey:#"Event"] forState:UIControlStateNormal];
[cell.eventLabel addTarget:self action:#selector(eventPage:) forControlEvents:UIControlEventTouchUpInside];
}
[cell.timeLabel setTitle:[self getDaysBetween:object.createdAt] forState:UIControlStateNormal];
PFFile *imageFile = [object objectForKey:#"profileImage"];
NSData *data = [imageFile getData];
cell.profileImage.image = [UIImage imageWithData:data];
NSArray *likesArray = [object objectForKey:#"likes"];
NSString *likeString = [NSString stringWithFormat:#"%lu Likes", (unsigned long)likesArray.count];
if ([likesArray containsObject:[PFUser currentUser].objectId]) {
cell.likeButton.hidden = true;
}
else{
cell.likeButton.hidden = false;
}
NSArray *commentArray = [object objectForKey:#"Comments"];
NSString *commentString = [NSString stringWithFormat:#"%lu Comments", (unsigned long)commentArray.count];
[cell.likePage setTitle:likeString forState:UIControlStateNormal];
[cell.commentButton setTitle:commentString forState:UIControlStateNormal];
cell.eventLabel.tag = indexPath.row;
cell.profileImageButton.tag = indexPath.row;
cell.likeButton.tag = indexPath.row;
cell.commentButton.tag = indexPath.row;
cell.likePage.tag = indexPath.row;
cell.flagButton.tag = indexPath.row;
[cell.flagButton addTarget:self action:#selector(flagPost:) forControlEvents:UIControlEventTouchUpInside];
[cell.profileImageButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[cell.likePage addTarget:self action:#selector(likesPage:) forControlEvents:UIControlEventTouchUpInside];
[cell.likeButton addTarget:self action:#selector(like:) forControlEvents:UIControlEventTouchUpInside];
[cell.commentButton addTarget:self action:#selector(commentsPage:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
if ([object objectForKey:#"Group"] != nil) {
if (groupPost == nil) {
groupPost = [[groupPostCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"groupPostCell"];
}
[groupPost.groupNameButton setTitle:[object objectForKey:#"Group"] forState:UIControlStateNormal];
groupPost.groupNameButton.tag = indexPath.row;
[groupPost.groupNameButton addTarget:self action:#selector(groupPage:) forControlEvents:UIControlEventTouchUpInside];
[groupPost.groupNameButton setTitleColor:[self checkType:[object objectForKey:#"Type"]] forState:UIControlStateNormal];
NSArray *likesArray = [object objectForKey:#"likes"];
NSString *likeString = [NSString stringWithFormat:#"%lu Likes", (unsigned long)likesArray.count];
if ([likesArray containsObject:[PFUser currentUser].objectId]) {
groupPost.likeButton.hidden = true;
}
else{
groupPost.likeButton.hidden = false;
}
NSArray *commentArray = [object objectForKey:#"Comments"];
NSString *commentString = [NSString stringWithFormat:#"%lu Comments", (unsigned long)commentArray.count];
[groupPost.likePage setTitle:likeString forState:UIControlStateNormal];
[groupPost.commentsButton setTitle:commentString forState:UIControlStateNormal];
groupPost.likePage.tag = indexPath.row;
groupPost.likeButton.tag = indexPath.row;
groupPost.commentsButton.tag = indexPath.row;
[groupPost.likeButton addTarget:self action:#selector(like:) forControlEvents:UIControlEventTouchUpInside];
[groupPost.likePage addTarget:self action:#selector(likesPage:) forControlEvents:UIControlEventTouchUpInside];
[groupPost.commentsButton addTarget:self action:#selector(commentsPage:) forControlEvents:UIControlEventTouchUpInside];
if ([object objectForKey:#"Event"] == nil) {
groupPost.eventButton.hidden = true;
}
else{
groupPost.eventButton.hidden = false;
[groupPost.eventButton setTitle:[object objectForKey:#"Event"] forState:UIControlStateNormal];
groupPost.eventButton.tag = indexPath.row;
[groupPost.eventButton addTarget:self action:#selector(eventPage:) forControlEvents:UIControlEventTouchUpInside];
}
groupPost.flagButton.tag = indexPath.row;
[groupPost.flagButton addTarget:self action:#selector(flagPost:) forControlEvents:UIControlEventTouchUpInside];
[groupPost.timeButton setTitle:[self getDaysBetween:object.createdAt] forState:UIControlStateNormal];
groupPost.postLabel.text = [object objectForKey:#"stringPost"];
return groupPost;
}
Whenever you're working with data on a server, try to avoid, at all costs, loading that data synchronously. The line that says
NSData *data = [imageFile getData];[imageFile getData];
will make it so that nothing else can execute on the main thread until the data is done downloading. Here's how you should do it:
[imageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
if (!error) {
cell.profileImage.image = [UIImage imageWithData:imageData];
}
}];
That will make it so that all other code executes on the main thread and then when the data finishes downloading THEN it will load in the image. I would suggest putting a placeholder or loading view in the "cell.profileImage" and then when the image loads from Parse, it'll overwrite that placeholder.

Multiple Tableviews in UIScrollview

I'm adding multiple tableviews into the scrollview based on the array count...and the code is here
int currentX = 3;
for(int i=0;i<[restNameArray count]; i++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(currentX, 0, 150, 35)];
button.tag = i+1;
//[button setUserInteractionEnabled:NO];
[button addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[button setBackgroundImage:[UIImage imageNamed:#"ohris_applytics_ipad_middle_oc.png"] forState:UIControlStateNormal];
button.titleLabel.font = [UIFont fontWithName:#"HelveticaNeue-CondensedBold" size:15.0f];
[button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[button setTitle:[NSString stringWithFormat:#"%#", [restNameArray objectAtIndex:i]] forState:UIControlStateNormal];
restaurantTable = [[UITableView alloc] initWithFrame:CGRectMake(currentX, 35, 150, 310) style:UITableViewStylePlain];
[restaurantTable setTag:i+1];
[restaurantTable setBackgroundColor:[UIColor whiteColor]];
restaurantTable.delegate = self;
restaurantTable.dataSource = self;
[scrollView addSubview:button];
[scrollView addSubview:restaurantTable];
NSLog(#"tag %d",restaurantTable.tag);
currentX = restaurantTable.frame.size.width+currentX+3;
[tagArray addObject:[NSString stringWithFormat:#"%d", restaurantTable.tag]];
}
NSLog(#"aaaa %#", tagArray);
[scrollView setContentSize:CGSizeMake(currentX, 349)];
It is showing fine in the simulator. And i need to populate the tableviews with array.
And the code at cellforrowatindexpath is
if(tableView == restaurantTable){
for (int i =0;i<[tagArray count];i++)
{
table1Array = [[[restSalesArray objectAtIndex:i]componentsSeparatedByString:#","]mutableCopy];
NSLog(#"Sales array :%d %#", i, table1Array);
cell.textLabel.text = [formatter stringFromNumber:[NSNumber numberWithInteger:[[table1Array objectAtIndex:indexPath.row]intValue]]];
cell.textLabel.textAlignment = NSTextAlignmentCenter;
}
}
But the problems is, it is populating only in the last tableview.. remaining are empty... plz help me out guys....
It is ok what you are trying to do. But you are overriding the restaurantTable variable in your for loop. So the variable is the last table view. You need to add them to an array or seperate variables to be able to compare with if in you cellForRowAtIndexPath method.
_allTableViews is defined in your header file
you for loop
_allTableViews = [NSMutableArray array];
for (.....) {
.
.
.
UITableView *tableView = [[UITableView alloc] initWith....];
.
.
.
[_allTableViews addObject tableView];
}
cellForRowAtIndePath
NSInteger tableIndex = [_allTableViews indexOfObject:tableView];
// Now you have the index of table view
switch (tableIndex) {
case 0:
// first table
break;
case 1:
// second table
break;
default:
break;
}
You need to compare each tableView either by its outlet name or tag.
As :
if(tableView == _restaurantTableOutlet){
...
}
else if(tableView == _barTableOutlet){
...
}
else if(tableView == _loungeTableOutlet){
...
}
You are storing each table view into restaurantTable, so the references to previous table views are lost. Either store them all in an array, or don't store any of them
Why are you checking if(tableView == restaurantTable)? You should check the tables by tag and work with each one separately
You have to first assign tag for each tableView. Then you can get selected row of particular table by following code:-
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int tableTag = tableView.tag;
if(tableTag==0)
{
//do something here
}
else if(tableTag==1)
{
//do something here
}
}

Implementing toggle feature in a UIButton

I want to know how to add the toggling feature to a UIButton, something like the user taps a unselected button the button becomes selected and stays selected till the user taps it again there by making unselected like it was before.
I was thinking of making an IBAction which changes it from unselected to selected, how can I do that?
Heres what I tried:
-(IBAction)toggle {
//Toggle on implementation.
button.selected = YES;
button.highlighted = NO;
button.enabled = YES;
//Toggle off implementation.
if (button.highlighted == YES) {
button.selected = NO;
button.highlighted = YES;
button.enabled = NO;
}
}
Problem...
-(IBAction)toggleFav {
if (favButton == nil) {
UIImage *unselectedImage = [UIImage imageNamed:#"favUntapped.png"];
UIImage *selectedImage = [UIImage imageNamed:#"favTapped.png"];
[favButton setImage:unselectedImage forState:UIControlStateNormal];
[favButton setImage:selectedImage forState:UIControlStateSelected];
[favButton setFrame:CGRectMake(0, 0, 40, 40)];
}
if([favButton isSelected]){
//Add to menu.
[favButton setSelected:NO];
} else {
//Remove from menu.
[favButton setSelected:YES];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UIImage *unselectedImage = [UIImage imageNamed:#"unselected.png"];
UIImage *selectedImage = [UIImage imageNamed:#"selected.png"];
UIButton *b = [UIButton buttonWithType:UIButtonTypeCustom];
[b setBackgroundImage:unselectedImage forState:UIControlStateNormal];
[b setBackgroundImage:selectedImage forState:UIControlStateSelected];
[b addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[b setFrame:CGRectMake(0, 0, 40, 40)];
[cell.contentView addSubview:b];
}
return cell;
}
-(void) buttonPressed:(UIButton *)sender
{
if([sender isSelected]){
//...
[sender setSelected:NO];
} else {
//...
[sender setSelected:YES];
}
}
Your toggleFav code doesn't make much sense.
if (favButton == nil) { checks, if favButton is present. But if you are wiring it up with IB, it should always been there at that point. And if it wasn't how could the button call this method? So do it like this:
-(void)viewDidLoad
{
//....
UIImage *unselectedImage = [UIImage imageNamed:#"favUntapped.png"];
UIImage *selectedImage = [UIImage imageNamed:#"favTapped.png"];
[favButton setImage:unselectedImage forState:UIControlStateNormal];
[favButton setImage:selectedImage forState:UIControlStateSelected];
[favButton setFrame:CGRectMake(0, 0, 40, 40)];
//....
}
-(IBAction)toggleFav:(UIButton *)sender {
if([sender isSelected]){
//...
[sender setSelected:NO];
} else {
//...
[sender setSelected:YES];
}
}
Here you'll find an example project, with a DetaiView, that holds a Button with the 2 states.
Note: I am saving the information of what button was selected in the NSUserDefaults. You should not do that. Instead you'll want to save it in the model. But as I dont have informations on your model, I am just using NSUserDefaults.
-(void)hitButton:(UIButton*)button
{
buttonOnFlag = !buttonOnFlag;
if( buttonFlag )
[self performSelector:#selector(setHighlight:) withObject:button afterDelay:0];
}
- (void)setHighlight:(UIButton*)button
{
button.highlighted = true;
}
Use button.highlighted property
You should code like this:
-(IBAction)toggle:(id)sender {
//Toggle on implementation.
if (sender.highlighted == NO)
{
sender.selected = YES;
sender.highlighted = NO;
sender.enabled = YES;
}
//Toggle off implementation.
else{
sender.selected = NO;
sender.highlighted = YES;
sender.enabled = NO;
}
}