Ui学习--UITableView

UI学习

  • UITableView基础
  • UITableView协议
  • UITableView高级协议与单元格
  • 总结


UITableView基础

UITableView作为iOS中的一个控件,用于以表格形式展示数据。例如通讯录好友,朋友圈信息等,都是UITableView的实际运用场景。
首先我们先要加入两个协议:UITableViewDelegate,UITableViewDataSource
在这两个协议中,有必须实现的四个协议方法:

  1. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section :获取每组元素的个数
  2. -(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView:获取每组元素的行数
  3. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath:创建单元格对象函数。

然后我们现在接口文件中添加协议和UITableView对象


#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
<
//实现数据视图的普通协议
//数据视图的普通事件处理
UITableViewDelegate,
//实现数据视图的数据代理协议
//实现数据视图的数据代理
UITableViewDataSource
>
{
    //定义一个数据视图对象
    //数据视图用来显示大量相同格式的大量信息的视图
    //例如:电话通讯录,QQ好友,朋友圈信息
    //相同格式信息内容不同
    UITableView *_tablelView;
}

@end

然后我们在实现部分创建数据视图并实现协议函数


#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    //创建数据视图,传入两个参数
    //参一:数据视图的位置
    //参二:数据视图的风格
    //UITableViewStylePlain:普通风格
    //UITableViewStyleGrouped:分组风格
    _tablelView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
    
    //设置数据视图的代理对象
    _tablelView.delegate = self;
    
    //设置数据视图的数据源对象
    _tablelView.dataSource = self;
    
    [self.view addSubview:_tablelView];
}

//获取每组元素的个数(行数)
//必须要实现的协议函数
//程序在显示数据视图是会调用此函数
//返回值:表示每组元素的个数
//P1:数据视图对象本身
//P2:哪一组需要的行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 6;
}

-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
    return 4;
}


//创建单元格对象函数

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellStr = @"cell";
    
    UITableViewCell *cell = [_tablelView dequeueReusableCellWithIdentifier:cellStr];
    
    if (cell == nil) {
        //创建一个单元格对象
        //参一:单元格的样式
        //参二:单元格的复用标记
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellStr];
    }
    NSString *str = [NSString stringWithFormat:@"第%ld组,第%ld行", indexPath.section, indexPath.row];
    
    //将单元格的主文字内容赋值
    cell.textLabel.text = str;
    
    return cell;
}
@end

效果:
在这里插入图片描述


UITableView协议

我们在此处学习如下几个协议:

  1. - (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath:获取单元格高度
  2. -(NSString*) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section:获取每组头部标题
  3. -(NSString*) tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section:获取每组尾部标题
  4. - (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section:获取头部高度
  5. -(CGFloat) tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section:获取尾部高度

我们省略接口部分,给出实现部分并将上述协议实现:


#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    //创建数据视图对象
    _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
    
    //设置代理对象
    _tableView.delegate = self;
    //设置数据代理对象
    _tableView.dataSource = self;
    //数据视图显示
    [self.view addSubview:_tableView];
    
    //创建一个可变数组
    _arrayData = [[NSMutableArray alloc] init];
    
    for (int i = 'A'; i <= 'Z'; i++) {
        //定义小数组
        NSMutableArray *arraySmall = [[NSMutableArray alloc] init];
        
        for (int j = 1; j <= 5 ; j++) {
            NSString *str = [NSString stringWithFormat:@"%c%d", i, j];
            
            [arraySmall addObject:str];
        }
        //生成一个二维数组
        [_arrayData addObject:arraySmall];
    }
}

//获取组数
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
    return _arrayData.count;
}

//获取每组的元素个数
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    NSInteger numRow = [[_arrayData objectAtIndex:section] count];
    
    return numRow;
}

-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *str = @"cell";
    
    UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:str];
    
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:str];
    }
    
    cell.textLabel.text = _arrayData[indexPath.section][indexPath.row];
    
    return cell;
}

//获取高度
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 100;
}

