iOS_動態插入刪除行

來源:互聯網
上載者:User

iOS_動態插入刪除行
最終:

分MVC三層設計;自訂的Cell有兩種;一種是MainCell,由ModelArr提供資料來源;另一種是插入的cell,由代碼建立,並且由另外一個數組供狀態資料<喎?http://www.bkjia.com/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPjxicj4KCgrK/b7d1LSyv7fWOjxicj4KCgo8aW1nIHNyYz0="http://www.2cto.com/uploadfile/Collfiles/20141020/20141020084601125.png" alt="\">

////  MyProjectCellModel.h//  動態插入刪除行////  Created by beyond on 14-10-18.//  Copyright (c) 2014年 com.beyond All rights reserved.//  列表 的cell用到的資料模型#import @interface MyProjectCellModel : NSObject// 表徵圖@property (nonatomic,copy) NSString *icon;// 標題@property (nonatomic,copy) NSString *title;// 發布狀態@property (nonatomic,copy) NSString *publishStatus;// 日期@property (nonatomic,copy) NSString *date;// 多少人關注@property (nonatomic,copy) NSString *num;// 點擊最右側的按鈕,需要進行什麼操作??彈出一個View,用於修改發布的狀態???// 類方法,字典 轉 對象 類似javaBean一次性填充+ (MyProjectCellModel *)modelWithDict:(NSDictionary *)dict;// 對象方法,設定對象的屬性後,返回對象- (MyProjectCellModel *)initWithDict:(NSDictionary *)dict;@end

////  MyProjectCellModel.m//  動態插入刪除行////  Created by beyond on 14-10-18.//  Copyright (c) 2014年 com.beyond All rights reserved.//  列表 的cell用到的資料模型#import "MyProjectCellModel.h"@implementation MyProjectCellModel// 類方法,字典 轉 對象 類似javaBean一次性填充+ (MyProjectCellModel *)modelWithDict:(NSDictionary *)dict{    // 只是調用對象的initWithDict方法,之所以用self是為了對子類進行相容    return [[self alloc]initWithDict:dict];}// 對象方法,設定對象的屬性後,返回對象- (MyProjectCellModel *)initWithDict:(NSDictionary *)dict{    // 必須先調用父類NSObject的init方法    if (self = [super init]) {        // 設定對象自己的屬性        [self setValuesForKeysWithDictionary:dict];    }    // 返回填充好的對象    return self;}@end


主Cell,由xib和類聲明、類實現組成

////  MyProjectCell.h//  動態插入刪除行////  Created by beyond on 14-10-18.//  Copyright (c) 2014年 com.beyond All rights reserved.//  這個是主要的Cell,用於展示微博資料的Cell#import // 定義一個block,作用是點擊了 右側的按鈕,告訴主控制器彈出一個 View(包含暫停、修改、刪除),block的參數是(int row)typedef void(^cellRightBtnBlock)(int) ;@class MyProjectCellModel;@interface MyProjectCell : UITableViewCell// 表徵圖@property (nonatomic,weak)IBOutlet UIImageView *iconView;// 標題@property (nonatomic,weak)IBOutlet UILabel *titleLabel;// 微博的發布狀態【暫停、草稿、發布、到期】@property (nonatomic,weak)IBOutlet UILabel *publishStatusLabel;// 日期@property (nonatomic,weak)IBOutlet UILabel *dateLabel;// 多少人關注的數字 部分@property (nonatomic,weak)IBOutlet UILabel *numLabel;// 多少人關注的固定的文字,沒有人關注此條微博時,就不顯示@property (nonatomic,weak)IBOutlet UILabel *constLabel;// 一個成員屬性block,當cell右邊的按鈕被點擊的時候,就會調用,彈出一個view,供使用者修改微博的狀態@property (nonatomic,copy)cellRightBtnBlock wannaChangeStatusBlock;// 從xib中載入 執行個體化一個對象+ (MyProjectCell *)myProjectCell;// 返回封裝好資料之後的對象- (MyProjectCell *)cellWithCellModel:(MyProjectCellModel *)cellModel;@end


