I have a HabitViewController (UITableViewController) with a button to add cells. When a cell is added its default title is "New Habit". Then the user can tap the cell and a detailViewController appears with a picker to choose the habit. The cell.label.text is then set to the selected option in the picker. This is where my problem is. For example, if i added 3 cells by pressing the button three times, then selected the third row. And then I chose the option Hello World. The top cell would be named hello world, not the third cell. Is this normal? Here is my code:
HabitViewController.h
#import <UIKit/UIKit.h>
#import "DetailViewController.h"
#interface HabitViewController : UITableViewController <DetailViewDelegate> {
}
#property (nonatomic, strong) NSString *cellNameSender;
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#property (strong, nonatomic) NSIndexPath *selectedCell;
#end
.m
#import "HabitViewController.h"
#import "DetailViewController.h"
#interface HabitViewController () {
NSMutableArray *myCells;
}
#property(strong, nonatomic) NSString *cellName2;
#end
#implementation HabitViewController
#synthesize cellNameSender, selectedCell;
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
[self.editButtonItem setTintColor:[UIColor colorWithRed:.33 green:.33 blue:.33 alpha:1]];
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(insertNewObject:)];
self.navigationItem.rightBarButtonItem = addButton;
addButton.tintColor = [UIColor colorWithRed:.33 green:.33 blue:.33 alpha:1];
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"nav_bar.png"] forBarMetrics:UIBarMetricsDefault];
}
- (void)viewDidAppear:(BOOL)animated {
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
- (void)insertNewObject:(id)sender
{
if (!myCells) {
myCells = [[NSMutableArray alloc] init];
}
[myCells insertObject:#"New Habit" atIndex:0];
NSIndexPath *path = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[path] withRowAnimation:UITableViewRowAnimationAutomatic];
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return myCells.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = myCells[indexPath.row];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[myCells removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
}
}
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
DetailViewController *vc = segue.destinationViewController;
vc.delegate = self;
}
#pragma mark - DetailViewDelegate
-(void)setCellName2:(NSString *)cellName {
NSInteger selectedRow = [self.tableView indexPathForSelectedRow].row;
[myCells replaceObjectAtIndex:selectedRow withObject:cellName];
[self.tableView reloadData];
}
#end
DetailViewController.h
#import <UIKit/UIKit.h>
#protocol DetailViewDelegate <NSObject>
- (void)setCellName2:(NSString *)cellName;
#end
#interface DetailViewController : UIViewController<UIPickerViewDelegate> {
NSArray *PickerData;
}
#property (weak, nonatomic) IBOutlet UITextField *habitField;
#property (strong, nonatomic) UIToolbar *toolBar;
#property (weak, nonatomic) id<DetailViewDelegate> delegate;
#property (nonatomic, strong) NSString *cellName;
#property (nonatomic, strong) UIBarButtonItem *backButton;
#property (nonatomic, strong) UIPickerView *Picker;
#property (retain, nonatomic) NSArray *PickerData;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *doneButton;
#property (nonatomic, strong) UIBarButtonItem *barDoneButton;
#property (nonatomic, strong) UIBarButtonItem *flexSpace;
#property (nonatomic, strong) NSString *customHabit;
- (IBAction)backToRoot:(id)sender;
#end
.m
#import "DetailViewController.h"
#import "HabitViewController.h"
#interface DetailViewController () {
}
#end
#implementation DetailViewController
#synthesize PickerData, Picker, toolBar, backButton, barDoneButton, flexSpace;
- (void)viewDidLoad
{
[super viewDidLoad];
self.pickerData = #[#"Posture",#"Paludies Abbs",#"Custom"];
[self.delegate setCellName2:self.cellName];
toolBar = [[UIToolbar alloc] init];
toolBar.barStyle = UIBarStyleBlackOpaque;
[toolBar sizeToFit];
[toolBar setBackgroundImage:[UIImage imageNamed:#"red_navigation_bar.png"] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:self
action:nil];
// Done button on toolbar
barDoneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:#selector(releasePicker)];
// Back button on toolbar
backButton = [[UIBarButtonItem alloc] initWithTitle:#"Back"style:UIBarButtonItemStyleDone
target:self
action:#selector(backToPicker)];
// Habit PickerView
Picker = [[UIPickerView alloc] init];
Picker.showsSelectionIndicator = YES;
Picker.delegate = self;
barDoneButton.image = [UIImage imageNamed:#"button.png"];
// Toolbar above picker
[toolBar setItems:#[flexSpace, barDoneButton] animated:YES];
self.habitField.inputAccessoryView = toolBar;
[self.habitField addTarget:self action:#selector(customHabitChanged) forControlEvents:UIControlEventEditingChanged];
[self.habitField setInputView:Picker];
}
- (void)customHabitChanged {
self.customHabit = self.habitField.text;
self.cellName = self.customHabit;
NSLog(#"%#", self.customHabit);
[self.delegate setCellName2:self.cellName];
}
- (void)backToPicker {
[toolBar setItems:#[flexSpace, barDoneButton] animated:YES];
[self.habitField resignFirstResponder];
[self.habitField setInputView:Picker];
[self.habitField becomeFirstResponder];
}
- (void)releasePicker {
[self.habitField resignFirstResponder];
[self.habitField setInputView:Picker];
[toolBar setItems:#[flexSpace, barDoneButton] animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)backToRoot:(id)sender {
[self.navigationController popToRootViewControllerAnimated:YES];
}
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [PickerData count];
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [PickerData objectAtIndex:row];
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
[self.delegate setCellName2:self.PickerData[row]];
/* int select = row;
if (select == 0) {
self.cellName = #"Posture";
self.habitField.text = #"Posture";
[self.delegate setCellName2:self.cellName];
NSLog(#"%# Is Selected", self.cellName);
}
if (select == 1) {
self.cellName = #"Palaudies Abbs";
self.habitField.text = #"Palaudies Abbs";
[self.delegate setCellName2:self.cellName];
NSLog(#"%# Is Selected", self.cellName);
}
if (select == 2) {
[self.habitField resignFirstResponder];
[self.habitField setInputView:nil];
[self.habitField becomeFirstResponder];
[toolBar setItems:#[backButton, flexSpace, barDoneButton] animated:YES];
self.habitField.text = #"";
self.habitField.placeholder = #"Custom";
[self.delegate setCellName2:self.cellName];
NSLog(#"%# Is Selected", self.cellName);
*/ //}
}
IN cellForRowAtIndexPath
if(indexPath.row == object.count-1)
cell.textLabel.text = #"New Habit";
else
{
NSDate *object = _objects[indexPath.row];
cell.textLabel.text = [object description];
}
return cell;
Your thinking on this is not right. You shouldn't think in terms of setting the title of a cell, but instead think about updating the array that you use to populate the table view with data. Here is a simplified version of your app. When you click the add button it adds a new cell in row 0 with the label's text being "New Habit". When you click on that cell (or any other), it takes you to the controller with the picker view where you choose a string, and that string is passed back to the table view in a delegate method. In that method I update the array, myCells with that passed in string at the correct index gotten from the table's indexPathForSelectedRow, and then call reloadData on the table view to update it's view.
This is the table view controller:
#import "TableController.h"
#import "ViewController.h"
#interface TableController ()
#property (strong,nonatomic) NSMutableArray *myCells;
#end
#implementation TableController
- (IBAction)insertNewObject:(UIBarButtonItem *)sender
{
if (!self.myCells) {
self.myCells = [[NSMutableArray alloc] init];
}
[self.myCells insertObject:#"New Habit" atIndex:0];
NSIndexPath *path = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[path] withRowAnimation:UITableViewRowAnimationAutomatic];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.myCells.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.myCells[indexPath.row];
return cell;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
ViewController *vc = segue.destinationViewController;
vc.delegate = self;
}
-(void)setCellName2:(NSString *)cellName {
NSInteger selectedRow = [self.tableView indexPathForSelectedRow].row;
[self.myCells replaceObjectAtIndex:selectedRow withObject:cellName];
[self.tableView reloadData];
}
Here is the controller (ViewController) with the picker view:
#interface ViewController ()
#property (strong,nonatomic) NSArray *pickerData;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.pickerData = #[#"Posture",#"Paludies Abbs",#"Custom"];
}
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [self.pickerData count];
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [self.pickerData objectAtIndex:row];
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
[self.delegate setCellName2:self.pickerData[row]];
}
Related
I have a tableView where I added a header section. Somehow the header hides the rows... When I remove the header section, the rows are visible. When I add the header section, it hides the rows. Normally the rows shall be visible after the header section. I have no glue why this does not work...
I have a similar tableView and there it works perfectly with the same setup, header and rows are displayed.
The table header section and rows shall be visible at the same time. How can I do this?
Below the code:
LocationViewController.h
#import <UIKit/UIKit.h>
#import "SingletonClass.h"
#import "WebApi.h"
#import <AFNetworking/UIImageView+AFNetworking.h>
#interface LocationViewController : UITableViewController
#property (nonatomic, strong) SingletonClass *sshare;
#property (nonatomic, strong) WebApi *swebapi;
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#property (strong, nonatomic) NSString *locationID;
#end
LocationViewController.m
#import "LocationViewController.h"
#interface LocationViewController ()
#end
#implementation LocationViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
}
return self;
}
- (void)vinit {
self.sshare = [SingletonClass sharedInstance];
self.swebapi = [[WebApi alloc] init];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleNotification:) name:#"reloadDetails" object:nil ];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleNotification:) name:NFlocationReload object:nil ];
}
- (void)viewDidLoad
{
[self vinit];
[self.navigationController setNavigationBarHidden:NO animated:NO];
[super viewDidLoad];
self.tableView.tableFooterView = [[UIView alloc] init];
[self getData];
}
- (void)viewDidAppear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:NO animated:NO];
}
-(void)handleNotification:(NSNotification *)message {
if ([[message name] isEqualToString:#"reloadDetails"]) {
[self.tableView reloadData];
}
if ([[message name] isEqualToString:NFlocationReload]) {
DLog(#"%#, lData", self.sshare.lData);
[self.tableView reloadData];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.sshare.lData.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"locationCell" forIndexPath:indexPath];
NSString *foo = [NSString stringWithFormat:#"row %ld", (long)indexPath.row];
cell.textLabel.text = foo;
DLog(#"logged: %#", foo);
cell.backgroundColor = [UIColor purpleColor];
return cell;
}
-(void)getData {
[self.swebapi getLocationStream:self.locationID];
}
#pragma mark table header image and size
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIImageView *BGView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 10, 320, 174)];
[BGView setBackgroundColor:[UIColor whiteColor]];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 169)];
[imageView setBackgroundColor:[UIColor orangeColor]];
imageView.contentMode = UIViewContentModeScaleAspectFill;
[imageView setClipsToBounds:YES];
NSString *photoURL;
if (self.sshare.imageDetails) {
photoURL = self.sshare.imageDetails.url
[imageView setImageWithURL:[NSURL URLWithString:photoURL] placeholderImage:[UIImage imageNamed:#"foo.jpg"]];
[BGView addSubview:imageView];
}
return BGView;
}
#end
It's missing a delegate method. From the docs on viewForHeaderInSection: ...
The returned object can be a UILabel or UIImageView object, as well as
a custom view. This method only works correctly when
tableView:heightForHeaderInSection: is also implemented.
So add...
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 174;
}
So far I have made a UITableView in a HabitViewControlle with a button to add a new cell. When the cell is tapped, a detialViewController is revealed. In this View their is a textField, that when tapped a UIPicker is launched. I want to set the title of a tableViewCell to the picker selection.. I have made a string called cellName and I can send it to the other ViewController. I also made it so that when the picker is changed, I set the string cellName to the title I want the cell to be when the picker selection is selected. So I almost have it ready, except actually setting the cell title to the string when the cellName is set, and the picker selection has changed. If this didn't make sense, send a comment to me, and I will try to help, because I hard time writing my question into words
habitViewController.h
#import <UIKit/UIKit.h>
#import "DetailViewController.h"
#interface HabitViewController : UITableViewController <DetailViewDelegate> {
UITableViewCell *cell;
}
#end
.m
#import "HabitViewController.h"
#import "DetailViewController.h"
#interface HabitViewController () {
NSMutableArray *_objects;
}
#property(strong, nonatomic) NSString *cellName2;
#end
#implementation HabitViewController
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
[self.editButtonItem setTintColor:[UIColor colorWithRed:.33 green:.33 blue:.33 alpha:1]];
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(insertNewObject:)];
self.navigationItem.rightBarButtonItem = addButton;
addButton.tintColor = [UIColor colorWithRed:.33 green:.33 blue:.33 alpha:1];
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"nav_bar.png"] forBarMetrics:UIBarMetricsDefault];
//if ([cellName isEqualToString:#"Hello World"]) {
// }
}
- (void)viewDidAppear:(BOOL)animated {
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)insertNewObject:(id)sender
{
if (!_objects) {
_objects = [[NSMutableArray alloc] init];
}
[_objects insertObject:[NSDate date] atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _objects.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
NSDate *object = _objects[indexPath.row];
cell.textLabel.text = [object description];
cell.textLabel.text = #"New Habit";
NSLog(#"%#",self.cellName2);
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_objects removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"showDetail"]) {
/* assigning self as delegate, telling the detail view that I implement
* setCellName2:, so it (the detailVC) can call it whenever it wants to.
*/
[segue.destinationViewController setDelegate:self];
}
}
#pragma mark - DetailViewDelegate
// note: this is just a property setter so this is not actually needed
- (void)setCellName2:(NSString *)cellName {
cellName = cellName;
NSLog(#"%#",cellName);
cell.textLabel.text = cellName;
}
#end
DetailViewController.h
#import <UIKit/UIKit.h>
#protocol DetailViewDelegate <NSObject>
- (void)setCellName2:(NSString *)cellName;
#end
#interface DetailViewController : UIViewController<UIPickerViewDelegate> {
NSArray *PickerData;
}
#property (weak, nonatomic) IBOutlet UITextField *habitField;
#property (weak, nonatomic) id<DetailViewDelegate> delegate;
#property (nonatomic, strong) NSString *cellName;
#property (retain, nonatomic) NSArray *PickerData;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *doneButton;
- (IBAction)backToRoot:(id)sender;
#end
.m
#import "DetailViewController.h"
#import "HabitViewController.h"
#interface DetailViewController () {
UITableViewCell *_cell;
}
#end
#implementation DetailViewController
#synthesize PickerData;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSArray *array = [[NSArray alloc] initWithObjects:#"Posture",#"Paludies Abbs",#"Custom", nil];
self.PickerData = array;
[self.delegate setCellName2:self.cellName];
UIToolbar *toolBar = [[UIToolbar alloc] init];
toolBar.barStyle = UIBarStyleBlackOpaque;
[toolBar sizeToFit];
[toolBar setBackgroundImage:[UIImage imageNamed:#"red_navigation_bar.png"] forToolbarPosition:UIToolbarPositionAny barMetrics:UIBarMetricsDefault];
UIBarButtonItem *flexSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:self
action:nil];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:#selector(releasePicker)];
UIPickerView *Picker = [[UIPickerView alloc] init];
Picker.showsSelectionIndicator = YES;
Picker.delegate = self;
doneButton.image = [UIImage imageNamed:#"button.png"];
[toolBar setItems:#[flexSpace, doneButton] animated:YES];
self.habitField.inputAccessoryView = toolBar;
[self.habitField setInputView:Picker];
}
- (void)releasePicker {
[self.habitField resignFirstResponder];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)backToRoot:(id)sender {
[self.navigationController popToRootViewControllerAnimated:YES];
}
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 1;
}
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return [PickerData count];
}
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
return [self.PickerData objectAtIndex:row];
}
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
int select = row;
if (select == 0) {
self.cellName = #"Posture";
[self.view reloadInputViews];
NSLog(#"%# Is Selected", self.cellName);
}
}
#end
I think that you want to use your delegate to set your picker in the didSelectRow method. Like this:
DetailViewController.m:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
int select = row;
if (select == 0) {
self.cellName = #"Posture";
[self.delegate setCellName2:self.cellName];
NSLog(#"%# Is Selected", self.cellName);
}
}
and back in your habitViewController:
- (void)setCellName2:(NSString *)cellName {
cellName = cellName;
NSLog(#"%#",cellName);
selectedCell.textLabel.text = cellName;
[self.tableView reloadData];
}
You also have a few problems with "cell". Assuming you have many rows, this will get re-used over and over again and will always contain the last cell it displayed, which will seldom be what you expect.
I would rename it to selectedCell and set it when the cell is touched and your other view triggered.
#interface HabitViewController : UITableViewController <DetailViewDelegate> {
UITableViewCell *savedCell;
}
I would set it here:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"showDetail"]) {
if ([sender isKindOfClass[UITableViewCell class]]) {
savedCell = (UITableViewCell *)sender;
}
/* assigning self as delegate, telling the detail view that I implement
* setCellName2:, so it (the detailVC) can call it whenever it wants to.
*/
[segue.destinationViewController setDelegate:self];
}
}
I would just use a temp cell in this method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
NSDate *object = _objects[indexPath.row];
cell.textLabel.text = [object description];
cell.textLabel.text = #"New Habit";
NSLog(#"%#",self.cellName2);
return cell;
}
I fixed it with this
First in your habitViewController.h do the following :
#import <UIKit/UIKit.h>
#import "DetailViewController.h"
#interface HabitViewController : UITableViewController <DetailViewDelegate> {
UITableViewCell *cell;
}
#property (nonatomic, strong) NSString *cellNameSender;
#end
Then in your .m replace the code that looks like this with the following :
- (void)setCellName2:(NSString *)cellName {
cellName = cellName;
NSLog(#"%#",cellName);
self.cellNameSender = cellName;
}
#end
and the same with this
- (void)viewDidAppear:(BOOL)animated {
cell.textLabel.text = self.cellNameSender;
}
Now the tableViewCell should show the posture is posture is selected.
I'm trying to add a cell to my table view controller from a modal view controller. My data source array has multiple properties (name, time interval). Right now I have a delegate/protocol in my modal view controller that sends the data to the table view controller. However, for some reason I can add the data to the array but I can't add a cell to the tableview with that data. Here is my code:
ToDoTableViewController.h (TableViewController)
#interface ToDoTableViewController : UITableViewController <UITableViewDataSource, Properties2ViewControllerDelegate>
{
IBOutlet UIView *headerView;
}
#property (strong, nonatomic) NSMutableArray *taskArray;
-(UIView *)headerView;
-(IBAction)addCell:(id)sender;
ToDoTableViewController.m (TableViewController)
-(void) viewDidLoad{
[[self tableView] setDataSource:self];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (!cell)
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"UITableViewCell"];
[[cell textLabel] setText:[taskArray objectAtIndex:[indexPath row]]];
return cell;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [taskArray count];
}
-(IBAction)addCell:(id)sender{
Properties2ViewController *pvc = [[Properties2ViewController alloc]init];
[pvc setDelegate:self];
[self presentViewController:pvc animated:YES completion:NULL];
}
-(UIView *)headerView{
if (!headerView){
[[NSBundle mainBundle] loadNibNamed:#"HeaderView" owner:self options:nil];
}
return headerView;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
return [self headerView];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return [[self headerView] bounds].size.height;
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[self tableView] reloadData];
}
-(void)properties2ViewControllerDidEnterPropertiesSuccesfully:(Tasks *)t{
[taskArray addObject:t];
}
Properties2ViewController.h (ModalViewController)
#class Tasks;
#protocol Properties2ViewControllerDelegate;
#interface Properties2ViewController : UIViewController <UITextFieldDelegate>{
__weak IBOutlet UITextField *taskName;
__weak IBOutlet UIButton *doneButton;
__weak IBOutlet UIDatePicker *datePicker;
__weak IBOutlet UILabel *label1;
__weak IBOutlet UILabel *label2;
}
#property (strong, nonatomic) Tasks *testTask;
#property (weak, nonatomic) id <Properties2ViewControllerDelegate> delegate;
-(IBAction)dismiss:(id)sender;
-(IBAction)cancel:(id)sender;
#end
#protocol Properties2ViewControllerDelegate <NSObject>
#optional
-(void)properties2ViewControllerDidEnterPropertiesSuccesfully:(Tasks *)t;
#end
Properties2ViewController.m (ModalViewController)
-(IBAction)dismiss:(id)sender{
testTask = [[Tasks alloc]initWith:[taskName text] :[datePicker countDownDuration] :[NSDate date]];
if ([self.delegate respondsToSelector:#selector (properties2ViewControllerDidEnterPropertiesSuccesfully:)]){
[self.delegate properties2ViewControllerDidEnterPropertiesSuccesfully:testTask];
}
[self dismissViewControllerAnimated:YES completion:NULL];
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
}
-(BOOL) textFieldShouldReturn:(UITextField *)aTextField{
if (aTextField.tag == 1){
[taskName resignFirstResponder];
}
return YES;
}
-(void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
}
-(IBAction)cancel:(id)sender{
[self dismissViewControllerAnimated:YES completion:NULL];
}
#end
Here are the properties of the Task class...if it helps at all...
#interface Tasks : NSObject
#property (strong, nonatomic) NSString *taskName;
#property NSTimeInterval timeInterval;
#property NSDate *dateCreated;
-(id)initWith:(NSString *)tskNme :(NSTimeInterval)timeInt :(NSDate *)dateCreat;
#end
---EDIT-----
So I tried putting this in my properties2ViewControllerDidEnterPropertiesSuccesfully delegate method but the cell is still not being created...:
-(void)properties2ViewControllerDidEnterPropertiesSuccesfully:(Tasks *)t{
[taskArray addObject:t];
[self.tableView reloadData];
int lastRow = [[self tableView] numberOfRowsInSection:0];
NSIndexPath *ip = [NSIndexPath indexPathForItem:lastRow inSection:0];
[self.tableView cellForRowAtIndexPath:ip];
}
Also, if i switch
[self.tableView cellForRowAtIndexPath:ip];
with
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:ip] withRowAnimation:UITableViewRowAnimationTop];
then an exception is thrown (Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to insert row 0 into section 0, but there are only 0 rows in section 0 after the update')
You might want to try a [tableView reloadData] in
- properties2ViewControllerDidEnterPropertiesSuccesfully
The error you are getting at the end suggests that the entry never makes it into the Array. Can you check the length of your Array after you call [taskArray addObject:t]; ? Also, check the value of the object (t) and see if a proper testTask is actually passed in.
It seems you do not actually create the taskArray, just declare it. Try adding this in your ToDoTableViewControllers viewDidLoad
taskArray = [[NSMutableArray alloc] init];
Im having a problem connecting the different tableViewCells to different UiTableViewControllers. The first cellrow gets connected to the right TableViewController but after that cant get any further because I really dont know how to set the "else if" statement here.
Thanks in advance!
Please see the .m(master):
#import "GuideTableViewController.h"
#import "GuideDetailTableViewController.h"
#import "GuideDetailTableViewController2.h"
#import "GuideDetailTableViewController3.h"
#import <QuartzCore/QuartzCore.h>
#interface GuideTableViewController (){
NSArray *guide;
NSMutableData *weatherResponseData;
}
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (weak, nonatomic) IBOutlet UIImageView *imgHeader;
#property (weak, nonatomic) IBOutlet UIImageView *ImgTitle;
#property (weak, nonatomic) IBOutlet UIImageView *ImgWeather;
#property (weak, nonatomic) IBOutlet UIButton *btnMap;
#property (weak, nonatomic) IBOutlet UILabel *LabelWeather;
#end
#implementation GuideTableViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
//JSON method
- (void) loadJSON{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//code
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"https://dl.dropbox.com/u/100670549/test.json"]];
NSError *error;
if (data)
{
guide = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
for (NSDictionary *dictionary in guide){
//NSLog([dictionary description]);
}
}else
{
NSLog(#"Could not load data");
}
dispatch_sync(dispatch_get_main_queue(), ^{
// code
[self.tableView reloadData];
});
});
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//Call json
[self loadJSON];
[self loadWeather];
//set background
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"background.jpg"]];
//rounded corners
[self.tableView.layer setCornerRadius:9.0];
[self.ImgWeather.layer setCornerRadius:9.0];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//TableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 3;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
NSDictionary *dict = [guide objectAtIndex:indexPath.row];
cell.textLabel.text = [dict valueForKey:#"title"];
return cell;
}
//To detailView
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"showStay"]){
GuideDetailTableViewController *tvc = [segue destinationViewController];
NSIndexPath *index = sender;
NSDictionary *dict = [guide objectAtIndex:index.row];
tvc.stay = dict;
}
else if([segue.identifier isEqualToString:#"showEat"]){
GuideDetailTableViewController2 *tvc = [segue destinationViewController];
NSIndexPath *index = sender;
NSDictionary *dict = [guide objectAtIndex:index.row];
tvc.eat = dict;
}
else if([segue.identifier isEqualToString:#"showDo"]){
GuideDetailTableViewController3 *tvc = [segue destinationViewController];
NSIndexPath *index = sender;
NSDictionary *dict = [guide objectAtIndex:index.row];
tvc.todo = dict;
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self performSegueWithIdentifier:#"showStay" sender:indexPath];
}
- (void) viewWillAppear:(BOOL)animated{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.tableView.indexPathForSelectedRow];
//ta bort markeringen när man går tillbaka till master från detailView.
[cell setSelected:NO];
//Hide navbar
[self.navigationController setNavigationBarHidden:YES];
}
//Show navbar in detailView
-(void)viewWillDisappear:(BOOL)animated{
[self.navigationController setNavigationBarHidden:NO];
}
#end
I have made an a Tabbed Bar Application in Xcode and the First Tab is Decors. I asked a previous question on integrating a XIB Project into a StoryBoard Tabbed Project.
I have Been Successfully in the integration of this, And it works but when I push on one of the Deocrs, Or Table Cells I get the following Error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the "SelectedCellViewController" nib but the view outlet was not set.
If I put the Original Alert into my project The cell linking starts to work again.
Below are pics, links and code to my project, So you can see how it works
StoryBoard Project
XIB Project
DecorsViewController_iPhone.h
#import <UIKit/UIKit.h>
#interface DecorsViewController_iPhone : UIViewController
{
IBOutlet UITableView *tableViewDecors;
NSArray *sitesArray;
NSArray *imagesArray;
}
#property (nonatomic, retain) UITableView *tableViewDecors;
#property (nonatomic, retain) NSArray *sitesArray;
#property (nonatomic, retain) NSArray *imagesArray;
#end
DecorsViewController_iPhone.m
#import "DecorsViewController_iPhone.h"
#import "SelectedCellViewController.h"
#interface DecorsViewController_iPhone ()
#end
#implementation DecorsViewController_iPhone
#synthesize tableViewDecors;
#synthesize sitesArray;
#synthesize imagesArray;
#pragma mark - View lifecycle
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
// Load up the sitesArray with a dummy array : sites
NSArray *sites = [[NSArray alloc] initWithObjects:#"a", #"b", #"c", #"d", #"e", #"f", #"g", #"h", nil];
self.sitesArray = sites;
//[sites release];
UIImage *active = [UIImage imageNamed:#"a.png"];
UIImage *ae = [UIImage imageNamed:#"b.png"];
UIImage *audio = [UIImage imageNamed:#"c.png"];
UIImage *mobile = [UIImage imageNamed:#"d.png"];
UIImage *net = [UIImage imageNamed:#"e.png"];
UIImage *photo = [UIImage imageNamed:#"f.png"];
UIImage *psd = [UIImage imageNamed:#"g.png"];
UIImage *vector = [UIImage imageNamed:#"h.png"];
NSArray *images = [[NSArray alloc] initWithObjects: active, ae, audio, mobile, net, photo, psd, vector, nil];
self.imagesArray = images;
//[images release];
[super viewDidLoad];
}
#pragma mark - Table View datasource methods
// Required Methods
// Return the number of rows in a section
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
return [sitesArray count];
}
// Returns cell to render for each row
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure cell
NSUInteger row = [indexPath row];
// Sets the text for the cell
//cell.textLabel.text = [sitesArray objectAtIndex:row];
// Sets the imageview for the cell
cell.imageView.image = [imagesArray objectAtIndex:row];
// Sets the accessory for the cell
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// Sets the detailtext for the cell (subtitle)
//cell.detailTextLabel.text = [NSString stringWithFormat:#"This is row: %i", row + 1];
return cell;
}
// Optional
// Returns the number of section in a table view
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
#pragma mark -
#pragma mark Table View delegate methods
// Return the height for each cell
-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 78;
}
// Sets the title for header in the tableview
-(NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return #"Decors";
}
// Sets the title for footer
-(NSString *) tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
return #"Decors";
}
// Sets the indentation for rows
-(NSInteger) tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath {
return 0;
}
// Method that gets called from the "Done" button (From the #selector in the line - [viewControllerToShow.navigationItem setRightBarButtonItem:[[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissView)] autorelease]];)
- (void)dismissView {
[self dismissViewControllerAnimated:YES completion:NULL];
}
// This method is run when the user taps the row in the tableview
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
SelectedCellViewController *viewControllerToShow = [[SelectedCellViewController alloc] initWithNibName:#"SelectedCellViewController" bundle:[NSBundle mainBundle]];
[viewControllerToShow setLabelText:[NSString stringWithFormat:#"You selected cell: %d - %#", indexPath.row, [sitesArray objectAtIndex:indexPath.row]]];
[viewControllerToShow setImage:(UIImage *)[imagesArray objectAtIndex:indexPath.row]];
[viewControllerToShow setModalPresentationStyle:UIModalPresentationFormSheet];
[viewControllerToShow setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[viewControllerToShow.navigationItem setRightBarButtonItem:[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissView)]];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewControllerToShow];
viewControllerToShow = nil;
[self presentViewController:navController animated:YES completion:NULL];
navController = nil;
// UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Tapped row!"
// message:[NSString stringWithFormat:#"You tapped: %#", [sitesArray objectAtIndex:indexPath.row]]
// delegate:nil
// cancelButtonTitle:#"Yes, I did!"
// otherButtonTitles:nil];
// [alert show];
// [alert release];
}
#pragma mark - Memory management
- (void)didReceiveMemoryWarning {
NSLog(#"Memory Warning!");
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
self.sitesArray = nil;
self.imagesArray = nil;
[super viewDidUnload];
}
//- (void)dealloc {
//[sitesArray release];
//[imagesArray release];
// [super dealloc];
//}
#end
SelectedCellViewController.h
#interface SelectedCellViewController : UIViewController {
NSString *labelText;
UIImage *image;
IBOutlet UILabel *label;
IBOutlet UIImageView *imageView;
}
#property (nonatomic, copy) NSString *labelText;
#property (nonatomic, retain) UIImage *image;
#end
viewControllerToShow.m
#import "SelectedCellViewController.h"
#implementation SelectedCellViewController
#synthesize labelText;
#synthesize image;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
}
return self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
[label setText:self.labelText];
[imageView setImage:self.image];
}
- (void)viewDidUnload {
self.labelText = nil;
self.image = nil;
//[label release];
// [imageView release];
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
check the class inherited by the "The controller to be shown on click".XIB in the identity inspector .It seems you have not set the class for the "to be shown" XIB and the view outlet of the same XIB.