从iOS5中的TableView将数据传递给DetailViewController的问题 [英] Problems passing data to a DetailViewController from TableView in iOS5

查看:115
本文介绍了从iOS5中的TableView将数据传递给DetailViewController的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很感激任何帮助解决我在最后一天拉头发的问题!

I would appreciate any help in solving my problem that has had me pulling my hair out for the last day!

免责声明1 我这是一个Objective-C菜鸟 - 所以答案可能很简单(我来自多年的PHP)。请保持友好。

Disclaimer 1 I'm an Objective-C noob - so the answer to this may be very simple (I'm coming from years of PHP). Please be nice.

免责声明2 是的,我已经广泛谷歌搜索并查看了Apple文档 - 但未能达成谅解我的问题。

Disclaimer 2 Yes, I have extensively 'Googled' and looked at Apple Documentation - but have failed to come to an understanding of my problem.

摘要

Summary

I我试图将表视图中选择的值从单例传递给另一个控制器。我发现第二个视图控制器中的 viewDidLoad 方法在触发segue的 tableView:didSelectRowAtIndexPath:方法之前完成。这导致第二个视图控制器访问陈旧数据。

I am trying to pass a value selected in a table view to another controller from a singleton. I am finding that the viewDidLoad method in the second view controller is completing before the tableView: didSelectRowAtIndexPath: method which triggered the segue. This is leading to the second view controller access 'stale' data.

详细信息

Detail

我使用针对iOS5的ARC设置了一个非常简单的StoryBoard项目。

I have set up a project with a very simple StoryBoard using ARC targeting iOS5.

我创建了一个单例来存储视图控制器之间的NSString。

I have created a singleton to store a NSString between view controllers.

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

The TableView in the story board is linked to the following 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

表格单元格是segue- ed(推送)到一个带有单个标签的基本ViewController。

The table cell is segue-ed (push) to a basic ViewController with a single label.

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

选择表格单元格时,我想要

When a table cell is selected, I am wanting


  • TableViewController在共享单例NSString中设置一个值

  • 开始细节视图的细分

  • DetailViewController获取共享单例NSString中的值并将其显示在标签中

  • 详细信息视图以进行渲染到屏幕

  • the TableViewController to set a value in the shared singleton NSString
  • to commence the segue to the Detail View
  • the DetailViewController to get the value in the shared singleton NSString and display it in a label
  • the Detail View to render to the screen

不幸的是,这与我的代码无法正常工作。如果我在控制台中查看NSLog详细信息,我可以看到详细视图的 viewDidLoad 函数实际上在启动表视图方法( didSelectRowAtIndexPath )之前完成。

Unfortunately this is not working as expected with my code. If I look at the NSLog details in the console I can see that the detail view's viewDidLoad function is actually finishing before the initiating table view method (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

Arrrrggghh!

Arrrrggghh!

如果我将标签文本的设置放在详细视图的 viewDidAppear 方法中,将显示共享单例NSString中的正确值。但是,通过这种方法,您实际上可以看到应用程序更改文本标签的值(例如,如果您单击第一行,当详细视图屏幕加载时,您可以看到标签从初始化字符串更改为第一行 )。

If I place the setting of the label text in the viewDidAppear method of the detail view, the correct value from shared singleton NSString will be displayed. With this approach, however, you can actually see the app changing the value of the text label (eg. if you click on the first row, when the detail view screen loads you can SEE the label change from "Initialization String" to "First").

有人可以解释我如何将一个共享值从一个单例传递到另一个视图,并在视图之前将它提供给第二个视图控制器实际上是渲染到屏幕

Can somebody please explain how I can pass a shared value from a singleton to another view and have it available to the second view controller before the view is actually rendered to screen.

如果需要澄清 - 请告诉我。

If any clarification is required - please let me know.

我确信这与我未能理解视图生命周期的微妙之处有关。

I'm sure this has something to do with my failure to appreciate the subtleties of the view lifecycle.

更新

感谢* 8vius。

TableViewController.m 中的新方法解决了我的问题:

My new method in TableViewController.m which solves my problem:

- (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);

    }
}


推荐答案

在目标视图控制器中设置属性(公共),以便设置您希望传入的值。在原始视图控制器中实现 prepareForSegue 并导入目标视图控制器的标头。

In your destination view controller set up a property (public) so you can set the value you wish to pass in. Implement prepareForSegue in your origin view controller and import the header of your destination view controller.

要获取表视图单元的indexPath,您应该将IBOutlet设置为表视图,这样您就可以使用prepareForSegue方法中的indexPathForCell方法获取indexPath 。

To get the indexPath of a table view cell you should have an IBOutlet set to your table view, this way you can get the indexPath using the indexPathForCell method in your prepareForSegue method.

在你的 prepareForSegue 中你应该有这样的东西:

In your prepareForSegue you should have something like this:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
  NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
  if ([segue.identifier isEqualToString:@"[identifier for your segue]"]) {
     [segue.destinationViewController setValueIWantToSet:value];
  }
}

您还可以在此处设置标签文本的值,如果你愿意的话。

You could also set the value of the label text here, if you wish.

你的 viewDidLoad 之前完成的原因是因为iOS在转换之前设置了目标视图控制器使用 prepareForSegue 方法保证您的目标视图控制器已经实例化并设置,因此您可以设置所需的值。

The reason your viewDidLoad finishes before is because iOS sets up the destination view controller before transitioning to it, using the prepareForSegue method guarantees that your destination view controller is already instantiated and set up, so you can set the values you wish.

这篇关于从iOS5中的TableView将数据传递给DetailViewController的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