Populate UITableView from button pressed - objective-c

I am trying to populate UITableView from NSMutableArray. I have UITextField and a button on a ViewController. When I type any text in the UITextField and click button, I can see the text being added to the array with NSLog. I set breakpoints on the data source method of UITableView but it does not even hit those breakpoints when I click the button.
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
{
NSMutableArray *arrBarcode;
IBOutlet UITextField *txtInsert;
}
#property IBOutlet UITableView *myTableView;
-(IBAction)btnPressed:(id)sender;
#end
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.myTableView.delegate = self;
self.myTableView.dataSource = self;
arrBarcode = [[NSMutableArray alloc]init];
}
-(IBAction)btnPressed:(id)sender{
[arrBarcode addObject:txtInsert.text];
NSLog(#"array count is : %i", [arrBarcode count]);
[self.myTableView reloadData];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[txtInsert resignFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfSectionsInTableView: (UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if ([arrBarcode count] == 0){
return 0;
}
else{
NSLog(#"Number of Rows : %i", [arrBarcode count]);
return [arrBarcode count];
}
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell Identifier";
[tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *barcode = [arrBarcode objectAtIndex:[indexPath row]];
[cell.textLabel setText:barcode];
return cell;
}
#end
When I initialize a NSMutable Array with some data in the viewDidLoad method, the UITableView is populating fine but not with dynamic array. I am newbie in Objective C, Can someone point me to right direction?

Code looks OK (even if not very efficient). You have to check if the button is indeed connected to the action. In storyboard or Interface Builder, select the button and check the rightmost inspector on the right. See if the action is correctly connected.
Maybe you want to get rid of the touchesBegan call and call resignFirstResponder when the button is pressed.
For numberOfRowsInSection I think this is enough:
return arrBarcode.count;

I'm not sure but the following line looks strange to me:
#synthesize myTableView = myTableView_;
This is telling the compiler to make a getter and setter for the property myTableView and backing it with an iVar named myTableView_. But in your case you have already defined an iVar named myTableView_.
Try connecting the UITableView as a property instead. A property will be backed by an instance variable with the form _yourProperty and have getter and setter generated automatically so #synthesize isn't really needed in this case.

Related

Custom TableView-Cell (Data from server) select multiple values with accessory change

I am working with TableView and wanted Custom TableViewCell to have a Small Image, Name and one custom image (With Tickmark and without Tick) can be on accessory to show if Cell is selected and if it's not selected it will show without Tick image on unselected cells.
And if i want to select multiple cells then it should show Tick image on selected Cells and Untick image on unselected cells and after that when i click on a button then i should be able to get the selected cell id's.
On the tableView i am getting all the values from the server and images also from URL's but the Tickmark and Unselected Tick mark image will be used the project itself.
So far i have created :
Class .h,.m,.xib of "ResultTableCell" of type UITableViewCell and my Main view "Result" with the TableView and a Button on top (on click of button i'll get the values of selected cells)
ResultTableCell.h
#import <UIKit/UIKit.h>
#interface ResultTableCell : UITableViewCell
#property (nonatomic, retain) IBOutlet UILabel *nameLabel;
#property (nonatomic, retain) IBOutlet UIImageView *thumbImageView;
ResultTableCell.m
#import "ResultTableCell.h"
#implementation ResultTableCell
#synthesize nameLabel,thumbImageView;
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
ResultTableCell.xib
The right hand side image on the xib is the place where the accessor image will come.
ResultTableCell.xib
And the main xib
Result.h
#import <UIKit/UIKit.h>
#import "ASIFormDataRequest.h"
#interface Results : UIViewController <UITableViewDelegate,UITableViewDataSource>
{
NSMutableArray *nameData;
}
#property (nonatomic, retain)NSMutableArray *nameData;
#property (nonatomic, retain)NSMutableArray *ImageData;
#property (nonatomic, retain)NSMutableArray *idData;
#property (nonatomic, retain)UITableView *table;
#property (nonatomic, retain) IBOutlet UIButton *done;
#property (nonatomic, retain) NSMutableArray *arFors;
-(IBAction)save_done:(id)sender;
Result.m
#import "Results.h"
#import "ResultTableCell.h"
#interface Results ()
#end
#implementation Results
#synthesize arFors;
#synthesize done,nameData,table,addressData,ImageData,idData;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.arFors=[NSMutableArray array];
// I am Getting Name,id and image url data from my HomeViewController
NSLog(#"Name Data from home view is %#",nameData); // 10 Names get's printed in log
NSLog(#"id Data is %#",idData);
NSLog(#"URL image data is %#",ImageData);
table = [[UITableView alloc]initWithFrame:CGRectMake(0, 221, 320, 327) style:UITableViewStylePlain];
table.delegate = self;
table.dataSource = self;
[self.view addSubview:table];
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"Name data count is %d",nameData.count);
return nameData.count;
//return 10;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 70;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
/* UITableViewCell *cell = [tableView dequeueReusableHeaderFooterViewWithIdentifier:#"MainCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MainCell"];
}*/
static NSString *simpleTableIdentifier = #"ResultTableCell";
ResultTableCell *cell = (ResultTableCell *)[table dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ResultTableCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if ([self.arFors containsObject:[NSNumber numberWithInt:indexPath.row]]) {
cell.accessoryView = [[ UIImageView alloc ]
initWithImage:[UIImage imageNamed:#"table_tick" ]];
}
else {
cell.accessoryView = [[ UIImageView alloc ]
initWithImage:[UIImage imageNamed:#"table_add" ]];
}
NSLog(#"data is ************* %#",nameData);
cell.nameLabel.text = [nameData objectAtIndex:indexPath.row];
NSURL * imageURL = [NSURL URLWithString:[ImageData objectAtIndex:indexPath.row]];
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
UIImage * image2 = [UIImage imageWithData:imageData];
cell.ImageView.image = image2;
cell.ImageView.contentMode = UIViewContentModeScaleAspectFit;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"didSelectRowAtIndexPath %d",indexPath.row);
if ([self.arFors containsObject:[NSNumber numberWithInt:indexPath.row]]) {
[self.arFors removeObject:[NSNumber numberWithInt:indexPath.row]];
}
else{
[self.arFors addObject:[NSNumber numberWithInt:indexPath.row]];
// [self.table cellForRowAtIndexPath:indexPath];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[tableView reloadData];
}
-(IBAction)save_done:(id)sender
{
NSLog(#"selected cell values are %#",self.arFors);
}
Now with this code everything is working fine (tick image is shown on selected cells and untick image on unslected cells and on clicking the Done button i am getting the selected cell values),
But the Problem comes when i tapp on a cell then it like hangs and takes 5-6 seconds of time to change accessor image as it fires [tableView reloadData] in didselectrowatindexpath method so all data reloads again in the tableview and then the accessor image changes, please can any one correct my code or enhance it so that it works fast.
I have tried a lot of ways but i was not able to do it without the reloading of table and if i reload table it takes long time.
Coding help will be much tankful.
Your problem is:
NSData * imageData = [NSData dataWithContentsOfURL:imageURL];
Because it downloads all of the image data from the network each time you reload the table view. You should be doing this asynchronously and caching the returned image so you don't need to download it repeatedly. Take a look at a library like SDWebImage to help you with this.

Load information from text field to table view

Hi I am trying to make an app that has a text field, tableview and a button.
When you press the button it adds the information from the text field to de tableview.
Do any one know when I can find a tutorial for this? I had one on a book but I cant find it.
Thanks in advance.
Here is my code so far:
code of .h
#interface BlockNotasViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
IBOutlet UITableView *tableNota;}
#property (strong, nonatomic) IBOutlet UITextField *textonota;
#property (nonatomic, retain) IBOutlet UITableView *tableNota;
#property (nonatomic, strong) NSMutableArray * arrayNota;
- (IBAction)AddNota:(id)sender;
#end
code of .m
- (void)viewDidLoad{
[super viewDidLoad];
self.textonota.delegate = self;
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return NO;
}
- (IBAction)AddNota:(id)sender {
[arrayNota addObject: textonota.text];
[tableNota reloadData];
}
//TableView------------------------------------
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [arrayNota count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (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] init];
}
cell.textLabel.text = [arrayNota objectAtIndex: indexPath.row];
return cell;
}
//----------------------------------------------
#end
No more errors but the button doesnt do anything
You can set up a NSMutableArray property that contains all the cells you want to add to the tableView.
When that button is pressed, you create a cell with a tag, and set text of that cell to the text of your UITextField:
cell.textLabel.text = aUITextField.text;
then add the cell into that NSMutableArray, and call [tableView reloadData] to refresh the table view.
In cellForRowAtIndexPath:indexPath delegate, you can use that tag to determine which cell in NSMutableArray to return, for example:
[return [self.cellArray objectAtIndex:indexPath.row]];
Hope this helps! :)
You should keep mutable array with strings. And use this array for fill content of tableview as data source. In delegate method - (UITableViewCell*) tableView:cellForRowAtIndexPath: you will create UITableViewCell if needed like this:
- (UITableViewCell*) tableView: (UITableView*) tableView
cellForRowAtIndexPath: (NSIndexPath*) indexPath
{
UITableViewCell* cell = [tableViewdequeueReusableCellWithIdentifier: #"identifier"];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault
reuseIdentifier: #"identifier"] autorelease];
}
cell.textLabel.text = [myMutableArray objectAtIndex: indexPath.row];
return cell;
}
- (NSInteger)tableView: (UITableView*) tableView numberOfRowsInSection:(NSInteger)section
{
return [myMutableArray count];
}
- (IBAction) pressButton: (id) sender
{
[myMutableArray addObject: textField.text];
[myTableView reloadData];
}
Every book for iOS developers contains information about UITableView.
Please read https://stackoverflow.com/questions/3403049/best-book-resources-for-learning-ios-programming

How to load array into a UITableView, not TableViewController

I am trying to take an array that I loaded from another viewer and put it into a UITableView, not a TableViewController. I don't know how I would do this. Right now I have this code:
CRHCommentSection.m
#import "CRHCommentSection.h"
#import "CRHViewControllerScript.h"
#interface CRHCommentSection ()
#end
#implementation CRHCommentSection
#synthesize observationTable;
NSArray *myArray;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
myArray = [CRHViewControllerScript theArray];
NSLog(#"%#", myArray);
//NSArray* paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:1]];
//[observationTable insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationTop];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
NSLog(#" in method 1");
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#" in method 2");
// Return the number of rows in the section.
return [myArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#" in method 3");
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [myArray objectAtIndex:indexPath.row];
return cell;
}
CRHCommentSection.h
#import <UIKit/UIKit.h>
#interface CRHCommentSection : UIViewController
#property (weak, nonatomic) IBOutlet UITableView *observationTable;
#end
Since you have posted this same example code more than once, Ill give you the way to do this without using statics. And Yes you do need to set the collection (array) on the view controller not the UITableView as the tableView uses the controller as a datasource.
Lets say you had a UITableView that displayed search results... And you launch this view controller from either some other view or from the application delegate like so..
In your viewController (yours is CRHCommentSection) define a property for the array you are going to populate the table with.
#property (nonatomic,retain, setter=setSearchResults:) NSArray *searchResults; //use your array name here
//BTW please dont call it ARRAY..its confusing.
Also in your commentsController (which would be a better name that what you have) add the setter for
the array
-(void) setSearchResults:(NSArray *)searchResults
{
//in case we loaded this view with results previously release the previous results
if ( _searchResults )
{
[_searchResults release];
}
_searchResults = [searchResults retain];
[_tableView reloadData];
}
When you instantiate the new view controller with the UITableView in it - set the "array",
in your case comments in my case searchResults
_searchResultsViewController = [[SearchResultsViewController alloc] initWithNibName:#"SearchResultsViewController" bundle:nil];
//now set the array on the controller
_searchResultsViewController.searchResults = mySearchResults; //(your array)
Thats a simple way to communicate the array for the table view when you instantiate a view controller.
Also the naming conventions will help you clear things up
If you have a view controller for comments it should be
CommentsViewController
And the array if it contains comments should be called comments - for readability.
Cheers.
As for the rest of the boilerplate setting the datasource and delegate and cellForRow etc,
you got that advice on the last go around so I wont repeat it here.
#bigkm had a good point
#interface SearchResultsViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
Your view controller has to be defined properly as above with the protocols.
You need to set the data source
[self setDataSource:self];
And also add the protocol to your interface.
<UITableViewDataSource>

Objective c - Best practice to handle a button touch event for a button of a custom UITableViewCell

What is best practice to handle a button touch event for a button of a custom UITableViewCell?
my classes:
MyViewController, MyCustomCell
I can think of three options:
First option- Have the button as a property of MyCustomCell, and then add a target to it in the MyViewController .m file with MyViewController as the target.
MyViewController .m file
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"customCell";
MyCustomCell *cell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
[cell.theButton addTarget:self
action:#selector(theButtonTapped:)
forControlEvents:UIControlEventTouchUpInside];
}
// Configure the cell...
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)theButtonTapped:(UIButton *)sender
{
MyCustomCell *selectedCell = (MyCustomCell *)sender.superview;
if (selectedCell) {
NSIndexPath *indexPath = [self.tableView indexPathForCell:selectedCell];
MyModel *selectedModel = [self.model objectAtIndex:indexPath.row];
// do something with the model...
}
}
Second option- If the custom cell was made in IB, Set the nib File's Owner to be MyViewController, implement buttonTapped: method in MyViewController and connect the button's Touch Up Inside event to the buttonTapped: method.
Third option- if the custom cell wasn't made in IB, add a target to the button in the MyCustomCell .m file with MyCustomCell as the target.
Define a MyCustomCellDelegate add #property (nonatomic, assign) id<MyCustomCellDelegate> delegate to MyCustomCell and call this delegate when button tapped.
Set MyViewController as the cell's delegate when creating cells and implement the MyCustomCellDelegate protocol.
MyCustomCell .h file
#class MyCustomCell;
#protocol MyCustomCellDelegate <NSObject>
- (void)buttonTappedOnCell:(MyCustomCell *)cell;
#end
#interface MyCustomCell : UITableViewCell
#property (nonatomic, retain) UIButton *theButton;
#property (nonatomic, assign) id<MyCustomCellDelegate> delegate;
#end
MyCustomCell .m file
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
self.theButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.theButton.frame = CGRectMake(10,10,50,30);
[self addSubview:self.theButton];
[self.theButton addTarget:self
action:#selector(theButtonTapped:)
forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
- (void)theButtonTapped:(UIButton *)sender
{
[self.delegate buttonTappedOnCell:self];
}
MyViewController .m file
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"customCell";
MyCustomCell *cell = (MyCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[MyCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.delegate = self;
}
// Configure the cell...
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)buttonTappedOnCell:(MyCustomCell *)selectedCell
{
if (selectedCell) {
NSIndexPath *indexPath = [self.tableView indexPathForCell:selectedCell];
MyModel *selectedModel = [self.model objectAtIndex:indexPath.row];
// do something with the model...
}
}
Store the row of the cell as tag property of your custom button.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// bla bla bla
if (!cell)
{
//bla bla bla
[cell.yourButton addTarget:self selector:#selector(yourButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
}
// bla bla bla
cell.yourButton.tag = indexPath.row;
}
-(void)yourButtonTapped:(id)sender
{
int tag = [(UIButton *)sender tag];
NSLog(#"tapped button in cell at row %i", tag);
}
Using tag, from my point of view, would break the strictness of your code. In addition, when you have multiple sections, using tag definitely would make a mess of your code.
To avoid this problem, you can subclass UITableViewCell and make it hold an indexPath property to let the cell know its precise position.
Another problem here is, if UITableView invokes API to insert or delete row, you have to update visible cells' position data
I don't think that is the best practice.
There exists a better way.
I strongly recommend to use MVVM when you have to handle different touch events in your Cell.
In this pattern, your custom UITableViewCell would hold a custom CellViewModel. This class would be responsible for holding all data you associate with the cell, so you can retrieve the data and put the event handling logic inside the cell.
I have implemented block based approach by subclassing UIButton :
typedef void (^ActionBlock)(id sender);
#interface UIBlockButton : UIButton {
ActionBlock _actionBlock;
}
-(void)handleControlEvent:(UIControlEvents)event withBlock:(ActionBlock) action;
​#end
#implementation UIBlockButton
-(void) handleControlEvent:(UIControlEvents)event withBlock:(ActionBlock) action
{
_actionBlock = action;
[self addTarget:self action:#selector(callActionBlock:) forControlEvents:event];
}
-(void) callActionBlock:(id)sender{
_actionBlock(sender);
}
#end
And in tableview delegate :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (!cell)
{
cell.yourButton.tag = indexPath.row;// pass tag
[cell.yourButton handleControlEvent:UIControlEventTouchUpInside withBlock:^(id sender) {
// your selector action code
NSLog(#"tapped button in cell at row %i",[(UIButton *)sender tag]);
}];
}
}
At some point your button is tapped, and at that point it is a subview of a cell which is a subview of some tableview.
Just write a method that takes a view, goes up the superview chain to find the containing cell, goes further up to find the tableview, and then asks the tableview for the indexPath of the cell.
That is a lot easier and more reliable than storing a tag containing a row, because you don't run into problems when tableview is edited, and it's much better to have code that finds out which indexPath it is when you need the indexPath, and not in some completely unrelated code when the cell is created.
Swift 3.0 Solution
cell.btnRequest.tag = indexPath.row
cell.btnRequest.addTarget(self,action:#selector(buttonClicked(sender:)), for: .touchUpInside)
func buttonClicked(sender:UIButton) {
let buttonRow = sender.tag
}

UITableView with UISegmented control and checkmark accessory

I am a newbie in the world of Objective-C and iOS coding so I'll appreciate a little bit of help.
Here is my issue. I've got a UITableView with a UISegmentedControl. This one has 6 different segments which modify the content of the table by modifying an NSMutableArray. I managed to do that so I'm already pretty proud of me but still the newbie curse is back today. I want to implement checkmarks in order to select cells and pass the cells' data to another UITableView. The first issue is that I've got my checkmarks but I click on a different segment the data are updated but the checkmarks from the previous segment remain. How to address this problem.
Second what is the best way to pass data from all of the segment of this UITableView to another tableview by selecting the cells?
Here is my UITableViewController.h
#class MesExercicesViewController;
#protocol MesExercicesViewControllerDelegate <NSObject>
- (void) mesExercicesViewControllerDidCancel:
(MesExercicesViewController *) controller;
- (void) mesExercicesViewControllerDidSave:
(MesExercicesViewController *)controller;
#end
#interface MesExercicesViewController : UITableViewController {
NSMutableArray *exercicesList;
UISegmentedControl *segment;
}
- (IBAction)segmentChange;
#property (nonatomic, retain) IBOutlet UISegmentedControl *segment;
#property (nonatomic, weak) id <MesExercicesViewControllerDelegate> delegate;
- (IBAction)cancel:(id)sender;
- (IBAction)done:(id)sender;
#end
And here is the code of the UISegmentedControl in the UITableViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
exercicesList = [NSMutableArray arrayWithObjects:
#"A",#"A1",#"A2",#"A3",#"A4",#"A5",#"A6",#"A7", nil];
}
- (IBAction)segmentChange {
if (segment.selectedSegmentIndex == 0) {
exercicesList = [NSMutableArray arrayWithObjects:#"A",#"A1",#"A2",#"A3",#"A4",#"A5",#"A6", nil];
[[self tableView]reloadData];
} else if (segment.selectedSegmentIndex == 1) {
exercicesList = [NSMutableArray arrayWithObjects:#"C",#"C1",#"C2",#"C3",#"C4", nil];
[[self tableView] reloadData];
} else if (segment.selectedSegmentIndex == 2) {
exercicesList = [NSMutableArray arrayWithObjects:#"E",#"E1",#"E2",#"E3",#"E4",#"E5",#"E6",#"E7",#"F",#"F1", nil];
[[self tableView] reloadData];
} else if (segment.selectedSegmentIndex == 3) {
exercicesList = [NSMutableArray arrayWithObjects:#"I",#"I1",#"I2",#"I3",#"I4",#"I5",#"I6",#"I7",#"I8",#"J", nil];
[[self tableView] reloadData];
} else if (segment.selectedSegmentIndex == 4) {
exercicesList = [NSMutableArray arrayWithObjects:#"L",#"M",#"M1",#"N",#"N1", nil];
[[self tableView] reloadData];
} else if (segment.selectedSegmentIndex == 5) {
exercicesList = [NSMutableArray arrayWithObjects:#"R",#"S",#"T",#"U",#"V",#"W",#"X",#"Y",#"Z", nil];
[[self tableView] reloadData];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:[tableView indexPathForSelectedRow] animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
//reflect selection in data model
}else if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
cell.accessoryType = UITableViewCellAccessoryNone;
//reflect the deselection in data model
}
Thank you very much for your help in advance
Firstly, in your cellForRowAtIndexPath set
cell.accessoryType = UITableViewCellAccessoryNone;
this way, whenever you reloadData on your tableView it will get rid of the check marks. You could do this when a new segment is tapped.
2nd Edit
Secondly, set up 2 complimentary methods - in didSelectRow and didDeselectRow. Create a NSMutableArray in your viewDidLoad and then add to it. So your didSelectRow would have:
(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[mutableArray addObject:[exercisesList objectAtIndex:indexPath.row]];
}
and your didDeselectRow would have
(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[mutableArray removeObject:[exercisesList objectAtIndex:indexPath.row]];
}
and as far as the checkmarks go, have you implemented this?
[[self tableView] setEditing:YES animated:YES];
Then you would use this mutableArray to populate the new table.
1st EDIT
Here is some extra detail for how to set the delegate
So lets call the VC that has your original table - OriginalTableViewController
and the VC with the new table that you want to populate from the mutableArray - NextTableViewController (best to stay away from the word 'new' at the start of any names...)
NextTableViewController.h - right after the # import < UIKit/UIKit.h>
#class NextTableViewController;
#protocol NextTableViewControllerDelegate
-(NSMutableArray*)sendThroughTheMutableArray;
#end
declare your delegate
#property (nonatomic, assign) id delegate;
NextTableViewController.m
#synthesize delegate;
Then, you may be familiar with making calls to self like - [self getThatArray]; its the same with a delegate, but you just make the call to delegate instead of self
This is assuming you've declared the myTablePopulatingArray in your h file:
if(delegate != nil)
{
myTablePopulatingArray = [[NSMutableArray Alloc] initWithArray: [delegate sendThroughTheMutableArray]];
}
Basically to this point we have just set up the delegate. We are saying, this is what I need. Who's up for it? Who will volunteer for this job. We put the if(delegate != nil) as a safety - but you are the one who will make sure there is a delegate, so you probably don't really need it
Now for the delegate itself - you only need 2 things:
in your OriginalTableViewController.h file
#import "NextTableViewController.h"
#class DetailViewController;
OriginalTableViewController
in your OriginalTableViewController.m file you must put the method that you declared earlier
-(NSMutableArray*)sendThroughTheMutableArray
{
return mutableArray;
}
so this mutableArray is now ready to populate your tableView.