1 摘要
本文通过两个实例:创建多组和单组列表,学习了UITableView的基本知识,还涉及了UIAlert的一些知识。
2 UITableView基本知识总结
3 列表实例
3.1 多组列表实例
3.1.1 viewController h代码
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
3.1.2 viewController m代码
//
// ViewController.m
// UITableView多section练习
//
// Created by dqw on 15/5/14.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "ViewController.h"
#import "Province.h"
@interface ViewController ()<UITableViewDataSource, UITableViewDelegate>
{
NSMutableArray *_provinces;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_provinces = [NSMutableArray arrayWithObjects:
[Province provinceWithHeader:@"广东省" Footer:@"好" Cities:@[@"深圳", @"广州"]],
[Province provinceWithHeader:@"河南省" Footer:@"不好" Cities:@[@"郑州", @"南阳"]],
[Province provinceWithHeader:@"河南省2" Footer:@"不好" Cities:@[@"郑州", @"南阳"]],
[Province provinceWithHeader:@"河南省3" Footer:@"不好" Cities:@[@"郑州", @"南阳"]],
nil];
Province *HB = [Province provinceWithHeader:@"湖北省" Footer:@"还可以" Cities:@[@"武汉", @"襄阳"]];
[_provinces addObject:HB];
// 如果不设置frame,不会显示。
UITableView *tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 20, 320, 460) style:UITableViewStyleGrouped];
#pragma mark 注意点1: UITableView有两个代理,它们有不同的方法。
tableView.dataSource = self;
// tableView.delegate = self;
// 它继承自UIScrollview,所以可以设置其scrollview属性。
// tableView.scrollEnabled = NO;
[self.view addSubview:tableView];
}
#pragma mark 重点1:设置section个数,如果不设置,则默认为一个section。
// 是NSIntegr 而不是NSUintegr
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#pragma mark 疑问1:此处的打印和下面每个方法的打印,是为了研究这些方法的调用顺序和次数,结果显示section和row分别被调用了三次,header和footer也调用混乱,不明白????
NSLog(@"section");
return _provinces.count;
}
#pragma mark 重点2:设置每个section的row个数。
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#pragma mark 注意点2:因为数组的元素默认是id类型的,不能应用点语法,所以用cities的getter方法代替,这样不需要在额外将数组元素取出。
// Province *province = _provinces[section];
NSLog(@"row");
return [_provinces[section] cities].count;
}
#pragma mark 重点3:设置每个cell的内容。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"cell");
// 设置cell的类型。
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil];
NSInteger section = indexPath.section;
NSInteger row = indexPath.row;
// Province *province = _provinces[section];
cell.textLabel.text = [_provinces[section] cities][row];
cell.detailTextLabel.text = @"desc.....";
cell.image = [UIImage imageNamed:[NSString stringWithFormat:@"00%d.png", arc4random_uniform(9) + 1]];
return cell;
}
#pragma mark 注意点3:设置每个section的header和footer(不是必选的)。
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSLog(@"header");
return [_provinces[section] header];
}
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
NSLog(@"footer");
return [_provinces[section] footer];
}
#pragma mark 注意点4:这个方法是UITableViewDelegate协议的方法。
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// return 70 + indexPath.row * 20;
return 50;
}
#pragma mark 注意点4:设置右边的索引标题,有疑问:标题没有散开????
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
NSMutableArray *titles = [[NSMutableArray alloc]init];
for (Province *province in _provinces)
{
[titles addObject:province.header];
}
return titles;
}
@end
3.1.3 province h代码
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface Province : NSObject
//@property(nonatomic, copy)NSString *icon;
//@property(nonatomic, copy)NSString *title;
//@property(nonatomic, copy)NSString *desc;
@property(nonatomic, copy)NSString *header;
@property(nonatomic, copy)NSString *footer;
@property(nonatomic, strong)NSArray *cities;
#pragma mark 重点0:方法里面后面的参数,如果其前面没有修饰词如for with等,则其首字符小写,所以下面是不规范的。
+ (Province *)provinceWithHeader:(NSString *)header Footer:(NSString *)footer Cities:(NSArray *)cities;
@end
3.1.4 province m代码
#import "Province.h"
@implementation Province
+ (Province *)provinceWithHeader:(NSString *)header Footer:(NSString *)footer Cities:(NSArray *)cities;
{
Province *province = [[Province alloc]init];
// province.icon = icon;
// province.title = title;
// province.desc = desc;
province.header = header;
province.footer = footer;
province.cities = cities;
return province;
}
@end
3.2 单组列表实例
3.2.1 viewController h代码
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@end
3.2.2 viewController m代码
//
// ViewController.m
// UITableView-淘宝商品列表
//
// Created by dqw on 15/5/14.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "ViewController.h"
#import "Shop.h"
@interface ViewController ()<UITableViewDataSource, UITableViewDelegate, UIAlertViewDelegate>
{
NSMutableArray *_shops;
// NSInteger _index;
}
@end
@implementation ViewController
#pragma mark 1. 创建数据。
- (void)viewDidLoad {
[super viewDidLoad];
// 创建数组
_shops = [NSMutableArray array];
// 创建数据
Shop *shop1 = [Shop shopWithName:@"图书/音像" icon:@"001.png" desc:@"小说,情感,卡拉OK"];
Shop *shop2 = [Shop shopWithName:@"母婴用品" icon:@"002.png" desc:@"防尿,奶粉,喂养"];
Shop *shop3 = [Shop shopWithName:@"玩具" icon:@"003.png" desc:@"卡车,积木,鸡毛"];
[_shops addObjectsFromArray:@[shop1, shop2, shop3]];
//添加其他假数据
// for (int i = 0; i<20; i++) {
//
// NSString *name = [NSString stringWithFormat:@"随机产品-%d", i];
// NSString *desc = [NSString stringWithFormat:@"%@ - 好好好", name];
// NSString *icon = [NSString stringWithFormat:@"00%d.png", (i % 9) + 1];
// Shop *shop = [Shop shopWithName:name icon:icon desc:desc];
//
// [_shops addObject:shop];
// }
}
#pragma mark 2. 设置section。
// 缺省的话,就默认是一个section。
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSLog(@"section");
return 1;
}
#pragma mark 3. 设置row。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(@"row");
return _shops.count;
}
#pragma mark 4. 设置cell。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@"cell");
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil];
#pragma mark 重点1:下面的image属性,属于分类@interface UITableViewCell (UIDeprecated),表示被弃用的,但是还是可以调用的。分类不是不可以添加成员变量么????。下面的imageview和textlabel及detailtextlabel虽然都是readonly性质,但是可以更改其自身的image和text属性。
// cell.image = [UIImage imageNamed:[_shops[indexPath.row] icon]];
cell.imageView.image = [UIImage imageNamed:[_shops[indexPath.row] icon]];
cell.textLabel.text = [_shops[indexPath.row] name];
cell.detailTextLabel.text = [_shops[indexPath.row] desc];
return cell;
}
#pragma mark 5. 监听是否选择了某个row。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
#pragma mark 重点2:创建alertView,熟悉其属性设置。
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"产品信息" message:[_shops[indexPath.row] desc] delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定",nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
// _index = indexPath.row;
alert.tag = indexPath.row;
#pragma mark 重点3:alterView的textfield属性是重点。
[alert textFieldAtIndex:0].text = [_shops[indexPath.row] name];
#pragma mark 重点4:调用了alert的show方法后,虽然alert是在该代码块中创建,但是其具有了全局变量的功能,可以在下面的clickbuttonXXX方法中传递。
[alert show];
}
#pragma mark 6. 监听alert的button按钮。
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
#pragma mark 疑问1:添加功能,如果textfield中内容为空,则不做任何改变,但是没有成功,条件一直不成立。
if ([alertView textFieldAtIndex:0].text == nil) {
NSLog(@"dfd");
return;
}
else
{
NSLog(@"text%@text", [alertView textFieldAtIndex:0].text);
#pragma mark 重点5:将textfield中的值赋值给数据源。
[_shops[alertView.tag] setName:[alertView textFieldAtIndex:0].text];
NSLog(@"fff");
}
#pragma mark 重点6:修改数据模型,全部修改,和局部修改。
// [_tableView reloadData];
[_tableView reloadRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:alertView.tag inSection:0]] withRowAnimation:nil];
}
@end
3.2.3 shop h代码
#import <Foundation/Foundation.h>
@interface Shop : NSObject
// 图片
@property (nonatomic, copy) NSString *icon;
// 名称
@property (nonatomic, copy) NSString *name;
// 描述
@property (nonatomic, copy) NSString *desc;
// 方法的参数,后面的如果没有修饰词,则小写。
+ (id)shopWithName:(NSString *)name icon:(NSString *)icon desc:(NSString *)desc;
@end
3.2.4 shop m代码
#import "Shop.h"
@implementation Shop
+ (id)shopWithName:(NSString *)name icon:(NSString *)icon desc:(NSString *)desc
{
Shop *shop = [[Shop alloc] init];
shop.icon = icon;
shop.name = name;
shop.desc = desc;
return shop;
}
@end
4 重点 难点 注意点
- <>如果不设置section个数,则默认为1.
- 针对数组中元素是id类型,不能使用点语法的现象,可以使用属性的getter方法,这样就不需要把元素额外拿出,节省代码。
- 设置row高度的方法是tableViewdelegate的方法。
- 方法中的次数,如果前面没有with或者for等次数修饰,则其首字母是要小写的。
- 某个类的代理协议名字和协议中的方法名字,一般都是以该类名开头的,而且方法中一般都要传进一个该类型的实例参数,虽然有时候没有使用该参数。如uiscrollview和UITableView及uialertview。
- <>在监听选中某个cell的方法中,创建了局部变量UIAlertView(alert),但是因为调用了他的show方法,所以在它可以传递到它的clickbutton方法中,方法中的alertview就代表上面创建的alert。因此这两种方法通过该对象建立了联系,如在上面方法中设置alert.tag = indexpath.row,在下面的方法中,再通过alertview.tag,既可以将indexpath.row取出。
- <>对于系统自带的类,其有些属性是readonly性质的,这代表它不可以被整体赋值,但是可以对该属性值的属性值进行修改。如textlabel是只读的,但是可以更改其text属性。有点类似于copy可变数组,copy属于深拷贝,copy后的数组是不可变的,但是其中的元素是浅拷贝。
- UITableView的image属性,属于分类(UIDeprecated),建议被弃用,但是还可以被调用。
5 疑问
- section和row以及header和footer的调用顺序和次数,有些混乱??
- 设置索引标题,排列很紧,没有散开?
- @interface UITableViewCell (UIDeprecated),这个是分类,为什么还可以添加属性(@property)?
- 如果textfield中内容为空,则cell中内容不做修改,为什么判断条件不成立??
6 待补充
- 熟悉UITableView的其它属性和方法。
- 属性UIAlert的其它属性和方法。
- 再进一步熟悉一下深浅拷贝