年年有"余"

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 4106|回复: 0

[实用控件] ios实战开发之UITableView应用(商品展示)

[复制链接]
  • TA的每日心情
    奋斗
    2022-12-13 21:26
  • 签到天数: 371 天

    [LV.9]以坛为家II

    发表于 2014-4-1 17:36:50 | 显示全部楼层 |阅读模式
    本帖最后由 Sian 于 2014-4-1 21:29 编辑

    1、效果演示



    2、过程说明
    2.1 使用storyboard画出基本界面(UITableView和ToolBar),并将UITableView代理设置为当前控制器,并设置为成员变量
    QQ20140401-1@2x.png

    2.2 准备好数据源,以备商品展示时调用,如商品图片,商品名,商品描述等;
    2.3 图片可直接导入到项目,商品名和商品描述及图片名用plist文件保存,如下图所示:
    QQ20140401-2@2x.png

    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
    1. //
    2. //  SAShop.h
    3. //  UITabelView-2
    4. //
    5. //  Created by yusian on 14-4-1.
    6. //  Copyright (c) 2014年 yusian. All rights reserved.
    7. //
    8. #import <Foundation/Foundation.h>
    9. @interface SAShop : NSObject
    10. // 三个成员变量属性
    11. @property (nonatomic, copy) NSString *icon;
    12. @property (nonatomic, copy) NSString *name;
    13. @property (nonatomic, copy) NSString *desc;
    14. // 两个构造方法方便快速创建模型
    15. + (id)shopWithDict:(NSDictionary *)dict;
    16. - (id)initWithDict:(NSDictionary *)dict;
    17. @end
    复制代码
    SAShop.m
    1. //
    2. //  SAShop.m
    3. //  UITabelView-2
    4. //
    5. //  Created by yusian on 14-4-1.
    6. //  Copyright (c) 2014年 yusian. All rights reserved.
    7. //
    8. #import "SAShop.h"
    9. @implementation SAShop
    10. // 构造方法实现
    11. + (id)shopWithDict:(NSDictionary *)dict
    12. {
    13.     return [[self alloc] initWithDict:dict];
    14. }
    15. - (id)initWithDict:(NSDictionary *)dict
    16. {
    17.     if (self = [super init]) {
    18.         self.name = dict[@"name"];
    19.         self.icon = dict[@"icon"];
    20.         self.desc = dict[@"desc"];
    21.     }
    22.     return self;
    23. }
    24. @end
    复制代码
    SAViewController.h
    1. //
    2. //  SAViewController.h
    3. //  UITabelView-2
    4. //
    5. //  Created by yusian on 14-4-1.
    6. //  Copyright (c) 2014年 yusian. All rights reserved.
    7. //
    8. #import <UIKit/UIKit.h>
    9. @interface SAViewController : UIViewController
    10. @property (weak, nonatomic) IBOutlet UITableView *tableView;
    11. @end
    复制代码
    SAViewController.m
    1. //
    2. //  SAViewController.m
    3. //  UITabelView-2
    4. //
    5. //  Created by yusian on 14-4-1.
    6. //  Copyright (c) 2014年 yusian. All rights reserved.
    7. //
    8. #import "SAViewController.h"
    9. #import "SAShop.h"
    10. #define kCount 20
    11. #define kCellHight 60
    12. // 本操作器充当TableView的数据源、TableView的代理、弹框(AlertView)的代理,因此要遵守以下三个协议
    13. @interface SAViewController () <UITableViewDataSource, UITableViewDelegate, UIAlertViewDelegate>
    14. {
    15.     NSMutableArray *_cars;
    16. }
    17. @end
    18. @implementation SAViewController
    19. #pragma mark View加载完后调用
    20. - (void)viewDidLoad
    21. {
    22.     [super viewDidLoad];
    23.    
    24.     // 从文件读取数据到程序
    25.     NSString *path = [[NSBundle mainBundle] pathForResource:@"Des.plist" ofType:nil];
    26.     NSArray *data= [[NSArray alloc] initWithContentsOfFile:path];
    27.    
    28.     // 传承面向对象的思想,将一条商品展示信息抽象成一个类,通过该类来创建多个对象,并且对象具备三个成员变量:图标、名称、描述
    29.     // 当前只有5条商品素材,为使展示信息丰富一点,通过for循环创建从这5条商品素材中提取数据,创建20个对象
    30.     // 将这20个对象存储到全局数组中,便于后续使用
    31.     _cars = [NSMutableArray array];
    32.     for (int i = 0; i < kCount; i++) {
    33.         SAShop *shop = [SAShop shopWithDict:data[i % data.count]];
    34.         [_cars addObject:shop]; // 将对象添加到数组,循环20次即数组中保存20个对象
    35.     }
    36. }
    37. #pragma mark 数据源方法一(Table行数)
    38. // 做为UITableView的数据源必须实现的两个方法之一,返回数据行数,返回数组长度可以实现让数据决定界面展示
    39. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    40. {
    41.     return _cars.count;
    42. }
    43. #pragma mark 数据源方法二(创建cell)
    44. // UITableView数据源必须实现的两个方法之一,创建每行(UITabelViewCell)的内容
    45. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    46. {
    47.     // 创建一个shop对象,一个cell对象,该方法会被动态调用n次,n等于表格行数
    48.     // 每次调用都会传入当前行号(indexPath.row)进来,利用该变量可以实现动态取数组中的对象,即对象中的值
    49.     // 将动态获取到的值分别赋值给每一个cell,可实现表格不同行上展示不同的商品信息
    50.     SAShop *shop = _cars[indexPath.row];
    51.     static NSString *ID = @"t"; // 加static关键字,使得局部变量保持不被释放,变量被存储到静态区
    52.    
    53.     // 考虑到性能优化,如果缓存池中存在带有该标记的对象则重复使用
    54.     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    55.     if (nil == cell) {
    56.         
    57.         // 如果没有则分配空间创建,并在创建时做相关标记以便重复利用
    58.         cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    59.     }
    60.    
    61.     cell.imageView.image = [UIImage imageNamed:shop.icon];  // 图片名赋值
    62.     cell.textLabel.text = shop.name;    // 商品名赋值
    63.     cell.detailTextLabel.text = shop.desc;  // 商品描述赋值
    64.     cell.detailTextLabel.textColor = [UIColor lightGrayColor];
    65.    
    66.     cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;   // 每行后面的">"图标
    67.     return cell;
    68. }
    69. #pragma mark UITableView代理方法 -- cell高度
    70. // UITableView代理方法:设置每行表格的高度
    71. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
    72. {
    73.     return kCellHight;  // 返回60个像素高
    74. }
    75. #pragma mark UITableView代理方法 -- 触摸事件
    76. // UITableView代理的另一个方法,当选择(点击或触摸)某行时所执行的动作
    77. -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    78. {
    79.     SAShop *shop = _cars[indexPath.row];    // 先创建一个对象指针,指向当前行在数组中所对应的商品对象;
    80.    
    81.     // 创建一个弹窗(UIAlertView)并初始化弹窗的样式,设置标题、设置当前控制器为该弹窗的代理、设置两个按钮(按钮有序号,从0开始标记)
    82.     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"修改汽车名称" message:nil delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
    83.    
    84.     alert.alertViewStyle = UIAlertViewStylePlainTextInput;  // 设置弹窗的样式为单文本输入框样式(还有密码输入/用户名密码输入等)
    85.     [alert textFieldAtIndex:0].text = shop.name;    // 设置文本输入框中默认值为当前商品名称
    86.    
    87.     alert.tag = indexPath.row;  // 记录当前行号到tag字段,这个是额外处理,主要是为方便将该值通过参数传递能带给其他方法
    88.    
    89.     [alert show];   // 显示弹窗
    90. }
    91. #pragma mark UIAlertView代理方法 -- 按钮事件
    92. // 由于在弹窗中有事件处理,所以需要一个方法来响应弹窗中的相关事件,由于上一个方法中已经将一控制器设置为弹窗的代理,所以需要在这里实现相关方法
    93. - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    94. {
    95.     // 该方法将UIAlertView通过参数传递进来,UIAlertView中几个关键参数
    96.     // 1、按钮序号;2、弹窗所发生的cell所在行
    97.     // 由于上一个方法中通过将indexPath.row赋值给弹窗的tag字段,所以UIAlertView会将这两个值带过来
    98.     if (0 == buttonIndex) return;   // 如果buttonIndex==0则说明点击的是取消按钮,不执行任何操作
    99.    
    100.     // 如果点击确定,将当前弹窗中第0个textField(这里只有一个,在有用户名密码输入的rextField中就会有多个)中的信息赋值给当前行商品信息名称
    101.     // 这个步骤是整个程序的难点,也是最关键的业务部分,也是处理最为巧妙的部分
    102.     SAShop *shop = _cars[alertView.tag];
    103.     NSString *str = [alertView textFieldAtIndex:0].text;
    104.     shop.name = str;
    105.    
    106.     // 数据处理完毕后刷新UITableView,展示新信息
    107.     // [_tableView reloadData];
    108.    
    109.     // 最好的方法是局部刷新,局部刷新的方法中需要传递参数为NSIndexPath类型的数组
    110.     NSIndexPath *indexPath = [NSIndexPath indexPathForRow:alertView.tag inSection:0];
    111.     NSArray *array = @[indexPath];  // 由于只修改了一行,所以该数组中只有一个元素
    112.    
    113.     [_tableView reloadRowsAtIndexPaths:array withRowAnimation:UITableViewRowAnimationLeft]; // 局部刷新
    114.    
    115. }
    116. @end
    复制代码
    4、源代码下载
    游客,本帖隐藏的内容需要积分高于 1 才可浏览,您当前积分为 0



    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    手机版|小黑屋|Archiver|iOS开发笔记 ( 湘ICP备14010846号 )

    GMT+8, 2024-4-27 18:52 , Processed in 0.057843 second(s), 26 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表