Textfield insdie UITableViewCell - ios

I have a textfield and two buttons inside a tableview cell and when you click on the textfield, it opens up a pickerview to make a selection. What I want is that, the user should only be able to click on the textfield and the buttons, and not on the tableviewcell. I don't want the cell to be selectable, only the textfield and buttons to be selectable, how do I do that?
I have already tried cell.selectionType and cell.userinteractionenabled but they just make the whole cell unselectable, even the textfield inside it...so that's not what I want.
screenshot of what tableviewcell looks like
Kindly help!
Thanks!

In cellForRowAtIndexPath:
if (indexPath.section == 0) {
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
then also implement willSelectRowAtIndexPath:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == 0) {
return nil;
}
return indexPath;
}

Related

Approaches to implement tapped inserting table cell with radio buttons

What I'm trying to do is to insert some new data into the data source array, and then do [tableView reloadData]. The new array can be inserted, but there are two problems.
1) I want to have two radio buttons in the new cell for users to choose. Should I define a new cell object or something?
2) When reloading the data, the selected cell's color cannot be set to green as before.
Or any other suggestions on how to best implement this, thanks!!:
For the first problem, what I would do is pre-layout that cell containing the two radio buttons either in the storyboard (You can also do it in a .xib file). Then I will set an identifier for it like "LanguageSkillSelectionTableViewCell" or something. After that, when I am about to load the new set of data into the table view I can manage the presentation of cells in the table view through the callback cellForRowAtIndexPath:
An example would be if I want to load that LanguageSkillSelectionTableViewCell always at the beginning, then I would just set it at indexPath.row == 0. else set the contents of the data list to other rows.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *tableCell;
if(_loadedNewData)
{
if(indexPath.row < dataList.count && indexPath.row > 0)
{
tableCell = (DataTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"DataTableViewCell"];
//set attributes of the tableCell
}
else
{
tableCell = (LanguageSkillSelectionTablViewCell *)[tableView dequeueReusableCellWithIdentifier:#"LanguageSkillSelectionTableViewCell"];
//set attributes of the tableCell
}
}
else
{
//load in default order
}
return tableCell;
}
You can just play with the arrangement and presentation of the cells under this callback.
For the second problem, you have to store a flag or state for that selection picked by the user in a global variable within the class. Then everytime the cells are reloaded you can just update the selection state of that cell by setting a method for that cell that would update the selection state of the radio button.
For example:
If user selected English, then it would be like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *tableCell;
if(_loadedNewData)
{
if(indexPath.row < dataList.count && indexPath.row > 0)
{
tableCell = (DataTableViewCell *)[tableView dequeueReusableCellWithIdentifier:#"DataTableViewCell"];
//set attributes of the tableCell
}
else
{
tableCell = (LanguageSkillSelectionTablViewCell *)[tableView dequeueReusableCellWithIdentifier:#"LanguageSkillSelectionTableViewCell"];
//set attributes of the tableCell
[(LanguageSkillSelectionTablViewCell *)tableCell setLanguageSelectionState:canReadWrite];
}
}
else
{
//load in default order
}
return tableCell;
}

Get UItextFields text from custom UITableView

I have a custom UITableViewCell with a UITextField (which is linked to the custom cells class). I am trying to access the textField from my VC class.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
menuCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
if ([indexpath row] == 2) {
menuCell.nameTextField.delegate = self;
}
return cell;
}
-(void) textFieldDidEndEditing:(UITextField*) textfield
{
}
How do I get the textFields text from textFieldDidEndEditing?
Depending on where you want to access this text depends on how difficult it is.
Want to access the text in cellForRowAtIndex - (very easy)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
menuCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
if ([indexpath row] == 2) {
menuCell.nameTextField.delegate = self;
}
NSString * text = menuCell.nameTextField.text;
return cell;
If you want to access the text anywhere in the VC and the menuCell is unique (there is only one of them) - (medium difficult)
In your header file add the custom cell as a class
#class menuCell;
This means you can set it a variable in the interface
menuCell * _menuCell;
Next in cellForRowAtIndex you want to allocate this custom cell
- (UITableViewCell *)tableView:(UITableView *)tableView_ cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == bCustomCellSection) {
if (!_menuCell) {
_menuCell = [tableView_ dequeueReusableCellWithIdentifier:bProfileNameCell];
_menuCell.nameTextField.delegate = self;
}
_menuCell.nameTextField.placeholder = #"Name";
_menuCell.selectionStyle = UITableViewCellSelectionStyleNone;
return _menuCell;
}
...
}
This means that we now have access to the menu cell from anywhere in the VC and can get the text by calling
_menuCell.nameTextField.text
Multiple custom cells with multiple textfields - (tough)
I have never done this but would probably do it one of two ways
a) Create an array and as we are creating the custom cells add a pointer to the textFields to the array each time. We can then access the textField we want from that array
For this method I would add the custom cells to a mutable array defined in the interface
NSMutableArray * cellsArray;
remember to initialise it in viewDidLoad
cellsArray = [NSMutableArray new];
Then in cellForRowAtIndex i would add the cell each time
menuCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
[cellsArray addObject: menuCell];
This obviously depends on how many sections we have. If we have more than one section it gets more complicated again:
Then we would need to add an array for each section to an overall array. This is quite complicated and could have a whole question on its own, there is a good link of how to do this here:
Once you have an array of cells (or an array of arrays of cells) you can call the cell you want based on the indexPath and get the textField
b) Call a pointer to the specific cell we want
menuCell * menuCell = [self tableView:table cellForRowAtIndexPath:indexPath];
and then get the textField from this cell as we did previously.
Remember you can calculate your own indexPath if you want to create one outside of cellForRow:
NSIndexPath * indexPath = [self.tableView indexPathForCell:cell];
This method is pretty good if you want to access a specific cell but a bit cumbersome if you want to access it a lot and keep having to call this code all over your VC
Hope this helps
If you are asking how to get the text from the delegate method textFieldDidEndEditing, then you simply do this:
-(void) textFieldDidEndEditing:(UITextField*) textfield
{
NSString *textFieldText = textfield.text;
}
However, if you have multiple textFields and you want to know what textfield is calling the delegate, you could tag your textField:
[myTextField setTag:indexPath.row]
and then put a if statement in the delegate textFieldDidEndEditing like this:
-(void) textFieldDidEndEditing:(UITextField*) textfield
{
if(textfield.tag == index0) do something..
else if(textfield.tag == index1) do something..
}

