Problemy z przekazywaniem danych do DetailViewController z TableView w iOS5

Byłbym wdzięczny za wszelką pomoc w rozwiązaniu mojego problemu, który spowodował, że wyciągnąłem włosy na ostatni dzień!

Zastrzeżenie 1 Jestem noobem Objective-C - więc odpowiedź na to może być bardzo prosta (pochodzę z lat PHP). Proszę bądź miły.

Zastrzeżenie 2 Tak, obszernie „Googled” i przyjrzałem się Dokumentacji Apple - ale nie udało mi się zrozumieć mojego problemu.

streszczenie

Próbuję przekazać wartość wybraną w widoku tabeli do innego kontrolera z singletonu. Stwierdzam, żeviewDidLoad Metoda w drugim widoku kontrolera kończy się przedtableView: didSelectRowAtIndexPath: metoda, która uruchomiła segue. Prowadzi to do uzyskania przez kontroler drugiego widoku dostępu do „starych” danych.

Szczegół

Założyłem projekt z bardzo prostą kartą StoryBoard za pomocą ARC targetowanie na iOS5.

Stworzyłem singleton do przechowywania NSString między kontrolerami widoku.

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>

TableView w tablicy opowieści jest połączony z następującym kontrolerem 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>

Komórka tabeli jest segregowana (push) do podstawowego ViewControllera z pojedynczą etykietą.

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>

Gdy zaznaczona jest komórka tabeli, chcę

TableViewController ustawić wartość we współdzielonym singleton NSStringaby rozpocząć segment do widoku szczegółowegoDetailViewController, aby uzyskać wartość we wspólnym singletonie NSString i wyświetlić ją w etykieciewidok szczegółów do renderowania na ekran

Niestety mój kod nie działa zgodnie z oczekiwaniami. Jeśli patrzę na szczegóły NSLog w konsoli, widzę, że widok szczegółówviewDidLoad funkcja kończy się przed metodą inicjowania widoku tabeli (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!

Jeśli ustawię tekst etykiety wviewDidAppear Metoda widoku szczegółowego wyświetli poprawną wartość ze współdzielonego pojedynczego NSString. Dzięki takiemu podejściu można jednak zobaczyć, jak aplikacja zmienia wartość etykiety tekstowej (np. Po kliknięciu pierwszego wiersza, gdy ładuje się ekran widoku szczegółowego, można ZOBACZYĆ zmianę etykiety z „Ciąg inicjujący” na „Najpierw „).

Czy ktoś może wyjaśnić, w jaki sposób mogę przekazać udostępnioną wartość z singletonu do innego widoku i udostępnić ją drugiemu kontrolerowi widokuprzed wyświetleniem widoku na ekranie.

Jeśli wymagane są jakiekolwiek wyjaśnienia - daj nam znać.

Jestem pewien, że ma to coś wspólnego z tym, że nie doceniam subtelności cyklu życia widoku.

AKTUALIZACJA

Dzięki * 8vius.

Moja nowa metoda wTableViewController.m co rozwiązuje mój problem:

<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