update array when the user updates the text field in the cell - ios

I was wondering if there's a way to update barcodeItemsQuantity array when the user updates the text field in a custom uitableviewcell. Below are my code snippets. and I want to update data from my array whenever the user changes the textfield from the custom tableviewcell.
viewcontroller.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Cell Initialized");
static NSString *cellIdentifier = #"BarcodeItemsCell";
BarcodeItemsTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if (cell == nil) {
cell = [[BarcodeItemsTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Configure the cell...
if (indexPath.row == [barcodeItems count]) {
// Add new row
cell.barcodeLabel.text = #"scan SKU";
cell.barcodeLabel.textColor = [UIColor lightGrayColor];
UIImage *btnImage = [UIImage imageNamed:#"barcodeIcon"];
[cell.leftButton setImage:btnImage forState:UIControlStateNormal];
cell.leftButton.tintColor = [UIColor blackColor];
cell.quantityTextField.userInteractionEnabled = NO;
[cell.leftButton addTarget:self action:#selector(scanBarcode) forControlEvents:UIControlEventTouchUpInside];
NSLog(#"Add another Item Requested");
}
else {
// Display barcode items
cell.barcodeLabel.text = [barcodeItems objectAtIndex:indexPath.row];
UIImage *btnImage = [UIImage imageNamed:#"deleteIcon"];
cell.leftButton.tintColor = [UIColor redColor];
[cell.leftButton setImage:btnImage forState:UIControlStateNormal];
cell.leftButton.tag = indexPath.row;
[cell.leftButton addTarget:self action:#selector(deleteRow:) forControlEvents:UIControlEventTouchUpInside];
[barcodeItemsQuantity addObject:cell.quantityTextField];
}
NSLog(#"Cell Populated");
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return true;
}
-(void) deleteRow:(id)sender {
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:photoCaptureView.itemsTableView];
NSIndexPath *indexPath = [photoCaptureView.itemsTableView indexPathForRowAtPoint:buttonPosition];
[barcodeItems removeObjectAtIndex:indexPath.row];
[photoCaptureView.itemsTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
NSLog(#"Item Removed");
}
barcodeitestableviewcell.h
#interface BarcodeItemsTableViewCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UIButton *leftButton;
#property (strong, nonatomic) IBOutlet UILabel *barcodeLabel;
#property (strong, nonatomic) IBOutlet UITextField *quantityTextField;
#end

Yes, you can update your data model value for the textfield text placed inside custom table cell.
STEP 1:
Add delegate in your current class "UITextFieldDelegate"
class ViewController: UIViewController,UITextFieldDelegate
STEP 2:
on your "cellForRowAt indexPath" invoke the delegate to current textfield and also add the tag
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
// add the following lines
cell.textField.delegate = self
cell.textField.tag = indexPath.row
return cell
}
STEP 3:
call the UITextField Delegates
func textFieldDidEndEditing(textField: UITextField) {
if !textField.text.isEmpty { // check textfield contains value or not
if textField.tag == 0 {
firstName = textField.text!
} else {
lastName = textField.text!
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
func textFieldDidBeginEditing(textField: UITextField!) {
if textField.tag == 0 {
firstName = ""
} else {
lastName = ""
}
}
Here, you can replace the firstName and lastName with your desired model variables.
Hope this will work for you.

Related

Changing image of a button in UITableViewCell on clicking it.

I am developing an app in which, the image of the UIButton in UITableViewCell should change on click and I have done this in a custom cell. Right now, I am able to change the image of the button but it is also changing the image of few other buttons too as I scroll down (as cellForRowAtIndexPath: is called on scrolling).
Here is the code.
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
_cell = (ListTableViewCell *)[self.tblList dequeueReusableCellWithIdentifier:#"listTableViewCell"];
if (_cell == nil) {
_cell = [[ListTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"listTableViewCell"];
} else {
_cell.imgIcon.image = [UIImage imageNamed:[NSString stringWithFormat:#"%#",[_arrImages objectAtIndex:indexPath.row]]];
_cell.lblList.text = [NSString stringWithFormat:#"%#",[_arrNames objectAtIndex:indexPath.row]];
_cell.btnList.tag = indexPath.row;
if (_cell.btnList.tag == indexPath.row) {
[_cell.btnList addTarget:self action:#selector(btnPressedMethodCall:) forControlEvents:UIControlEventTouchUpInside];
}
}
return _cell;
}
- (void) btnPressedMethodCall:(UIButton*)sender {
if ([sender isSelected]) {
[sender setImage:[UIImage imageNamed:#"red_image.png"] forState:UIControlStateSelected];
[sender setSelected:NO];
} else {
[sender setImage:[UIImage imageNamed:#"black_image.png"] forState:UIControlStateNormal];
[sender setSelected:YES];
}
}
Could someone please tell how this problem can be solved. Any help is appreciated thanks.
Instead of changing image in button click event. Add selected button indexPath in NSMutableArray and in cellForRow method check NSMutableArray contain current indexPath. if yes than change button image else set normal image like below.
Swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:TableViewCell = self.tblVW.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
cell.selectionStyle = .none
cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: #selector(btnTapped), for: .touchUpInside)
if arrIndexPaths.contains(indexPath) {
cell.btn.setImage(YOUR_BUTTON_SELECTED_IMAGE, for: .normal)
}
else {
cell.btn.setImage(YOUR_BUTTON_DEFAULT_IMAGE, for: .normal)
}
cell.layoutSubviews()
return cell;
}
#IBAction func btnTapped(_ sender: UIButton) {
let selectedIndexPath = NSIndexPath.init(row: sender.tag, section: 0)
arrIndexPaths.add(selectedIndexPath)
self.tblVW.reloadData()
}
If you want to reload only single row than replace self.tblVW.reloadData() with self.tblVW.reloadRows(at: [selectedIndexPath as IndexPath], with: UITableViewRowAnimation.none)
Objective C
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"TableViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[NSBundle mainBundle] loadNibNamed:cellIdentifier owner:self options:nil] objectAtIndex:0];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.btn.tag = indexPath.row
[cell.btn addTarget:self action:#selector(btnTapped:) forControlEvents:UIControlEventTouchUpInside];
if ([arrIndexPaths containsObject: indexPath]) {
[cell.btn setImage:YOUR_BUTTON_SELECTED_IMAGE forState:UIControlStateNormal];
}
else {
[cell.btn setImage:YOUR_BUTTON_DEFAULT_IMAGE forState:UIControlStateNormal];
}
[cell layoutSubviews];
return cell;
}
-(IBAction)btnTapped:(UIButton *)sender {
NSIndexPath *selectedIndexPath = [NSIndexPath indexPathForRow:sender.tag inSection:0];
[arrIndexPaths addObject:selectedIndexPath];
[self.tblVW reloadData]; // Reload Whole TableView
//OR
NSArray* indexArray = [NSArray arrayWithObjects:selectedIndexPath, nil];
[self.tblVW reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationNone]; // Reload Single Row
}

Swift 3 - Reload UICollectionView inside the UITableViewCell

I have a UICollectionView inside a UITableViewCell. You may refer the image at here
I would like to reload the collectionView if any update happen.
I have done some research and found this :
how to reload a collectionview that is inside a tableviewcell
Reloading collection view inside a table view cell happens after all cells in table view have been loaded
UICollectionView not updating inside UITableViewCell
I called the #IBOutlet weak var collectionView: UICollectionView! from UITableViewCell to UITableViewController at cellForRowAt.
Here is the code:
var refreshNow: Bool = false
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Storyboard.allCardCell, for: indexPath) as! AllCardTableViewCell
if refreshNow {
cell.collectionView.reloadData()
refreshNow = false
}
cell.collectionView.collectionViewLayout.invalidateLayout()
return cell
}
If the user click Ok on UIAlertAction :
let alert = UIAlertController(title: "Success", message: "Card successfully added", preferredStyle: .alert)
let action = UIAlertAction(title: "Ok", style: .default) { (action) in
self.refreshNow = true
self.tableView.reloadData()
}
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
The reason why I put the refreshNow is to prevent the apps from lagging and slow. But still did not update if any changes happen.
The problem is the collectionView did not refresh. But when I debug, it was went through the cell.collectionView.reloadData().
The update/changes only happen when I restart the apps. I want it to be so called real-times update.
Any help is really appreciated and many thanks.
Image credit: How to use StoryBoard quick build a collectionView inside UITableViewCell
At end of your update add:
DispatchQueue.main.async() { () -> Void in
self.tableView.reloadData()
}
In your case, you should assign tag to your collection view in order to get access outside the cellForRowAt function.
This is how your function should look like:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Storyboard.allCardCell, for: indexPath) as! AllCardTableViewCell
cell.collectionView.tag = 1234
return cell
}
and the action will reload it will access the collectionView by using the tag
let action = UIAlertAction(title: "Ok", style: .default) { (action) in
let collectionView = self.tableView.viewWithTag(1234) as! UICollectionView
collectionView.reloadData()
}
Also take note that cellForRowAt will keep reload the content based what you added inside it every time the cell appear. So, keep updating your data outside the cellForRowAt function.
Because you reused UITableViewCell so you must alway reload your UICollectionView. If you use refreshNow to reload UICollectionView, at the cell have refreshNow = false, UICollectionView will display like cell that it 's reused => wrong
Udate rep:
See , in picture uitableviewcell 1 will reuse at index 6. If you not reload content of cell (reload collectionview) it will display like uitableviewcell 1 at index 0
#import "AddPhotoViewController.h"
#import "PhotoTableViewCell.h"
#import "ShareTableViewCell.h"
#interface AddPhotoViewController ()
#property (weak, nonatomic) IBOutlet UITableView *tblView;
#property (strong,nonatomic)NSMutableArray *arrImages,*arrIndexPath,*selectImages;
#end
#pragma mark - TableViewDelegate&DataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 3;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *returnCell;
static NSString *cellIdentifier = #"CellOne";
static NSString *cellIdentifierTwo = #"CellTwo";
static NSString *cellIdentifierThree = #"CellThree";
if (indexPath.row == 0) {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
returnCell = cell;
} else if (indexPath.row == 1){
ShareTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifierTwo forIndexPath:indexPath];
cell.viewMood.layer.cornerRadius = 5;
cell.viewPeople.layer.cornerRadius = 5;
[cell.viewMood layer].borderWidth = 1;
[cell.viewMood layer].borderColor = [UIColor colorWithRed:241.0/255.0 green:143.0/255.0 blue:48.0/255.0 alpha:1].CGColor;
[cell.viewPeople layer].borderWidth = 1;
[cell.viewPeople layer].borderColor = [UIColor colorWithRed:241.0/255.0 green:143.0/255.0 blue:48.0/255.0 alpha:1].CGColor;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
returnCell = cell;
}else if (indexPath.row == 2){
PhotoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifierThree forIndexPath:indexPath];
cell.collView.dataSource = self;
cell.collView.delegate = self;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
returnCell = cell;
}
return returnCell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return UITableViewAutomaticDimension;
}
#pragma mark- UIImagePickerControllerDelegate
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerOriginalImage];
[_arrImages addObject:chosenImage];
PhotoTableViewCell *cell = [self.tblView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]];
[cell.collView reloadData];
[picker dismissViewControllerAnimated:YES completion:^{
}];
}
#pragma mark - CollectionViewDataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [_arrImages count];
}
- ( UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellIdentifier = #"CellCollection";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
UIImageView *imgView = [(UIImageView*)[cell contentView] viewWithTag:100];
UIImageView *imgViewTick = [(UIImageView*)[cell contentView] viewWithTag:200];
UIView *view = [(UIView*)[cell contentView] viewWithTag:300];
if (indexPath.row == 0){
imgViewTick.hidden = YES;
view.hidden = YES;
}
if ([_arrIndexPath containsObject:indexPath]) {
[_selectImages removeAllObjects];
view.hidden = NO;
view.alpha = 0.4;
imgViewTick.hidden = NO;
imgView.image = [_arrImages objectAtIndex:indexPath.row];
[_selectImages addObject:[_arrImages objectAtIndex:indexPath.row]];
NSLog(#"Pick images:%#",_selectImages);
}else{
view.hidden = YES;
imgViewTick.hidden = YES;
imgView.image = [_arrImages objectAtIndex:indexPath.row];
}
return cell;
}

How to create fixed amount of UITableViewCell and if the data is null then row should be not be shown

I am using tableView to display some information which is just four line of information. And i want to assign respective information to each row.
Like how shown in the below image there are four rows, same as in the image so i am using tableView for that. Here my problem is that i have created four cells but don't know how should i use label in specific cell and show the info.
and also if the value is null that row should not be there means if two values among four are null then only two rows having values should be there in tableView. How can i achieve this. Till now i am only able to show one row information only.
- (NSArray *)myTableViewCells
{
if (!_myTableViewCells)
{
_myTableViewCells = #[
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil],
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil],
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil],
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]
];
}
return _myTableViewCells;
}
if([managedObject valueForKey:#"personality_company_master_values"] != nil)
{
[_displayValues addObject:[NSString stringWithFormat:#"Personality %#",[managedObject valueForKey:#"personality_company_master_values"]]];
}
if([managedObject valueForKey:#"video_tag"] != nil)
{
[_displayValues addObject:[NSString stringWithFormat:#"Tag %#",[managedObject valueForKey:#"video_tag"]]];
}
if([managedObject valueForKey:#"industry_master_values"] != nil)
{
[_displayValues addObject:[NSString stringWithFormat:#"Industry %#",[managedObject valueForKey:#"industry_master_values"]]];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.myTableViewCells.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = self.myTableViewCells[indexPath.row];
// NSManagedObject *managedObject = [self.devices lastObject];
cell.backgroundColor = [self colorFromHexString:#"#014455"];
cell.textLabel.text = _displayValues[indexPath.row];
cell.textLabel.backgroundColor = [self colorFromHexString:#"#014455"];
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.font=[UIFont systemFontOfSize:14.0];
// UILabel *lbl=(UILabel*)[cell viewWithTag:900];
// [lbl setText:[managedObject valueForKey:#"personality_company_master_values"]];
// lbl.textColor=[UIColor blackColor];
return cell;
}
Get the value you want display in an array.
Something like this
#property (monatomic, strong)NSMuatableArray *displayValues;
-(void)viewDidLoad
{
self.displayValues = [[NSMutableArray alloc]init];
NSManagedObject *managedObject = [self.devices lastObject];
if([managedObject valueForKey:#"personality_company_master_values"] != nil)
{
[self.displayValues addObject:[managedObject valueForKey:#"personality_company_master_values"]];
}
if([managedObject valueForKey:#"company_master_values"] != nil)
{
[self.displayValues addObject:[managedObject valueForKey:#"company_master_values"]];
}
if([managedObject valueForKey:#"tag_master_values"] != nil)
{
[self.displayValues addObject:[managedObject valueForKey:#"tag_master_values"]];
}
}
- (NSArray *)myTableViewCells
{
if (!_myTableViewCells)
{
_myTableViewCells = #[
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil],
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil],
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil],
[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]
];
}
return _myTableViewCells;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.displayValues.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = self.myTableViewCells[indexPath.row];
// NSManagedObject *managedObject = [self.devices lastObject];
//cell.textLabel.text = [NSString stringWithFormat:#"%#",[managedObject valueForKey:#"personality_company_master_values"]];
cell.textLabel.text = self.displayValues[indexPath.row];
//not getting have to do this way or any other way please help
// secondLabel.text = [NSString stringWithFormat:#"%#",[managedObject valueForKey:#"company_master_values"]];
// thirdLabel.text = [NSString stringWithFormat:#"%#",[managedObject valueForKey:#"tag_master_values"]];
return cell;
}
I'm afraid you're doing several things wrong, starting with preallocating an array of cells. Tableviews don't work like that, you provide cells on demand and populate them with values from your data model. When you want to remove a cell update your data model then call reloadData(). Here's a simple example:
import UIKit
class MyCell: UITableViewCell {
var row: Int = -1 // serves no purpose but to show how you might subclass a UITableViewCell
}
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var dataModel = [
"Hello", "World,", "this", "is", "a", "tableview"
]
var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
var frame = view.bounds
let statusBarHeight = UIApplication.sharedApplication().statusBarFrame.height
frame.origin.y += statusBarHeight
frame.size.height -= statusBarHeight
tableView = UITableView(frame: frame, style: .Plain)
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(MyCell.self, forCellReuseIdentifier: "mycell")
view.addSubview(tableView)
}
// MARK: - UITableViewDataSource
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataModel.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("mycell") as! MyCell
let row = indexPath.row
cell.row = row // there is no point in doing this other than to show it as an example
cell.textLabel!.text = dataModel[row]
return cell
}
// MARK: - UITableViewDelegate
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
dataModel.removeAtIndex(indexPath.row)
tableView.reloadData()
}
}
EDIT: Here's an objective c version
////////////////////////////
/// Objective C Version //
////////////////////////////
#import "ViewController.h"
#interface MyCell: UITableViewCell
#property(assign) NSInteger row; // serves no purpose but to show how you might subclass a UITableViewCell
#end
#implementation MyCell #end
#interface ViewController() <UITableViewDataSource, UITableViewDelegate>
#property NSMutableArray *dataModel;
#property UITableView *tableView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_dataModel = [NSMutableArray arrayWithArray: #[#"Hello", #"World,", #"this", #"is", #"a", #"tableview"]];
CGRect frame = self.view.bounds;
CGFloat statusBarHeight = [UIApplication sharedApplication].statusBarFrame.size.height;
frame.origin.y += statusBarHeight;
frame.size.height -= statusBarHeight;
_tableView = [[UITableView alloc] initWithFrame: frame style: UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
[_tableView registerClass: [MyCell class] forCellReuseIdentifier: #"mycell"];
[self.view addSubview: _tableView];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _dataModel.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MyCell *cell = (MyCell *) [tableView dequeueReusableCellWithIdentifier: #"mycell"];
NSInteger row = indexPath.row;
cell.row = row; // there is no point in doing this other than to show it as an example
cell.textLabel.text = _dataModel[row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[_dataModel removeObjectAtIndex: indexPath.row];
[_tableView reloadData];
}
#end
You dont need to create a fixed amount of cells this is not an efficient solution to the problem. You should create NSMutableDictionary and save the data like this:
NSMutableArray *data = [NSMutableDictionary dictionary];
[data setValue:#"Vijayakanth" forKey:#"Personality"];
Now in the table view delegate you can return the keys count for noOfRowsInSection and in cellForRowAtIndexPath you can get the key from dictionary get the value w.r.t that key and assign the values to your cell. In your case:
Key: Personality (which is shown on the left side)
Value: Vijayakanth (which is shown on the right side)
Hope you understand the point.

UITableViewCell get deleted directly by tapping delete control on the left but not show delete button on the right

When I involve [tableView setEditing:YES animated:YES], delete control shows on every cell on the left,what I want to do is to get the event when I tap delete control,and directly delete cell but not to show delete button on the right.
I know apple's standard way to do this is to show delete button on the right, and when I tap it ,datasource's
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
gets involved, the reason I don't want to do like this is my cell is customised by scrollview which scroll horizontally so scroll to show delete button would made it a mess, so I wouldn't implement
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
in my datasource.
Have any idea?
one way u do is, customising the cell and put your own way of deleting the cell for example,
create a new custom cell by subclassing the UITableviewCell name it as something like CustomCellTableViewCell
in CustomCellTableViewCell.h define a delegate method for example,
#import <UIKit/UIKit.h>
#class CustomCellTableViewCell;
#protocol CellDelegate <NSObject>
- (void)deleteCell:(CustomCellTableViewCell *)cell;
#end
#interface CustomCellTableViewCell : UITableViewCell
+ (CustomCellTableViewCell *)createCell;
#property (weak, nonatomic) IBOutlet UIButton *deleteButton;
#property (weak, nonatomic) IBOutlet UILabel *descriptionLabel;
#property (weak,nonatomic) id<CellDelegate> cellDelegate;
- (IBAction)deleteAction:(id)sender;
- (void)showDeleteButton;
- (void)hideDeleteButton;
#end
and in CustomCellTableViewCell.xib add a button and set label connect to deleteButton and descriptionLabel
in CustomCellTableViewCell.m file
#import "CustomCellTableViewCell.h"
#implementation CustomCellTableViewCell
- (void)awakeFromNib {
// Initialization code
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self)
{
self = [CustomCellTableViewCell createCell];
}
return self;
}
+ (CustomCellTableViewCell *)createCell
{
NSArray *arrayOfViews = [[NSBundle mainBundle] loadNibNamed:#"CustomCellTableViewCell" owner:nil options:nil];
if ([arrayOfViews count] < 1) {
return nil;
}
for (id item in arrayOfViews) {
if([item isKindOfClass:[UITableViewCell class]])
return item;
}
return nil;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (IBAction)deleteAction:(id)sender {
if([self.cellDelegate respondsToSelector:#selector(deleteCell:)])
{
[self.cellDelegate deleteCell:self];
}
}
- (void)showDeleteButton
{
CGRect destRect = self.descriptionLabel.frame;
destRect.origin.x += 80;
[UIView animateWithDuration:0.3 animations:^{
self.descriptionLabel.frame = destRect;
}];
}
- (void)hideDeleteButton
{
CGRect destRect = self.descriptionLabel.frame;
destRect.origin.x = 0;
[UIView animateWithDuration:0.3 animations:^{
self.descriptionLabel.frame = destRect;
}] ;
}
#end
and in controller .m file
- (void)viewDidLoad {
[super viewDidLoad];
stringsArray = [[NSMutableArray alloc]initWithObjects:#"apple",#"dell",#"windows",#"nokia",#"sony",#"hp",#"lenovo", nil];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [stringsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomCellTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"SuggestionCell"];
if(cell == nil)
{
cell = [[CustomCellTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"SuggestionCell"];
}
if(customEditTableView)
[cell showDeleteButton];
else
[cell hideDeleteButton];
cell.cellDelegate = self;
cell.descriptionLabel.text = [stringsArray objectAtIndex:indexPath.row];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 50.0f;
}
- (IBAction)deleteCellsAction:(id)sender
{
if(customEditTableView)
customEditTableView = NO;
else
customEditTableView = YES;
[self.aTableView reloadData];
}
- (void)deleteCell:(CustomCellTableViewCell *)cell
{
NSIndexPath *indexPath = [self.aTableView indexPathForCell:cell];
[stringsArray removeObjectAtIndex:indexPath.row];
[self.aTableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
try out in new project u will get it
You can achive this thing using UIViewController
Add tableview and tableviewcell in UIViewController
I have achive this same thing using swift. It will give you idea how to do in Objective-C
Below is Code:
var data:[String] = ["One","Three","Four","Five","Six"]
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.rightBarButtonItem = self.editButtonItem()
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel.text = self.data[indexPath.row]
if editing
{
cell.imageView.image = UIImage(named: "Button-Delete-icon.png")
}
else
{
cell.imageView.image = UIImage(named: "")
}
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if editing
{
self.data.removeAtIndex(indexPath.row)
self.tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
}
}
override func setEditing(editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
self.tableView.reloadData()
}
Hope It will Help

UITextField inside UITableViewCell: becomeFirstResponder in didSelectRowAtIndexPath

I am currently trying to get this working. Any help is appreciated.
I have a custom UITableViewCell that has a UITextField inside. When I select the table cell, I would like to make the UITextField first Responder.
However [textField becomeFirstResponder]; returns false.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
UITextField *textField;
for (UIView *view in [cell subviews]) {
if ([view isMemberOfClass:[UITextField class]]) {
textField = ((UITextField *)view);
}
}
[textField becomeFirstResponder];
}
As requested, the initialisation of the textfield. This is done in the UITableViewCell subclass:
- (id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Init Textfield
_textField = [[UITextField alloc] init];
_textField.backgroundColor = [UIColor clearColor];
_textField.delegate = self;
[self addSubview:_textField];
}
return self;
}
If you have a custom cell, then you can do something like this:
#implementation CustomCell
#pragma mark - UIResponder
- (BOOL)canBecomeFirstResponder
{
return YES;
}
- (BOOL)becomeFirstResponder
{
return [self.textField becomeFirstResponder];
}
#end
Then inside the table view delegate:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell canBecomeFirstResponder]) {
[cell becomeFirstResponder];
}
}
Give tag for each UITextField and and use Following code:
UITableViewCell* cell = (UITableViewCell*)sender.superview.superview;
UITextField *txtField = (UITextField*)[cell viewWithTag:tag];
[txtField becomeFirstResponder];
In didSelectRowAtIndexPath method.
Its working very good.. :)
I believe you need to set you textField's delegate property.
Add textField.delegate = self; to your method, before you call [textField becomeFirstResponder]
I think you should include a tag value on the textfield when creating the cell:
- (id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Init Textfield
_textField = [[UITextField alloc] init];
_textField.backgroundColor = [UIColor clearColor];
_textField.delegate = self;
_textField.tag = 999;
[self addSubview:_textField];
}
return self;
}
And on the didSelectRowAtIndexPath method use the tag value to recover the object:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
UITextField *textField = (UITextField*)[cell viewWithTag:999];
if (![textField isFirstResponder]){
[textField becomeFirstResponder];
}
}
I've including a validation to control if the textfield is already the first responder.
Hope it works as you expect
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
UITextField *textField;
for (id subV in [cell subviews]) {
if ([subV isKindOfClass:[UITextField class]]) {
textField = (UITextField *)subV;
[textField becomeFirstResponder];
break;
}
}
}
I think it will be helpful to you.
Updated the answer from #josh-fuggle to use Swift 2.2.
import Foundation
import UIKit
class CustomTableCell:UITableViewCell {
#IBOutlet var textValue: UITextField!
override func canBecomeFirstResponder() -> Bool {
return true
}
override func becomeFirstResponder() -> Bool {
return self.textValue.becomeFirstResponder()
}
}
And this is in your table view delegate:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
if ((cell?.canBecomeFirstResponder()) != nil) {
cell?.becomeFirstResponder()
}
}
You can do something like this:
class CustomCell: UITableViewCell {
#IBOutlet weak var textField: UITextField!
override func awakeFromNib() {
super.awakeFromNib()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(contentViewTapped))
self.contentView.addGestureRecognizer(tapGesture)
}
#objc func contentViewTapped() {
_ = self.textField.becomeFirstResponder()
}
}
[self.titleLab performSelector:#selector(becomeFirstResponder) withObject:nil afterDelay:0.2];

Resources