Sian 发表于 2014-4-1 17:36:50

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]
查看完整版本: ios实战开发之UITableView应用(商品展示)