When I hit an element in my tableView it comes up with an error. I have checked all of the connections but still cant work it out. Here is my code
#import "CGViewController.h"
#import "CGAppDelegate.h"
#import "sls.h"
#import "patientController.h"
#interface CGViewController ()
#end
#implementation CGViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Patients";
CGAppDelegate *delegate =
(CGAppDelegate *)[[UIApplication sharedApplication] delegate];
patients = delegate.patients;
self.navigationItem.rightBarButtonItem = self.editButtonItem;
UIBarButtonItem *addButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(add:)];
self.navigationItem.leftBarButtonItem = addButtonItem;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark UITableViewDataSource Methods
- (UITableViewCell *)tableView:(UITableView *)tv
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:#"cell"];
if( nil == cell) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"cell"];
}
if (indexPath.row < patients.count) {
sls *thissls = [patients objectAtIndex:indexPath.row];
cell.textLabel.text = thissls.patientName;
}
else {
cell.textLabel.text = #"";
cell.textLabel.textColor = [UIColor lightGrayColor];
}
return cell;
}
-(void)setEditing:(BOOL)editing animated:(BOOL)animated {
if ( editing != self.editing) {
[super setEditing:editing animated:animated];
[self.tableView setEditing:editing animated:animated];
NSArray *indexes =
[NSArray arrayWithObject:
[NSIndexPath indexPathForRow:patients.count inSection:0]];
if ( editing == YES ) {
[self.tableView insertRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationLeft];
} else {
[self.tableView deleteRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationLeft];
}
}
[self.tableView reloadData];
}
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row < patients.count ) {
return UITableViewCellEditingStyleDelete;
}
else {
return UITableViewCellEditingStyleNone;
}
}
- (NSInteger)tableView:
(UITableView *)tv numberOfRowsInSection:
(NSInteger)section {
NSInteger count = patients.count;
if (self.editing) {
count = count + 1;
}
return count;
}
-(void)tableView:(UITableView *)tv didSelectRowAtIndexPath:
(NSIndexPath *)indexPath {
CGAppDelegate *delegate =
(CGAppDelegate *)[[UIApplication sharedApplication] delegate];
patientController *patient = [[patientController alloc] init];
[delegate.navController pushViewController:patient animated: YES];
[tv deselectRowAtIndexPath:indexPath animated: YES];
}
-(void) tableView:(UITableView *)tv
commitEditingStyle:(UITableViewCellEditingStyle)editing forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editing == UITableViewCellEditingStyleDelete) {
[patients removeObjectAtIndex:indexPath.row];
[tv deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationLeft];
}
}
#end
Any ideas on what is wrong if you know please can you help as soon as possible as i am on a deadline
Thanks in advance.
The error says Thread 1:signal SIGABRT
The error is in main.m
#import <UIKit/UIKit.h>
#import "CGAppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([CGAppDelegate class]));
}
}
it says that the error is here
patientController *patient = [[patientController alloc] init];
here is my patientController.h file
#import <UIKit/UIKit.h>
#interface patientController : UIViewController {
NSIndexPath *index;
IBOutlet UIImageView * pictureView;
IBOutlet UILabel * descriptionView1;
IBOutlet UILabel * descriptionView2;
IBOutlet UILabel * descriptionView3;
}
- (id)initwithIndexPath:(NSIndexPath *)indexPath;
#end
and my .m file
#import "patientController.h"
#import "CGAppDelegate.h"
#import "sls.h"
#interface patientController ()
#end
#implementation patientController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
CGAppDelegate *delegate =
(CGAppDelegate *)[[UIApplication sharedApplication] delegate];
sls *thissls = [delegate.patients objectAtIndex:index.row];
self.title = thissls.patientName;
self->descriptionView1.text = thissls.patientName;
self->descriptionView2.text = thissls.surnameName;
self->descriptionView3.text = thissls.dateOfBirth;
self->pictureView.image = thissls.patientImage;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (id)initwithIndexPath:(NSIndexPath *)indexPath {
if ( (self == [super init]) ) {
index = indexPath;
}
return self;
}
#end
Please can anyone at all help
Use:
[self.navigationController pushViewController:patient animated: YES];
If you are currently in a navigationController (which you have to in order to push a new ViewController), then you can push your new controller by just calling these lines
-(void)tableView:(UITableView *)tv didSelectRowAtIndexPath:
(NSIndexPath *)indexPath {
patientController *patient = [[patientController alloc] init];
[self.navigationController pushViewController:patient animated: YES];
}
Use
[self.navController pushViewController:patient animated: YES];
Every viewcontroller has its navigation controller reference in itself,no need to call the application delegate to invoke it[The navigation controller Must be initialised and all the viewcontrollers must be pushed into the navigation stack until this one to make it work]
So use this to setup the navigation controller in the appdelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Note : this is an example set like this with your viewcontroller instance
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_iPhone" bundle:nil];
} else {
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController_iPad" bundle:nil];
}
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
[self.window makeKeyAndVisible];
return YES;
}
To check where your exception is raised, in Xcode, in the breakpoints navigation tab click on the plus button in the bottom-left corner and add an Exceptions Breakpoint. Then run the app from Xcode. The next time an exception is raised, as in your case, the execution of your app will stop and Xcode will point at the line of code where the exception is raised.
Anyway, to make you understand how navigationControllers work:
UINavigationController is a UIViewController that controls a stack of other UIViewController instances. This other view controllers are said to be in the 'navigation stack'. The top item in the navigation stack is the view controller whose view you see at a given time onto the screen. You can push (present) or pop (dismiss) a view controller on/from the navigation stack.
A UINavigationController is initialized with a 'rootViewController' which is going to be it's first view controller onto the stack and therefore the first you see when you add the navigationController onto the screen (e.g. by setting it as the appDelegate window's rootViewController). Each UIViewController on the navigation stack references it's navigationController through the property 'navigationController'.
At any given point, you can use the UINavigationController methods pushViewController:animated: and popViewControllerAnimated: or popToViewController:animated: or popToRootViewControllerAnimated: to add or remove viewControllers from the navigationStack. To see the results of this methods, of course, you should have the navigationController on screen.
For more informations refer to the UINavigationController Class Reference.
Related
I'm trying to disable the swipe back gesture, so that swiping back in my detail view will not open the master view.
I'm aware that this question and this question exist, but I have tried all the solutions suggested and none of them have worked for me. It may be because I am on iOS 11.
To demonstrate the issue, I've created a new master-detail project in Xcode and only added the solutions which I saw in the linked questions, which is adding this:
self.splitViewController.presentsWithGesture = NO;
To the viewDidLoad of the MasterViewController and adding this
- (void)viewWillLayoutSubviews {
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
}
To the DetailViewController
MasterViewController
#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] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(insertNewObject:)];
self.navigationItem.rightBarButtonItem = addButton;
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
self.splitViewController.presentsWithGesture = NO;
}
- (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
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
- (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)viewWillLayoutSubviews {
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.navigationController.interactivePopGestureRecognizer.enabled = NO;
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
}
#pragma mark - Managing the detail item
- (void)setDetailItem:(NSDate *)newDetailItem {
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
#end
AppDelegate
#import "AppDelegate.h"
#import "DetailViewController.h"
#interface AppDelegate () <UISplitViewControllerDelegate>
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem;
splitViewController.delegate = self;
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
#pragma mark - Split view
- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
if ([secondaryViewController isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[DetailViewController class]] && ([(DetailViewController *)[(UINavigationController *)secondaryViewController topViewController] detailItem] == nil)) {
// Return YES to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
return YES;
} else {
return NO;
}
}
#end
How do I disable the swipe back feature?
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
This line definitely worked for me. Anyway, I suggest you moving it to the viewDidLoad function so it is executed just once.
For Objective-C :
- (void)viewWillAppear:(BOOL)animated {
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.enabled = NO;
}
}
For Swift:
self.navigationController?.interactivePopGestureRecognizer?.isEnabled = false
But it is not recommended.
Find similar question
I figured it out. I had to add this to my DetailViewController
id savedGestureRecognizerDelegate1;
id savedGestureRecognizerDelegate2;
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
savedGestureRecognizerDelegate1 = self.navigationController.interactivePopGestureRecognizer.delegate;
self.navigationController.interactivePopGestureRecognizer.delegate = self;
}
if ([self.navigationController.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
savedGestureRecognizerDelegate2 = self.navigationController.navigationController.interactivePopGestureRecognizer.delegate;
self.navigationController.navigationController.interactivePopGestureRecognizer.delegate = self;
}
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if ([self.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.interactivePopGestureRecognizer.delegate = savedGestureRecognizerDelegate1;
}
if ([self.navigationController.navigationController respondsToSelector:#selector(interactivePopGestureRecognizer)]) {
self.navigationController.navigationController.interactivePopGestureRecognizer.delegate = savedGestureRecognizerDelegate2;
}
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer == self.navigationController.interactivePopGestureRecognizer || gestureRecognizer == self.navigationController.navigationController.interactivePopGestureRecognizer) {
return NO;
}
return YES;
}
This is because there's two navigation controllers in a split view controller. The saved gesture recognizer delegate is because of this.
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've been toying around with state restoration. In the code below, the scroll position of the UITableViewController gets restored, however, if I were to tap through into the detail view (pushing an instance of MyViewController onto the navigation stack), when the app restarts, it always returns to the first view controller in the navigation stack (i.e. MyTableViewController). Would somebody be able to help me restore to the correct view controller (i.e. MyOtherViewController)?
AppDelegate.m
- (BOOL)launchWithOptions:(NSDictionary *)launchOptions
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
MyTableViewController *table = [[MyTableViewController alloc] initWithStyle:UITableViewStylePlain];
table.depth = 0;
UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:table];
navCon.restorationIdentifier = #"navigationController";
self.window.rootViewController = navCon;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
});
return YES;
}
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return [self launchWithOptions:launchOptions];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
return [self launchWithOptions:launchOptions];
}
MyTableViewController.m
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if(self)
{
self.restorationIdentifier = #"master";
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Master";
self.tableView.restorationIdentifier = #"masterView";
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 5;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [NSString stringWithFormat:#"Section %d", section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:#"%d", indexPath.row];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
MyOtherViewController *vc = [[MyOtherViewController alloc] initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:vc animated:YES];
}
MyOtherViewController.m
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.restorationIdentifier = #"detail";
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Detail";
self.view.backgroundColor = [UIColor redColor];
self.view.restorationIdentifier = #"detailView";
}
Because you are creating your detail view controller in code, and not instantiating it from a Storyboard, you need to implement a restoration class, so the system restoration process knows how to create the detail view controller.
A restoration class is really just a factory which knows how to create a specific view controller from a restoration path. You don't actually have to create a separate class for this, we can just handle it in MyOtherViewController:
in MyOtherViewController.h, implement the protocol: UIViewControllerRestoration
Then when you set the restorationID in MyOtherViewController.m, also set the restoration class:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.restorationIdentifier = #"detail";
self.restorationClass = [self class]; //SET THE RESTORATION CLASS
}
return self;
}
You then need to implement this method in the restoration class (MyOtherViewController.m)
+(UIViewController *) viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
{
//At a minimum, just create an instance of the correct class.
return [[MyOtherViewController alloc] initWithNibName:nil bundle:nil];
}
That gets you as far as the restoration subsystem being able to create and push the Detail View controller onto the Navigation Stack. (What you initially asked.)
Extending the Example to handle state:
In a real app, you'd need to both save the state and handle restoring it... I added the following property definition to MyOtherViewController to simulate this:
#property (nonatomic, strong) NSString *selectedRecordId;
And I also modified MyOtherViewContoller's viewDidLoad method to set the Detail title to whatever record Id the user selected:
- (void)viewDidLoad
{
[super viewDidLoad];
// self.title = #"Detail";
self.title = self.selectedRecordId;
self.view.backgroundColor = [UIColor redColor];
self.view.restorationIdentifier = #"detailView";
}
To make the example work, I set selectedRecordId when initially pushing the Detail View from MyTableViewController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
MyOtherViewController *vc = [[MyOtherViewController alloc] initWithNibName:nil bundle:nil];
vc.selectedRecordId = [NSString stringWithFormat:#"Section:%d, Row:%d", indexPath.section, indexPath.row];
[self.navigationController pushViewController:vc animated:YES];
}
The other missing piece are the methods in MyOtherViewController, your detail view, to save the state of Detail controller.
-(void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
[coder encodeObject:self.selectedRecordId forKey:#"selectedRecordId"];
[super encodeRestorableStateWithCoder:coder];
}
-(void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
self.selectedRecordId = [coder decodeObjectForKey:#"selectedRecordId"];
[super decodeRestorableStateWithCoder:coder];
}
Now this actually doesn't quite work yet. This is because the "ViewDidLoad" method is called on restoration before the decoreRestorablStateWithCoder method is. Hence the title doesn't get set before the view is displayed. To fix this, we handle either set the title for the Detail view controller in viewWillAppear: , or we can modify the viewControllerWithRestorationIdentifierPath method to restore the state when it creates the class like this:
+(UIViewController *) viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
{
MyOtherViewController *controller = [[self alloc] initWithNibName:nil bundle:nil];
controller.selectedRecordId = [coder decodeObjectForKey:#"selectedRecordId"];
return controller;
}
That's it.
A few other notes...
i presume you did the following in your App Delegate even though i didn't see the code?
-(BOOL) application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder
{
return YES;
}
- (BOOL) application:(UIApplication *)application shouldRestoreApplicationState:(NSCoder *)coder
{
return YES;
}
I saw a bit of flakiness when running the demo code in the simulator with it correctly preserving the Scroll offset. It seemed to work occasionally for me, but not all the time. I suspect this may be because really restoration of MyTableViewController should also use a restorationClass approach, since it's instantiated in code. However I haven't tried that out yet.
My testing method, was to put the app in the background by returning to springboard (required for the app state to be saved.) , then relaunching the app from within XCode to simulate a clean start.
the only problem with your code is navigation controller
these two lines
UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:table];
navCon.restorationIdentifier = #"navigationController";
i dont know why navigation controller never get its restoration class. i had the same problem. i found some alternative solution to create a navigation controller stand alone in storyboard and use that.
here is code
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle:nil];
UINavigationController* navigationController = [storyboard
instantiateViewControllerWithIdentifier:
#"UINavigationController"];
navigationController.viewControllers = #[myController];
it will work fine .
just follow this http://petr-pavlik.squarespace.com/blog/2013/6/16/stare-restoration-without-storyboard
Since you are doing this in code and not via Storyboard, you will need to provide not only a restorationIdentifier but also a restorationClass to you detail view controller.
You could leave it unassigned in which case -(UIViewController *)application:(UIApplication *)application viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder gets called on the application delegate to make the object (view controller with a restorationIdentifier but no restorationClass).
Try the following (please note the UIViewControllerRestoration protocol):
#interface MyViewController ()<UIViewControllerRestoration>
#end
#implementation
- (id)init
{
self = [super init];
if (self) {
// Custom initialization
}
if( [self respondsToSelector:#selector(restorationIdentifier)] ){
self.restorationIdentifier = #"DetailViewController";
self.restorationClass = [self class];
}
return self;
}
#pragma mark - State restoration
+ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents coder:(NSCoder *)coder
{
UIViewController *viewController = [[self alloc] init];
return viewController;
}
#end
Also note that this is a very simple example, usually you might have a lot more interesting things going on in -viewControllerWithRestorationIdentifierPath:coder:
I am using Apple's MuiltipleDetailViewController sample app and get the message "UIViewController may not respond to showRootPopoverButtonItem"
This worked in XCode 3.X, but I get the message with 4.2
The app itself functions 100%, the popover is recognized in every nib, as is the table on the left when in landscape mode. But I can't submit with this warning. What do I need to change??
RootViewController.h
#import <UIKit/UIKit.h>
/*
SubstitutableDetailViewController defines the protocol that detail view controllers must adopt. The protocol specifies methods to hide and show the bar button item controlling the popover.
*/
#protocol SubstitutableDetailViewController <NSObject>
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem;
#end
#interface RootViewController : UITableViewController <UISplitViewControllerDelegate> {
UISplitViewController *splitViewController;
UIPopoverController *popoverController;
UIBarButtonItem *rootPopoverButtonItem;
//UINavigationBar *navigationBar;
}
#property (nonatomic, assign) IBOutlet UISplitViewController *splitViewController;
#property (nonatomic, retain) UIPopoverController *popoverController;
#property (nonatomic, retain) UIBarButtonItem *rootPopoverButtonItem;
//#property (nonatomic, retain) IBOutlet UINavigationBar *navigationBar;
#end
RootViewController.m:
#import "RootViewController.h"
#import "WebViewController.h"
#import "Twitter.h"
//#import "SubstitutableDetailViewController.h"
#implementation RootViewController
#synthesize splitViewController, popoverController, rootPopoverButtonItem;//, navigationBar;
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
// Set the content size for the popover: there are just two rows in the table view, so set to rowHeight*2.
self.contentSizeForViewInPopover = CGSizeMake(310.0, self.tableView.rowHeight*2.0);
//self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:255/255 green:104/255 blue:1/255 alpha:1];
}
/*
-(void)customizeAppearance {
//create resizable images
UIImage *bluImage = [UIImage imageNamed:#"blu.jpg"];// resizableImageWithCapInsets:(0, 0, 0, 0)];
//set the bg for *all* UINavBars
[[UINavigationBar appearance] setBackgroundImage:bluImage forBarMetrics:UIBarMetricsDefault];
}
*/
-(void) viewDidUnload {
[super viewDidUnload];
self.splitViewController = nil;
self.rootPopoverButtonItem = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
- (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem
forPopoverController:(UIPopoverController*)pc {
// Keep references to the popover controller and the popover button, and tell the detail view controller to show the button.
barButtonItem.title = #"Index";
self.popoverController = pc;
self.rootPopoverButtonItem = barButtonItem;
UIViewController <SubstitutableDetailViewController> *detailViewController = [splitViewController.viewControllers objectAtIndex:1];
[detailViewController showRootPopoverButtonItem:rootPopoverButtonItem];
}
- (void)splitViewController:(UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController
invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
// Nil out references to the popover controller and the popover button, and tell the detail view controller to hide the button.
UIViewController <SubstitutableDetailViewController> *detailViewController = [splitViewController.viewControllers objectAtIndex:1];
[detailViewController invalidateRootPopoverButtonItem:rootPopoverButtonItem];
self.popoverController = nil;
self.rootPopoverButtonItem = nil;
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section {
// Two sections, one for each detail view controller.
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"RootViewControllerCellIdentifier";
// Dequeue or create a cell of the appropriate type.
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
//cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Set appropriate labels for the cells.
if (indexPath.row == 0) {
cell.textLabel.text = #"Twitter";
}
else if (indexPath.row == 1) {
cell.textLabel.text = #"Contact Us";
}
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor blackColor];
cell.contentView.backgroundColor = [UIColor blackColor];
cell.detailTextLabel.backgroundColor = [UIColor blackColor];
return cell;
}
#pragma mark -
#pragma mark Table view selection
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
/*
Create and configure a new detail view controller appropriate for the selection.
*/
NSUInteger row = indexPath.row;
UIViewController *detailViewController = nil;
if (row == 0) {
Twitter *newDetailViewController = [[Twitter alloc]
initWithNibName:#"Twitter"
bundle:nil];
detailViewController = newDetailViewController;
}
if (row == 1) {
WebViewController *newDetailViewController = [[WebViewController alloc]
initWithNibName:#"WebViewController"
bundle:nil];
newDetailViewController.detailURL=
[[NSURL alloc] initWithString:#"http://www.chipmunkmobile.com/contact.html"];
detailViewController = newDetailViewController;
}
// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
[viewControllers release];
// Dismiss the popover if it's present.
if (popoverController != nil) {
[popoverController dismissPopoverAnimated:YES];
}
// Configure the new view controller's popover button (after the view has been displayed and its toolbar/navigation bar has been created).
if (rootPopoverButtonItem != nil) {
[detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
}
[detailViewController release];
}
#pragma mark -
#pragma mark Managing the popover
/*
- (void)showRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Add the popover button to the left navigation item.
[navigationBar.topItem setLeftBarButtonItem:barButtonItem animated:NO];
}
- (void)invalidateRootPopoverButtonItem:(UIBarButtonItem *)barButtonItem {
// Remove the popover button.
[navigationBar.topItem setLeftBarButtonItem:nil animated:NO];
}
*/
#pragma mark -
#pragma mark Memory management
- (void)dealloc {
[popoverController release];
[rootPopoverButtonItem release];
[super dealloc];
}
#end
Here is an image of the exact line where I get the warning
The reason you getting this warning is because of this UIViewController *detailViewController UIViewController does not have a method called "showRootPopoverButtonItem". If you want to get rid of the warning just do this instead:
[(WebViewController*)detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
or
[(Twitter*)detailViewController showRootPopoverButtonItem:self.rootPopoverButtonItem];
You just need to let it know its not really just a viewController, its a subclassed viewController you created. So what ever class showRootPopoverButtonItem: is in you just need to type cast it.
If you want to leave your code exactly the same but get rid of the warning you can do this.
if (rootPopoverButtonItem != nil) {
[detailViewController performSelector:#selector(showRootPopoverButtonItem:) withObject:self.rootPopoverButtonItem];
}
If you want to be more careful you should use this.
if (rootPopoverButtonItem != nil && [detailViewController respondsToSelector:#selector(showRootPopoverButtonItem:)]) {
[detailViewController performSelector:#selector(showRootPopoverButtonItem:) withObject:self.rootPopoverButtonItem];
}
Update
After reading through your code you could just specify the delegate on the detailViewController like you did in the other functions.
UIViewController<SubstitutableDetailViewController> *detailViewController = nil;
if (row == 0) {
//...
(1)Specify the Type for the detailedViewController: [(TYPE *)OBJECTNAME...
(2) Then Specify method call [(TYPE *)OBJECTNAME METHODCALL];
(*) You get the warning because the compiler does not know what type of object you are using. If you subclass a UIViewController then you have to specify type when accessing methods.Make sure the method is in .h so that you can access it.
I'm trying to get my data to load in my detail view. Can any one take a look and see why it isnt showing? It loads fine in my rootviewcontroller, just not the detail view.
DetailViewController.m
#import "DetailViewController.h"
#implementation DetailViewController
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
// Release anything that's not essential, such as cached data
}
- (void)setIcon:(UIImage *)newIcon
{
[super setIcon:newIcon];
iconView.image = newIcon;
}
- (void)setPublisher:(NSString *)newPublisher
{
[super setPublisher:newPublisher];
publisherLabel.text = newPublisher;
}
- (void)setName:(NSString *)newName
{
[super setName:newName];
nameLabel.text = newName;
}
- (void)dealloc
{
[iconView release];
[publisherLabel release];
[nameLabel release];
[priceLabel release];
[super dealloc];
}
#end
detailviewcontroller.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface DetailViewController : UIViewController {
IBOutlet UIImageView *iconView;
IBOutlet UILabel *publisherLabel;
IBOutlet UILabel *nameLabel;
IBOutlet UILabel *priceLabel;
}
#end
RootViewControllerPoints.m
#import "RootViewControllerPoints.h"
#import "DetailViewController.h"
#define USE_INDIVIDUAL_SUBVIEWS_CELL 1
#define DARK_BACKGROUND [UIColor colorWithRed:151.0/255.0 green:152.0/255.0 blue:155.0/255.0 alpha:1.0]
#define LIGHT_BACKGROUND [UIColor colorWithRed:172.0/255.0 green:173.0/255.0 blue:175.0/255.0 alpha:1.0]
#implementation RootViewController
#synthesize tmpCell, data;
#pragma mark View controller methods
- (void)viewDidLoad
{
[super viewDidLoad];
// Configure the table view.
self.tableView.rowHeight = 73.0;
self.tableView.backgroundColor = DARK_BACKGROUND;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
// Load the data.
NSString *dataPath = [[NSBundle mainBundle] pathForResource:#"Data" ofType:#"plist"];
self.data = [NSArray arrayWithContentsOfFile:dataPath];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
switch (toInterfaceOrientation) {
case UIInterfaceOrientationPortrait:
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
return YES;
default:
return NO;
}
}
#pragma mark Table view methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [data count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ApplicationCell";
ApplicationCell *cell = (ApplicationCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
#if USE_INDIVIDUAL_SUBVIEWS_CELL
[[NSBundle mainBundle] loadNibNamed:#"IndividualSubviewsBasedApplicationCell" owner:self options:nil];
cell = tmpCell;
self.tmpCell = nil;
#endif
}
// Display dark and light background in alternate rows -- see tableView:willDisplayCell:forRowAtIndexPath:.
cell.useDarkBackground = (indexPath.row % 2 == 0);
// Configure the data for the cell.
NSDictionary *dataItem = [data objectAtIndex:indexPath.row];
cell.icon = [UIImage imageNamed:[dataItem objectForKey:#"Icon"]];
cell.publisher = [dataItem objectForKey:#"Publisher"];
cell.name = [dataItem objectForKey:#"Name"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
detailViewController. = [data objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
}
#end
This has been bugging me for quite a while, I've looked at numerous examples, tutorials and even asked other iphone devs. Everything source seems to say something different.
First problem is that the setXXX methods in DetailViewController try to make calls to super setXXX but since DetailViewController is a subclass of UIViewController those calls to super will fail because UIViewController doesn't have such methods. Remove the calls to super in the setXXX methods.
Second problem is that the setXXX methods are setting the controls on the DetailViewController directly but the controls won't be accessible until the view is loaded so it won't work if the methods are called before the pushViewController call.
If you change the code in didSelectRowAtIndexPath as follows it should work:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController setName:#"name here"];
[detailViewController setPublisher:#"publisher here"];
[detailViewController setIcon:yourImageVariableHere];
[detailViewController release];
}
Although the above change should work, you might want to consider creating ivars to hold the values in DetailViewController (instead of using the ui controls themselves to hold the data). Then create properties for them using #property and #synthesize. The properties can be set immediately after DetailViewController is created and in the viewDidLoad of the view, you can set the ui controls to the property values. This will give the DetailViewController more control over how its ui is updated, allow you to change the ui without affecting callers, and it doesn't need to be displayed to set its properties.