Я был бы признателен за любую помощь в решении моей проблемы, из-за которой я рвал на себе волосы в последний день!
Отказ от ответственности 1 Я новичок в Objective-C, поэтому ответ на этот вопрос может быть очень простым (у меня многолетний опыт работы с PHP). Пожалуйста будь вежлив.
Отказ от ответственности 2 Да, я много гуглил и просматривал документацию Apple, но не смог понять свою проблему.
Сводка
Я пытаюсь передать значение, выбранное в табличном представлении, другому контроллеру из синглтона. Я обнаружил, что метод viewDidLoad во втором контроллере представления завершается раньше, чем метод tableView: didSelectRowAtIndexPath:, который инициировал переход. Это приводит к «устаревшим» данным доступа к контроллеру второго представления.
Подробности
Я создал проект с очень простой StoryBoard, используя ARC для iOS5.

Я создал синглтон для хранения NSString между контроллерами представления.
Singleton.h
#import <Foundation/Foundation.h>
@interface Singleton : NSObject
@property (strong, nonatomic) NSString *sharedString;
+ (id)singletonManager;
@end
Singleton.m
#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
TableView в раскадровке связан со следующим TableViewController
TableViewController.h
#import <UIKit/UIKit.h>
@interface TableViewController : UITableViewController
@end
TableViewController.m
#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
Ячейка таблицы переходит (push) к базовому ViewController с одной меткой.
DetailViewController.h
#import <UIKit/UIKit.h>
@interface DetailViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *displayLabel;
@end
DetailViewController.m
#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
Когда выбрана ячейка таблицы, я хочу
- TableViewController для установки значения в общем сингле NSString
- чтобы начать переход к подробному просмотру
- DetailViewController, чтобы получить значение в общем сингле NSString и отобразить его в метке
- Детальный вид для отображения на экране
К сожалению, это не работает должным образом с моим кодом. Если я посмотрю на детали NSLog в консоли, то увижу, что функция viewDidLoad подробного представления на самом деле завершается до запуска метода табличного представления (didSelectRowAtIndexPath).
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
Арррррррррррр!
Если я помещу настройку текста метки в метод viewDidAppear подробного представления, будет отображаться правильное значение из общего синглтона NSString. Однако при таком подходе вы можете фактически увидеть, как приложение меняет значение текстовой метки (например, если вы нажмете на первую строку, когда загрузится экран подробного просмотра, вы увидите изменение метки с «Строка инициализации» на «Первый ").
Может кто-нибудь объяснить, как я могу передать общее значение из синглтона в другое представление и сделать его доступным для второго контроллера представления до того, как представление будет фактически отображено на экране.
Если потребуются какие-либо разъяснения - дайте мне знать.
Я уверен, что это как-то связано с моей неспособностью оценить тонкости жизненного цикла представления.
ОБНОВЛЕНИЕ
Благодаря *8vius.
Мой новый метод в TableViewController.m, который решает мою проблему:
- (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);
}
}