//获取每组头部标题
-(NSString*) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return @"哈哈!";
}

//获取每组尾部标题
-(NSString*) tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
    return @"尾巴哈哈";
}

//获取头部高度
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 40;
}

//获取尾部高度
-(CGFloat) tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    return 60;
}

@end

注意:这些协议函数是可选择实现的
效果:
在这里插入图片描述


UITableView高级协议与单元格

我们在此处学习以下高级协议:

  1. - (UITableViewCellEditingStyle) tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath:单元格显示效果协议
  2. - (void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath:当手指在单元格上移动时,显示编辑状态
  3. - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath:选中单元格
  4. -(void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath:取消所选单元格,需要在已选择单元格后再选另一单元格后调用。

我们先在接口文件中创建对象,并在SceneDelegate文件里添加导航控制器。

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
<UITableViewDelegate,
UITableViewDataSource
>

{
    //数据视图
    UITableView *_tableView;
    //数据源
    NSMutableArray* _arrayData;
    
    //添加导航按钮
    UIBarButtonItem *btnEdit;
    UIBarButtonItem *btnFinish;
    UIBarButtonItem *btnDelete;
    //设置编辑状态
    BOOL isEdit;
}
@end

然后,我们在实现部分中,完成对导航栏按钮的创建。并且实现高级协议。


#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
    
    //自动调整子视图大小
    _tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    
    //设置代理
    _tableView.delegate = self;
    _tableView.dataSource = self;
    
    //数据视图的头部视图的设定
    _tableView.tableHeaderView = nil;
    //数据视图的尾部视图
    _tableView.tableFooterView = nil;
        
    [self.view addSubview:_tableView];
    
    //初始化数据源数组
    
    _arrayData = [[NSMutableArray alloc] init];
    
    for (int i = 1; i < 20; i++) {
        NSString *str = [NSString stringWithFormat:@"A %d",i];
        
        [_arrayData addObject:str];
    }
    
    //当数据的数据源发生变化时,
    //更新数据视图,重新加载数据
    [_tableView reloadData];
    
    [self createBtn];
}

-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return _arrayData.count;
}

//默认情况下
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

-(UITableViewCell*) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *strID = @"ID";

    //尝试获取可以复用的单元格
    //如歌得不到,返回nil
    UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:strID];
    
    //需要显示子标题必须为UITableViewCellStyleSubtitle
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:strID];
    }
    
    //单元格文字赋值
    cell.textLabel.text = [_arrayData objectAtIndex:indexPath.row];
    
    cell.detailTextLabel.text = @"儿子标题";
    
    NSString *str = [NSString stringWithFormat:@"%d.jpg",(indexPath.row % 10 + 1)];
    
    UIImage *image = [UIImage imageNamed:str];
    
    UIImageView *iView = [[UIImageView alloc] initWithImage:image];
    
    cell.imageView.image = image;
    // UIImageView *iView = [[UIImageView alloc] initWithImage:image]
    //设置默认的图标信息
    return cell;
    
   
}

-(void) createBtn
{
    isEdit = NO;
    
    btnEdit = [[UIBarButtonItem alloc] initWithTitle:@"编辑" style:UIBarButtonItemStylePlain target:self action:@selector(pressEdit)];
    btnFinish = [[UIBarButtonItem alloc] initWithTitle:@"完成" style:UIBarButtonItemStylePlain target:self action:@selector(pressFinish)];
    btnDelete = [[UIBarButtonItem alloc] initWithTitle:@"删除" style:UIBarButtonItemStylePlain target:self action:@selector(pressDelete)];
    
    self.navigationItem.rightBarButtonItem = btnEdit;
    
}

-(void) pressEdit
{
    isEdit = YES;
    self.navigationItem.rightBarButtonItem = btnFinish;
    [_tableView setEditing:YES];
    self.navigationItem.leftBarButtonItem = btnDelete;
    
}

-(void) pressFinish
{
    isEdit = NO;
    self.navigationItem.rightBarButtonItem = btnEdit;
    [_tableView setEditing:NO];
    self.navigationItem.leftBarButtonItem = nil;
    
}


