Problemas na transmissão de dados para um DetailViewController do TableView no iOS5

Eu apreciaria qualquer ajuda na resolução do meu problema que me fez tirar o cabelo do último dia!

Disclaimer 1 Eu sou um noob Objective-C - então a resposta para isso pode ser muito simples (eu estou vindo de anos de PHP). Por favor seja gentil.

Aviso de isenção 2 Sim, eu tenho 'Googled' extensivamente e olhei para documentação da Apple - mas não consegui chegar a uma compreensão do meu problema.

Resumo

Eu estou tentando passar um valor selecionado em uma exibição de tabela para outro controlador de um singleton. Eu estou achando que oviewDidLoad método no segundo controlador de visão está completando antes dotableView: didSelectRowAtIndexPath: método que desencadeou a segue. Isso está levando aos dados do segundo acesso do controlador de visualização 'obsoletos'.

Detalhe

Eu configurei um projeto com um StoryBoard muito simples usando o ARC de segmentação por iOS5.

Eu criei um singleton para armazenar um NSString entre os controladores de exibição.

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>

O TableView no storyboard está vinculado ao seguinte 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>

A célula da tabela é seguida (push) para um ViewController básico com um único rótulo.

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>

Quando uma célula da tabela é selecionada, estou querendo

o TableViewController para definir um valor no singleton compartilhado NSStringpara iniciar o segue para a vista de detalheo DetailViewController para obter o valor no NSString singleton compartilhado e exibi-lo em um rótuloa Visualização de detalhes para renderizar na tela

Infelizmente isso não está funcionando como esperado com o meu código. Se eu olhar para os detalhes do NSLog no console, posso ver que a visão de detalhesviewDidLoad função está realmente terminando antes do método de visualização da tabela de inicialização (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!

Se eu colocar a configuração do texto da etiqueta noviewDidAppear método da visualização detalhada, o valor correto da NSString singleton compartilhada será exibido. Com essa abordagem, no entanto, você pode realmente ver o aplicativo alterando o valor do rótulo de texto (por exemplo, se você clicar na primeira linha, quando a tela de exibição detalhada carregar, poderá VER a alteração de rótulo de "Initialization String" para "First ").

Alguém pode explicar como posso passar um valor compartilhado de um singleton para outro modo de exibição e disponibilizá-lo para o segundo view controller?antes que a exibição seja realmente renderizada na tela.

Se algum esclarecimento for necessário, por favor me avise.

Tenho certeza de que isso tem algo a ver com meu fracasso em apreciar as sutilezas do ciclo de vida da exibição.

ATUALIZAR

Graças a * 8vius.

Meu novo método emTableViewController.m o que resolve meu 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>

questionAnswers(1)

yourAnswerToTheQuestion