Probleme beim Übertragen von Daten von TableView in iOS5 an einen DetailViewController

Ich würde mich über jede Hilfe bei der Lösung meines Problems freuen, bei dem ich mir am letzten Tag die Haare ausgerissen habe!

Haftungsausschluss 1 Ich bin ein Objective-C-Neuling - daher ist die Antwort möglicherweise sehr einfach (ich komme aus Jahren mit PHP). Bitte sei nett.

Haftungsausschluss 2 Ja, ich habe ausgiebig "gegoogelt" und mir die Apple-Dokumentation angesehen, konnte aber mein Problem nicht verstehen.

Zusammenfassung

Ich versuche, einen in einer Tabellenansicht ausgewählten Wert von einem Singleton an einen anderen Controller zu übergeben. Ich finde, dass dieviewDidLoad Methode in der zweiten Ansicht Controller abgeschlossen ist, bevor dietableView: didSelectRowAtIndexPath: Methode, die das Segue ausgelöst hat. Dies führt dazu, dass der zweite View Controller auf veraltete Daten zugreift.

Detail

Ich habe ein Projekt mit einem sehr einfachen StoryBoard erstellt, das ARC für iOS5 verwendet.

Ich habe einen Singleton erstellt, um einen NSString zwischen Ansichtscontrollern zu speichern.

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>

Die TableView im Storyboard ist mit dem folgenden TableViewController verknüpft

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>

Die Tabellenzelle wird auf einen einfachen ViewController mit einer einzelnen Beschriftung aufgeteilt (Push).

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>

Wenn eine Tabellenzelle ausgewählt ist, möchte ich

den TableViewController, um einen Wert im gemeinsam genutzten Singleton-NSString festzulegenum mit dem Übergang zur Detailansicht zu beginnenden DetailViewController, um den Wert im freigegebenen Singleton-NSString abzurufen und in einer Beschriftung anzuzeigenDie Detailansicht zum Rendern auf dem Bildschirm

Leider funktioniert dies mit meinem Code nicht wie erwartet. Wenn ich mir die NSLog-Details in der Konsole ansehe, sehe ich, dass die Detailansicht istviewDidLoad Funktion wird tatsächlich beendet, bevor die Methode zum Anzeigen der Tabelle gestartet wurde (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!

Wenn ich die Einstellung des Beschriftungstextes in dasviewDidAppear In der Detailansicht wird der korrekte Wert aus dem gemeinsam genutzten Singleton-NSString angezeigt. Mit diesem Ansatz können Sie jedoch tatsächlich sehen, wie die App den Wert der Textbeschriftung ändert (z. B. wenn Sie auf die erste Zeile klicken und der Detailansichtsbildschirm geladen wird, können Sie die Beschriftungsänderung von "Initialisierungszeichenfolge" in "Erste" SEHEN ").

Kann jemand erklären, wie ich einen gemeinsam genutzten Wert von einem Singleton an eine andere Ansicht übergeben und dem zweiten Ansichtscontroller zur Verfügung stellen kann?bevor die Ansicht tatsächlich auf dem Bildschirm gerendert wird.

Wenn eine Klarstellung erforderlich ist, lassen Sie es mich bitte wissen.

Ich bin sicher, das hat etwas damit zu tun, dass ich die Feinheiten des Ansichtslebenszyklus nicht richtig eingeschätzt habe.

AKTUALISIEREN

Vielen Dank an * 8vius.

Meine neue Methode inTableViewController.m was mein problem löst:

<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>

Antworten auf die Frage(1)

Ihre Antwort auf die Frage