IOS开发基础—UITableView的基本使用。

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 重点 难点 注意点

  1. <>如果不设置section个数,则默认为1.
  2. 针对数组中元素是id类型,不能使用点语法的现象,可以使用属性的getter方法,这样就不需要把元素额外拿出,节省代码。
  3. 设置row高度的方法是tableViewdelegate的方法。
  4. 方法中的次数,如果前面没有with或者for等次数修饰,则其首字母是要小写的。
  5. 某个类的代理协议名字和协议中的方法名字,一般都是以该类名开头的,而且方法中一般都要传进一个该类型的实例参数,虽然有时候没有使用该参数。如uiscrollview和UITableView及uialertview。
  6. <>在监听选中某个cell的方法中,创建了局部变量UIAlertView(alert),但是因为调用了他的show方法,所以在它可以传递到它的clickbutton方法中,方法中的alertview就代表上面创建的alert。因此这两种方法通过该对象建立了联系,如在上面方法中设置alert.tag = indexpath.row,在下面的方法中,再通过alertview.tag,既可以将indexpath.row取出。
  7. <>对于系统自带的类,其有些属性是readonly性质的,这代表它不可以被整体赋值,但是可以对该属性值的属性值进行修改。如textlabel是只读的,但是可以更改其text属性。有点类似于copy可变数组,copy属于深拷贝,copy后的数组是不可变的,但是其中的元素是浅拷贝。
  8. UITableView的image属性,属于分类(UIDeprecated),建议被弃用,但是还可以被调用。

5 疑问

  1. section和row以及header和footer的调用顺序和次数,有些混乱??
  2. 设置索引标题,排列很紧,没有散开?
  3. @interface UITableViewCell (UIDeprecated),这个是分类,为什么还可以添加属性(@property)?
  4. 如果textfield中内容为空,则cell中内容不做修改,为什么判断条件不成立??

6 待补充

  1. 熟悉UITableView的其它属性和方法。
  2. 属性UIAlert的其它属性和方法。
  3. 再进一步熟悉一下深浅拷贝
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值