- (void)pressDelete {
    // 获取被选中的行的索引集合
    NSArray *selectedRows = [_tableView indexPathsForSelectedRows];
    
    if (selectedRows.count > 0) {
        // 创建一个可变数组,用于存储需要删除的数据
        NSMutableArray *rowsToDelete = [NSMutableArray array];
        
        for (NSIndexPath *indexPath in selectedRows) {
            // 获取需要删除的数据的索引
            NSInteger row = indexPath.row;
            
            // 添加到需要删除的数据数组中
            [rowsToDelete addObject:[NSNumber numberWithInteger:row]];
        }
        
        // 排序需要删除的数据的索引,以确保正确删除
        NSArray *sortedRows = [rowsToDelete sortedArrayUsingSelector:@selector(compare:)];
        
        // 逆序遍历需要删除的数据的索引,从数据源数组中删除对应的数据
        for (NSInteger i = sortedRows.count - 1; i >= 0; i--) {
            NSInteger deleteRow = [sortedRows[i] integerValue];
            [_arrayData removeObjectAtIndex:deleteRow];
        }
        
        // 删除对应的行
        [_tableView deleteRowsAtIndexPaths:selectedRows withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}
//单元格显示效果协议
- (UITableViewCellEditingStyle) tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
    //默认为删除
    //UITableViewCellEditingStyleDelete:删除
    //UITableViewCellEditingStyleInsert:插入
    //UITableViewCellEditingStyleNone:空
    //多选状态UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert
    return UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert;
}

//可以显示编辑状态,当手指在单元格上移动时。
- (void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    //删除数据源对应的数据
    [_arrayData removeObjectAtIndex:indexPath.row];
    //数据源更新
    [_tableView reloadData];
    
    
    
    NSLog(@"delete!");
}

//选中时调用
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"选中单元格! %ld, %ld",(long)indexPath.section, (long)indexPath.row);
}

//取消时调用
-(void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"取消选中单元格! %ld, %ld",(long)indexPath.section, (long)indexPath.row);
}
@end

我们通过加入一个布尔变量isEdit来判断是否处于编辑状态。在编辑状态下,我们可以对单元格进行插入,删除等操作。
通过使用UITableViewCellEditingStyleDelete|UITableViewCellEditingStyleInsert多选状态,我们可以实现批量删除的操作。
多选后,我们需要重新写编辑状态的删除按钮。即:

- (void)pressDelete {
    // 获取被选中的行的索引集合
    NSArray *selectedRows = [_tableView indexPathsForSelectedRows];
    
    if (selectedRows.count > 0) {
        // 创建一个可变数组,用于存储需要删除的数据
        NSMutableArray *rowsToDelete = [NSMutableArray array];
        
        for (NSIndexPath *indexPath in selectedRows) {
            // 获取需要删除的数据的索引
            NSInteger row = indexPath.row;
            
            // 添加到需要删除的数据数组中
            [rowsToDelete addObject:[NSNumber numberWithInteger:row]];
        }
        
        // 排序需要删除的数据的索引,以确保正确删除
        NSArray *sortedRows = [rowsToDelete sortedArrayUsingSelector:@selector(compare:)];
        
        // 逆序遍历需要删除的数据的索引,从数据源数组中删除对应的数据
        for (NSInteger i = sortedRows.count - 1; i >= 0; i--) {
            NSInteger deleteRow = [sortedRows[i] integerValue];
            [_arrayData removeObjectAtIndex:deleteRow];
        }
        
        // 删除对应的行
        [_tableView deleteRowsAtIndexPaths:selectedRows withRowAnimation:UITableViewRowAnimationAutomatic];
    }
}

效果:
在这里插入图片描述


总结

以上就是对UITableView粗略的学习,还有许多未知的领域等待探索。
下一步,自定义cell和cell的复用!在学习中不断有进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/714180.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

苹果加大AI布局,上海新店开业昭示中国市场新动向

