上个项目我们完成了 JXHomepwner 简单的应用展示,项目地址。本节我们需要在上节项目基础上,增加一些响应用户操作。包括添加,删除和移动表格。

  • 编辑模式

  UITableView 有一个名为  editing 的属性,如果将其设置为  YES UITableView 就会进入编辑模式。在编辑模式下,用户可以管理 UITableView 中的表格行,我们可以添加、删除和移动等操作。但是编辑模式没有听过修改行的内容的功能。

  首先要更新界面,使用户可以将 UITableView 对象设置为编辑模式。示例程序是为 UITableView 对象的 表头视图 增加一个按钮,然后通过按钮使  UITableView 对象进入或者退出编辑模式。表头视图是指 UITableView 对象可以在其表格上方显示特定视图,适合放置针对某个表格段或者整张表格的标题和控件。表头视图可以是任意的 UIView 对象。

  表头视图有两种,分别针对表格段和表格。类似的,还有 表尾视图 也具有表格段和表格两种。

  接下来创建一个针对表格的表头视图。这个表头视图包含两个 UIButton 对象,其中一个负责切换 UITableView 对象的编辑模式,另一个负责创建新的 JXItem 对象并加入 UITableView 对象。可以使用代码,也可以使用 XIB 方式来创建。

#import "JXItemsViewController.h"
#import "JXItem.h"
#import "JXItemStore.h" @interface JXItemsViewController ()
/** 头部视图 */
@property (nonatomic,weak) UIView * headerView;
/** 编辑按钮 */
@property (nonatomic,strong) UIButton * editButton;
@end @implementation JXItemsViewController - (instancetype)init {
// 调用父类的指定初始化方法
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
for (NSInteger i=; i<; i++) {
[[JXItemStore sharedStore] createItem];
}
}
return self;
} - (instancetype)initWithStyle:(UITableViewStyle)style {
return [self init];
}
- (void)viewDidLoad {
[super viewDidLoad]; // 向控制器注册
[self.tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:@"UITableViewCell"]; // 加载头视图
[self headerView];
} #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[[JXItemStore sharedStore] allItem] count];
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// 创建 UITableViewCell 对象,风格使用默认风格
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"
forIndexPath:indexPath];
// 获取 allItem 的第 n 个 JXItem 对象
// 然后将该 JXItem 对象的描述信息赋值给 UITableViewCell 对象的 textLabel
// 这里的 n 是该 UITableViewCell 对象所对应的表格索引
NSArray * items = [[JXItemStore sharedStore] allItem];
JXItem * item = items[indexPath.row]; cell.textLabel.text = [item description];
return cell;
} #pragma mark - 懒加载
- (UIView *)headerView{
if (_headerView == nil) {
UIView * headerView = [[UIView alloc] initWithFrame:CGRectMake(, , self.view.bounds.size.width, )];
// 设置头部视图
self.tableView.tableHeaderView = headerView;
headerView.backgroundColor = [UIColor cyanColor];
[headerView addSubview:self.editButton];
_headerView = headerView;
}
return _headerView;
} - (UIButton *)editButton{
if (_editButton == nil) {
_editButton = [UIButton buttonWithType:UIButtonTypeCustom];
_editButton.frame = CGRectMake(, , self.view.bounds.size.width / , );
[_editButton setTitle:@"Edit" forState:UIControlStateNormal];
_editButton.backgroundColor = [UIColor greenColor];
[_editButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[_editButton addTarget:self action:@selector(editClick:) forControlEvents:UIControlEventTouchDown];
}
return _editButton;
} #pragma mark - 点击事件
- (void)editClick:(UIButton *)sender {
if (self.isEditing) { // 如果是编辑状态,取消编辑 // 更改文字
[sender setTitle:@"Edit" forState:UIControlStateNormal]; // 取消编辑
[self setEditing:NO animated:YES];
} else { // 更改文字
[sender setTitle:@"Done" forState:UIControlStateNormal]; // 开始编辑
[self setEditing:YES animated:YES];
}
}
@end

  构建并运行结果

  • 增加行

  通常有两种方式可以在运行时为 UITableView 对象增加行。

  * 在表视图上方放置添加按钮。如果数据的字段比较多的话,就需要显示一个用于输入的详细视图,就可以使用这种方式。例如,在iOS自带通讯录中,点击添加按钮。

  * 在 UITableViewCell 对象左边显示一个绿色加号按钮。在为数据添加一个新字段时可以使用这种方式。在联系人应用中为联系人添加生日。

 本节采用另一种方式:在  headView 中放置一个标题为 New 的按钮。当用户点击这个按钮,添加一行新数据。

#import "JXItemsViewController.h"
#import "JXItem.h"
#import "JXItemStore.h" @interface JXItemsViewController ()
/** 头部视图 */
@property (nonatomic,weak) UIView * headerView;
/** 编辑按钮 */
@property (nonatomic,strong) UIButton * editButton; /** 增加按钮 */
@property (nonatomic,strong) UIButton * addButton;
@end @implementation JXItemsViewController - (instancetype)init {
// 调用父类的指定初始化方法
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
for (NSInteger i=; i<; i++) {
[[JXItemStore sharedStore] createItem];
}
}
return self;
} - (instancetype)initWithStyle:(UITableViewStyle)style {
return [self init];
}
- (void)viewDidLoad {
[super viewDidLoad]; // 向控制器注册
[self.tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:@"UITableViewCell"]; // 加载头视图
[self headerView];
} #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[[JXItemStore sharedStore] allItem] count];
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// 创建 UITableViewCell 对象,风格使用默认风格
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"
forIndexPath:indexPath];
// 获取 allItem 的第 n 个 JXItem 对象
// 然后将该 JXItem 对象的描述信息赋值给 UITableViewCell 对象的 textLabel
// 这里的 n 是该 UITableViewCell 对象所对应的表格索引
NSArray * items = [[JXItemStore sharedStore] allItem];
JXItem * item = items[indexPath.row]; cell.textLabel.text = [item description];
return cell;
} #pragma mark - 懒加载
- (UIView *)headerView{
if (_headerView == nil) {
UIView * headerView = [[UIView alloc] initWithFrame:CGRectMake(, , self.view.bounds.size.width, )];
// 设置头部视图
self.tableView.tableHeaderView = headerView;
headerView.backgroundColor = [UIColor cyanColor];
[headerView addSubview:self.editButton];
[headerView addSubview:self.addButton];
_headerView = headerView;
}
return _headerView;
} - (UIButton *)editButton{
if (_editButton == nil) {
_editButton = [UIButton buttonWithType:UIButtonTypeCustom];
_editButton.frame = CGRectMake(, , self.view.bounds.size.width / , );
[_editButton setTitle:@"Edit" forState:UIControlStateNormal];
_editButton.backgroundColor = [UIColor greenColor];
[_editButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[_editButton addTarget:self action:@selector(editClick:) forControlEvents:UIControlEventTouchDown];
}
return _editButton;
} - (UIButton *)addButton{
if (_addButton == nil) {
UIButton * addButton = [UIButton buttonWithType:UIButtonTypeCustom];
addButton.frame = CGRectMake(self.view.bounds.size.width / , , self.view.bounds.size.width / , );
[addButton setTitle:@"Add" forState:UIControlStateNormal];
addButton.backgroundColor = [UIColor blueColor];
[addButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[addButton addTarget:self action:@selector(addClick:) forControlEvents:UIControlEventTouchDown];
_addButton = addButton;
}
return _addButton;
} #pragma mark - 点击事件
- (void)editClick:(UIButton *)sender {
if (self.isEditing) { // 如果是编辑状态,取消编辑 // 更改文字
[sender setTitle:@"Edit" forState:UIControlStateNormal]; // 取消编辑
[self setEditing:NO animated:YES];
} else { // 更改文字
[sender setTitle:@"Done" forState:UIControlStateNormal]; // 开始编辑
[self setEditing:YES animated:YES];
}
} /**
* 添加表格时,必须保证 UITableView 对象当前显示的行数与数据源的提供的行数相同。
* 所以,在添加之前,必须先创建一个新的 JXItem 对象并加入到 JXItemStore 中
*
* @param sender 按钮
*/
- (void)addClick:(UIButton *)sender { // 创建新的 JXItem 对象,并加入到 JXItemStore 中
JXItem * newItem = [[JXItemStore sharedStore] createItem]; // 获取新的对象在 allItem 数组中的索引
NSInteger lastRow = [[[JXItemStore sharedStore] allItem] indexOfObject:newItem];
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:lastRow inSection:]; // 将新航插入 UITableView 对象
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
}
@end

  构建并运行

  • 删除行

  在编辑模式下,UITableViewCell 对象可能是会显示中间有个减号的红色圆圈。这个红色圆圈是删除行控件,按下删除控件就可以删除其所属的那个表格行。但是目前我们的应用按下不会有任何操作。  

  要删除 JXHomepwner 中的某个表格行,就必须执行两步:1.从UITableView 对象删除指定的 UITableViewCell 对象。2.找到和需要删除的 UITableViewCell 对象对应的 JXItem 对象,也将其从 JXItemStore 中删除。为了完成第二步,我们必须在 JXItemStore 中实现新的方法。

#import <Foundation/Foundation.h>

@class JXItem;
@interface JXItemStore : NSObject /** 存放 JXItem 对象数组 */
@property (nonatomic,readonly) NSArray * allItem; // 注意,这是一个类方法,前缀是+
+ (instancetype)sharedStore; - (JXItem *)createItem; /**
* 删除对象
*
* @param item 需要删除的对象
*/
- (void)removeItem:(JXItem *)item;
@end
#import "JXItemStore.h"
#import "JXItem.h" @interface JXItemStore () /** 可变数组,用来操作 JXItem 对象 */
@property (nonatomic,strong) NSMutableArray * privateItems; @end @implementation JXItemStore // 单粒对象
+ (instancetype)sharedStore {
static JXItemStore * sharedStore = nil; // 判断是否需要创建一个 sharedStore 对象
if (!sharedStore) {
sharedStore = [[self alloc] init];
}
return sharedStore;
}
- (NSArray *)allItem {
return [self.privateItems copy];
} - (JXItem *)createItem {
JXItem * item = [JXItem randomItem];
[self.privateItems addObject:item];
return item;
} /**
* 还可以调用 [self.privateItems removeObject:item]
* [self.privateItems removeObjectIdenticalTo:item] 与上面的方法的区别就是:上面的方法会枚举数组,向每一个数组发送 isEqual: 消息。
* isEqual: 的作用是判断当前对象和传入对象所包含的数据是否相等。可能会复写 这个方法。
* removeObjectIdenticalTo: 方法不会比较对象所包含的数据,只会比较指向对象的指针
*
* @param item 需要删除的对象
*/
- (void)removeItem:(JXItem *)item { [self.privateItems removeObjectIdenticalTo:item]; }
#pragma mark - 懒加载
- (NSMutableArray *)privateItems{
if (_privateItems == nil) {
_privateItems = [[NSMutableArray alloc] init];
}
return _privateItems;
}
@end

  接下来为  JXItemsViewController 实现

- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath

  这个方法是  UITableViewDataSource 协议所声明的方法之一。当 UITableView 对象在向其数据源发送这个消息的时候,会传入三个实参。第一个参数是发送该消息的 UITableView 对象。第二个实参是 UITableViewCellEditingStyle 类型的常量(删除表格行时,传入的是UITableViewCellEditingStyleDelete)。第三个实参是一个 NSIndexPath 对象,其中包含相应表格行所在的表格段索引和行索引。

  

#import "JXItemsViewController.h"
#import "JXItem.h"
#import "JXItemStore.h" @interface JXItemsViewController ()
/** 头部视图 */
@property (nonatomic,weak) UIView * headerView;
/** 编辑按钮 */
@property (nonatomic,strong) UIButton * editButton; /** 增加按钮 */
@property (nonatomic,strong) UIButton * addButton; @end @implementation JXItemsViewController - (instancetype)init {
// 调用父类的指定初始化方法
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
for (NSInteger i=; i<; i++) {
[[JXItemStore sharedStore] createItem];
}
}
return self;
} - (instancetype)initWithStyle:(UITableViewStyle)style {
return [self init];
}
- (void)viewDidLoad {
[super viewDidLoad]; // 向控制器注册
[self.tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:@"UITableViewCell"]; // 加载头视图
[self headerView];
} #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[[JXItemStore sharedStore] allItem] count];
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// 创建 UITableViewCell 对象,风格使用默认风格
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"
forIndexPath:indexPath];
// 获取 allItem 的第 n 个 JXItem 对象
// 然后将该 JXItem 对象的描述信息赋值给 UITableViewCell 对象的 textLabel
// 这里的 n 是该 UITableViewCell 对象所对应的表格索引
NSArray * items = [[JXItemStore sharedStore] allItem];
JXItem * item = items[indexPath.row]; cell.textLabel.text = [item description];
return cell;
} /**
* 删除行
*
* @param tableView 对象
* @param editingStyle 操作
* @param indexPath 操作的行数
*/
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath { // 如果tableView请求的是删除对象
if (editingStyle == UITableViewCellEditingStyleDelete) { // 取出需要删除的对象
NSArray * items = [[JXItemStore sharedStore] allItem];
JXItem * item = items[indexPath.row]; // 删除对象
[[JXItemStore sharedStore] removeItem:item]; // 刷新表格
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} }
#pragma mark - 懒加载
- (UIView *)headerView{
if (_headerView == nil) {
UIView * headerView = [[UIView alloc] initWithFrame:CGRectMake(, , self.view.bounds.size.width, )];
// 设置头部视图
self.tableView.tableHeaderView = headerView;
headerView.backgroundColor = [UIColor cyanColor];
[headerView addSubview:self.editButton];
[headerView addSubview:self.addButton];
_headerView = headerView;
}
return _headerView;
} - (UIButton *)editButton{
if (_editButton == nil) {
_editButton = [UIButton buttonWithType:UIButtonTypeCustom];
_editButton.frame = CGRectMake(, , self.view.bounds.size.width / , );
[_editButton setTitle:@"Edit" forState:UIControlStateNormal];
_editButton.backgroundColor = [UIColor greenColor];
[_editButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[_editButton addTarget:self action:@selector(editClick:) forControlEvents:UIControlEventTouchDown];
}
return _editButton;
} - (UIButton *)addButton{
if (_addButton == nil) {
UIButton * addButton = [UIButton buttonWithType:UIButtonTypeCustom];
addButton.frame = CGRectMake(self.view.bounds.size.width / , , self.view.bounds.size.width / , );
[addButton setTitle:@"Add" forState:UIControlStateNormal];
addButton.backgroundColor = [UIColor blueColor];
[addButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[addButton addTarget:self action:@selector(addClick:) forControlEvents:UIControlEventTouchDown];
_addButton = addButton;
}
return _addButton;
} #pragma mark - 点击事件
- (void)editClick:(UIButton *)sender {
if (self.isEditing) { // 如果是编辑状态,取消编辑 // 更改文字
[sender setTitle:@"Edit" forState:UIControlStateNormal]; // 取消编辑
[self setEditing:NO animated:YES];
} else { // 更改文字
[sender setTitle:@"Done" forState:UIControlStateNormal]; // 开始编辑
[self setEditing:YES animated:YES];
}
} /**
* 添加表格时,必须保证 UITableView 对象当前显示的行数与数据源的提供的行数相同。
* 所以,在添加之前,必须先创建一个新的 JXItem 对象并加入到 JXItemStore 中
*
* @param sender 按钮
*/
- (void)addClick:(UIButton *)sender { // 创建新的 JXItem 对象,并加入到 JXItemStore 中
JXItem * newItem = [[JXItemStore sharedStore] createItem]; // 获取新的对象在 allItem 数组中的索引
NSInteger lastRow = [[[JXItemStore sharedStore] allItem] indexOfObject:newItem];
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:lastRow inSection:]; // 将新航插入 UITableView 对象
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
}
@end

  接下来,继续调用数据源代理的另一个方法

- (void)tableView:(UITableView *)tableView
moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toIndexPath:(NSIndexPath *)destinationIndexPath

  是当在编辑模式下,会在每个表格行的右侧显示一个换位控件,按住拖动,可以将相应的表格行移动到手指拖动的位置。对象在向其数据源发送这个消息的时候,同样会传入三个实参。第一个参数是发送该消息的 UITableView 对象。第二个实参是 NSIndexPath 对象是表格原位置。第三个实参是一个 NSIndexPath 对象是目的位置

#import <Foundation/Foundation.h>

@class JXItem;
@interface JXItemStore : NSObject /** 存放 JXItem 对象数组 */
@property (nonatomic,readonly) NSArray * allItem; // 注意,这是一个类方法,前缀是+
+ (instancetype)sharedStore; - (JXItem *)createItem; /**
* 删除对象
*
* @param item 需要删除的对象
*/
- (void)removeItem:(JXItem *)item; /**
* 移动对象
*
* @param fromIndex 移动对象的起始位置
* @param toIndex 移动后的位置
*/
- (void)moveItemAtIndex:(NSInteger)fromIndex
toIndex:(NSInteger)toIndex;
@end
#import "JXItemStore.h"
#import "JXItem.h" @interface JXItemStore () /** 可变数组,用来操作 JXItem 对象 */
@property (nonatomic,strong) NSMutableArray * privateItems; @end @implementation JXItemStore // 单粒对象
+ (instancetype)sharedStore {
static JXItemStore * sharedStore = nil; // 判断是否需要创建一个 sharedStore 对象
if (!sharedStore) {
sharedStore = [[self alloc] init];
}
return sharedStore;
}
- (NSArray *)allItem {
return [self.privateItems copy];
} - (JXItem *)createItem {
JXItem * item = [JXItem randomItem];
[self.privateItems addObject:item];
return item;
} /**
* 还可以调用 [self.privateItems removeObject:item]
* [self.privateItems removeObjectIdenticalTo:item] 与上面的方法的区别就是:上面的方法会枚举数组,向每一个数组发送 isEqual: 消息。
* isEqual: 的作用是判断当前对象和传入对象所包含的数据是否相等。可能会复写 这个方法。
* removeObjectIdenticalTo: 方法不会比较对象所包含的数据,只会比较指向对象的指针
*
* @param item 需要删除的对象
*/
- (void)removeItem:(JXItem *)item { [self.privateItems removeObjectIdenticalTo:item]; } - (void)moveItemAtIndex:(NSInteger)fromIndex toIndex:(NSInteger)toIndex { // 如果起始位置和最终位置相同,则不懂
if (fromIndex == toIndex) return; // 需要移动的对象的指针
JXItem * item = self.privateItems[fromIndex]; // 将 item 从 allItem 数组中移除
[self.privateItems removeObjectAtIndex:fromIndex]; // 根据新的索引位置,将item 插入到allItem 数组中
[self.privateItems insertObject:item atIndex:toIndex];
}
#pragma mark - 懒加载
- (NSMutableArray *)privateItems{
if (_privateItems == nil) {
_privateItems = [[NSMutableArray alloc] init];
}
return _privateItems;
}
@end
#import "JXItemsViewController.h"
#import "JXItem.h"
#import "JXItemStore.h" @interface JXItemsViewController ()
/** 头部视图 */
@property (nonatomic,weak) UIView * headerView;
/** 编辑按钮 */
@property (nonatomic,strong) UIButton * editButton; /** 增加按钮 */
@property (nonatomic,strong) UIButton * addButton; @end @implementation JXItemsViewController - (instancetype)init {
// 调用父类的指定初始化方法
self = [super initWithStyle:UITableViewStylePlain];
if (self) {
for (NSInteger i=; i<; i++) {
[[JXItemStore sharedStore] createItem];
}
}
return self;
} - (instancetype)initWithStyle:(UITableViewStyle)style {
return [self init];
}
- (void)viewDidLoad {
[super viewDidLoad]; // 向控制器注册
[self.tableView registerClass:[UITableViewCell class]
forCellReuseIdentifier:@"UITableViewCell"]; // 加载头视图
[self headerView];
} #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[[JXItemStore sharedStore] allItem] count];
} - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// 创建 UITableViewCell 对象,风格使用默认风格
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"
forIndexPath:indexPath];
// 获取 allItem 的第 n 个 JXItem 对象
// 然后将该 JXItem 对象的描述信息赋值给 UITableViewCell 对象的 textLabel
// 这里的 n 是该 UITableViewCell 对象所对应的表格索引
NSArray * items = [[JXItemStore sharedStore] allItem];
JXItem * item = items[indexPath.row]; cell.textLabel.text = [item description];
return cell;
} /**
* 删除行
*
* @param tableView 对象
* @param editingStyle 操作
* @param indexPath 操作的行数
*/
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath { // 如果tableView请求的是删除对象
if (editingStyle == UITableViewCellEditingStyleDelete) { // 取出需要删除的对象
NSArray * items = [[JXItemStore sharedStore] allItem];
JXItem * item = items[indexPath.row]; // 删除对象
[[JXItemStore sharedStore] removeItem:item]; // 刷新表格
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} }
/**
* 移动行
*
* @param tableView 对象
* @param sourceIndexPath 需要移动的行
* @param destinationIndexPath 目标行
*/
- (void)tableView:(UITableView *)tableView
moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toIndexPath:(NSIndexPath *)destinationIndexPath { [[JXItemStore sharedStore] moveItemAtIndex:sourceIndexPath.row
toIndex:destinationIndexPath.row];
}
#pragma mark - 懒加载
- (UIView *)headerView{
if (_headerView == nil) {
UIView * headerView = [[UIView alloc] initWithFrame:CGRectMake(, , self.view.bounds.size.width, )];
// 设置头部视图
self.tableView.tableHeaderView = headerView;
headerView.backgroundColor = [UIColor cyanColor];
[headerView addSubview:self.editButton];
[headerView addSubview:self.addButton];
_headerView = headerView;
}
return _headerView;
} - (UIButton *)editButton{
if (_editButton == nil) {
_editButton = [UIButton buttonWithType:UIButtonTypeCustom];
_editButton.frame = CGRectMake(, , self.view.bounds.size.width / , );
[_editButton setTitle:@"Edit" forState:UIControlStateNormal];
_editButton.backgroundColor = [UIColor greenColor];
[_editButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[_editButton addTarget:self action:@selector(editClick:) forControlEvents:UIControlEventTouchDown];
}
return _editButton;
} - (UIButton *)addButton{
if (_addButton == nil) {
UIButton * addButton = [UIButton buttonWithType:UIButtonTypeCustom];
addButton.frame = CGRectMake(self.view.bounds.size.width / , , self.view.bounds.size.width / , );
[addButton setTitle:@"Add" forState:UIControlStateNormal];
addButton.backgroundColor = [UIColor blueColor];
[addButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[addButton addTarget:self action:@selector(addClick:) forControlEvents:UIControlEventTouchDown];
_addButton = addButton;
}
return _addButton;
} #pragma mark - 点击事件
- (void)editClick:(UIButton *)sender {
if (self.isEditing) { // 如果是编辑状态,取消编辑 // 更改文字
[sender setTitle:@"Edit" forState:UIControlStateNormal]; // 取消编辑
[self setEditing:NO animated:YES];
} else { // 更改文字
[sender setTitle:@"Done" forState:UIControlStateNormal]; // 开始编辑
[self setEditing:YES animated:YES];
}
} /**
* 添加表格时,必须保证 UITableView 对象当前显示的行数与数据源的提供的行数相同。
* 所以,在添加之前,必须先创建一个新的 JXItem 对象并加入到 JXItemStore 中
*
* @param sender 按钮
*/
- (void)addClick:(UIButton *)sender { // 创建新的 JXItem 对象,并加入到 JXItemStore 中
JXItem * newItem = [[JXItemStore sharedStore] createItem]; // 获取新的对象在 allItem 数组中的索引
NSInteger lastRow = [[[JXItemStore sharedStore] allItem] indexOfObject:newItem];
NSIndexPath * indexPath = [NSIndexPath indexPathForRow:lastRow inSection:]; // 将新航插入 UITableView 对象
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationTop];
}
@end

  构建并运行

iOS 编辑UITableView(根据iOS编程编写)的更多相关文章

  1. 【iOS与EV3混合机器人编程系列之三】编写EV3 Port Viewer 应用监測EV3port数据

    在前两篇文章中,我们对iOS与EV3混合机器人编程做了一个主要的设想.而且介绍了要完毕项目所需的软硬件准备和知识准备. 那么在今天这一篇文章中,我们将直接真正開始项目实践. ==第一个项目: EV3 ...

  2. iOS开发网络篇—网络编程基础

    iOS开发网络篇—网络编程基础 一.为什么要学习网络编程 1.简单说明 在移动互联网时代,移动应用的特征有: (1)几乎所有应用都需要用到网络,比如QQ.微博.网易新闻.优酷.百度地图 (2)只有通过 ...

  3. iOS多线程拾贝------操作巨人编程

    iOS多线程拾贝------操作巨人编程 多线程 基本 实现方案:pthread - NSThread - GCD - NSOperation Pthread 多平台,可移植 c语言,要程序员管理生命 ...

  4. 【iOS与EV3混合机器人编程系列之中的一个】iOS要干嘛?EV3能够更酷!

    乐高Mindstorm EV3智能机器人(下面简称EV3)自从在2013年的CES(Consumer Electronics Show美国消费电子展)上展出之后,就吸引了全球广大机器人爱好者的眼球!E ...

  5. IOS 推送-配置与代码编写

    IOS 推送配置与代码编写 这里介绍IOS的推送,本文章已经在IOS6/7/8上都能运行OK,按照道理IOS9应该没问题. 大纲: 1.文章前提 2.推送介绍 3.推送文件账号设置 4.推送证书介绍 ...

  6. iOS中UITableView的cell点击事件不触发didSelectRowAtIndexPath(汇总)

    iOS中UITableView的cell点击事件不触发didSelectRowAtIndexPath 首先分析有几种原因,以及相应的解决方法 1.UITableViewCell的userInterac ...

  7. IOS SDK -UITableView的奇葩特性

    UITableView是IOS提供的一个带有复用机制的滚动表格,目前的基本功能就是垂直的表格,可以有多个section,每个section可以有多个row,然后还包含有sectionview,foot ...

  8. iOS开发-UITableView自定义Cell

    UITableView在iOS中开发的重要地位是毋庸置疑的,基本上应用中用到的比例是一半左右,而且大部分情况都是需要自定义单元格的,这样用户看到的App才能更有美感.之前写过UITableView的基 ...

  9. iOS开发-UITableView表格优化

    之前的一篇文章大概讲述了一下UITableView的使用,UITableView在iOS的地位和ListView在Android中的地位基本上算是不相上下,关于ListView的优化网上的也有很多文章 ...

随机推荐

  1. CSS HTML元素布局及Display属性

    本篇文章主要介绍HTML的内联元素.块级元素的分类与布局,以及dispaly属性对布局的影响. 目录 1. HTML 元素分类:介绍内联元素.块级元素的分类. 2. HTML 元素布局:介绍内联元素. ...

  2. 使用ubuntu作为web开发环境的一些感受

    从ms-dos,win95,win98,winMe,winXp,vista,win7,win10我都有使用的经历,我使用时间最长的应属winxp,其次是win7,说实话,我觉得这两个系统是微软做的最好 ...

  3. git-2.10.2-64-bit介绍&&git下载&&git安装教程

    Git介绍 分布式:Git系统是一个分布式的系统,是用来保存工程源代码历史状态的命令行工具. 保存点:Git的保存点可以追踪源码中的文件, 并能得到某一个时间点上的整个工程项目的状态:可以在该保存点将 ...

  4. 开源一款简单清爽的日历组件,JavaScript版的

    源码会在最后给出地址,需要的朋友自己去下载.最近项目需要做一个日程安排的功能,就是点击日历的某一天弹出一个录入页面,填完信息后保存当天的日程安排.有日程的日期会有不同的标记(比如加一个背景色啥的).网 ...

  5. RMS:不能对生产服务器使用测试清单

    问题说明:在使用office软件RMS加密时报:不能对生产服务器使用测试清单,或者使用 rmsbulk.exe进行RMS加密时,报不能连接到RMS服务器. 解决办法: 请到https://suppor ...

  6. Android中Fragment和ViewPager那点事儿(仿微信APP)

    在之前的博文<Android中使用ViewPager实现屏幕页面切换和引导页效果实现>和<Android中Fragment的两种创建方式>以及<Android中Fragm ...

  7. 【转】组件化的Web王国

    本文由 埃姆杰 翻译.未经许可,禁止转载!英文出处:Future Insights. 内容提要 使用许多独立组件构建应用程序的想法并不新鲜.Web Component的出现,是重新回顾基于组件的应用程 ...

  8. Linux下的C Socket编程 -- server端的继续研究

    Linux下的C Socket编程(四) 延长server的生命周期 在前面的一个个例子中,server在处理完一个连接后便会立即结束掉自己,然而这种server并不科学啊,server应该是能够一直 ...

  9. js中的null 和undefined

    参考链接:http://blog.csdn.net/qq_26676207/article/details/53100912 http://www.ruanyifeng.com/blog/2014/0 ...

  10. .NET跨平台:在CentOS上编译dnx并运行ASP.NET 5示例程序

    在之前的博文中我们在 Ubuntu 上成功编译出了 dnx ,并且用它成功运行了 ASP.NET 5 示例程序.在这篇博文中我们将 Ubuntu 换成 CentOS. 目前 dnx 的编译需要用到 m ...