ios实战开发之UITableView应用(商品展示)
本帖最后由 Sian 于 2014-4-1 21:29 编辑1、效果演示
http://player.youku.com/player.php/sid/XNjkzMDgxODEy/v.swf
2、过程说明
2.1 使用storyboard画出基本界面(UITableView和ToolBar),并将UITableView代理设置为当前控制器,并设置为成员变量
2.2 准备好数据源,以备商品展示时调用,如商品图片,商品名,商品描述等;
2.3 图片可直接导入到项目,商品名和商品描述及图片名用plist文件保存,如下图所示:
2.4 创建一个用于展示商品的类,该类的成员变量即为图片名称、商品名称、商品描述,一条商品信息即为一个对象(其他方法也能实现,但这是面向对象的思想);
2.5 UITableView数据加载;
2.5.1 设置数据源(在storybord画UITableView时就已设置当前控制器为dataSource);
2.5.2 数据源必须实现的两个方法(设置总行数、每行内容初始化),关键点在于将行数与每行内容通过数据动态更新而不修改代码。
2.6 设置监听方法,监听UITableViewCell被点击(触摸)事件,并做出响应,这个为代理方法实现;
2.7 监听方法中涉及到弹窗事件,弹窗为另外一个类,该类的代理又设置为当前控制器,所以控制再实现这个代理的相关方法
2.8 实现UIAlertView代理方法,实现通过弹窗修改商品名称
3、关键代码
SAShop.h
//
//SAShop.h
//UITabelView-2
//
//Created by yusian on 14-4-1.
//Copyright (c) 2014年 yusian. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface SAShop : NSObject
// 三个成员变量属性
@property (nonatomic, copy) NSString *icon;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *desc;
// 两个构造方法方便快速创建模型
+ (id)shopWithDict:(NSDictionary *)dict;
- (id)initWithDict:(NSDictionary *)dict;
@end
SAShop.m
//
//SAShop.m
//UITabelView-2
//
//Created by yusian on 14-4-1.
//Copyright (c) 2014年 yusian. All rights reserved.
//
#import "SAShop.h"
@implementation SAShop
// 构造方法实现
+ (id)shopWithDict:(NSDictionary *)dict
{
return [ initWithDict:dict];
}
- (id)initWithDict:(NSDictionary *)dict
{
if (self = ) {
self.name = dict[@"name"];
self.icon = dict[@"icon"];
self.desc = dict[@"desc"];
}
return self;
}
@end
SAViewController.h
//
//SAViewController.h
//UITabelView-2
//
//Created by yusian on 14-4-1.
//Copyright (c) 2014年 yusian. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface SAViewController : UIViewController
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@end
SAViewController.m
//
//SAViewController.m
//UITabelView-2
//
//Created by yusian on 14-4-1.
//Copyright (c) 2014年 yusian. All rights reserved.
//
#import "SAViewController.h"
#import "SAShop.h"
#define kCount 20
#define kCellHight 60
// 本操作器充当TableView的数据源、TableView的代理、弹框(AlertView)的代理,因此要遵守以下三个协议
@interface SAViewController () <UITableViewDataSource, UITableViewDelegate, UIAlertViewDelegate>
{
NSMutableArray *_cars;
}
@end
@implementation SAViewController
#pragma mark View加载完后调用
- (void)viewDidLoad
{
;
// 从文件读取数据到程序
NSString *path = [ pathForResource:@"Des.plist" ofType:nil];
NSArray *data= [ initWithContentsOfFile:path];
// 传承面向对象的思想,将一条商品展示信息抽象成一个类,通过该类来创建多个对象,并且对象具备三个成员变量:图标、名称、描述
// 当前只有5条商品素材,为使展示信息丰富一点,通过for循环创建从这5条商品素材中提取数据,创建20个对象
// 将这20个对象存储到全局数组中,便于后续使用
_cars = ;
for (int i = 0; i < kCount; i++) {
SAShop *shop = ];
; // 将对象添加到数组,循环20次即数组中保存20个对象
}
}
#pragma mark 数据源方法一(Table行数)
// 做为UITableView的数据源必须实现的两个方法之一,返回数据行数,返回数组长度可以实现让数据决定界面展示
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _cars.count;
}
#pragma mark 数据源方法二(创建cell)
// UITableView数据源必须实现的两个方法之一,创建每行(UITabelViewCell)的内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 创建一个shop对象,一个cell对象,该方法会被动态调用n次,n等于表格行数
// 每次调用都会传入当前行号(indexPath.row)进来,利用该变量可以实现动态取数组中的对象,即对象中的值
// 将动态获取到的值分别赋值给每一个cell,可实现表格不同行上展示不同的商品信息
SAShop *shop = _cars;
static NSString *ID = @"t"; // 加static关键字,使得局部变量保持不被释放,变量被存储到静态区
// 考虑到性能优化,如果缓存池中存在带有该标记的对象则重复使用
UITableViewCell *cell = ;
if (nil == cell) {
// 如果没有则分配空间创建,并在创建时做相关标记以便重复利用
cell = [ initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}
cell.imageView.image = ;// 图片名赋值
cell.textLabel.text = shop.name; // 商品名赋值
cell.detailTextLabel.text = shop.desc;// 商品描述赋值
cell.detailTextLabel.textColor = ;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; // 每行后面的">"图标
return cell;
}
#pragma mark UITableView代理方法 -- cell高度
// UITableView代理方法:设置每行表格的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return kCellHight;// 返回60个像素高
}
#pragma mark UITableView代理方法 -- 触摸事件
// UITableView代理的另一个方法,当选择(点击或触摸)某行时所执行的动作
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SAShop *shop = _cars; // 先创建一个对象指针,指向当前行在数组中所对应的商品对象;
// 创建一个弹窗(UIAlertView)并初始化弹窗的样式,设置标题、设置当前控制器为该弹窗的代理、设置两个按钮(按钮有序号,从0开始标记)
UIAlertView *alert = [ initWithTitle:@"修改汽车名称" message:nil delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;// 设置弹窗的样式为单文本输入框样式(还有密码输入/用户名密码输入等)
.text = shop.name; // 设置文本输入框中默认值为当前商品名称
alert.tag = indexPath.row;// 记录当前行号到tag字段,这个是额外处理,主要是为方便将该值通过参数传递能带给其他方法
; // 显示弹窗
}
#pragma mark UIAlertView代理方法 -- 按钮事件
// 由于在弹窗中有事件处理,所以需要一个方法来响应弹窗中的相关事件,由于上一个方法中已经将一控制器设置为弹窗的代理,所以需要在这里实现相关方法
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
// 该方法将UIAlertView通过参数传递进来,UIAlertView中几个关键参数
// 1、按钮序号;2、弹窗所发生的cell所在行
// 由于上一个方法中通过将indexPath.row赋值给弹窗的tag字段,所以UIAlertView会将这两个值带过来
if (0 == buttonIndex) return; // 如果buttonIndex==0则说明点击的是取消按钮,不执行任何操作
// 如果点击确定,将当前弹窗中第0个textField(这里只有一个,在有用户名密码输入的rextField中就会有多个)中的信息赋值给当前行商品信息名称
// 这个步骤是整个程序的难点,也是最关键的业务部分,也是处理最为巧妙的部分
SAShop *shop = _cars;
NSString *str = .text;
shop.name = str;
// 数据处理完毕后刷新UITableView,展示新信息
// ;
// 最好的方法是局部刷新,局部刷新的方法中需要传递参数为NSIndexPath类型的数组
NSIndexPath *indexPath = ;
NSArray *array = @;// 由于只修改了一行,所以该数组中只有一个元素
; // 局部刷新
}
@end
4、源代码下载
**** Hidden Message *****
页:
[1]