I have a rate button. Upon clicking on that button a view containing 5 stars opens. But when I click on rate button of particular cell, particular view opens but some views of other cells also get opens. I want the view containing 5 stars of that particular view only to get opened.
I am attaching the code of that view.
cv = [[ASStarRatingView alloc]initWithFrame:CGRectMake(190, y-5, 140, 30)]; //creat an instance of your custom view
cv.tag = indexPath.row ;
if([delegate.constants.snsrate[indexPath.row] isEqualToString: #"0"])
{
cv.hidden=TRUE;
}
else
{
cv.hidden=FALSE;
}
delegate.constants.selected=1;
[cell addSubview:cv];
And my code to close and open the view.
-(void)Rate_Comment:(UIButton *)sender
{
UIButton *b = (UIButton *)sender;
NSInteger row = b.tag ;
for(int i=0;i<[delegate.constants.snsrate count];i++)
delegate.constants.snsrate[i]= #"0";
delegate.constants.buttontag = row;
UITableViewCell *buttonCell = (UITableViewCell *)[b superview];
UITableView* table = (UITableView *)[buttonCell superview];
NSIndexPath* pathOfTheCell = [table indexPathForCell:buttonCell];
delegate.constants.snsIndexPath = pathOfTheCell;
if(![delegate.constants.user_id isEqualToString:[delegate.constants.snsCreatedBy objectAtIndex:row]])
{
if([[delegate.constants.snstotalrating_count objectAtIndex:row] isEqualToString:#"0"])
{
if(cv.hidden)
{
delegate.constants.snsrate[row]= #"1";
cv.hidden=FALSE;
}
else{
delegate.constants.snsrate[row]= #"0";
cv.hidden=TRUE;
}
[streamTable reloadRowsAtIndexPaths:#[pathOfTheCell] withRowAnimation:UITableViewRowAnimationNone];
}else
{
if(cv.hidden==FALSE)
cv.hidden=TRUE;
}
}
}
I am new to IOS. Please if anyone can help it will be much appreciated.
Thank you in advance.
I assume every cell has a "rate" button and a target method, like this:
// --------------------------------------------------------------------
// Sorry, I'm typing from memory, these code might not be 100% correct
// --------------------------------------------------------------------
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = #"cell";
MyCustomCell *cell = [tableView dequeueReusableCellForIdentifier:cellID];
if(cell == nil)
{
cell = [[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
// --------------------------------------------------------
// Add the method to execute when tapping on a button
// --------------------------------------------------------
[cell.btnRate addTarget:self action:#selector(showRateControl:) forControlEvent:UIControlEventTouchUpInside];
}
// self.selectedRow should init with -1, since we don't want to show stars
// for the first row if self.selectedRow defaults to 0
if(self.selectedRow == indexPath.row)
{
cell.starsView.alpha = 1;
cell.btnRate.alpha = 0;
}
else
{
cell.starsView.alpha = 0;
cell.btnRate.alpha = 1;
}
return cell;
}
-(void)showRateControl:(id)sender
{
UIButton *rateButton = (UIButton *)sender;
// finding the row which the rate button was tapped
CGPoint rootPoint = [rateButton convertPoint:CGPointZero inView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:rootPoint];
// ------------------------------------------------------------
// here we record the row which the rate button was tapped
// in a property we declared in the .h file (see below)
// ------------------------------------------------------------
self.selectedRow = indexPath.row;
// refresh just the selected row (you could alternatively use self.tableView reloadData)
[self.tableView reloadRowsAtIndexPath:#[indexPath]];
}
In your header file, you can declare your selectedRow property like this:
...
class MyViewController: UIViewController
{
}
#property (nonatomic, assign) NSInteger selectedRow;
#end
In your implementation file's viewDidLoad, don't forget to initialise self.selectedRow to -1:
-(void)viewDidLoad
{
[super viewDidLoad];
...
self.selectedRow = -1;
}
See if that helps.
Related
This is the type of screen I'm making:
So when the UISwitch state changes it should change the label to ON or OFF. In my cellForRowAtIndexPath I'm calling [cell.mainSwitch addTarget:self action:#selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; and switchChanged is as follow:
-(void) switchChanged:(id)sender {
UISwitch* cellNew = (UISwitch*)sender;
if ([cellNew isOn]) {
cell.funcStatus.text = [funcStatusArr objectAtIndex:0];
} else {
cell.funcStatus.text = [funcStatusArr objectAtIndex:1];
}
}
Now the problem I'm facing is that it is not changing the Label at the specific cell butt all the switches are changing the Label of 4th(last) cell as shown in the figure below.
As you can see that the first label is off but it is changing the label of last row. Any ideas why it is happening or how to tell the functions that this index.row is sending the request.
So u must add tag property to all UISwitch. Fasters way its in - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath call
// code
// its good work if u have only 1 section
mySwitch.tag = indexPath.row.
//code
Than fix u're code
-(void) switchChanged:(UISwitch*)switch {
SettingsTableViewCell *selectedCell;
NSIndexPath *selectedIndexPath;
if(switch.tag == 0)
// create selectedIndexPath with correctrly row and section
selectedIndexPath = [NSIndexPath indexPathForRow:'YourRow'inSection:'Your section']
// create cell
selectedCell = [self.tableView cellForIndexPath:selectedIndexPath];
} else if(switch.tag == 1) {
// same logic;
}
// and replace text for selected cell
if ([switch isOn]) {
selectedCell.funcStatus.text = [funcStatusArr objectAtIndex:0];
} else {
selectedCell.funcStatus.text = [funcStatusArr objectAtIndex:1];
}
}
it's must work.
You doing wrong thing.First you need to get cell at specific changed event.
follow this code.
-(void) switchChanged:(id)sender {
UISwitch* switchBtn = (UISwitch*)sender;
//self.tableView is UITableView's outlet named tableView
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:buttonPosition];
//First detect Tableview's Cell then do the stuff
//CustomCellTableViewCell replace it with you custom cell class
CustomCellTableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if ([switchBtn isOn]) {
cell.funcStatus.text = [funcStatusArr objectAtIndex:0];
} else {
cell.funcStatus.text = [funcStatusArr objectAtIndex:1];
}
[self.tableView reloadRowsAtIndexPaths:[[NSArray alloc] initWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
}
Cheers.
This is driving me crazy.
I have implemented MGSwipeTableCell which shows three buttons on the left and one button on the right when it is swiped to the right and left respectively.
https://github.com/MortimerGoro/MGSwipeTableCell
But, I am not able to trigger the delegate methods when those buttons are pressed after swiping. Here is an excerpt of my code.
detailviewcontroller.h
#interface DetailViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, MGSwipeTableCellDelegate>
detailviewcontroller.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
DataStruct *showCredit;
static NSString *CellIdentifier = #"Credit_Cell";
MGSwipeTableCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
//cell = [[CreditCustomViewTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Credit_Cell"];
cell = [[MGSwipeTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Credit_Cell"];
}
cell.leftButtons = [self createLeftButtons:3];
cell.leftSwipeSettings.transition = MGSwipeTransition3D;
cell.rightButtons = [self createRightButtons:1];
cell.rightSwipeSettings.transition = MGSwipeTransition3D;
cell.delegate = self;
return cell;
}
-(NSArray*) swipeTableCell:(MGSwipeTableCell*) cell swipeButtonsForDirection:(MGSwipeDirection)direction
swipeSettings:(MGSwipeSettings*) swipeSettings expansionSettings:(MGSwipeExpansionSettings*) expansionSettings
{
NSIndexPath *myPath = [creditTableView indexPathForCell:cell];
NSLog(#"Pressed Credit last = %d", myPath.row);
...
}
My Objective : To get the indexpath.row in which the button is pressed after swiping. Can somebody put me into right direction?
Use tappedButtonAtIndex delegate method to get the indexpath of the that cell in which the button gets clicked.
-(BOOL) swipeTableCell:(MGSwipeTableCell*) celll tappedButtonAtIndex:(NSInteger)index direction:(MGSwipeDirection)direction fromExpansion:(BOOL) fromExpansion{
NSIndexPath *indexPath = [tableVw indexPathForCell:celll];
NSInteger rowOfTheCell = [indexPath row];
NSInteger sectionOfTheCell = [indexPath section];
NSLog(#"rowofthecell %ld", rowOfTheCell);
NSLog(#"sectionOfTheCell %ld", sectionOfTheCell);
return NO; // If you don't want to hide the cell.
}
There is callback method which work without delegate, you can try that
[MGSwipeButton buttonWithTitle:#"More" backgroundColor:[UIColor lightGrayColor] callback:^BOOL(MGSwipeTableCell *sender) {
NSLog(#"Convenience callback for swipe buttons!");
}]
I'm a newbie with iOS programming language. I try to use table with button in each row.
when i click button in the first cell, it work pretty well.
but when i scroll down, the cell that i don't click also appear click.
I want to show the clicked button in only cell(s) that I clicked?
Code:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath{
ClassifyCustomCell * cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if ([[[arrayResult objectAtIndex:indexPath.row] objectForKey:#"COLABO_FLD_SRNO"] isEqualToString:#"I"]) {
cell.editButton.hidden = YES;
cell.folder_name.text = [[arrayResult objectAtIndex:indexPath.row] objectForKey:#"COLABO_FLD_NM"];
}else{
cell.editButton.hidden = NO;
cell.folder_name.text = [[arrayResult objectAtIndex:indexPath.row] objectForKey:#"COLABO_FLD_NM"];
cell.editButton.tag = indexPath.row;
[cell.editButton addTarget:self action:#selector(editButtonAction:) forControlEvents:UIControlEventTouchUpInside];
cell.checkButton.tag = indexPath.row;
[cell.checkButton addTarget:self action:#selector(checkButtonActoin:) forControlEvents:UIControlEventTouchUpInside];
}
return cell;
}
-(void)checkButtonActoin:(UIButton *)sender{
if (sender.selected == YES) {
sender.selected = NO;
}else if(sender.selected == NO){
sender.selected = YES;
}else {
sender.selected = NO;
}
}
UITableView reuse the state of cell's subviews for new cells. To prevent reusing just configure your subviews explisitly in tableView:cellForRowAtIndexPath:. In your case you need to set selected property of your button to YES, if it was selected, and to NO, if it was not selected.
Add NSMutableArray property to your view controller:
#property (strong, nonatomic) NSMutableArray *arrayForSelectedIndexPaths;
Change your tap method:
-(void)checkButtonAction:(UIButton *)sender{
UITableViewCell *cell = (UITableViewCell *) sender.superview.superview...; //find appropriate number of superviews to get your cell
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
if (sender.selected) {
sender.selected = NO;
[self.arrayForSelectedIndexPaths removeObject:indexPath];
}else {
sender.selected = YES;
[self.arrayForSelectedIndexPaths addObject:indexPath];
}
}
Then in tableView:cellForRowAtIndexPath: add this line:
cell.checkButton.selected = [self.arrayForSelectedIndexPaths containsObject:indexPath];
I used the amended DateCell code from the following link DateCell without storyboard.
I want to replace UIDatePicker with UIPickerView. Below is the code that I have amended/commented to make it work for UIPickerView.
On each cell tap, I'm able to show UIPickerView but it only loads once and for the rest of the cells UIPickerView with same row titles appears and it crashes when I select a row from UIPickerView. I'm stuck into this for last couple of days.
Any help would be highly appreciated.
MoreTableViewController.h
#import <UIKit/UIKit.h>
#interface MoreTableViewController : UITableViewController<UIPickerViewDataSource, UIPickerViewDelegate>
#property(nonatomic,retain)NSArray *ASOR;
#property(nonatomic,retain)NSArray *ASQT;
#property(nonatomic,retain)NSArray *respectiveOptions;
#end
MoreTableViewController.m
#import "MoreTableViewController.h"
#import "AppDelegate.h"
#define kPickerAnimationDuration 0.40 // duration for the animation to slide the date picker into view
#define kDatePickerTag 99 // view tag identifiying the date picker view
//#define kTitleKey #"title" // key for obtaining the data source item's title
//#define kDateKey #"date" // key for obtaining the data source item's date value
// keep track of which rows have date cells
#define kDateStartRow 1
#define kDateEndRow 2
static NSString *kDateCellID = #"dateCell"; // the cells with the start or end date
static NSString *kDatePickerID = #"datePicker"; // the cell containing the date picker
static NSString *kOtherCell = #"otherCell"; // the remaining cells at the end
#pragma mark -
#interface MoreTableViewController ()
#property (nonatomic, strong) NSArray *dataArray;
//#property (nonatomic, strong) NSDateFormatter *dateFormatter;
// keep track which indexPath points to the cell with UIDatePicker
#property (nonatomic, strong) NSIndexPath *datePickerIndexPath;
#property (assign) NSInteger pickerCellRowHeight;
#property (nonatomic, strong) UIPickerView *pickerView;
#end
#implementation MoreTableViewController
#synthesize ASOR, ASQT, respectiveOptions;
- (UITableViewCell *) createCellWithIdetifier:(NSString *)cellId {
NSArray *reusableUiComponents = [[NSBundle mainBundle] loadNibNamed:#"ReusableUIComponents" owner:self options:nil];
if ([kDateCellID isEqualToString:cellId]) {
return reusableUiComponents[0];
}
if ([kDatePickerID isEqualToString:cellId]) {
return reusableUiComponents[1];
}
// if ([kOtherCell isEqualToString:cellId]) {
// return reusableUiComponents[2];
// }
return nil;
}
- (AppDelegate *)appDelegate {
return (AppDelegate *)[[UIApplication sharedApplication] delegate];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)setupDataSource {
// setup our data source
// NSMutableDictionary *itemOne = [#{ kTitleKey : #"Tap a cell to change its date:" } mutableCopy];
// NSMutableDictionary *itemTwo = [#{ kTitleKey : #"Start Date",
// kDateKey : [NSDate date] } mutableCopy];
// NSMutableDictionary *itemThree = [#{ kTitleKey : #"End Date",
// kDateKey : [NSDate date] } mutableCopy];
// NSMutableDictionary *itemFour = [#{ kTitleKey : #"(other item1)" } mutableCopy];
// NSMutableDictionary *itemFive = [#{ kTitleKey : #"(other item2)" } mutableCopy];
self.dataArray = [[self appDelegate]advanceSearchQuestionsText];
//self.dateFormatter = [[NSDateFormatter alloc] init];
//[self.dateFormatter setDateStyle:NSDateFormatterShortStyle]; // show short-style date format
//[self.dateFormatter setTimeStyle:NSDateFormatterNoStyle];
// obtain the picker view cell's height, works because the cell was pre-defined in our storyboard
UITableViewCell *pickerViewCellToCheck = [self createCellWithIdetifier:kDatePickerID];
self.pickerCellRowHeight = pickerViewCellToCheck.frame.size.height;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupDataSource];
//self.title = #"DateCell";
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
ASQT = [[NSArray alloc]init];
ASOR = [[NSArray alloc]init];
ASQT = [[self appDelegate]advanceSearchQuestionsText];
ASOR = [[self appDelegate]advanceSearchOptionsArray];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Utilities
/*! Returns the major version of iOS, (i.e. for iOS 6.1.3 it returns 6)
*/
NSUInteger UNUSED_DeviceSystemMajorVersion() // TODO - move this to Utils
{
static NSUInteger _deviceSystemMajorVersion = -1;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_deviceSystemMajorVersion = [[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:#"."] objectAtIndex:0] intValue];
});
return _deviceSystemMajorVersion;
}
/*! Determines if the given indexPath has a cell below it with a UIDatePicker.
#param indexPath The indexPath to check if its cell has a UIDatePicker below it.
*/
- (BOOL)hasPickerForIndexPath:(NSIndexPath *)indexPath
{
BOOL hasDatePicker = NO;
NSInteger targetedRow = indexPath.row;
targetedRow++;
UITableViewCell *checkDatePickerCell =
[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:targetedRow inSection:0]];
UIPickerView *checkDatePicker = (UIPickerView *)[checkDatePickerCell viewWithTag:kDatePickerTag];
hasDatePicker = (checkDatePicker != nil);
return hasDatePicker;
}
/*! Updates the UIDatePicker's value to match with the date of the cell above it.
*/
- (void)updateDatePicker
{
if (self.datePickerIndexPath != nil)
{
UITableViewCell *associatedDatePickerCell = [self.tableView cellForRowAtIndexPath:self.datePickerIndexPath];
UIPickerView *targetedDatePicker = (UIPickerView *)[associatedDatePickerCell viewWithTag:kDatePickerTag];
if (targetedDatePicker != nil)
{
// we found a UIDatePicker in this cell, so update it's date value
//
// NSDictionary *itemData = self.dataArray[self.datePickerIndexPath.row - 1];
// [targetedDatePicker setDate:[itemData valueForKey:kDateKey] animated:NO];
// set the call action for the date picker to dateAction
// [targetedDatePicker addTarget:self action:#selector(dateAction:) forControlEvents:UIControlEventValueChanged];
}
}
}
/*! Determines if the UITableViewController has a UIDatePicker in any of its cells.
*/
- (BOOL)hasInlineDatePicker
{
return (self.datePickerIndexPath != nil);
}
/*! Determines if the given indexPath points to a cell that contains the UIDatePicker.
#param indexPath The indexPath to check if it represents a cell with the UIDatePicker.
*/
- (BOOL)indexPathHasPicker:(NSIndexPath *)indexPath
{
return ([self hasInlineDatePicker] && self.datePickerIndexPath.row == indexPath.row);
}
/*! Determines if the given indexPath points to a cell that contains the start/end dates.
#param indexPath The indexPath to check if it represents start/end date cell.
*/
- (BOOL)indexPathHasDate:(NSIndexPath *)indexPath
{
BOOL hasDate = NO;
if ((indexPath.row == kDateStartRow) ||
(indexPath.row == kDateEndRow || ([self hasInlineDatePicker] && (indexPath.row == kDateEndRow + 1))))
{
hasDate = YES;
}
return hasDate;
}
#pragma mark - Table view data source
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat height = ([self indexPathHasPicker:indexPath] ? self.pickerCellRowHeight : self.tableView.rowHeight);
return height;
}
//- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
//{
// return 1;
//}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self hasInlineDatePicker])
{
// we have a date picker, so allow for it in the number of rows in this section
NSInteger numRows = self.dataArray.count;
return ++numRows;
}
return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = nil;
NSString *cellID = kDateCellID;
if ([self indexPathHasPicker:indexPath])
{
// the indexPath is the one containing the inline date picker
cellID = kDatePickerID; // the current/opened date picker cell
}
else if ([self indexPathHasDate:indexPath])
{
// the indexPath is one that contains the date information
cellID = kDateCellID; // the start/end date cells
}
cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (!cell) {
cell = [self createCellWithIdetifier:cellID];
}
if (indexPath.row == 0)
{
// we decide here that first cell in the table is not selectable (it's just an indicator)
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
// if we have a date picker open whose cell is above the cell we want to update,
// then we have one more cell than the model allows
//
NSInteger modelRow = indexPath.row;
if (self.datePickerIndexPath != nil && self.datePickerIndexPath.row < indexPath.row)
{
modelRow--;
}
NSDictionary *itemData = self.dataArray[modelRow];
// proceed to configure our cell
if ([cellID isEqualToString:kDateCellID])
{
// we have either start or end date cells, populate their date field
//
cell.textLabel.text = [self.dataArray objectAtIndex:indexPath.row];
//cell.detailTextLabel.text = [self.dateFormatter stringFromDate:[itemData valueForKey:kDateKey]];
}
// else if ([cellID isEqualToString:kOtherCell])
// {
// // this cell is a non-date cell, just assign it's text label
// //
// //cell.textLabel.text = [itemData valueForKey:kTitleKey];
// cell.textLabel.text = [self.dataArray objectAtIndex:indexPath.row];
// }
return cell;
}
/*! Adds or removes a UIDatePicker cell below the given indexPath.
#param indexPath The indexPath to reveal the UIDatePicker.
*/
- (void)toggleDatePickerForSelectedIndexPath:(NSIndexPath *)indexPath
{
[self.tableView beginUpdates];
NSArray *indexPaths = #[[NSIndexPath indexPathForRow:indexPath.row + 1 inSection:0]];
// check if 'indexPath' has an attached date picker below it
if ([self hasPickerForIndexPath:indexPath])
{
// found a picker below it, so remove it
[self.tableView deleteRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
else
{
// didn't find a picker below it, so we should insert it
[self.tableView insertRowsAtIndexPaths:indexPaths
withRowAnimation:UITableViewRowAnimationFade];
}
[self.tableView endUpdates];
}
/*! Reveals the date picker inline for the given indexPath, called by "didSelectRowAtIndexPath".
#param indexPath The indexPath to reveal the UIDatePicker.
*/
- (void)displayInlineDatePickerForRowAtIndexPath:(NSIndexPath *)indexPath
{
// display the date picker inline with the table content
[self.tableView beginUpdates];
BOOL before = NO; // indicates if the date picker is below "indexPath", help us determine which row to reveal
if ([self hasInlineDatePicker])
{
before = self.datePickerIndexPath.row < indexPath.row;
}
BOOL sameCellClicked = (self.datePickerIndexPath.row - 1 == indexPath.row);
// remove any date picker cell if it exists
if ([self hasInlineDatePicker])
{
[self.tableView deleteRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:self.datePickerIndexPath.row inSection:0]]
withRowAnimation:UITableViewRowAnimationFade];
self.datePickerIndexPath = nil;
}
if (!sameCellClicked)
{
// hide the old date picker and display the new one
NSInteger rowToReveal = (before ? indexPath.row - 1 : indexPath.row);
NSIndexPath *indexPathToReveal = [NSIndexPath indexPathForRow:rowToReveal inSection:0];
[self toggleDatePickerForSelectedIndexPath:indexPathToReveal];
self.datePickerIndexPath = [NSIndexPath indexPathForRow:indexPathToReveal.row + 1 inSection:0];
}
// always deselect the row containing the start or end date
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
[self.tableView endUpdates];
// inform our date picker of the current date to match the current cell
[self updateDatePicker];
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
respectiveOptions = [[NSArray alloc]init];
respectiveOptions = [ASOR objectAtIndex:indexPath.row];
if ([kDateCellID isEqualToString:cell.reuseIdentifier])
{
[self displayInlineDatePickerForRowAtIndexPath:indexPath];
}
else
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
- (UIPickerView*)pickerViewForCell:(UITableViewCell*)cell {
UIPickerView * picker = [[UIPickerView alloc] initWithFrame:cell.bounds];
[picker setDelegate:self];
[picker setDataSource:self];
picker.hidden = YES;
[cell addSubview:picker];
return picker;
}
#pragma mark - Actions
/*! User chose to change the date by changing the values inside the UIDatePicker.
#param sender The sender for this action: UIDatePicker.
*/
//- (void)dateAction:(id)sender
//{
// NSIndexPath *targetedCellIndexPath = nil;
//
// if ([self hasInlineDatePicker])
// {
// // inline date picker: update the cell's date "above" the date picker cell
// //
// targetedCellIndexPath = [NSIndexPath indexPathForRow:self.datePickerIndexPath.row - 1 inSection:0];
// }
// else
// {
// // external date picker: update the current "selected" cell's date
// targetedCellIndexPath = [self.tableView indexPathForSelectedRow];
// }
//
// UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:targetedCellIndexPath];
// UIDatePicker *targetedDatePicker = sender;
//
// // update our data model
// NSMutableDictionary *itemData = self.dataArray[targetedCellIndexPath.row];
// [itemData setValue:targetedDatePicker.date forKey:kDateKey];
//
// // update the cell's date string
// cell.detailTextLabel.text = [self.dateFormatter stringFromDate:targetedDatePicker.date];
//}
// Number of components.
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 1;
}
// Total rows in our component.
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return [respectiveOptions count];
}
// Display each row's data.
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
return [respectiveOptions objectAtIndex:row];
}
// Do something with the selected row.
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
}
Here is an example of UITableView making use of UIPickerView embedded in the cells.
I am not changing the color of the picker view, cells, height of cells - I will leave that up to you to do something that suits your needs.
But the main idea here is to show you how you could have picker view in cells and be able to get value accordingly.
#interface YourController ()
#property (strong, nonatomic) NSMutableArray *pickerViewsArray;
#end
#implementation YourController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self)
{
// Custom initialization
}
return self;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.pickerViewsArray = [[NSMutableArray alloc] init];
[self createYourPickerViews];
}
- (void)createYourPickerViews
{
for(int x = 0; x < 10; x++) //number of picker views
{
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:(CGRect){{0, 0}, 150, 10}];
pickerView.delegate = self;
pickerView.dataSource = self;
pickerView.tag = x;
[self.pickerViewsArray addObject:pickerView];
}
}
#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.pickerViewsArray count]; //As mentioned before, this is important.
}
- (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];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
// Configure the cell...
cell.textLabel.text = [NSString stringWithFormat:#"%i", indexPath.row];
[cell.contentView addSubview:(UIPickerView*)[self.pickerViewsArray objectAtIndex:indexPath.row]];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 150.0f; //just some arbitrary value, change it to suit your needs.
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
//tag corresponds to row on tables view.
NSLog(#"view tag:%ld", (long)pickerView.tag);
//row here corresponds to the value selected from picker view.
NSLog(#"view value:%ld", (long)row);
}
- (NSString*) pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
return [NSString stringWithFormat:#"%d", row+1];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
//change this value to suit your needs.
return 10;
}
#end
Finally make sure to do this in your .h:
#interface YourController : UITableViewController <UITableViewDataSource, UITableViewDelegate, UIPickerViewDelegate, UIPickerViewDataSource>
With this you could be able to retrieve the value from picker view from each different cell accordingly.
For UI I leave that to you. Code is tested. Hope this helps.
Post-Comment (Update 2):
I ran it again and I see what you meant, although it didn't happen to me yesterday.
I made changes to the following and ran another test, this will fix it:
In cellForRowAtIndexPath:
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.text = [NSString stringWithFormat:#"%i", indexPath.row];
[cell.contentView addSubview:[self.pickerViewsArray objectAtIndex:indexPath.row]];
}
Another Update (concerning UI: how to hide and un-hide picker when tapped on cells):
Modify this to:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIPickerView *temp;
temp = [self.pickerViewsArray objectAtIndex:indexPath.row];
if(!temp.isUserInteractionEnabled)
{
[UIView animateWithDuration:1.0f animations:^
{
temp.userInteractionEnabled = YES;
temp.layer.opacity = 1.0f;
}
completion:^(BOOL finished)
{
}];
}
else
{
[UIView animateWithDuration:1.0f animations:^
{
temp.userInteractionEnabled = NO;
temp.layer.opacity = 0.0f;
}
completion:^(BOOL finished)
{
}];
}
}
And in:
- (void)createYourPickerViews
{
for(int x = 0; x < 10; x++)
{
UIPickerView *pickerView = [[UIPickerView alloc] initWithFrame:(CGRect){{0, 0}, 150, 10}];
pickerView.delegate = self;
pickerView.dataSource = self;
pickerView.layer.opacity = 0.0f; ======>>> //Add this
pickerView.userInteractionEnabled = NO; =======>>> //And this
pickerView.tag = x;
[self.pickerViewsArray addObject:pickerView];
}
}
Again, code is tested. Hope this (finally) helps.
Hey I'm working on a screen where user have option groups for example "Drink" which is title of section in my tableView, and their choices are "7up", "coke", etc which are cells of my table.
Now every Option Group choice (every cell in order words) has one radio button. I want to implement this. I'm facing problem if user selects any cell's radio button then other radio buttons should be deselected but how?
any help please
You should create a function to check your radio button from your custom cell and implements a delegate method to inform your TableViewController that your button on that cell was selected.
Your TableViewController needs to implements that delegate (dont forget to set each cell.delegate = self).
Then in your delegate method you create a loop to uncheck all of the radio buttons of the cells in the section except the cell you just checked.
Something like that :
This is a custom UITableViewCell with a button.
The images checked and uncheck need to look like a radio button checked and uncheked
Here is the .h file :
//RadioCell.h
#protocol RadioCellDelegate <NSObject>
-(void) myRadioCellDelegateDidCheckRadioButton:(RadioCell*)checkedCell;
#end
#interface RadioCell : UITableViewCell
-(void) unCheckRadio;
#property (nonatomic, weak) id <RadioCellDelegate> delegate;
#end
This is the .m file of RadioCell
//RadioCell.m
#property (nonatomic, assign) UIButton myRadio;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString*)reuseIdentifier
_myRadio = [UIButton buttonWithType:UIButtonTypeCustom];
[_myRadio setImage:[UIImage imageNamed:#"uncheck"] forState:UIControlStateNormal];
[_myRadio setImage:[UIImage imageNamed:#"check"] UIControlStateSelected];
[_myRadio addTarget:self action:#selector(radioTouched)orControlEvents:UIControlEventTouchUpInside];
_myRadio.isSelected = NO;
//don't forget to set _myRadio frame
[self addSubview:_myRadio];
}
-(void) checkRadio {
_myradio.isSelected = YES;
}
-(void) unCheckRadio {
_myradio.isSelected = NO;
}
-(void) radioTouched {
if(_myradio.isSelected == YES) {
return;
}
else {
[self checkRadio]
[_delegate myRadioCellDelegateDidCheckRadioButton:self];
}
}
Now just adapt your tableview controller with RadioCell (in .m file)
//MyTableViewController.m
#interface MyTableViewController () <RadioCellDelegate>
#end
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"RadioCell";
RadioCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[RadioCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel = #"Coke"; //or whatever you want
cell.delegate = self;
return cell;
}
-(void) myRadioCellDelegateDidCheckRadioButton:(RadioCell*)checkedCell {
NSIndexPath *checkPath = [self.tableView indexPathForCell:checkedCell];
for (int section = 0; section < [self.tableView numberOfSections]; section++) {
if(section == checkPath.section) {
for (int row = 0; row < [self.tableView numberOfRowsInSection:section]; row++) {
NSIndexPath* cellPath = [NSIndexPath indexPathForRow:row inSection:section];
RadioCell* cell = (CustomCell*)[tableView cellForRowAtIndexPath:cellPath];
if(checkPath.row != cellPath.row) {
[cell unCheckRadio];
}
}
}
}
}
Simple solution for a 2-option radio button UITableView (but you get the idea):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSIndexPath *newIP;
if (!indexPath.row)
newIP = [NSIndexPath indexPathForRow:indexPath.row+1 inSection:0];
else
newIP = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:0];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryCheckmark)
cell.accessoryType = UITableViewCellAccessoryNone;
else{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:newIP];
newCell.accessoryType = UITableViewCellAccessoryNone;
}
}
One solution would be to make use of the table views native selection capabilities.
In a standard UITableView it's only possible to have one row selected at a time and you can use this to your advantage. By setting "Selection" in storyboard to "None" the selection of a row will not be visible.
Now you can implement your own selection display. You can override the method -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath to update your cell when it gets selected.
And you can override the method -(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath to change the cell when it's no longer selected.
UITableViewDelegate automatically calls didSelectRowAtIndexPath on the old selection, when a new selection is made, keeping the selection unique like radio buttons.
I put together a little sample project for you to try, you can download it here.
Hopefully, I have been at least a bit helpful.
Cheers!