Problemas al pasar datos a DetailViewController desde TableView en iOS5

¡Apreciaría cualquier ayuda para resolver mi problema que me ha sacado el pelo el último día!

Descargo de responsabilidad 1 Soy un noob Objective-C, por lo que la respuesta a esto puede ser muy simple (vengo de años de PHP). Por favor, ser amable.

Descargo de responsabilidad 2 Sí, he buscado en Google extensivamente y he consultado la documentación de Apple, pero no he llegado a comprender mi problema.

Resumen

Estoy intentando pasar un valor seleccionado en una vista de tabla a otro controlador desde un singleton. Estoy encontrando que elviewDidLoad método en el segundo controlador de vista se completa antes de latableView: didSelectRowAtIndexPath: Método que desencadenó la segue. Esto está llevando a la segunda vista del controlador de acceso a datos "obsoletos".

Detalle

He configurado un proyecto con un StoryBoard muy simple que utiliza ARC para iOS5.

He creado un singleton para almacenar una NSString entre controladores de vista.

Singleton.h

<code>#import <Foundation/Foundation.h>
@interface Singleton : NSObject
@property (strong, nonatomic) NSString *sharedString;
+ (id)singletonManager;
@end
</code>

Singleton.m

<code>#import "Singleton.h"

static Singleton *sharedInstance = nil;

    @implementation Singleton
    @synthesize sharedString = _sharedString;
    +(id)singletonManager
    {
        @synchronized(self){
            if (sharedInstance == nil)
                sharedInstance = [[self alloc] init];
        }
        return sharedInstance;
    }
    -(id) init {
        if (self = [super init]) {
            _sharedString = [[NSString alloc] initWithString:@"Initialization String"];
        }
        return self;
    }

    @end
</code>

El TableView en el storyboard está vinculado al siguiente TableViewController

TableViewController.h

<code>#import <UIKit/UIKit.h>

@interface TableViewController : UITableViewController
@end
</code>

TableViewController.m

<code>#import "TableViewController.h"
#import "Singleton.h"

@interface TableViewController ()
@property NSArray *tableData;
@end

@implementation TableViewController
@synthesize tableData;

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
    }
    return self;
}

- (void)viewDidLoad
{

    [super viewDidLoad];
    self.tableData = [NSArray arrayWithObjects:@"First", @"Second", @"Third", nil];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
}


- (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.tableData count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // Configure the cell...
    cell.textLabel.text = [self.tableData objectAtIndex:indexPath.row];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{    
    NSLog(@"TableViewController: didSelectRowAtIndexPath start");
    Singleton *sharedInstance = [Singleton singletonManager];
    sharedInstance.sharedString = [self.tableData objectAtIndex:indexPath.row];
    NSLog(@"TableViewController: Finished storing data into shared string: %@", sharedInstance.sharedString);
    NSLog(@"TableViewController: didSelectRowAtIndexPath start");
}

@end
</code>

La celda de la tabla es segue-ed (push) a un ViewController básico con una sola etiqueta.

DetailViewController.h

<code>#import <UIKit/UIKit.h>

@interface DetailViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *displayLabel;

@end
</code>

DetailViewController.m

<code>#import "DetailViewController.h"
#import "Singleton.h"

@interface DetailViewController ()

@end

@implementation DetailViewController
@synthesize displayLabel = _displayLabel;

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"DetailViewController: viewDidLoad start");
    Singleton *sharedInstance = [Singleton singletonManager];
    self.displayLabel.text = sharedInstance.sharedString;
    NSLog(@"displayLabel.text: %@", self.displayLabel.text);
    NSLog(@"DetailViewController: viewDidLoad end");
}

- (void)viewDidUnload
{
    [self setDisplayLabel:nil];
    [super viewDidUnload];
}

@end
</code>

Cuando se selecciona una celda de tabla, estoy deseando

el TableViewController para establecer un valor en el singleton compartido NSStringpara comenzar el segue a la vista detalladael DetailViewController para obtener el valor en el singleton NSString compartido y mostrarlo en una etiquetaLa vista detallada para renderizar en la pantalla.

Desafortunadamente esto no está funcionando como se esperaba con mi código. Si miro los detalles de NSLog en la consola, puedo ver que la vista de detallesviewDidLoad La función está terminando antes del método de inicio de vista de tabla (didSelectRowAtIndexPath).

<code>2012-05-10 23:17:45.756 TestSingleton[12105:f803] DetailViewController: viewDidLoad start
2012-05-10 23:17:45.758 TestSingleton[12105:f803] displayLabel.text: Initialization String
2012-05-10 23:17:45.759 TestSingleton[12105:f803] DetailViewController: viewDidLoad end
2012-05-10 23:17:45.763 TestSingleton[12105:f803] TableViewController: didSelectRowAtIndexPath start
2012-05-10 23:17:45.764 TestSingleton[12105:f803] TableViewController: Finished storing data into shared string: First
2012-05-10 23:17:45.765 TestSingleton[12105:f803] TableViewController: didSelectRowAtIndexPath start
</code>

Arrrrggghh!

Si coloco el ajuste del texto de la etiqueta en laviewDidAppear En el método de la vista de detalles, se mostrará el valor correcto de singleton compartido NSString. Sin embargo, con este enfoque, realmente puede ver la aplicación cambiando el valor de la etiqueta de texto (por ejemplo, si hace clic en la primera fila, cuando se carga la pantalla de vista detallada, puede VER el cambio de etiqueta de "Cadena de inicialización" a "Primero ").

¿Alguien puede explicar cómo puedo pasar un valor compartido de un singleton a otra vista y tenerlo disponible para el segundo controlador de vista?antes de que la vista se renderice en la pantalla.

Si se requiere alguna aclaración, por favor hágamelo saber.

Estoy seguro de que esto tiene algo que ver con mi incapacidad para apreciar las sutilezas del ciclo de vida de la vista.

ACTUALIZAR

Gracias a * 8vius.

Mi nuevo metodo enTableViewController.m lo que resuelve mi problema:

<code>- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([segue.identifier isEqualToString:@"mySegue"]) {
        NSLog(@"Preparing for Segue to detail view");
        Singleton *sharedInstance = [Singleton singletonManager];
        NSIndexPath *selectedRow = [self.tableView indexPathForSelectedRow];
        sharedInstance.sharedString = [self.tableData objectAtIndex:selectedRow.row];
        NSLog(@"TableViewController: Finished storing data into shared string: %@", sharedInstance.sharedString);

    }
}
</code>

Respuestas a la pregunta(1)

Su respuesta a la pregunta