随着全球科技巨头纷纷进军人工智能领域&#xff0c;苹果公司亦不甘示弱&#xff0c;近期在上海静安新店的开业以及CEO蒂姆库克的一系列动作&#xff0c;都显示出苹果在AI方面的雄心壮志。这不仅是对未来技术趋势的积极回应&#xff0c;更是对市场竞争态势的精准把握。 库克的访…

CSS从入门到精通——动画:CSS3动画延迟和完成后状态的保持

目录 任务描述 相关知识 动画状态 动画完成时的状态 动画延迟 编程要求 任务描述 本关任务&#xff1a;用 CSS3 实现小车等待红绿灯的效果。效果图如下&#xff1a; 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.动画状态&#xff0c;2.动画完成时的状…

奥特曼谈AI的机遇、挑战与人类自我反思:中国将拥有独特的大语言模型

奥特曼在对话中特别提到&#xff0c;中国将在这个领域扮演重要角色&#xff0c;孕育出具有本土特色的大语言模型。这一预见不仅彰显了中国在全球人工智能领域中日益增长的影响力&#xff0c;也预示着未来技术发展的多元化趋势。 ①奥特曼认为AI在提升生产力方面已显现积极作用&…

一文了解Redis

一.什么是Redis 与MySQL一样&#xff0c;Redis也是客户端服务器结构的程序&#xff0c;是基于内存的键值对存储系统&#xff0c;属于NoSQL的一种。与很多键值对数据库不同的是&#xff0c;Redis 中的值可以是由 string&#xff08;字符串&#xff09;、hash&#xff08;哈希&a…

探索Chrome DevTools的高级技巧与隐藏功能

Chrome DevTools是网页开发者不可或缺的调试工具&#xff0c;它提供了丰富的功能&#xff0c;帮助开发者快速诊断和解决问题。然而&#xff0c;除了常见的功能&#xff0c;如元素检查、网络监控和JavaScript调试之外&#xff0c;DevTools还有许多不为人知的强大功能和技巧。本文…

Paragon NTFS for Mac 15软件下载-详细安装教程视频

​Paragon NTFS for Mac是Mac平台上一款非常优秀的读写工具&#xff0c;可以在Mac OS X中完全读写、修改、访问NTFS硬盘、U盘等外接设备的文件。这款软件最大的亮点简书可以让我们读写 NTFS 分区&#xff0c;因为在Mac OS X 系统上&#xff0c;默认状态下我们只能读取NTFS 分区…

有趣的傅里叶变换与小波变换对比(Python)

不严谨的说&#xff0c;时域和频域分析就是在不同的空间看待问题的&#xff0c;不同空间所对应的原子(基函数)是不同的。你想一下时域空间的基函数是什么&#xff1f;频域空间的基函数是什么&#xff1f;一般的时-频联合域空间的基函数是什么&#xff1f;小波域空间的基函数是什…

Win11安装WSA 安卓系统,然后再电脑安装APK文件

参考文章&#xff1a; https://blog.csdn.net/m0_56076343/article/details/122334759 https://blog.csdn.net/u012514495/article/details/120885242 在微软的网站下载 打开&#xff1a;https://store.rg-adguard.net/ &#xff0c;如下图&#xff1a; 在 1 的那个地方&am…

二维数组与指针【C语言】

二维数组与指针 一维数组一维数组与指针二维数组二维数组与指针总结补充判断以下方式是否正确打印二维数组一维数组 int arr[] = {11, 22, 33, 44};arr:首地址(第一个元素的地址) 一维数组与指针 int arr[] = {11, 22, 33, 44};因为,arr表示的是首地址,等价于 int* p =…

谷粒商城实战(033 业务-秒杀功能4-高并发问题解决方案sentinel 2)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第332p-第p335的内容 熔断降级 开启对Feign远程服务的熔断保护机制 feign.sentinel.enabletrue 这里我们只是调用方加就行 被调用方不用加 正常…

PD19 Parallels Desktop 虚拟机 安装Windows10系统 操作步骤(保姆级教程,轻松上手)