Display and hide DatePicker on UITableViewCell tap

I have a table view controller in which I need to display a date&time picker when a cell is tapped and hide it when the cell is tapped again. Basically the same effect that the iphone has when you choose your start and end date and time to create a new event in the calendar.
I'm guessing the display and hiding goes in the following method but I'm unsure of what goes inside:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {}
Some example code or link would be great. Thank you!!
Create your cell with whatever you want to show and the picker:
-----------------------------------
cell visible part
-----------------------------------
cell invisible part (with picker)
-----------------------------------
Define a property that let you know if you have to show the entire cell:
#property (nonatomic) BOOL shouldShowPicker;
Initialise this property (on viewDidLoad for example);
self.shouldShowPicker = NO;
A couple of methods to touch:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == 4) { //where your picker row is
self.shouldShowPicker = YES;
[self.tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == 4 && self.shouldShowPicker) { //where your picker row is
return CELL_VISIBLE_PLUS_INVISIBLE_PART;
} else if(indexPath.row == 4 && !self.shouldShowPicker) {
return return CELL_VISIBLE_PART;
} else {
return OTHER_CELLS_HEIGHT;
}
}
You might find my answer here useful which describes what you need to do.
Inline UIPicker Implementation
Essentially you create a custom cell containing a date picker, with optional buttons. You then add this cell below the cell when you edit it and remove it when finished. All explained in the link.

UITableView - insert new row by tapping on existing cell

