单个屏幕中有多个TableView

时间:2011-09-01 22:51:28

标签: iphone ios uitableview

我有一个UIViewController,我打算在其中有两个TableView和一些其他项目。 我在其他屏幕上使用的两个TableView,所以我想让它们尽可能独立和可重用。其中一个TableView被称为messageList(A UITableView),它显示了我的ChatHistory。

我想知道我的方法是否正确。 [使用正确的代码编辑9/2以使此方法有效]

一种方法是使用具有2个不同部分的单个表,然后在委托方法中使用条件语句来查看哪个部分是哪个部分并相应地采取行动。

这种方法的问题在于可用性。我想在其他视图中轻松地重用我的TableViews,其中一个或另一个TableView可能存在,也可能不存在。此外,我希望DataSource在应用程序的整个生命周期中都存在,无论Controller是实例化还是活动的。

我的方法是将管理表视图的视图控制器与表UITableViewDataSource和UITableViewDelegate实现分开。但是我在解决这个问题时遇到了问题。

专注于其中一个TableViews,我的ChatTableView。

在我的AppDelegate中有一个ChatHistory类型的chatHistory属性,它实现了UITableViewDelegate& UITableViewDataSource。

// AppDelegate.h

ChatHistory *chatHistory;
...
@property (nonatomic, retain) ChatHistory *chatHistory;

// ChatHistory.h

#import <Foundation/Foundation.h>

@interface ChatHistory : NSObject <UITableViewDelegate, UITableViewDataSource> {
    UITableViewCell *nibLoadedCell;
    NSMutableArray *messages;
}
@property (nonatomic, retain) UITableViewCell   *nibLoadedCell;
@property (nonatomic, retain) NSMutableArray    *messages;

@end

// ChatHistory.m - 注意这段代码,包括自定义单元格在控制器的一部分时工作正常,所以我认为它应该是正确的

#import "ChatHistory.h"
#include "ChatMessage.h"

@implementation ChatHistory
@synthesize nibLoadedCell;   // custom cell design
@synthesize messages;

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}

- (NSInteger)tableView:(UITableView *)tableView 
 numberOfRowsInSection:(NSInteger)section {
return [messages count];
}

- (NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section {
return [NSString stringWithFormat:@"Discussion"];

}

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

if (cell == nil) {
    [[NSBundle mainBundle] loadNibNamed:@"ChatTableCell" owner:self options:nil];
    cell = nibLoadedCell;
    }
    // custom tag order - username; message; future - Avatar; like; dislike
ChatMessage *obj = [messages objectAtIndex:indexPath.row];
UILabel *messageLabel = (UILabel *) [cell viewWithTag:1];
messageLabel.text = obj.message;
UILabel *usernameLabel = (UILabel *)[cell viewWithTag:2];
usernameLabel.text = obj.sender;
return cell;
}

- (void)dealloc {
    if (messages) [messages release];
    [super dealloc];
}
@end

// MyViewController.m

- (void)viewDidLoad {   // MAKE SURE TO INITIALIZE viewDidLoad not InitWithNib
        if (!appDelegate.chatHistory)
                appDelegate.chatHistory = [[ChatHistory alloc] init];

        messageList = [[UITableView alloc] initWithFrame:CGRectMake(0, 54, 320, 100) style:UITableViewStylePlain];
        messageList.dataSource = appDelegate.chatHistory;
        messageList.delegate = appDelegate.chatHistory;
        [self.view addSubview:messageList];
        ...

3 个答案:

答案 0 :(得分:2)

您不需要将视图控制器作为tableview DataSource或委托;任何对象都可以设置。您可以使用Felix建议的单身,或任何其他您想要的类结构。由于您提到您希望聊天历史记录可以在应用程序的任何位置使用,因此为该聊天记录提供UITableViewDataSource协议是有意义的。

对于UITableViewDelegate,您可以简单地创建一个新类作为NSObject的子类,并在那里实现委托。确保它已正确创建和保留,并在(加载时)设置为表视图的委托。

答案 1 :(得分:1)

如果您想要一个中央数据存储,可以使用数据创建一个Singleton类。 然后将其设置为表视图的数据源,或从UIViewController / UITableViewController中的数据存储中获取数组(或任何您获得的数组)。

如果您在AppDelegate中初始化数据存储,则可以从所需的每个类中访问它(请注意,您加载的所有数据将保留在内存中,直到您的应用程序被iOS终止)

How to create a Singleton class in Objective-C

答案 2 :(得分:0)

我会这样做:制作一个视图控制器的两个UITableView子视图。

在{strong>每个的datasource方法中,您只需区分两个表,类似于Apple在UISearchDisplayController示例中提供的代码。例如:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  if (tableView == myTableView1) {
    // return appropriate number of rows
  }
  // return appropriate number of rows for the other table view
}

我知道这并没有非常巧妙地将两个表视图类分开。您必须拥有一个视图控制器来控制两个其他视图控制器,每个视图控制器一个。

或许必须考虑可重用性与更复杂的架构的复杂性之间的权衡(这通常也会导致在可重用性方面表现不佳的类)。这就是为什么我会推荐Apple样本项目的方法。