Mac分享吧 文章目录 效果一、准备工作二、开始安装1、打开pd 19 虚拟机&#xff0c;点击右上角文件&#xff0c;新建2、通过下载好的镜像安装Windows10系统。找到镜像文件位置&#xff0c;安装&#xff0c;配置2、显示安装完成&#xff0c;打开Windows10系统 三、运行测试1、打…

SQLAlchemy:filter()和filter_by()的微妙差异

哈喽&#xff0c;大家好&#xff0c;我是木头左&#xff01; 在Python编程中&#xff0c;SQLAlchemy是一个强大的ORM&#xff08;对象关系映射&#xff09;工具&#xff0c;它允许使用Python代码来操作数据库。然而&#xff0c;对于新手来说&#xff0c;SQLAlchemy中的一些函数…

cocos开发的时候 wx.onShow在vscode里面显示红色

这个函数是在微信小游戏平台才会用到。 cocos识别不到wx这个变量。 可以改成下面的写法。 只要在变量前面加一个globalThis.就能识别这个变量了。也不报错了。 搞死强迫症了。orz 欢迎大家来玩我的微信小游戏。多多提意见啊。

【Java】图的初识

文章目录 【Java】图的初识图是什么图的基本组成部分图的类型图的表示方法图的常见操作 Java中图的表示方法邻接矩阵邻接表 常见操作图的遍历深度优先搜索&#xff08;DFS&#xff09;广度优先搜索&#xff08;BFS) 结论 【Java】图的初识 图是什么 图是一种数学概念&#xf…

[Linux] TCP协议介绍(1): TCP协议 数据格式、可靠性的控制、标记位... 简单介绍

上一篇文章, 针对UDP协议的格式、数据等内容做了一些简单的介绍. 并且提到, 在网络协议栈TCP/IP模型的传输层中, 有两个最具代表性的协议: UDP和TCP 下面就简单介绍分析一下TCP协议 TCP协议, 完整的称呼其实叫: 传输控制协议(Transmission Control Protocol) 从名字就可以看出…

Vue51-插件

一、插件的定义 vue里面的插件&#xff0c;类似于游戏的外挂。 vue中插件的本质&#xff1a;一个对象&#xff0c;里面必须包含install方法。 二、插件的使用 2-1、创建一个插件js文件&#xff08;写在src中plugins.js&#xff09; 2-2、应用插件&#xff1a;Vue.use(插件) …

基于Python+OpenCV高速公路行驶车辆的速度检测系统

简介&#xff1a; 基于Python和OpenCV的高速公路行驶车辆的速度检测系统旨在实时监测高速公路上的车辆&#xff0c;并测量它们的速度。该系统可以用于交通监控、道路安全管理等领域&#xff0c;为相关部门提供重要的数据支持。 系统实现&#xff1a; 视频流输入&#xff1a;系…

Python学习打卡:day07

day7 笔记来源于&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了 目录 day753、列表的常用操作课后练习题54、列表的循环遍历列表的遍历—— while 循环列表的遍历—— for 循环while 循环和 for 循环的对比练习 55、元组…

解决使用Jmeter进行测试时出现“302“,‘‘401“等用户未登录的问题

使用 JMeter 压力测试时解决登录问题的两种方法 在使用 JMeter 进行压力测试时&#xff0c;可能会遇程序存在安全验证&#xff0c;必须登录后才能对里面的具体方法进行测试&#xff1a; 如果遇到登录问题&#xff0c;通常是因为 JMeter 无法模拟用户的登录状态&#xff0c;导…

工程设计问题---行星轮系设计问题

该问题的主要目标是使汽车传动比的最大误差最小。为了使最大误差最小&#xff0c;对自动行星传动系统的齿轮齿数进行了计算。该问题包含6个整数变量和11个不同几何约束和装配约束的约束。 参考文献&#xff1a; Abhishek Kumar, Guohua Wu, Mostafa Z. Ali, Rammohan Malliped…