How can i implemented delete button in AQGridViewCell - iphone

i want to add button in my Customized AQGridViewCell with ImageView. when i Click Edit button its showing delete button on the ImageGridViewCell like below image.i added delete button in cellForItemAtIndex method. here my code
- (AQGridViewCell *) gridView: (AQGridView *) gridView cellForItemAtIndex: (NSUInteger) index
{
static NSString *photoCellIdentifier = #"IBImageGridViewCell";
IBImageGridViewCell *cell = (IBImageGridViewCell *)[self.gridView dequeueReusableCellWithIdentifier:photoCellIdentifier];
if (cell == nil) {
cell = [[IBImageGridViewCell alloc] initWithFrame:CGRectMake(3.0, 3.0, 100.0, 120.0) reuseIdentifier:photoCellIdentifier];
cell.selectionStyle = AQGridViewCellSelectionStyleNone;
}
PTKEntry *entry = [_objects objectAtIndex:index];
UIButton *deletebutton = [UIButton buttonWithType:UIButtonTypeCustom];
[deletebutton addTarget:self
action:#selector(deleteimage:)
forControlEvents:UIControlEventTouchDown];
[deletebutton viewWithTag:index];
deletebutton.frame = CGRectMake(70,0,30,30);
UIImage * buttonImage = [UIImage imageNamed:#"delete.png"];
[deletebutton setImage:buttonImage forState:UIControlStateNormal];
if (self.gridView.editing) {
deletebutton.hidden=NO;
}
else{
deletebutton.hidden=YES;
}
[cell.contentView addSubview:deletebutton];
[cell.contentView bringSubviewToFront:deletebutton];
if (entry.data && entry.data.photo) {
cell.imageView.image = entry.data.photo;
NSLog(#"load table");
} else {
cell.imageView.image = nil;
NSLog(#"Not load table");
}
return cell;
}
when the view loading didn't show delete button. and while click delete button it showing delete for each grid cell and click done button that delete button didn't hidden from my grid View cell view here

You can create delegate method in AQGridView and implement it in your class like
-(void) gridView:(AQGridView *)gridView didSelectItemAtIndex:(NSUInteger)index
This a delegate method approach.
If you create delegate method
-(void) gridView:(AQGridView *)argGridView deleteCell:(AQGridViewCell *)cell atIndex:(NSUInteger)index;
This will get invoked as didSelectItemAtIndex: when you click on delete button.
To do this follow this procedure.
Add a method canHideDelete: to show and hide delete button in your custom cell IBImageGridViewCell.
When you click on a specified cell then [cell canHideDelete:NO] to show delete button.
In your IBImageGridViewCell,
you can create a block to delete a specified cell.
To do this,
create an extension AQGridViewCell_Extension.h to AQGridViewCell like
#import "AQGridViewCell.h"
typedef void(^AQGridViewCellDeleteBlock)(AQGridViewCell*);
#interface AQGridViewCell ()
#property(nonatomic, copy) AQGridViewCellDeleteBlock deleteBlock;
#end
import "AQGridViewCell_Extension.h" in IBImageGridViewCell.m and AQGridView.m
Now, create a selector to handle delete button and call a block to delete cell.
-(void)deleteButtonAction
{
self.deleteBlock(self);
}
Create a delegate method to be implemented in your class to delete cell
Add this to AQGridView.h under #protocol AQGridViewDelegate
-(void) gridView:(AQGridView*) gridView deleteCell:(AQGridViewCell*) cell atIndex:(NSUInteger) index;
Now, in AQGridView.m,
change method
- (AQGridViewCell *) createPreparedCellForIndex: (NSUInteger) index usingGridData: (AQGridViewData *) gridData
{
[UIView setAnimationsEnabled: NO];
AQGridViewCell * cell = [_dataSource gridView: self cellForItemAtIndex: index];
cell.separatorStyle = _flags.separatorStyle;
cell.editing = self.editing;
cell.displayIndex = index;
cell.frame = [self fixCellFrame: cell.frame forGridRect: [gridData cellRectAtIndex: index]];
if ( _backgroundView.superview == self )
[self insertSubview: cell aboveSubview: _backgroundView];
else
[self insertSubview: cell atIndex: 0];
[UIView setAnimationsEnabled: YES];
__block AQGridView *localAQGridView = self;
// DELETE BUTTON BLOCK - TO CALL DELEGATE METHOD
cell.deleteBlock = ^(AQGridViewCell *argCell)
{
NSInteger index = [localAQGridView indexForCell:argCell];
//NSLog(#"Cell to be deleted is %d", index);
[localAQGridView.delegate gridView:localAQGridView deleteCell:argCell atIndex:index];
};
return ( cell );
}
Implement following method to delete a cell in your class
-(void) gridView:(AQGridView *)argGridView deleteCell:(AQGridViewCell *)cell atIndex:(NSUInteger)index
{
NSLog(#"ON deleting cell at %d", index);
[mediaItemsArray removeObjectAtIndex:index];
NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:index];
[argGridView beginUpdates];
[argGridView deleteItemsAtIndices:indexSet withAnimation:AQGridViewItemAnimationFade];
[argGridView endUpdates];
}
I hope this helps you.

Another way of doing it without modifying the AQGridView class
Add a delete button in your IBImageGridViewCell.xib file and Modify your IBImageGridViewCell.h as
#class IBImageGridViewCell;
#protocol CustomGridCellViewDelegate<NSObject>
#optional
-(void) onDeleteButtonTouched:(IBImageGridViewCell *)sender;
#end
#interface IBImageGridViewCell : AQGridViewCell
+ (id) cellFromNib;
#property (nonatomic,assign) id <CustomGridCellViewDelegate> delegate;
#property (nonatomic, readonly, retain) IBOutlet UIView *contentView;
#property (weak, nonatomic) IBOutlet UIButton *deleteButton;
#property (nonatomic, copy) NSString *reuseIdentifier;
- (IBAction)deleteButtonAction:(UIButton *)sender;
#end
In your IBImageGridViewCell.m file add
- (IBAction)deleteButtonAction:(UIButton *)sender
{
[self.delegate onDeleteButtonTouched:self];
}
Now in your mainViewController.h add the delegate
#interface mainViewController : UIViewController<CustomGridCellViewDelegate>
In your mainViewController.m file
In the method
- (AQGridViewCell *) gridView: (AQGridView *) gridView cellForItemAtIndex: (NSUInteger) index
Add
cell.delegate=self;
cell.deleteButton.tag =index;
Handle the delete button action
-(void)onDeleteButtonTouched:(NTGridViewCell *)sender
{
NSLog(#"Selected Button:%d",sender.deleteButton.tag);
[yourArrayList removeObjectAtIndex:sender.deleteButton.tag];
[self.gridView reloadData];
//***Animated delete
// [yourArrayList removeObjectAtIndex:sender.deleteButton.tag];
// NSIndexSet* set = [NSIndexSet indexSetWithIndex:sender.deleteButton.tag];
// [self.gridView beginUpdates];
// [self.gridView deleteItemsAtIndices:set withAnimation:AQGridViewItemAnimationFade];
// [self.gridView endUpdates];
}

Related

Adding values in a table view cell

I have two view controllers. The CardWallet View Controller is my table view. Then the AddCard View Controller is where I input values for a new instance of an object named Card. So far, I am adding those Card instances in an array named myWallet which is in my CardWallet View Controller using a delegate and it works.
What I want is, after clicking the button in my AddCard View Controller, a new table cell will appear in my Card Wallet View, with the name depending on the recently added instance of Card. Below is my code, kindly check why is it that when I'm finished adding a new instance of Card, nothing appears in my table. I've done some research and went through some tutorials, this one is good, http://kurrytran.blogspot.com/2011/10/ios-5-storyboard-and.html, it helped me a lot regarding table view controllers. However, the tutorial doesn't cater my main concern for it's table's values only come from an array with static values.
Thanks!
CardWalletViewController.h
#import <UIKit/UIKit.h>
#interface CardWalletViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
}
#property (nonatomic, strong) NSMutableArray *myWallet;
-(void) printArrayContents;
#end
CardWalletViewController.m
#import "CardWalletViewController.h"
#import "AddCardViewController.h"
#import "Card.h"
#interface CardWalletViewController () <AddCardDelegate>
#end
#implementation CardWalletViewController
#synthesize myWallet = _myWallet;
- (NSMutableArray *) myWallet
{
if (_myWallet == nil) _myWallet = [[NSMutableArray alloc] init];
return _myWallet;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showAddCardVC"]) {
AddCardViewController *addCardVC = (AddCardViewController *)segue.destinationViewController;
addCardVC.delegate = self;
}
}
- (void)printArrayContents
{
// I want to show the name of each instance of card
for ( int i = 0; i < self.myWallet.count; i++) {
Card *cardDummy = [self.myWallet objectAtIndex:i];
NSLog(#"Element %i is %#", i,cardDummy.name );
}
}
- (void)addCardViewController:(AddCardViewController *)sender didCreateCard:(Card *)newCard
{
// insert a new card to the array
[self.myWallet addObject:newCard];
[self printArrayContents];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
// Release any retained subviews of the main view.
}
- (void)viewWillAppear:(BOOL)animated
{
}
- (void)viewWillDisappear:(BOOL)animated
{
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//this method will return the number of rows to be shown
return self.myWallet.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell...
//---------- CELL BACKGROUND IMAGE -----------------------------
UIImageView *imageView = [[UIImageView alloc] initWithFrame:cell.frame];
UIImage *image = [UIImage imageNamed:#"LightGrey.png"];
imageView.image = image;
cell.backgroundView = imageView;
[[cell textLabel] setBackgroundColor:[UIColor clearColor]];
[[cell detailTextLabel] setBackgroundColor:[UIColor clearColor]];
//this will show the name of the card instances stored in the array
//
for ( int i = 0; i < self.myWallet.count; i++) {
Card *cardDummy = [self.myWallet objectAtIndex:i];
cell.textLabel.text = cardDummy.name;
}
//Arrow
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
AddCardViewController.h
#import <UIKit/UIKit.h>
#import "Card.h"
#class AddCardViewController;
#protocol AddCardDelegate <NSObject>
- (void)addCardViewController:(AddCardViewController *)sender
didCreateCard:(Card *) newCard;
#end
#interface AddCardViewController : UIViewController <UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet UITextField *cardNameTextField;
#property (strong, nonatomic) IBOutlet UITextField *pinTextField;
#property (strong, nonatomic) IBOutlet UITextField *pointsTextField;
#property (nonatomic, strong) id <AddCardDelegate> delegate;
#end
AddCardViewController.m
#import "AddCardViewController.h"
#import "Card.h"
#import "CardWalletViewController.h"
#interface AddCardViewController ()
#end
#implementation AddCardViewController
#synthesize cardNameTextField = _cardNameTextField;
#synthesize pinTextField = _pinTextField;
#synthesize pointsTextField = _pointsTextField;
#synthesize delegate = _delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.cardNameTextField becomeFirstResponder];
}
- (void) viewWillDisappear:(BOOL)animated
{
}
- (BOOL) textFieldShouldReturn:(UITextField *)textField{
if ([textField.text length]) {
[self.cardNameTextField resignFirstResponder];
[self.pinTextField resignFirstResponder];
[self.pointsTextField resignFirstResponder];
return YES;
}
else {
return NO;
}
}
- (void)viewDidLoad
{
self.cardNameTextField.delegate = self;
self.pinTextField.delegate = self;
self.pointsTextField.delegate = self;
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setCardNameTextField:nil];
[self setPinTextField:nil];
[self setPointsTextField:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (IBAction)addCard:(id)sender
{
Card *myNewCard = [[Card alloc] init];
myNewCard.name = self.cardNameTextField.text;
myNewCard.pin = self.pinTextField.text;
myNewCard.points = [self.pointsTextField.text intValue];
// to check if the text fields were filled up by the user
if ([self.cardNameTextField.text length] && [self.pinTextField.text length] && [self.pointsTextField.text length])
{
[[self presentingViewController] dismissModalViewControllerAnimated:YES];
NSLog(#"name saved %#", myNewCard.name);
NSLog(#"pin saved %#", myNewCard.pin);
NSLog(#"points saved %i", myNewCard.points);
[self.delegate addCardViewController:self didCreateCard:myNewCard];
// to check if there is a delegate
if (self.delegate){
NSLog(#"delegate is not nil");
}
}
}
#end
Card.h
#import <Foundation/Foundation.h>
#interface Card : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *pin;
#property (nonatomic) int points;
#end
Card.m
#import "Card.h"
#implementation Card
#synthesize name = _name;
#synthesize pin = _pin;
#synthesize points = _points;
#end
I should get the obvious question out of the way before anyone starts dwelling too deep into this - do you have some mechanism of reloading the data after you add a new card (e.g. call [tableView reloadData] from the CardWalletViewController)? I didn't see anything like that, and I've always used this whenever I add something new to a table.*
*If the table contains too much data, you may want to reload only a part of it.
Update 1: Class Inheritance
Every Objective C class has to inherit from some other class in the hierarchy. By default, unless you say otherwise, all of your custom classes will inherit from NSObject, which is the most generic object out there (equivalent of Object, if you've done Java programming). Changing the parent class is done by simply changing the class after the : in your interface declaration. So when you say
#interface CardWalletViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
what you are saying is "declare a CardWallerViewController custom class that inherits from UIViewController and implements the UITableViewDelegate and UITableViewDataSource protocols" (if you don't know what protocols are, ask).
Now, back to your question. Changing the parent class should be easy now - you just change that : UIViewController to : UITableViewController and you are done. After you do this, your CardWallerViewController (also, "Waller", really?) will behave like a UITableView, not like a generic UIView. When doing this, you will also not need to tell it to implement the delegate and dataSource protocols - UITableViewController does that by default.
As a final note, when you add new files to your Xcode project, you can tell the program which class you want to inherit from. It defaults to UIView for views, but that's simply because this is the most generic view class. As you begin to use more specific classes (UITableViewController, UIPickerViewController, UITableViewCell, to name a few), changing the parent class off the bat will prove to be more than helpful.
Update 2: UITableViewCells
That for-loop you've got going there is a (relatively) lot of work you don't need to do. Since your table corresponds directly to your myWallet property, this means that the cell in row N of your table will represent the card at index N of your array. You can use that to your advantage. In the tableView:cellForRowAtIndexPath: method, you tell the program what to do with the cell at the specific indexPath (which is really just section + row for that table). The trick is, this method instantiates the cells one at a time. So instead of doing the for-loop, you can just say (at the end)
cell.textLabel.text = [self.myWallet objectAtIndex:indextPath.row].name;
For any cell in row N, this will look at the Nth Card object inside myWallet and use its name to set the cell's textLabel.text. If it gives you problems, save [self.myWallet objectAtIndex:indextPath.row] in some tempCard object, and then do cell.textLabel.text = tempCard.name. This is also the proper way to populate cells in a tableView - you only care about one cell at a time, because that's how the method works anyway. Imagine if you had 1,000,000 Cards inside your array - doing the for-loop would force the program to go through the array 1,000,000 times for each cell. Say hello to a 1,000,000,000,000 operations :)
i think u can add the imageview as subview to cell
UIImageView *imageView = [[UIImageView alloc] initWithFrame:cell.frame];
UIImage *image = [UIImage imageNamed:#"LightGrey.png"];
imageView.image = image;
[cell addSubview:imageView];
[[cell textLabel] setBackgroundColor:[UIColor clearColor]];
[[cell detailTextLabel] setBackgroundColor:[UIColor clearColor]];

Create a two tableview list using one TableViewController class

I want to do an sample application where in a view i have two buttons one is COUNTRY and another is STATE.
when i click on a country button the country list should appear in a tableview class like a popup and when i click on state button state list should appear in a tableview like popup,So how can i do this please suggest with sample code.
NOTE:I should use only one TableViewcontroller class for both country and state Data list.
Here is the Code:
RootViewController.h
#interface RootViewController : UIViewController {
UIButton *btnCountry;
UIButton *btnState;
NSMutableArray *tempArray;
NSMutableArray *countryArray;
NSMutableArray *stateArray;
IBOutlet UITableView *tempTable;
}
#property (nonatomic,retain) UIButton *btnCountry;
#property (nonatomic,retain) UIButton *btnState;
#property (nonatomic,retain) NSMutableArray *countryArray;
#property (nonatomic,retain) NSMutableArray *stateArray;
#property (nonatomic,retain) NSMutableArray *tempArray;
#property (nonatomic,retain) UITableView *tempTable;
- (IBAction) showState:(id)sender;
- (IBAction) showCountry:(id)sender;
#end
RootViewController.m
#implementation RootViewController
#synthesize btnState,btnCountry, stateArray,countryArray,tempArray;
#synthesize tempTable;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
tempTable.hidden = YES;
countryArray = [[NSMutableArray alloc]initWithObjects:#"India",#"Pakistan",#"USA",nil];
stateArray = [[NSMutableArray alloc]initWithObjects:#"Gujarat",#"Maharashtra", #"Karnataka",nil];
tempArray = [[NSMutableArray alloc]init];
}
- (IBAction) showCountry:(id)sender
{
btnCountry = (UIButton *)sender;
tempArray = countryArray;
[tempTable reloadData];
if([btnCountry isSelected])
{
tempTable.hidden = YES;
btnCountry.selected = NO;
}
else
{
tempTable.hidden = NO;
btnCountry.selected = YES;
}
}
- (IBAction) showState:(id)sender
{
btnState = (UIButton *)sender;
tempArray = stateArray;
[tempTable reloadData];
if([btnState isSelected])
{
tempTable.hidden = YES;
btnState.selected = NO;
}
else
{
tempTable.hidden = NO;
btnState.selected = YES;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tempArray count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [tempArray objectAtIndex:indexPath.row];
return cell;
}
#end
The question is not clear enough ,, what did you try? ..
But, You can use UIPopOverController for that
see
THIS LINK
Or Just a Static UiTableView in the same Nib file ,, make it hidden when you don't need it .
You can use One Tableview for this: Here i am attaching only the logic.
In viewdidload,
There will be two arrays countryArray and stateArray.
There will be a third array : tempArray
there are two buttons: button1 and button2
tableview.hidden=YES;
in button1Action assign the countryArray to tempArray and also [tableview reload]
in button2Action assign the stateArray to tempArray and also [tableview reload]
then in tableview delegates,
(NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
return [tempArray count];
}
and then in
(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
use tempArray.......
}
try this...and if you want more detailed pls inform....
Take Two tableViews and two Buttons.
Place each tableview below each of the button.
Initially both the TableViews are hidden. When the Button is clicked show the TableView with Animation.
I think you should only use one TableViewController but with different data sources.

How to call an action from a Custom UITableViewCell for reload tableView

I have a simple problem: I can't call "[tableView reloadData]" from a UIButton in an UITableViewCell .m.
I have a tableView that show the UITableViewCell that contain a UIButton on each row. When I click on the button of the cell, I want to reloadData from my tableView.
As long as you hold a reference to your tableView, you should be able to reload the data by hitting a button. The easiest way to do this is to make a reference in your header file
#interface MyClass ... {
UITableView *myTableView;
// all your other stuff;
}
// any methods and properties you want to declare;
#end
Then when you put your buttons into the cell in your - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method, do something like the following
UIButton *myButton = [UIButton buttonWithType:whateverTypeYouPick];
[myButton addTarget:self action:#selector(reloadTableView) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:myButton]; // or cell.contentView or wherever you want to place it
Then simply set up your action method
- (IBAction)reloadTableView {
[myTableView reloadData];
// anything else you would like to do;
}
I tested this out and it works fine for me, so hopefully it does the trick for you as well
One of the way would be to have delegate on the Cell and make the tableViewController implement the delegates when the action happens.
MyCell.h
#protocol MyCellDelegate
-(void)myCell:(MyCell*)cell reloadTableView:(id)sender;
#end
#interface MyCell : UITableViewCell
#property (nonatomic, weak) id <MyCellDelegate> delegate;
-(IBAction)reloadTableView:(id)sender;
#end
MyCell.m
#implementation MyCell
#property (nonatomic, weak) id <MyCellDelegate> delegate;
-(IBAction)reloadTableView:(id)sender;
{
if(self.delegate)
{
[self.delegate myCell:self reloadTableView:sender];
}
}
#end
Implement the delegate method in the tableViewController and do the task you want to perform.
-(void)myCell:(MyCell*)cell reloadTableView:(id)sender;
{
CGPoint location = [sender locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
//Here is the indexPath
[self.tableView reloadData];
}

How to achieve similar UI with UITextField inside UITableView (UITableViewCell)?

I am looking to mimic the following UI using a UITextField within a UITableViewCell (within a UITableView). I am new to MonoTouch and I can't seem to figure out what the code would look like for this.
This is very simple. Just add a UITextField with no background color to the cell. Add the below code in your cellForRowAtIndexPath method.
UITextField *inputText = [[UITextField alloc]initWithFrame:CGRectMake(10,10,280,22)];
inputText.textAlignment = UITextAlignmentLeft;
inputText.backgroundColor = [UIColor clearColor];
inputText.placeHolder = #"Street";
[cell.contentView addSubview:inputText];
[inputText release];
The cell is a custom cell. It has some properties, a editable UITextField, and a placehold string for empty content. The following code is writed by hand, so maybe there are some bugs inside.
#interface EditableCell : UITableViewCell {
UITextField *mTextField;
}
#property UITextField *textField;
- (void)setPlaceHoldString:(NSString *)placeHolder;
#end
#implement EditableCell
#synthesize textField = mTextField;
- (void)setPlaceHoldString:(NSString *)placeHolder
{
self.textField.placeHolder = placeHolder;
}
- (UITextField *)textField
{
if (mTextField == nil) {
mTextField = [[UITextField alloc] init];
// Configure this text field.
...
[self addSubView:mTextField];
}
return mTextField;
}
- (void)dealloc
{
self.textField = nil;
[super dealloc];
}
#end

#property not getting set with new value

I'm building an iphone app that uses table views contained within UIViewControllers pushed onto a UINavigation controller (very similar to the Contacts app). When you touch a particular table cell it pushes a new view controller onto the navigation controller to allow you to select a value from a table view list. When you select and touch "save" it pops that view off the stack and moves you back to the first view, where the original table view should show the value you selected.
The problem is that I'm storing the selected value in a #property located in the first view controller, and it doesn't seem to be getting the value that is selected. This is happening in the "setDiff" method. I can log it out and it seems to have been set, but the it's not set when the view renders after the property has been changed.
This is the code for the first view controller (where the selected value from the second view controller will be displayed after it is selected).
/**
*
* ManageWorkoutViewController
*
**/
#class ManageWODiffController;
#interface ManageWorkoutViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
IBOutlet ManageWODiffController *workoutDifficultyController;
IBOutlet UITableView *woTableView;
IBOutlet UITableViewCell *workoutCommentsCell;
IBOutlet UITableViewCell *workoutDifficultyCell;
IBOutlet UITableViewCell *workoutDateCell;
NSString *workoutDifficulty;
NSString *workoutDate;
}
#property (nonatomic, retain) UITableView *woTableView;
#property (nonatomic, retain) NSString *workoutDifficulty;
#property (nonatomic, retain) NSString *workoutDate;
-(void)setupWorkoutAddEdit;
-(void)setDiff:(NSString *)value;
#end
#import "ManageWorkoutViewController.h"
#implementation ManageWorkoutViewController
#synthesize woTableView;
#synthesize workoutDifficulty;
#synthesize workoutDate;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
if (indexPath.row == 0) {
//workout comments
cell = [tableView dequeueReusableCellWithIdentifier:#"workoutCommentsCell"];
if (nil == cell) {
cell = workoutCommentsCell;
cell.selectionStyle = UITableViewCellStyleValue1;
}
}else if (indexPath.row == 1) {
//difficulty
cell = [tableView dequeueReusableCellWithIdentifier:#"workoutDifficultyCell"];
if (nil == cell) {
cell = workoutDifficultyCell;
cell.selectionStyle = UITableViewCellStyleValue1;
cell.textLabel.text = self.workoutDifficulty;
}
}else if (indexPath.row == 2) {
//workoutDate
cell = [tableView dequeueReusableCellWithIdentifier:#"workoutDateCell"];
if (nil == cell) {
cell = workoutDateCell;
cell.selectionStyle = UITableViewCellStyleValue1;
cell.textLabel.text = self.workoutDate;
}
}//end if-else
return cell;
}//end cellForRowAtIndexPath
- (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section {
return 3;
}//end numberOfRowsInSection
-(void)setDiff:(NSString *)value{
self.workoutDifficulty = value;
[woTableView reloadData];
NSLog(#"setter: workoutDifficulty set as: %#", self.workoutDifficulty);
}//end setDiff
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.row) {
case 0:
//do nothing no nav-view here
break;
//DIFFICULTY
case 1:
workoutDifficultyController.title = #"Workout Difficulty";
workoutDifficultyController.originalDifficulty = self.workoutDifficulty;//set the selected difficulty string
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[(UINavigationController *)self.parentViewController pushViewController:workoutDifficultyController
animated:YES];
break;
case 2:
workoutDateController.title = #"Workout Date";
[tableView deselectRowAtIndexPath:indexPath animated:YES];
[(UINavigationController *)self.parentViewController pushViewController:workoutDateController
animated:YES];
break;
default:
break;
}//end switch
}//end didSelectRowAtIndexPath
- (void)viewWillAppear:(BOOL)animated {
//setup the UI to add / edit the workout
[self setupWorkoutAddEdit];
[super viewWillAppear:animated];
}//end viewWillAppear
-(void)setupWorkoutAddEdit{
//load the difficulty
if (nil == self.workoutDifficulty) {
switch ([[workout retrieveValueForKey:#"workoutDifficultyId"] intValue]) {
case 0:
self.workoutDifficulty = #"Easy";
break;
case 1:
self.workoutDifficulty = #"Medium";
break;
case 2:
self.workoutDifficulty = #"Hard";
break;
default:
break;
}
}//end if nil
NSLog(#"workoutDifficulty is: %#", self.workoutDifficulty);
}//end setupWorkoutAddEdit
#end
Here is the code for the ManageWODiffController (where a value is selected from a table view and saved).
/**
*
* ManageWODiffController
*
**/
#class ManageWorkoutViewController;
#interface ManageWODiffController : UIViewController <UITableViewDelegate> {
IBOutlet UITableView *tableView;
IBOutlet UITableViewCell *checkCell;
NSString *selectedDifficulty;
NSString *originalDifficulty;
IBOutlet ManageWorkoutViewController *manageWorkoutController;
}
#property (nonatomic, retain) UITableView *tableView;
#property (nonatomic, retain) NSString *selectedDifficulty;
#property (nonatomic, retain) NSString *originalDifficulty;
-(IBAction)cancelDifficulty:(id)sender;
-(IBAction)saveDifficulty:(id)sender;
#end
#import "ManageWODiffController.h"
#import "ManageWorkoutViewController.h"
#implementation ManageWODiffController
#synthesize tableView;
#synthesize selectedDifficulty;
#synthesize originalDifficulty;
-(IBAction)saveDifficulty:(id)sender {
NSLog(#"[ManageWODiffController.saveDifficulty] returning: %#", self.selectedDifficulty);
[manageWorkoutController setDiff: self.selectedDifficulty];
[(UINavigationController *)self.parentViewController popViewControllerAnimated:YES];
}//end saveDifficulty
-(IBAction)cancelDifficulty:(id)sender { /*...*/ }
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath { /*...*/ }
- (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section { /*...*/ }
#end
You should try to add [self.tableView reloadData] to your viewWillAppear (between the two other statements) in the first controller.
How about this...
...
//difficulty
cell = [tableView dequeueReusableCellWithIdentifier:#"workoutDifficultyCell"];
if (nil == cell) {
cell = workoutDifficultyCell;
cell.selectionStyle = UITableViewCellStyleValue1;
}
cell.textLabel.text = self.workoutDifficulty;
...
Approach with context object:
In your 1st controller, the ManageWorkoutViewController, invent an context object
#property (nonatomic, retain) NSMutableDictonary *workout;
In the table cell where the difficulty is shown it should be picked from
[workout objectForKey:#"Difficulty"];
Do the same in the second controller (ManageWODiffController).
Then in the first one you go like this
//DIFFICULTY
case 1:
ManageWODiffController *diffController = [[ManageWODiffController alloc] initWithNibName:#"ManageWODiffController" bundle:[NSBundle mainBundle]];
diffController.workout = workout;
[[self navigationController] setNavigationBarHidden:NO animated:NO];
[self.navigationController pushViewController:diffController animated:YES];
[diffController release];
diffController = nil;
break;
In the second controller it should be like
-(IBAction)saveDifficulty:(id)sender
{
[workout setObject: selectDifficulty forKey:#"Difficulty"];
}
Then after putting the difficulty in the workout context pop the second controller.
[[self navigationController] popViewControllerAnimated:YES];
If you do so a
[self.tableView reloadData];
in the first controller should be enough to make things work