I use UITableView with prototype cells and would like the top most cell to be an "adder" cell: when user taps on that cell, the segue is being performed. As the UITableView is being dynamically generated (except the top one) and cells are being reused, I have two question:
1 - is it possible to make one static cell while all the others will remain prototype cells?
2 - If not, how to implement this solution? I think, it has to be implemented in
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
but I have no idea, is this method right place to do it. Am I correct, to implement this custom cell, I need to check, whether indexPath.row = 0 and substitute the needed cell with custom, while programmatically shifting all the cells one row down?
Yiu can do on the Tap of Your cell, you can create two different cell, one your prototype cell and one for your details
in your
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
AdderCell *cell = (AdderCell*)[tableView dequeueReusableCellWithIdentifier:#"AdderCell" forIndexPath:indexPath];
} else {
CustomCell *cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:#"CustomCell" forIndexPath:indexPath];
}
}
on tap of your Adder cell in
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
// add data to your row array and reload the tableRow
} else {
// do your tap action
}
}

Disable selection of a single UITableViewCell

How do you disable selecting only a single cell in a UITableView? I have several, and I only want the last to be disabled.
To stop just some cells being selected use:
cell.userInteractionEnabled = NO;
As well as preventing selection, this also stops tableView:didSelectRowAtIndexPath: being called for the cells that have it set. It will also make voiceover treat it the same as a dimmed button (which may or may not be what you want).
Note that if you have interactive elements in the cell (ie. switches/buttons), you'll need to use cell.selectionStyle = UITableViewCellSelectionStyleNone; instead and then make sure to ignore taps on the cell in tableView:didSelectRowAtIndexPath:.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = ...
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
Throw this in your custom Table VC:
// cells lacking UITableViewCellAccessoryDisclosureIndicator will not be selectable
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType != UITableViewCellAccessoryDisclosureIndicator) {
return nil;
}
return indexPath;
}
// disabled cells will still have userinteraction enabled for their subviews
- (void)setEnabled:(BOOL)enabled forTableViewCell:(UITableViewCell *)tableViewCell
{
tableViewCell.accessoryType = (enabled) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
// if you dont want the blue selection on tap, comment out the following line
tableViewCell.selectionStyle = (enabled) ? UITableViewCellSelectionStyleBlue : UITableViewCellSelectionStyleNone;
}
Then to enable/disable selection for someTableViewCell, do this:
[self setEnabled:state forTableViewCell:someTableViewCell];
You're done and can ship.
-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self numberOfRowsInSection] == [indexPath row]) {
return nil;
} else {
return indexPath;
}
}
the last row of the table will not be selected
As I mentioned in another thread all the above methods are not solving the problem precisely. The correct way of disabling a cell is through the method
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
and in that method one has to use
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
which disables cell selection but still allows the user to interact with subviews of the cell such as a UISwitch.
The cleanest solution that I have found to this only makes use of the delegate method willDisplayCell.
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if([indexPath row] == 0) //<-----ignores touches on first cell in the UITableView
{ //simply change this around to suit your needs
cell.userInteractionEnabled = NO;
cell.textLabel.enabled = NO;
cell.detailTextLabel.enabled = NO;
}
}
You don't have to take any further action in the delegate method didSelectRowAtIndexPath to ensure that the selection of this cell is ignored. All touches on this cell will be ignored and the text in the cell will be grayed out as well.
with iOS 6.
You can use the following delegate method and return NO in case you don't it to be selected and YES in case you want it to be selected.
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
return indexPath.section == 0;
}
Try this in swift:
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
If anyone wondering how to achieve this in swift then here is my code. I am using Xcode 7 and tested using iPad Retina(iOS 9).
cell.selectionStyle = UITableViewCellSelectionStyle .None
cell.userInteractionEnabled = false
Try to place this two line code whether you want. In my case I have used this in this method for displaying cells.
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath)
Remember this two line code will block any kind of selection or interaction to your cells but you can only use the first line individually if you want. That is...
cell.selectionStyle = UITableViewCellSelectionStyle .None
Only this line will block the selection to your cells.
However the second line will make the cell "Read-Only". That is..
cell.userInteractionEnabled = false
Thanks
Hope this helped.

Resources