////  MyProjectCell.m//  動態插入刪除行////  Created by beyond on 14-10-18.//  Copyright (c) 2014年 com.beyond All rights reserved.//  這個是主要的Cell,用於展示微博資料的Cell#import "MyProjectCell.h"#import "MyProjectCellModel.h"@implementation MyProjectCell// 從xib中載入 執行個體化一個對象+ (MyProjectCell *)myProjectCell{    // mainBundel載入xib,副檔名不用寫.xib    return [[NSBundle mainBundle] loadNibNamed:@"MyProjectCell" owner:nil options:nil][0];}// 返回封裝好資料之後的對象- (MyProjectCell *)cellWithCellModel:(MyProjectCellModel *)cellModel{        // 頭像圓角    _iconView.layer.cornerRadius = 6;    _iconView.layer.masksToBounds = YES;            _iconView.image = [UIImage imageNamed:cellModel.icon];    _titleLabel.text = cellModel.title;    _publishStatusLabel.text = cellModel.publishStatus;    _dateLabel.text = cellModel.date;    if ([_numLabel.text intValue]) {        _constLabel.hidden = YES;    } else {        _numLabel.text = cellModel.num;        _constLabel.hidden = NO;    }    // 產生一個右側按鈕,添加到cell最右方    UIButton *rightBtn = [UIButton buttonWithType:UIButtonTypeCustom];    [rightBtn setBackgroundImage:[UIImage imageNamed:@"MyProjectCellRightBtn"] forState:UIControlStateNormal];    rightBtn.frame = CGRectMake(286, 0, 34, 44);    [self.contentView addSubview:rightBtn];    rightBtn.tag = 5267;    [rightBtn setBackgroundImage:[UIImage imageNamed:@"MyProjectCellRightBtn.png"] forState:UIControlStateNormal];    [rightBtn addTarget:self action:@selector(rightBtnClicked:) forControlEvents:UIControlEventTouchUpInside];    return self;}// 定義宏,判斷ios7#define iOS7 [[[UIDevice currentDevice]systemVersion] floatValue] >= 7.0- (void)rightBtnClicked:(UIButton *)sender{    int row = 0;    MyProjectCell *cell;    UITableView *tableView;    if(iOS7){        NSLog(@"按鈕的父類2:%@",[[[sender superview] superview] superview]);        cell = (MyProjectCell *)[[[sender superview] superview] superview];                NSLog(@"cell的父類2:%@",[[cell superview] superview] );                tableView = ( UITableView*)[[cell superview] superview] ;    }else{        // iOS6        cell = (MyProjectCell *)[sender superview];        NSLog(@"被點擊的cell:%@",cell);        tableView = ( UITableView*)[cell superview];    }    NSIndexPath *path = [tableView indexPathForCell:cell];    row = path.row;    NSLog(@"父類1%@",[sender superview]);    NSLog(@"父類2%@",[[sender superview] superview]);    NSLog(@"父類3%@",[[[sender superview] superview]superview]);    NSLog(@"父類4%@",[[[[sender superview] superview]superview]superview]);        NSLog(@"點擊了第%d行 右邊的按鈕",row);    // 調用外界的控制器的block,並將cell的行號傳遞過去    _wannaChangeStatusBlock(row);}@end


附加的Cell,即當點擊MainCell最右側的按鈕時,動態添加在主Cell下方
////  ChangeStatusCell.m//  動態插入刪除行////  Created by beyond on 14-10-18.//  Copyright (c) 2014年 com.beyond All rights reserved.//  附加的Cell,當點擊MainCell最右側的按鈕時,動態添加在主Cell下方#import "ChangeStatusCell.h"@implementation ChangeStatusCell// 附加的cell,沒有xib,由代碼建立- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];    if (self) {        // 添加三個按鈕,並設定tag        UIButton *b1 = [self createButtonWithFrame:CGRectMake(0 , 0, 106.5, 44) Target:self Selector:@selector(btnAction:) Image:@"StatusPause_gray.png" ImagePressed:@"StatusPause_blue.png"];        b1.tag = 1;                UIButton *b2 = [self createButtonWithFrame:CGRectMake(106.5, 0, 106.5, 44) Target:self Selector:@selector(btnAction:) Image:@"StatusModify_gray.png" ImagePressed:@"StatusModify_blue.png"];        b2.tag = 2;                UIButton *b3 = [self createButtonWithFrame:CGRectMake(213, 0, 106.5, 44) Target:self Selector:@selector(btnAction:) Image:@"StatusTrash_gray.png" ImagePressed:@"StatusTrash_blue.png"];        b3.tag = 3;        // 添加到contentView,否則無法接收到事件        // 例如:直接添加一個按鈕到tableView裡面 是無法接收到事件的;因為tableView它不會把事件傳遞給它體系之外的任何控制項         [self.contentView addSubview:b1];        [self.contentView addSubview:b2];        [self.contentView addSubview:b3];    }    return self;}- (void)btnAction:(id)sender {    UIButton *btn = (UIButton *)sender;    switch (btn.tag) {        case 1:        {            NSLog(@">>>>>>>>>>B1");        }            break;        case 2:        {            NSLog(@">>>>>>>>>>B2");        }            break;        case 3:        {            NSLog(@">>>>>>>>>>B3");        }            break;        default:            break;    }        }#pragma mark - 工具方法- (UIButton*) createButtonWithFrame: (CGRect) frame Target:(id)target Selector:(SEL)selector Image:(NSString *)image ImagePressed:(NSString *)imagePressed{    UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];    [button setFrame:frame];    UIImage *newImage = [UIImage imageNamed: image];    [button setBackgroundImage:newImage forState:UIControlStateNormal];    UIImage *newPressedImage = [UIImage imageNamed: imagePressed];    [button setBackgroundImage:newPressedImage forState:UIControlStateHighlighted];    [button addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];    return button;}@end


