My Environment is Xcode 6.3, target is iOS8.3 for iPad.
I'm learning the Master-Detail view by using Xcode's template. Some strange problem appears when I try to set a label's text in the detail view:
If I put the statement which changes the label's text in P1 position, it works.
But if I put the statement in P2 position, it doesn't work.
Under both circumstances, the detailDescriptionLabel.text was changed, but only the P1 statement actually update the screen.(I have checked that function configureView() was called both times)
Can anybody helps me? Thanks a lot.
Below are my code snippets:
MasterController.m:
#import "MasterViewController.h"
#import "DetailViewController.h"
#interface MasterViewController ()
#property (copy, nonatomic) NSMutableArray *objects;
#end
#implementation MasterViewController
- (void)awakeFromNib {
[super awakeFromNib];
self.clearsSelectionOnViewWillAppear = NO;
self.preferredContentSize = CGSizeMake(320.0, 600.0);
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *path = [[NSBundle mainBundle] pathForResource:#"PresidentList" ofType:#"plist"];
NSDictionary *presidentInfo = [NSDictionary dictionaryWithContentsOfFile:path];
self.objects = [NSMutableArray arrayWithArray:[presidentInfo objectForKey:#"presidents"]];
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Segues
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"showDetail"]) {
DetailViewController *controller = (DetailViewController *)[[segue destinationViewController] topViewController];
controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
controller.navigationItem.leftItemsSupplementBackButton = YES;
//P1
//controller.detailItem = (self.objects[indexPath.row])[#"url"];
}
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.objects.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = (self.objects[indexPath.row])[#"name"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//P2
//self.detailViewController.detailItem = (self.objects[indexPath.row])[#"url"];
}
#end
DetailController.m:
#import "DetailViewController.h"
#interface DetailViewController ()
#property (strong, nonatomic) UIPopoverController *masterPopoverController;
#end
#implementation DetailViewController
#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem {
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
if (self.masterPopoverController != nil) {
[self.masterPopoverController dismissPopoverAnimated:YES];
}
}
- (void)configureView {
// Update the user interface for the detail item.
if (self.detailItem) {
self.detailDescriptionLabel.text = self.detailItem;
}
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Split view
- (void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc {
barButtonItem.title = NSLocalizedString(#"Master", #"Master");
[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
self.masterPopoverController = pc;
}
- (void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
self.masterPopoverController = nil;
}
#end
I guess you are using segues and that's the point of using the dedicated function (prepareForSegue) designated appositely to initialize values AFTER the view destination view has been anyway created.
Unless you instantiate and show the view by yourself in didSelectRowAtIndexPath there is no point in setting something to such a viewcontroller.
I'm going to guess that self.detailViewController is nil. Hence P2 will not work.
Difficult to say without seeing all the code but in prepareForSegue, you might want to assign it there.
Related
I used the Master - Detail application to create a new project in xcode. Each time I run my program, the rows are not visible in the master view. Thanks in advance! Please check my code below...
MasterViewController.h
#import <UIKit/UIKit.h>
#class DetailViewController;
#interface MasterViewController : UITableViewController
#property (strong, nonatomic) DetailViewController *detailViewController;
#end
MasterViewController.m
#import "MasterViewController.h"
#import "DetailViewController.h"
#interface MasterViewController ()
#property NSMutableArray *objects;
#end
#implementation MasterViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.leftBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButton = [[UIBarButtonItem alloc] ***emphasized text***initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(insertNewObject:)];
self.navigationItem.rightBarButtonItem = addButton;
self.detailViewController = (DetailViewController *) [[self.splitViewController.viewControllers lastObject] topViewController];
}
-(void)viewWillAppear:(BOOL)animated {
self.clearsSelectionOnViewWillAppear = self.splitViewController.isCollapsed;
[super viewWillAppear:animated];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)insertNewObject:(id)sender {
if (!self.objects) {
self.objects = [[NSMutableArray alloc] init];
}
[self.objects insertObject:[NSDate date] atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
#pragma mark - Segues
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"showDetail"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSDate *object = self.objects[indexPath.row];
DetailViewController *controller = (DetailViewController *)[[segue destinationViewController] topViewController];
[controller setDetailItem:object];
controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
controller.navigationItem.leftItemsSupplementBackButton = YES;
}
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section {
return self.objects.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
NSDate *object = self.objects[indexPath.row];
cell.textLabel.text = [object description];
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) {
[self.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.
}
}
#end
DetailViewController.h
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController
#property (strong, nonatomic) id detailItem;
#property (weak, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
#end
DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
#pragma mark - Managing the detail item
-(void)setDetailItem:(id)newDetailItem {
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
-(void)configureView {
// Update the user interface for the detail item.
if (self.detailItem) {
self.detailDescriptionLabel.text = [self.detailItem description];
}
}
-(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
}
-(void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I figured, if you scale the size of the device to 75% and 100%, the rows will display. I guess this has something to do with xcode.
I have developed a storyboard iPhone app and I have one issue that I just can't resolve. I've looked here for answers and googled but still can't find a remedy, thanks in advance for any help or answers.
I have a mainViewController that segues to a viewController with a tableView and single cell. The table displays a list of products populated from an array and navigates to a detailViewController that displays images from another array. The tableView and detail controller are working fine. My issue is the back button on my productViewController. When you first arrive at the product table the back button returns you to the mainViewController, after navigating to the detailViewController the back button return you to the last view and not to the MainViewController. I've tried using segues, IBAction codes etc. When I connect a segue in the storyboard it simply crashes the app. I've used the exact same segues on other viewControllers in the same app and they perform as expected. The problem is only on this one viewController.
#import "productViewController.h"
#import "detailViewController.h"
#import "MainViewController.h"
#interface productViewController ()
{
int _selectedRowNum;
}
#property (strong, nonatomic)NSString *list;
#end
#implementation productViewController
#synthesize images;
#synthesize details;
#synthesize detailTableView;
- (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.
self.productTableView.delegate = self;
self.productTableView.dataSource = self;
images = [[NSArray alloc]initWithObjects:
#"flor-sil",
#"flor-shield",
#"flor-finish",
#"flor-finish-lg",
#"flor-guard",
#"flor-color",
#"pc-5614",
#"rsg",
#"flor-cure",
#"flor-clean", nil];
details = [[NSArray alloc]initWithObjects:
#"sil-detail",
#"flor-shield-detail",
#"finish-detail",
#"finish_lg-detail",
#"ex-detail",
#"color-detail",
#"pc-5614-detail",
#"rsg-detail",
#"flor-cure-detail",
#"flor-clean-detail", nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
This is the next section in the same viewController;
#pragma mark - Table View Delegate
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return images.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"BasicCell";
UITableViewCell *myCell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
long row = indexPath.row;
myCell.imageView.image = [UIImage imageNamed: images[row]];
return myCell;
}
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_selectedRowNum = indexPath.row;
[self performSegueWithIdentifier:#"detailSegue" sender:self];
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
detailViewController *detailVC = segue.destinationViewController;
detailVC.imgName = details [_selectedRowNum];
NSLog(#"Segue");
}
- (IBAction)back:(id)sender {
[self dismissViewControllerAnimated:YES completion:NULL];
}
#end
Other code I've tried;
-(IBAction) back: (id)sender {
[self.navigationController popToRootViewControllerAnimated:YES];
}
Using this code when replacing "self dismissViewController" does nothing. No response.
Maybe I didn't ask it right in the title, sorry for this, i'm a beginner so I will explain myself:
I have 2 screens:
1. Create notes - this screen have a view controller, TextView and navigation(with create/cancel).
2. Notes page - this screen have a table view controller and a navigation with a plus button.
(very similar to apple notes app)
I want that in the table view, whenever I click a cell it will take me back to the editable page of this note...
So I added a push segue from the cell to the notes page, and every time I'm clicking on a cell it opens a NEW note page...
So I know i'm missing something here and would really appreciate if you can help me figure it out
This is my table view controller .m file:
#import "NMNotesListViewController.h"
#import "NMCreateNotesViewController.h"
#interface NMNotesListViewController ()
#property (strong, nonatomic) NSMutableArray *notes;
#end
#implementation NMNotesListViewController
- (IBAction) unwindToList: (UIStoryboardSegue *) segue
{
NMCreateNotesViewController *source = [segue sourceViewController];
NMNote *note = source.note;
if (note != nil) {
[self.notes addObject:note];
[self.tableView reloadData];
}
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.notes = [[NSMutableArray alloc] init];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.notes count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"NotesPrototypeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NMNote *note = [self.notes objectAtIndex:indexPath.row];
cell.textLabel.text = note.content;
return cell;
}
#end
And this is my view controller (create notes) .m file:
#import "NMCreateNotesViewController.h"
#interface NMCreateNotesViewController ()
#property (weak, nonatomic) IBOutlet UIBarButtonItem *createButton;
#property (weak, nonatomic) IBOutlet UITextView *textField;
#end
#implementation NMCreateNotesViewController
- (void)registerForKeyboardNotifications
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWasShown:) name:UIKeyboardDidShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWasShown:(NSNotification*)aNotification {
NSDictionary* info = [aNotification userInfo];
CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
CGRect bkgndRect = self.textField.superview.frame;
bkgndRect.size.height += kbSize.height;
[self.textField.superview setFrame:bkgndRect];
[self.textField setContentOffset:CGPointMake(0.0, self.textField.frame.origin.y-kbSize.height) animated:YES];
}
- (void) keyboardWillBeHidden: (NSNotification *) aNotification
{
UIEdgeInsets contentInsets = UIEdgeInsetsZero;
self.textField.contentInset = contentInsets;
self.textField.scrollIndicatorInsets = contentInsets;
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if (sender != self.createButton) return;
if (self.textField.text.length > 0) {
self.note = [[NMNote alloc] init];
self.note.content = self.textField.text;
}
}
- (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.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
#jeely was close but what you need to do is , create a segue from viewController to viewController.
In the tableView delegate didSelectRowAtIndexPath you would preform the segue:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self performSegueWithIdentifier:#"yourSegue" sender:sender];
}
Because you want to pass the note to the next controller you will need to do that in the prepareForSegue method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"yourSegue"])
{
//get the note
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NMNote *note = [self.notes objectAtIndex:indexPath.row];
//set the note
NMCreateNotesViewController *createVC = (NMCreateNotesViewController*)segue.destinationViewController;
createVC.noteToDisplay = note.content;
}
}
Finally noteToDisplay is just an NSString property that you will set to the textView property once the segue is performed.
I have a tableview controller that is a static table used for request data. When someone selects a row, it displays a new tableview controller with options using a modal segue, the user selects a option and then presses the 'hecho' (done) button and the value should be returned to the first table view controller, but it just not happening. If I inspect the delegate it just says null. What could I be doing wrong?
The story board
First table
AgregarCitaTableViewController.h
#import <UIKit/UIKit.h>
#import "SeleccionarPacienteTableViewController.h"
#interface AgregarCitaTableViewController : UITableViewController <SeleccionarPacienteTableViewControllerDelegate>
#end
AgregarCitaTableViewController.m
#import "AgregarCitaTableViewController.h"
#import "SeleccionarPacienteTableViewController.h"
#interface AgregarCitaTableViewController ()
{
NSDictionary *datosPaciente;
}
#end
#implementation AgregarCitaTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)paciente:(NSDictionary *)paciente
{
datosPaciente = paciente;
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
cell.detailTextLabel.text = [datosPaciente objectForKey:#"nombre"];
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if( [segue.identifier isEqualToString:#"listaPacientes"] )
{
SeleccionarPacienteTableViewController *viewController = segue.destinationViewController;
viewController.delegate = self;
}
}
Second Table
SeleccionarPacienteTableViewController.h
#protocol SeleccionarPacienteTableViewControllerDelegate <NSObject>
-(void)paciente:(NSDictionary *)paciente;
#end
#interface SeleccionarPacienteTableViewController : UITableViewController
{
id delegate;
}
#property(nonatomic,assign)id<SeleccionarPacienteTableViewControllerDelegate> delegate;
#end
SeleccionarPacienteTableViewController.m
#import "SeleccionarPacienteTableViewController.h"
#interface SeleccionarPacienteTableViewController ()
{
NSMutableArray *todosPacientes;
NSDictionary *paciente;
NSInteger checkmarkedRow;
}
#end
#implementation SeleccionarPacienteTableViewController
#synthesize delegate = _delegate;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
UIBarButtonItem *hecho = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(hecho)];
[[self navigationItem] setRightBarButtonItem:hecho];
UIBarButtonItem *cancelar = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(cancelar)];
[[self navigationItem] setLeftBarButtonItem:cancelar];
//Llamada asincrona, cargar las citas
[self performSelectorInBackground:#selector(cargarDatos) withObject:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
// Return the number of rows in the section.
return todosPacientes.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
NSDictionary *object;
object = todosPacientes[indexPath.row];
cell.textLabel.text = [object objectForKey:#"nombre"];
if(checkmarkedRow == indexPath.row){
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Guardar nombre del paciente selccionado
paciente = todosPacientes[indexPath.row];
// In cellForRow... we check this variable to decide where we put the checkmark
checkmarkedRow = indexPath.row;
// We reload the table view and the selected row will be checkmarked
[tableView reloadData];
// We select the row without animation to simulate that nothing happened here :)
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
// We deselect the row with animation
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void) cargarDatos
{
//Path donde se encuentra el plist con los datos
NSString *path = [[NSBundle mainBundle]pathForResource:#"pacientes" ofType:#"plist"];
//Guardamos las citas en un NSMutableArray
todosPacientes = [[NSMutableArray alloc]initWithContentsOfFile:path];
}
- (void) hecho
{
/*Is anyone listening
if([delegate respondsToSelector:#selector(paciente:)])
{
//send the delegate function with the amount entered by the user
[delegate paciente:paciente];
}*/
[self.delegate paciente:paciente];
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void) cancelar
{
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
Solution:
Im not really sure how it worked or even if this is the real solution. I used the anwer of Hani Ibrahim and it didn't work but what he said was right. Then i just changed [delegate paciente:paciente] in the hecho method for [self.delegate paciente:paciente] and it worked.
I hope this can help someone.
The problem is that your seque display UINavigationController and not SeleccionarPacienteTableViewController
Change this method
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if( [segue.identifier isEqualToString:#"listaPacientes"] )
{
SeleccionarPacienteTableViewController *viewController = segue.destinationViewController;
viewController.delegate = self;
}
}
to be
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if( [segue.identifier isEqualToString:#"listaPacientes"] )
{
UINavigationController *navController = segue.destinationViewController;
SeleccionarPacienteTableViewController *viewController = [navController.viewControllers objectAtIndex:0];
viewController.delegate = self;
}
}
You have another problem
When doing this
#property(nonatomic,assign)id<SeleccionarPacienteTableViewControllerDelegate> delegate;
and this
#synthesize delegate = _delegate;
Then Your property will work with an instance variable called '_delegate' as you are saying #synthesize delegate = _delegate;
However this code
#interface SeleccionarPacienteTableViewController : UITableViewController
{
id delegate;
}
defines a new instance variable called delegate which is completely different than your property
So to access your property you can use self.delegate or _delegate and NOT delegate as it is another instance variable !
I think the problem is in prepareForSegue. The destinationViewController is a UINavigationController and not a SeleccionarPacienteTableViewController.
You have to access the first child of the destinationViewController to get your SeleccionarPacienteTableViewController.
Replacing segue.destinationViewController with [segue.destinationViewController topViewController] will probably solve your problem.
I am following this tutorial which helps a lot a beginner like me.
There are 2 screens, Players (which displays a list of players) and PlayerDetails(which displays details about a player and also allows adding a new one)
This is the code
#import <UIKit/UIKit.h>
#import "PlayerDetailsViewController.h"
#interface PlayersViewController : UITableViewController<PlayerDetailsViewControllerDelegate>
#property (nonatomic, strong) NSMutableArray *players;
#end
#import "Player.h"
#import "PlayerCell.h"
#import "PlayersViewController.h"
#class PlayerDetailsViewController;
#interface PlayersViewController ()
#end
#implementation PlayersViewController
#synthesize players;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.players count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
PlayerCell *cell = (PlayerCell *)[tableView dequeueReusableCellWithIdentifier:#"PlayerCell"];
Player *player = [self.players objectAtIndex:indexPath.row];
cell.nameLabel.text = player.name;
cell.gameLabel.text = player.game;
cell.ratingImageView.image = [self imageForRating:player.rating];
return cell;
}
- (UIImage *)imageForRating:(int)rating
{
switch (rating)
{
case 1: return [UIImage imageNamed:#"1StarSmall.png"];
case 2: return [UIImage imageNamed:#"2StarsSmall.png"];
case 3: return [UIImage imageNamed:#"3StarsSmall.png"];
case 4: return [UIImage imageNamed:#"4StarsSmall.png"];
case 5: return [UIImage imageNamed:#"5StarsSmall.png"];
}
return nil;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[self.players removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
/*
// 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;
}
*/
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
*/
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"AddPlayer"])
{
UINavigationController *navigationController = segue.destinationViewController;
PlayerDetailsViewController *playerDetailsViewController = [[navigationController viewControllers] objectAtIndex:0];
playerDetailsViewController.delegate=self;
}
}
-(void) playerDetailsViewControllerDidCancel:(PlayerDetailsViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)playerDetailsViewController: PlayerDetailsViewController *)controller didAddPlayer:(Player *)player
{
[self.players addObject:player];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:[self.players count] - 1 inSection:0];
[self.tableView insertRowsAtIndexPaths: [NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
#import <UIKit/UIKit.h>
#import "Player.h"
#class PlayerDetailsViewController;
#protocol PlayerDetailsViewControllerDelegate<NSObject>
-(void)playerDetailsViewControllerDidCancel:(PlayerDetailsViewController*) controller;
-(void)playerDetailsViewController:(PlayerDetailsViewController *)controller didAddPlayer:(Player *)player;
#end
#interface PlayerDetailsViewController : UITableViewController
#property (strong, nonatomic) IBOutlet UITextField *nameTextField;
#property (strong, nonatomic) IBOutlet UILabel *detailLabel;
- (IBAction)cancel:(id)sender;
- (IBAction)done:(id)sender;
#property(weak, nonatomic) id<PlayerDetailsViewControllerDelegate> delegate;
#end
#import "PlayerDetailsViewController.h"
#class Player;
#interface PlayerDetailsViewController ()
#end
#implementation PlayerDetailsViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.section==0)
{
[self.nameTextField becomeFirstResponder];
}
}
- (IBAction)cancel:(id)sender
{
[self.delegate playerDetailsViewControllerDidCancel:self];
}
- (IBAction)done:(id)sender
{
Player *player = [[Player alloc] init];
player.name = self.nameTextField.text;
player.game = #"Chess";
player.rating = 1;
[self.delegate playerDetailsViewController:self didAddPlayer:player];
}
#end
Issue:
In PlayersViewController.m, on the following method:
-(void)playerDetailsViewController:PlayerDetailsViewController *)controller didAddPlayer:(Player *)player
I get the following error messages
Expected method body
Use of undeclared identifier player
What am i doing wrong?
You're missing an opening parenthesis:
-(void)playerDetailsViewController: PlayerDetailsViewController *)controller ...
should be:
-(void)playerDetailsViewController:(PlayerDetailsViewController *)controller ...