如何在表视图中选中后将数据传递给详细视图?

问题描述:

我有一个UITableViewController有一个名为userList的NSMutableArray填充数据。选择特定用户后,它将转到详细信息视图,并更新NavBar中的标题,但不会传递数据以更新UIView中的UILabel。如何在表视图中选中后将数据传递给详细视图?

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 

[tableView deselectRowAtIndexPath:indexPath animated:NO]; 

//Attempt at a singleton to pass the data 
DetailView *details = [[DetailView alloc] init]; 
details.userNameLbl = [userList objectAtIndex:indexPath.row]; 


DetailView *detailVC = [[DetailView alloc] initWithNibName:nil bundle:nil]; 

//This line doesn't pass the data 
detailVC.userNameLbl.text = [userList objectAtIndex:indexPath.row]; 

//This line does update the title in the NavBar 
detailVC.navigationItem.title = [userList objectAtIndex:indexPath.row]; 

[self.navigationController pushViewController:detailVC animated:YES]; 

[details release]; 
[detailVC release]; 

} 

我应该试图从表格视图中的数据推到详细信息视图,或者有详细视图尝试从表视图提取数据?

DetailView.h有以下一行,它实际上已经连接到IB。

IBOutlet UILabel *userNameLbl 

直到从nib文件加载视图,userNamelbl才被实例化。这在初始化时不会立即发生,但在调用viewDidLoad时会发生。

因此,您应该在DetailView中声明一个属性来存储您的标题,然后在viewDidLoad方法中将该值分配给userNamelbl.text

例如,在表中的viewController:

DetailView *detailVC = [[DetailView alloc] initWithNibName:nil bundle:nil]; 
detailVC.userName = [userList objectAtIndex: indexPath.row]; 

,并在您详细的viewController:

​​

时创建的viewController的navigationItem财产时的viewController被初始化,因此你可以分配给navigationItem.title立即。


斯威夫特代码

let detailVC = DetailView(nibName: nil, bundle: nil) 
detailVC.userName = userList.objectAtIndex(indexPath.row) as? NSString 

class DetailView: UIViewController { 

    @IBOutlet var userNameLbl: UILabel 
    var userName:NSString? 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.userNameLbl.text = self.userName 
    }  
} 
+0

另外,你可以考虑有一个'User'类并将它的一个实例传递给你的视图。然后你的视图可以初始化它自己的特定于用户的任何部分。它甚至可以帮助使这个'User'类成为一个核心数据实体类型。 – George

+0

这样做导致NSString和UILabel类型不匹配的警告 - 是否有一种方法来实现您的解决方案,并避免这种情况? – tarheel

+0

我假设userList是一个NSStrings的数组。如果userName属性也是NSString,则不应该出现不匹配 –

假设您的DetailView要求您所选行的数据起作用?

如果是这样,我会说'正确'的做法是创建一个自定义的init方法,传递你需要的数据。例如:

[[DetailView alloc] initWithTitle:(NSString *)title text:(NSString *)text] 

没有什么内在的错误你的做法是,不过将视图控制器需要的数据在其创建的建筑更好的(在我看来,我相信总有人会不同意!)。例如,考虑一个表视图控制器 - 您在init方法中传入表格视图样式,您以后不会设置它。 UIImageView相同 - 您有一个initWithImage方法,可让您在创建时设置图像。

+0

Ç从理论上讲,我绝对同意你的方法,但我需要多一点的帮助(即一个noob)的实施。我的理解是,上面的代码行将在TableView中的didSelectRowAtIndexPath:方法内部,然后(这是我弄糊涂的地方)initWithTitle:text:方法的实际实现位于DetailView中。对? – tarheel

+0

+1。我会推荐这一点,因为它的简单和优雅,只是提到了其他方法。 – Bourne

+0

@lxt我很想看到有关此解决方案的更多信息,但我不得不将信誉归功于AshleyMills,因为这是我在应用中使用的解决方案。感谢大家! – tarheel

你是混合UIViewsUIViewControllers?您应该有一个DetailViewController类,它继承自UIViewController或某个子类(如UITableViewController);它将有DetailViewController.mDetailViewController.h文件来声明和定义你的类。它应该有一个相应的笔尖,用于定义UIViewController加载的UIView;它将有一个DetailView.xib文件。

您不能直接将值分配给UILabel,因为UIView在您需要分配用户名值时尚未加载。

为了做到你想要的,你应该声明一个公共属性(userName),以便将值从主控制器“推送”到详细视图控制器中。一旦加载了详细视图,它可以将该属性的值分配给标签和导航栏。

在您的主视图控制器(UITableViewController):

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    [tableView deselectRowAtIndexPath:indexPath animated:NO]; 

    DetailViewController *detailVC = [[DetailView alloc] initWithNibName:@"DetailView" bundle:nil]; 

    detailVC.userName = [userList objectAtIndex:indexPath.row]; 

    [self.navigationController pushViewController:detailVC animated:YES]; 

    [detailVC release]; 
} 

在您的详细视图控制器:

DetailViewController.h

@property (retain) NSString* userName; 
@property (nonatomic, retain) IBOutlet UILabel *userNameLbl; 

DetailViewController.m

@synthesize userName; 
@synthesize userNameLbl; 

-(void) viewDidLoad { 
    [super viewDidLoad]; 
    self.userNameLbl.text = self.userName; 
    self.navigationItem.title = self.userName; 
}