以编程方式创建 UITableView
Posted
技术标签:
【中文标题】以编程方式创建 UITableView【英文标题】:Creating a UITableView Programmatically 【发布时间】:2013-03-28 14:56:54 【问题描述】:我在 Xcode 4.6 中有一个使用情节提要的应用程序。我向视图控制器类添加了一个 UITableView,它按预期工作。但是,当我尝试删除情节提要中的 UITableView 并以编程方式将其添加回同一个类时,我遇到了两个具体问题:
1)虽然我将 UITableViewCell 类型设置为 subtitle 类型,但是细节标签不再出现。
2)我选择单元格时应该发生的segue没有发生,甚至没有调用prepare segue,表明选择单元格时没有向表格视图发送消息。强>
以下是相关代码:
@interface StatsTableViewController () <UITableViewDataSource, UITableViewDelegate>
@property (strong, nonatomic) UITableView *tableView;
@end
@implementation StatsTableViewController
-(UITableView *)makeTableView
CGFloat x = 0;
CGFloat y = 50;
CGFloat width = self.view.frame.size.width;
CGFloat height = self.view.frame.size.height - 50;
CGRect tableFrame = CGRectMake(x, y, width, height);
UITableView *tableView = [[UITableView alloc]initWithFrame:tableFrame style:UITableViewStylePlain];
tableView.rowHeight = 45;
tableView.sectionFooterHeight = 22;
tableView.sectionHeaderHeight = 22;
tableView.scrollEnabled = YES;
tableView.showsVerticalScrollIndicator = YES;
tableView.userInteractionEnabled = YES;
tableView.bounces = YES;
tableView.delegate = self;
tableView.dataSource = self;
return tableView;
- (void)viewDidLoad
[super viewDidLoad];
self.tableView = [self makeTableView];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"newFriendCell"];
[self.view addSubview:self.tableView];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"newFriendCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil)
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
Friend *friend = [self.fetchedResultsController objectAtIndexPath:indexPath];
**//THIS DATA APPEARS**
cell.textLabel.text = friend.name;
cell.textLabel.font = [cell.textLabel.font fontWithSize:20];
cell.imageView.image = [UIImage imageNamed:@"icon57x57"];
**//THIS DATA DOES NOT APPEAR**
cell.detailTextLabel.text = [NSString stringWithFormat:@"%i Games", friend.gameCount];
cell.detailTextLabel.textColor = [UIColor lightGrayColor];
return cell;
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
[self performSegueWithIdentifier:@"detailsView" sender:self];
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
//I set the segue identifier in the interface builder
if ([segue.identifier isEqualToString:@"detailsView"])
NSLog(@"segue"); //check to see if method is called, it is NOT called upon cell touch
NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
///more code to prepare next view controller....
我不确定自己忘记做什么才能解决这两个问题。任何帮助表示赞赏。
【问题讨论】:
尝试定义单元格的高度。 行高不是单元格的高度吗?我把它设置为 45,这应该是足够的空间...... 哦,可以,我认为你定义了一个错误的方法 didDeselect 而应该是 didSelect。 【参考方案1】:当您注册一个类并使用 dequeueReusableCellWithIdentifier:forIndexPath: 时,dequeue 方法保证返回一个单元格,因此永远不会输入您的 if (cell == nil) 子句。所以,就照旧做,不要注册类,使用dequeueReusableCellWithIdentifier:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"newFriendCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
//etc.
return cell;
至于转场,它不能被调用,因为你不能对你在代码中创建的表进行转场,而不是在 IB 中。再次,回到旧方法并使用 tableView:didSelectRowAtIndexPath: 当您选择一个单元格时将调用它。在那里实例化您的细节控制器并在代码中进行转换。
修改后:
我没有在那里看到您添加的代码。您已经实现了 didDeselectRowAtIndexPath 而不是 didSelectRowAtIndexPath。如果你改变它,你的 segue 应该可以工作。
【讨论】:
我认为如果你的故事板中存在 segue,你可以使用它,但你仍然需要实现tableView:didSelectRowAtIndexPath:
并以编程方式执行 segue,这违背了目的。
@tapi,是的,我知道,我没有看到她的一些代码,并认为 OP 试图直接从单元格中进行转场。
我刚刚尝试添加 tableView:didSelectRowAtIndexPath: 并在正文中 performSegueWithIdentifier... 但这不起作用。我想我会尝试在代码中进行转换
@user1697845,它应该可以工作——你确定你在 IB 和代码中的 segue 名称相同吗?
@user1697845,为什么当您在 IB 中拥有表格视图时,您将其删除并在代码中重做?只是好奇。【参考方案2】:
你可能会做到 100% 。
- (void)viewDidLoad
[super viewDidLoad];
// init table view
tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
// must set delegate & dataSource, otherwise the the table will be empty and not responsive
tableView.delegate = self;
tableView.dataSource = self;
tableView.backgroundColor = [UIColor cyanColor];
// add to canvas
[self.view addSubview:tableView];
#pragma mark - UITableViewDataSource
// number of section(s), now I assume there is only 1 section
- (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView
return 1;
// number of row in the section, I assume there is only 1 row
- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section
return 1;
// the cell will be returned to the tableView
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *cellIdentifier = @"HistoryCell";
// Similar to UITableViewCell, but
JSCustomCell *cell = (JSCustomCell *)[theTableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
cell = [[JSCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
// Just want to test, so I hardcode the data
cell.descriptionLabel.text = @"Testing";
return cell;
#pragma mark - UITableViewDelegate
// when user tap the row, what action you want to perform
- (void)tableView:(UITableView *)theTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
NSLog(@"selected %d row", indexPath.row);
@end
【讨论】:
【参考方案3】:- (void)viewDidLoad
[super viewDidLoad];
arr=[[NSArray alloc]initWithObjects:@"ABC",@"XYZ", nil];
tableview = [[UITableView alloc]initWithFrame:tableFrame style:UITableViewStylePlain];
tableview.delegate = self;
tableview.dataSource = self;
[self.view addSubview:tableview];
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
return arr.count;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell"];
if(cell == nil)
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyCell"];
cell.textLabel.text=[arr objectAtIndex:indexPath.row];
return cell;
【讨论】:
【参考方案4】:- (void)viewDidLoad
[super viewDidLoad];
tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
tableView.delegate = self;
tableView.dataSource = self;
tableView.backgroundColor = [UIColor grayColor];
// add to superview
[self.view addSubview:tableView];
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)theTableView
return 1;
- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection: (NSInteger)section
return 1;
// the cell will be returned to the tableView
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *cellIdentifier = @"HistoryCell";
// Similar to UITableViewCell, but
UITableViewCell *cell = (UITableViewCell *)[theTableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.descriptionLabel.text = @"Testing";
return cell;
【讨论】:
【参考方案5】:样本表
#import "StartreserveViewController.h"
#import "CollectionViewController.h"
#import "TableViewCell1.h"
@interface StartreserveViewController ()
NSArray *name;
NSArray *images;
NSInteger selectindex;
@end
@implementation StartreserveViewController
- (void)viewDidLoad
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor blueColor];
_startReservetable.backgroundColor = [UIColor blueColor];
name = [[NSArray alloc]initWithObjects:@"Mobiles",@"Costumes",@"Shoes",
nil];
images = [[NSArray
alloc]initWithObjects:@"mobilestitle.jpg",@"costumetitle.jpeg",
@"shoestitle.png",nil];
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
pragma mark - UiTableview 数据源
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
return 1;
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:
(NSInteger)section
return 3;
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *cellId = @"tableview";
TableViewCell1 *cell =[tableView dequeueReusableCellWithIdentifier:cellId];
cell.cellTxt .text = [name objectAtIndex:indexPath.row];
cell.cellImg.image = [UIImage imageNamed:[images
objectAtIndex:indexPath.row]];
return cell;
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:
(NSIndexPath *)indexPath
selectindex = indexPath.row;
[self performSegueWithIdentifier:@"second" sender:self];
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
if ([segue.identifier isEqualToString:@"second"])
CollectionViewController *obj = segue.destinationViewController;
obj.receivename = [name objectAtIndex:selectindex];
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
@end
.h
#import <UIKit/UIKit.h>
@interface StartreserveViewController :
UIViewController<UITableViewDelegate,UITableViewDataSource>
@property (strong, nonatomic) IBOutlet UITableView *startReservetable;
@end
【讨论】:
这与这里已有的 7 个其他答案有何不同?给出答案时,最好给出some explanation as to WHY your answer 是那个。【参考方案6】:vc.m
#import "ViewController.h"
导入“secondViewController.h”
@interface ViewController ()
NSArray *cityArray;
NSArray *citySubTitleArray;
NSArray *cityImage;
NSInteger selectindexpath;
@end
@implementation ViewController
- (void)viewDidLoad
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
cityArray = [[NSArray
alloc]initWithObjects:@"Coimbatore",@"Salem",@"Chennai",nil];
citySubTitleArray = [[NSArray alloc]initWithObjects:@"1",@"2",@"3", nil];
cityImage = [[NSArray alloc]initWithObjects:@"12-300x272.png"
, @"380267_70d232fc33b44d4ebe7b42bbe63ee9be.png",@"apple-logo_318
-40184.png", nil];
#pragma mark - UITableView Data Source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
return 1;
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection
:(NSInteger)section
return cityImage.count;
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *cellId = @"city";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:cellId];
if (cell == nil)
cell = [[UITableViewCell
alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellId];
cell.textLabel.text = [cityArray objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [citySubTitleArray objectAtIndex:indexPath.row];
cell.imageView.image = [UIImage imageNamed:
[cityImage objectAtIndex:indexPath.row]];
// NSData *data = [[NSData alloc]initWithContentsOfURL:
[NSURL URLWithString:@""]];
// cell.imageView.image = [UIImage imageWithData:data];
return cell;
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath
: (NSIndexPath *)indexPath
NSLog(@"---- %@",[cityArray objectAtIndex:indexPath.row]);
NSLog(@"----- %@",[cityImage objectAtIndex:indexPath.row]);
selectindexpath=indexPath.row;
[self performSegueWithIdentifier:@"second" sender:self];
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little p
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
if ([segue.identifier isEqualToString:@"second"])
secondViewController *object=segue.destinationViewController;
object.cityName=[cityArray objectAtIndex:selectindexpath];
object.cityImage=[cityImage objectAtIndex:selectindexpath];
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
@end
vc.m
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController<UITableViewDataSource
, UITableViewDelegate>
@property (strong, nonatomic) IBOutlet UITableView *cityLabelList;
@end
sv.m
#import <UIKit/UIKit.h>
@interface secondViewController : UIViewController
@property(strong, nonatomic) NSString *cityName;
@property(strong,nonatomic)NSString *cityImage;
@end
sv.h
#import "secondViewController.h"
@interface secondViewController ()
@property (strong, nonatomic) IBOutlet UILabel *lbl_desc;
@property (strong, nonatomic) IBOutlet UIImageView *img_city;
@end
@implementation secondViewController
- (void)viewDidLoad
[super viewDidLoad];
// Do any additional setup after loading the view.
self.title=self.cityName;
if ([self.cityName isEqualToString:@"Coimbatore"])
self.lbl_desc.text=@"Coimbatore city";
self.img_city.image=[UIImage imageNamed:
[NSString stringWithFormat:@"%@",self.cityImage]];
else if ([self.cityName isEqualToString:@"Chennai"])
self.lbl_desc.text= @"Chennai City Gangstar";
self.img_city.image=[UIImage imageNamed:
[NSString stringWithFormat:@"%@",self.cityImage]];
else
self.lbl_desc.text= @"selam City";
self.img_city.image=[UIImage imageNamed:
[NSString stringWithFormat:@"%@",self.cityImage]];
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
【讨论】:
【参考方案7】:使用 tableViewController 创建一个表格视图。
import UIKit
class TableViewController: UITableViewController
let tableViewModel = TableViewModel()
var product: [String] = []
var price: [String] = []
override func viewDidLoad()
super.viewDidLoad()
self.tableView.contentInset = UIEdgeInsetsMake( 20, 20 , 0, 0)
let priceProductDetails = tableViewModel.dataProvider()
for (key, value) in priceProductDetails
product.append(key)
price.append(value)
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return product.count
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
let cell = UITableViewCell(style: .Value1, reuseIdentifier: "UITableViewCell")
cell.textLabel?.text = product[indexPath.row]
cell.detailTextLabel?.text = price[indexPath.row]
return cell
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
print("You tapped cell number \(indexPath.row).")
【讨论】:
【参考方案8】:- (NSInteger)tableView:(UITableView *)theTableView numberOfRowsInSection:(NSInteger)section
return 1;
- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *cellIdentifier = @"HistoryCell";
UITableViewCell *cell = (UITableViewCell *)[theTableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
cell.descriptionLabel.text = @"Testing";
return cell;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
//Code for selection.
这些是 UITableView 委托方法。
【讨论】:
最好每次都被记住【参考方案9】:#import "ViewController.h"
@interface ViewController ()
NSMutableArray *name;
@end
- (void)viewDidLoad
[super viewDidLoad];
name=[[NSMutableArray alloc]init];
[name addObject:@"ronak"];
[name addObject:@"vibha"];
[name addObject:@"shivani"];
[name addObject:@"nidhi"];
[name addObject:@"firdosh"];
[name addObject:@"himani"];
_tableview_outlet.delegate = self;
_tableview_outlet.dataSource = self;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
return [name count];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *simpleTableIdentifier = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
cell.textLabel.text = [name objectAtIndex:indexPath.row];
return cell;
【讨论】:
以上是关于以编程方式创建 UITableView的主要内容,如果未能解决你的问题,请参考以下文章
Android 编程:如何以网格方式以编程方式创建各种视图类型