小萌做开发的时候,项目需求是:拖拽单元格随意变换位置,变换位置之后仍然可以编辑其它,界面需求如下图所示。
小萌在网上找的例子自己使用的时候发现很多问题,下面发一种小萌亲测可行的方案,以及补充小萌一直以来忽略的知识点。NSMutableArray的中removeObjectAtIndex和的removeObject的正确使用方法
下面主要代码:
@interface AddController ()<UITableViewDelegate,UITableViewDataSource,UIImagePickerControllerDelegate,UINavigationControllerDelegate,UITextViewDelegate>
@property(nonatomic,strong)UITableView *myTableView;
@property(nonatomic,strong)NSMutableArray *dataArr;
/*****发文本******/
@property(nonatomic,strong)UIButton *textButton;
/******发图片********/
@property(nonatomic,strong)UIButton *imageButton;
/******上传图片的时候用到********/
@property(nonatomic,strong)NSIndexPath *selePatch;
@end
- (void)viewDidLoad {
[super viewDidLoad];
self.dataArr = [NSMutableArray array];
[self.view addSubview:self.myTableView];
//这两行很主要,开启可移动
self.myTableView.allowsMultipleSelection=YES;
self.myTableView.editing=YES;
//发图片按钮
self.imageButton = [[UIButton alloc]initWithFrame:CGRectMake(SCREEN_WIDTH - 84, SCREEN_HEIGHT - iPhoneXTabBarHeight - 85, 64, 65)];
[self.imageButton setImage:[UIImage imageNamed:@"icon_editdetail_addimg"] forState:UIControlStateNormal];
[self.imageButton addTarget:self action:@selector(addimageAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.imageButton];
//发文本按钮
self.textButton = [[UIButton alloc]initWithFrame:CGRectMake(SCREEN_WIDTH - 84*2, SCREEN_HEIGHT - iPhoneXTabBarHeight - 85, 64, 65)];
[self.textButton setImage:[UIImage imageNamed:@"icon_editdetail_addtype"] forState:UIControlStateNormal];
[self.textButton addTarget:self action:@selector(addtextAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.textButton];
//导航条右边的保存按钮,我是自定义的,不是自定义的朋友请修改
[self.navBar.titleRight setTitle:@"保存" forState:UIControlStateNormal];
[self.navBar.titleRight setTitleColor:UIColorFromRGB(0xFF4055) forState:UIControlStateNormal];
[self.navBar.titleRight addTarget:self action:@selector(saveAction) forControlEvents:UIControlEventTouchUpInside];
self.view.backgroundColor = UIColorFromRGB(0xf7f7f7);
}
#pragma mark -addimageAction 添加图片 发图片
- (void)addimageAction:(UIButton *)btn{
NSMutableDictionary *editDic = [NSMutableDictionary dictionary];
[editDic setValue:@"image" forKey:@"type"];
[editDic setValue:@"" forKey:@"content"];
[editDic setValue:@"" forKey:@"convertUrl"];
[self.dataArr addObject:editDic];
//刷新
[self.myTableView reloadData];
}
#pragma mark -addtextAction 添加文本 发文本
- (void)addtextAction:(UIButton *)btn{
NSMutableDictionary *editDic = [NSMutableDictionary dictionary];
[editDic setValue:@"text" forKey:@"type"];
[editDic setValue:@"" forKey:@"content"];
[self.dataArr addObject:editDic];
[self.myTableView reloadData];
}
//删除
#pragma mark - deleAction 删除
- (void)deleAction:(UIButton *)btn{
// //取出移动row数据
// NSDictionary *rowDic = self.dataArr[btn.tag - 3000];
// //从数据源中移除该数据
// [self.dataArr removeObject:rowDic];
//
//用下面这种,上面是小萌吃亏的地方removeObject和removeObjectAtIndex是有区别的,看上面的链接
[self.dataArr removeObjectAtIndex:btn.tag - 3000];
NSLog(@"%@",self.dataArr);
[self.myTableView reloadData];
}
#pragma mark - saveAction 保存
- (void)saveAction{
if (self.dataArr.count == 0) {
CustomToastView *toast = [[CustomToastView alloc]initWithView:self.view text:@"保存的数据不能为空" duration:KDuration];
[toast show];
return ;
}
NSLog(@"%@",self.dataArr);
for (int i = 0; i<self.dataArr.count; i ++ ) {
NSMutableDictionary *cellDic = [NSMutableDictionary dictionary];
[cellDic addEntriesFromDictionary:self.dataArr[i]] ;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:i];
DescAndTextCell *vd =(DescAndTextCell *)[self.myTableView cellForRowAtIndexPath:indexPath];
[cellDic setValue:[NSString stringWithFormat:@"%d",i + 1] forKey:@"no"];
if ([cellDic[@"type"] isEqualToString:@"text"]) {
[cellDic setValue:vd.textCellView.text forKey:@"content"];
}
NSString *contents = cellDic[@"content"];
if (DT_IsEmpty(contents) == YES) {
CustomToastView *toast = [[CustomToastView alloc]initWithView:self.view text:@"保存的数据不能为空" duration:KDuration];
[toast show];
return ;
}
}
if (self.block) {
self.block(self.dataArr);
}
[self.navigationController popViewControllerAnimated:YES];
}
#pragma mark - tipAction 开启了移动单元格点击作用消失,需要其他的方法
- (void)tipAction:(UIButton *)btn{
NSDictionary *cellDic = self.dataArr[btn.indexP.section];
if ([cellDic[@"type"] isEqualToString:@"text"]) {
return ;
}
self.selePatch = btn.indexP;
// 类方法
LCActionSheet *sheet = [LCActionSheet sheetWithTitle:nil buttonTitles:@[@"拍照",@"从手机相册选择"] redButtonIndex:-1 clicked:^(NSInteger buttonIndex) {
if (buttonIndex == 0) {
[self takePhoto];
}else if(buttonIndex == 1){
[self localPhoto];
}
}];
[sheet show];
}
//必须把编辑模式改成None,默认的是delete
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
return UITableViewCellEditingStyleNone;
}
#pragma mark 排序当移动了某一行时候会调用
//编辑状态下,只要实现这个方法,就能实现拖动排序---右侧会出现三条杠,点击三条杠就能拖动
-(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
// 取出要拖动的模型数据
NSDictionary *goods = self.dataArr[sourceIndexPath.section];
//删除之前行的数据
//[self.dataArr removeObject:goods];千万别这样做哦
[self.dataArr removeObjectAtIndex:sourceIndexPath.section];
// 插入数据到新的位置
[self.dataArr insertObject:goods atIndex:destinationIndexPath.section];
NSLog(@"%@",self.dataArr);
[self.myTableView reloadData];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return self.dataArr.count;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 1;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *indentifer = @"DescAndTextCell";
DescAndTextCell *cell = [tableView dequeueReusableCellWithIdentifier:indentifer];
if (cell == nil) {
cell = [[DescAndTextCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:indentifer];
}
NSDictionary *cellDic = self.dataArr[indexPath.section];
if ([cellDic[@"type"] isEqualToString:@"text"]) {
cell.moveButton.hidden = YES;
cell.textCellView.delegate = self;
cell.textCellView.tag = indexPath.section + 500;
cell.textCellView.hidden = NO;
cell.imageCellView.hidden = YES;
cell.textCellView.text = cellDic[@"content"];
}else{
cell.moveButton.hidden = NO;
cell.textCellView.hidden = YES;
cell.imageCellView.hidden = NO;
NSString *https = cellDic[@"convertUrl"];
NSLog(@"%@",https);
if (DT_IsEmpty(https) == NO) {
cell.photoLabel.hidden = YES;
cell.imageLabel.hidden = YES;
cell.photoImage.hidden = YES;
[cell.imageCellView sd_setImageWithURL:[NSURL URLWithString:https] placeholderImage:[UIImage imageNamed:@"icon-tong-default"]];
}else{
cell.photoLabel.hidden = NO;
cell.imageLabel.hidden = NO;
cell.photoImage.hidden = NO;
}
}
cell.deleButton.tag = indexPath.section + 3000;
[cell.deleButton addTarget:self action:@selector(deleAction:) forControlEvents:UIControlEventTouchUpInside];
cell.tipButton.indexP = indexPath;
[cell.tipButton addTarget:self action:@selector(tipAction:) forControlEvents:UIControlEventTouchUpInside];
cell.backgroundColor = [UIColor clearColor];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
return 0.000001;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
return 0.000001;
}
//失效
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
}
- (void)textViewDidEndEditing:(UITextView *)textView{
//取出移动row数据
NSDictionary *rowDic = self.dataArr[textView.tag - 500];
[rowDic setValue:textView.text forKey:@"content"];
}
#pragma mark - getter
- (UITableView *)myTableView{
if (!_myTableView) {
_myTableView = [[UITableView alloc]initWithFrame:CGRectMake(15, NavBarHeight, SCREEN_WIDTH - 30, SCREEN_HEIGHT-NavBarHeight) style:UITableViewStyleGrouped];
_myTableView.estimatedRowHeight = 0;
_myTableView.rowHeight = 130;
_myTableView.backgroundColor = UIColorFromRGB(0xf7f7f7);
_myTableView.estimatedSectionHeaderHeight = 0;
_myTableView.estimatedSectionFooterHeight = 0;
_myTableView.dataSource = self;
_myTableView.delegate = self;
_myTableView.separatorStyle = UITableViewCellSeparatorStyleNone;
if (@available(iOS 11.0, *)) {
_myTableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
// Fallback on earlier versions
}
_myTableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);//iPhoneX这里是88
_myTableView.scrollIndicatorInsets = _myTableView.contentInset;
}
return _myTableView;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - 拍照
/*3:从相册选择*/
- (void)localPhoto
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
//资源类型为图片库
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
picker.delegate = self;
//设置选择后的图片可被编辑
picker.allowsEditing = NO;
[self presentViewController:picker animated:YES completion:^{
}];
}
/*4:拍照*/
- (void)takePhoto
{
UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera;
//判断是否有相机
if([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]){
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
//设置拍照后的图片可被编辑
picker.allowsEditing = NO;
//资源类型为照相机
picker.sourceType = sourceType;
[self presentViewController:picker animated:YES completion:^{
}];
}else {
// NSLog(@"该设备不支持拍照");
}
}
//再调用以下委托:
#pragma mark UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
//UIImage *image=[info objectForKey:UIImagePickerControllerEditedImage];
//上传原图
UIImage *imageOrigina=[info objectForKey:UIImagePickerControllerOriginalImage];
[picker dismissViewControllerAnimated:YES completion:^{
}];
}