控制器,繼承自UIViewController,最核心的部分
////  MyProjectController.m//  動態插入刪除行////  Created by beyond on 14-10-18.//  Copyright (c) 2014年 com.beyond All rights reserved.//  控制器,最最重要的部分#import "MyProjectController.h"#import "MyProjectCell.h"#import "ChangeStatusCell.h"#import "MyProjectCellModel.h"// 非常好用的,快速建立rect並且適配的宏#define IsIOS7 ([[[[UIDevice currentDevice] systemVersion] substringToIndex:1] intValue]>=7)#define CGRECT_NO_NAV(x,y,w,h) CGRectMake((x), (y+(IsIOS7?20:0)), (w), (h))#define CGRECT_HAVE_NAV(x,y,w,h) CGRectMake((x), (y+(IsIOS7?64:0)), (w), (h))#define IS_IOS7 [[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0@interface MyProjectController (){    UITableView *_tableView;    // 資料來源 對象 數組    NSMutableArray *_modelArr;    // 輔助的狀態 字典 數組;長度與上面的modelArr一樣    NSMutableArray *_statusDictArr;    // 記錄已經展開的行號    int _ExpandedMainCellRow;}@end@implementation MyProjectController- (void)viewDidLoad{    [super viewDidLoad];        if (IS_IOS7) {        self.edgesForExtendedLayout = UIRectEdgeNone;        self.extendedLayoutIncludesOpaqueBars = NO;        self.modalPresentationCapturesStatusBarAppearance = NO;    }    // 添加tableView,並設定代理和資料來源    UITableView *tableView = [[UITableView alloc]initWithFrame:CGRECT_NO_NAV(0, 0, 320, 460) style:UITableViewStylePlain];    tableView.dataSource = self;    tableView.delegate = self;    [self.view addSubview:tableView];            _tableView = tableView;    _ExpandedMainCellRow = -1;    // 提供資料模型的數組    _modelArr = [NSMutableArray array];    // 用於記錄 主Cell和附加Cell 以及 附加狀態的數組;二者長度相同    _statusDictArr = [NSMutableArray array];    // 載入資料來源    [self loadData];}#pragma mark - 初始化資料- (void)loadData{    NSString *filePath = [[NSBundle mainBundle]pathForResource:@"MyProjectList.plist" ofType:nil];    NSArray *tempArr = [NSArray arrayWithContentsOfFile:filePath];    // 非常重要!!!!!!!僅供狀態數組 使用    NSDictionary *statusDict = @{  @"Cell": @"MyProjectCell",                                   @"isAttached":@(NO)                                   };    for (NSDictionary *dict in tempArr) {        MyProjectCellModel *model = [MyProjectCellModel modelWithDict:dict];        [_modelArr addObject:model];        [_statusDictArr addObject:statusDict];    }}#pragma mark - TableView代理方法// 取消預設點擊cell的選中效果- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{    [tableView deselectRowAtIndexPath:indexPath animated:YES];}// 行高- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{    return 44;}#pragma mark - TableView資料來源// 總的行數- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{    return _statusDictArr.count;}// 核心方法;分情況建立cell;或者為cell填充資料模型- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    if ([[_statusDictArr[indexPath.row] objectForKey:@"Cell"] isEqualToString:@"MyProjectCell"])    {        static NSString *cellID_1 = @"MyProjectCell";        MyProjectCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID_1];        if (cell == nil) {            cell = [MyProjectCell myProjectCell];            cell.selectionStyle = UITableViewCellSelectionStyleGray;            __unsafe_unretained MyProjectController *blockCtroller = self;            cell.wannaChangeStatusBlock = ^(int row){                NSLog(@"控制器中拿到被點擊的cell的行號: %d",row);                // 調用控制器的方法,顯示 或者 隱藏 用於更改狀態的view                [blockCtroller showHideChangeStatusView:row];            };        }        // 傳遞資料來源        // 設定cell中獨一無二的內容        int tempRow = indexPath.row;        if (_ExpandedMainCellRow != -1 && indexPath.row > _ExpandedMainCellRow) {            tempRow = indexPath.row - 1;        }        // 如果是由於 剛才展開的行,被關閉,而導致 本方法被調用;則沒有展開的,還是按原來的位置取資料模型        if (_ExpandedMainCellRow == -1) {            tempRow = indexPath.row;        }        MyProjectCellModel *model = [_modelArr objectAtIndex:tempRow];        cell = [cell cellWithCellModel:model];        return cell;    }else if([[_statusDictArr[indexPath.row] objectForKey:@"Cell"] isEqualToString:@"ChangeStatusCell"]){        static NSString *cellID_2 = @"ChangeStatusCell";        ChangeStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID_2];        if (cell == nil) {            cell = [[ChangeStatusCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID_2];            cell.selectionStyle = UITableViewCellSelectionStyleNone;        }        return cell;    }    return nil;}- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{    // 開始滾動之前先關閉已經展開的AttachRow}#pragma mark - 點擊了cell最右邊的按鈕時調用//顯示 或者 隱藏 用於更改狀態的view- (void)showHideChangeStatusView:(int)row{    if (row == _ExpandedMainCellRow) {        // 如果這次點擊的行 已經是開啟的行,則直接關閉,並返回        [self closeOneExpandedCell:_ExpandedMainCellRow];    }else{        if (_ExpandedMainCellRow == -1) {            //代表從來沒有展開過,首次展開            [self expandOneRow:row];        } else {            // 如果本次點擊的行還沒有展開,先關閉上次的展開的行;再展開開次的行            // 特別注意,這個row行號是包含了已經展開的AttachCell,因此,要 減去 1;此時的行號才是modelArr中的行號            if (_ExpandedMainCellRow < row) {                // 展開的行,在上面;新點擊的行 在下面                row = row - 1;            }            [self closeOneExpandedCell:_ExpandedMainCellRow];            [self expandOneRow:row];        }            }}// 關閉一個指定行的ExpandedCell- (void)closeOneExpandedCell:(int)row{    // 因為本操作執行完成後,就沒有展開的行,所以要先清零;必須先清零~~~~因為tableViewupdate方法中會調用cellForRow方法    _ExpandedMainCellRow = -1;        // 如果第0行已經是附加了,則關閉附加cell    NSDictionary * dic = @{@"Cell": @"MyProjectCell",@"isAttached":@(NO)};    // 主Cell中的bool還原為NO    _statusDictArr[row] = dic;    NSLog(@"刪除前:%d",[_statusDictArr count]);    // 主Cell數組中的的下一個位置處的AttchedCell刪除    [_statusDictArr removeObjectAtIndex:row+1];    NSLog(@"刪除後:%d",[_statusDictArr count]);    [_tableView beginUpdates];    NSIndexPath *path = [NSIndexPath indexPathForRow:row+1 inSection:0];    [_tableView deleteRowsAtIndexPaths:@[path]  withRowAnimation:UITableViewRowAnimationMiddle];    [_tableView endUpdates];        }//記錄下 並且 展開指定的行 (順序千萬不能反)- (void)expandOneRow:(int)row{    _ExpandedMainCellRow = row;    // 如果第0行沒有開啟附加的cell,則開啟附加cell    NSDictionary * dic = @{@"Cell": @"MyProjectCell",@"isAttached":@(YES)};    // 修改主Cell的狀態字 isAttached為yes    _statusDictArr[row] = dic;    // 插入一個新的ChangeStatusCell到數組中    NSDictionary * addDic = @{@"Cell": @"ChangeStatusCell",@"isAttached":@(YES)};    [_statusDictArr insertObject:addDic atIndex:row + 1];    [_tableView beginUpdates];    NSIndexPath *path = [NSIndexPath indexPathForRow:row + 1 inSection:0];    [_tableView insertRowsAtIndexPaths:@[path] withRowAnimation:UITableViewRowAnimationMiddle];    [_tableView endUpdates];    if (row == _modelArr.count -1) {        // 如果展開的是最後一行,還要讓tableView向上滾動44的高度        [self showExpandedCellForLastRow];    }}// 如果展開的是最後一行,還要讓tableView向上滾動44的高度- (void)showExpandedCellForLastRow{    NSIndexPath *path = [NSIndexPath indexPathForRow:_modelArr.count  inSection:0];    [_tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionMiddle animated:YES];}@end




聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.