├── gif2.gif ├── .DS_Store ├── XDMultTableView ├── .DS_Store ├── XDMultTableView │ ├── .DS_Store │ ├── XDMultTableView │ │ ├── down_blue@2x.png │ │ ├── XDMultTableView.h │ │ └── XDMultTableView.m │ ├── ViewController.h │ ├── AppDelegate.h │ ├── main.m │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Info.plist │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── AppDelegate.m │ └── ViewController.m └── XDMultTableView.xcodeproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── caixindong.xcuserdatad │ │ └── UserInterfaceState.xcuserstate │ ├── xcuserdata │ └── caixindong.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── XDMultTableView.xcscheme │ └── project.pbxproj └── README.md /gif2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caixindong/XDMultTableView/HEAD/gif2.gif -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caixindong/XDMultTableView/HEAD/.DS_Store -------------------------------------------------------------------------------- /XDMultTableView/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caixindong/XDMultTableView/HEAD/XDMultTableView/.DS_Store -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caixindong/XDMultTableView/HEAD/XDMultTableView/XDMultTableView/.DS_Store -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView/XDMultTableView/down_blue@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caixindong/XDMultTableView/HEAD/XDMultTableView/XDMultTableView/XDMultTableView/down_blue@2x.png -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView.xcodeproj/project.xcworkspace/xcuserdata/caixindong.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/caixindong/XDMultTableView/HEAD/XDMultTableView/XDMultTableView.xcodeproj/project.xcworkspace/xcuserdata/caixindong.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // XDMultTableView 4 | // 5 | // Created by 蔡欣东 on 2016/7/16. 6 | // Copyright © 2016年 蔡欣东. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // XDMultTableView 4 | // 5 | // Created by 蔡欣东 on 2016/7/16. 6 | // Copyright © 2016年 蔡欣东. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // XDMultTableView 4 | // 5 | // Created by 蔡欣东 on 2016/7/16. 6 | // Copyright © 2016年 蔡欣东. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView.xcodeproj/xcuserdata/caixindong.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | XDMultTableView.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 4EA4A1F61D39D95A00AC649C 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // XDMultTableView 4 | // 5 | // Created by 蔡欣东 on 2016/7/16. 6 | // Copyright © 2016年 蔡欣东. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # XDMultTableView 2 | 多级展开列表 3 | #effect diagram 4 | ![image](https://github.com/caixindong/XDMultTableView/blob/master/gif2.gif) 5 | 6 | #How To Use 7 | 8 | ##Init XDMultTableView 9 | ```ObjC 10 | #import "XDMultTableView.h" 11 | ... 12 | @property(nonatomic, readwrite, strong)XDMultTableView *tableView; 13 | 14 | _tableView = [[XDMultTableView alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height-64)]; 15 | _tableView.openSectionArray = [NSArray arrayWithObjects:@1,@2, nil]; 16 | _tableView.delegate = self; 17 | _tableView.datasource = self; 18 | _tableView.backgroundColor = [UIColor whiteColor]; 19 | [self.view addSubview:_tableView]; 20 | 21 | ``` 22 | 23 | ##Datasource Impletement 24 | 25 | ```ObjC 26 | 27 | - (NSInteger)mTableView:(XDMultTableView *)mTableView numberOfRowsInSection:(NSInteger)section{ 28 | return 5; 29 | } 30 | 31 | - (XDMultTableViewCell *)mTableView:(XDMultTableView *)mTableView 32 | cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 33 | static NSString *cellIdentifier = @"cell"; 34 | UITableViewCell *cell = [mTableView dequeueReusableCellWithIdentifier:cellIdentifier]; 35 | if (cell == nil) 36 | { 37 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 38 | } 39 | UIView *view = [[UIView alloc] initWithFrame:cell.bounds] ; 40 | view.layer.backgroundColor = [UIColor whiteColor].CGColor; 41 | view.layer.masksToBounds = YES; 42 | view.layer.borderWidth = 0.3; 43 | view.layer.borderColor = [UIColor lightGrayColor].CGColor; 44 | 45 | cell.backgroundView = view; 46 | cell.selectionStyle = UITableViewCellSelectionStyleNone; 47 | 48 | return cell; 49 | } 50 | 51 | - (NSInteger)numberOfSectionsInTableView:(XDMultTableView *)mTableView{ 52 | return 6; 53 | } 54 | 55 | -(NSString *)mTableView:(XDMultTableView *)mTableView titleForHeaderInSection:(NSInteger)section{ 56 | return @"我是头部"; 57 | } 58 | 59 | ``` 60 | 61 | ##Delegate Impletement 62 | 63 | ```ObjC 64 | 65 | - (CGFloat)mTableView:(XDMultTableView *)mTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 66 | return 50; 67 | } 68 | 69 | - (CGFloat)mTableView:(XDMultTableView *)mTableView heightForHeaderInSection:(NSInteger)section{ 70 | return 40; 71 | } 72 | 73 | 74 | - (void)mTableView:(XDMultTableView *)mTableView willOpenHeaderAtSection:(NSInteger)section{ 75 | NSLog(@"即将展开"); 76 | } 77 | 78 | 79 | - (void)mTableView:(XDMultTableView *)mTableView willCloseHeaderAtSection:(NSInteger)section{ 80 | NSLog(@"即将关闭"); 81 | } 82 | 83 | - (void)mTableView:(XDMultTableView *)mTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 84 | NSLog(@"点击cell"); 85 | } 86 | 87 | ``` 88 | 89 | ##Easy Extension 90 | 91 | ``` 92 | /** 93 | * ...易拓展出你想要的tableview的功能,写法可以参照上面的定义 94 | */ 95 | ``` 96 | 97 | 98 | -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // XDMultTableView 4 | // 5 | // Created by 蔡欣东 on 2016/7/16. 6 | // Copyright © 2016年 蔡欣东. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "XDMultTableView.h" 11 | 12 | @interface ViewController () 13 | 14 | @property(nonatomic, readwrite, strong)XDMultTableView *tableView; 15 | 16 | @end 17 | 18 | @implementation ViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | 23 | self.automaticallyAdjustsScrollViewInsets = NO; 24 | 25 | self.navigationItem.title = @"我是多级列表"; 26 | 27 | _tableView = [[XDMultTableView alloc] initWithFrame:CGRectMake(0, 64, self.view.frame.size.width, self.view.frame.size.height-64)]; 28 | _tableView.openSectionArray = [NSArray arrayWithObjects:@1,@2, nil]; 29 | _tableView.delegate = self; 30 | _tableView.datasource = self; 31 | _tableView.backgroundColor = [UIColor whiteColor]; 32 | _tableView.autoAdjustOpenAndClose = NO; 33 | [self.view addSubview:_tableView]; 34 | } 35 | 36 | #pragma mark - datasource 37 | - (NSInteger)mTableView:(XDMultTableView *)mTableView numberOfRowsInSection:(NSInteger)section{ 38 | return 5; 39 | } 40 | 41 | - (XDMultTableViewCell *)mTableView:(XDMultTableView *)mTableView 42 | cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 43 | static NSString *cellIdentifier = @"cell"; 44 | UITableViewCell *cell = [mTableView dequeueReusableCellWithIdentifier:cellIdentifier]; 45 | if (cell == nil) 46 | { 47 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 48 | } 49 | UIView *view = [[UIView alloc] initWithFrame:cell.bounds] ; 50 | view.layer.backgroundColor = [UIColor whiteColor].CGColor; 51 | view.layer.masksToBounds = YES; 52 | view.layer.borderWidth = 0.3; 53 | view.layer.borderColor = [UIColor lightGrayColor].CGColor; 54 | 55 | cell.backgroundView = view; 56 | cell.selectionStyle = UITableViewCellSelectionStyleNone; 57 | 58 | return cell; 59 | } 60 | 61 | - (NSInteger)numberOfSectionsInTableView:(XDMultTableView *)mTableView{ 62 | return 6; 63 | } 64 | 65 | -(NSString *)mTableView:(XDMultTableView *)mTableView titleForHeaderInSection:(NSInteger)section{ 66 | return @"我是头部"; 67 | } 68 | 69 | #pragma mark - delegate 70 | - (CGFloat)mTableView:(XDMultTableView *)mTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 71 | return 50; 72 | } 73 | 74 | - (CGFloat)mTableView:(XDMultTableView *)mTableView heightForHeaderInSection:(NSInteger)section{ 75 | return 40; 76 | } 77 | 78 | 79 | - (void)mTableView:(XDMultTableView *)mTableView willOpenHeaderAtSection:(NSInteger)section{ 80 | NSLog(@"即将展开"); 81 | } 82 | 83 | 84 | - (void)mTableView:(XDMultTableView *)mTableView willCloseHeaderAtSection:(NSInteger)section{ 85 | NSLog(@"即将关闭"); 86 | } 87 | 88 | - (void)mTableView:(XDMultTableView *)mTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 89 | NSLog(@"点击cell"); 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView.xcodeproj/xcuserdata/caixindong.xcuserdatad/xcschemes/XDMultTableView.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView/XDMultTableView/XDMultTableView.h: -------------------------------------------------------------------------------- 1 | // 2 | // XDMultTableView.h 3 | // XDMultTableView 4 | // 5 | // Created by 蔡欣东 on 2016/7/16. 6 | // Copyright © 2016年 蔡欣东. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol XDMultTableViewDelegate,XDMultTableViewDatasource; 12 | 13 | typedef UITableViewCell XDMultTableViewCell; 14 | 15 | typedef UITableViewRowAnimation XDMultTableViewRowAnimation; 16 | 17 | typedef NS_ENUM(NSInteger, XDMultTableViewCellEditingStyle) { 18 | XDMultTableViewCellEditingStyleNone, 19 | XDMultTableViewCellEditingStyleDelete, 20 | XDMultTableViewCellEditingStyleInsert 21 | }; 22 | 23 | @interface XDMultTableView : UIView 24 | 25 | 26 | @property (nonatomic, strong, readonly) UITableView *tableView; 27 | 28 | @property (nonatomic, assign, readwrite) id datasource; 29 | 30 | @property (nonatomic, assign, readwrite) id delegate; 31 | 32 | 33 | /** 34 | 若为YES,则点开一行,其他行关闭,默认为YES 35 | */ 36 | @property (nonatomic, assign, readwrite) BOOL autoAdjustOpenAndClose; 37 | 38 | /** 39 | 预先打开的行数组 40 | */ 41 | @property (nonatomic, copy, readwrite) NSArray *openSectionArray; 42 | 43 | @property (nonatomic, strong, readwrite) UIView *tableViewHeader; 44 | 45 | 46 | 47 | /** 48 | * Cell重用机制(一) 49 | * 50 | * @param identifier Cell标识 51 | * 52 | * @return Cell 53 | */ 54 | - (XDMultTableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier; 55 | 56 | /** 57 | * Cell重用机制(二) 58 | * 59 | * @param identifier Cell标识 60 | * @param indexPath 61 | * 62 | * @return Cell 63 | */ 64 | - (XDMultTableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier 65 | forIndexPath:(NSIndexPath *)indexPath; 66 | /** 67 | * 刷新数据源 68 | */ 69 | - (void)reloadData; 70 | 71 | /** 72 | * 注册cell(一) 73 | * 74 | * @param nib 75 | * @param identifier 76 | */ 77 | - (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier ; 78 | 79 | /** 80 | * 注册cell(二) 81 | * 82 | * @param cellClass 83 | * @param identifier 84 | */ 85 | - (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier; 86 | 87 | /** 88 | * 删除cell 89 | * 90 | * @param indexPaths 91 | * @param animation 92 | */ 93 | - (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation; 94 | 95 | @end 96 | 97 | /** 98 | * 数据源 99 | */ 100 | @protocol XDMultTableViewDatasource 101 | 102 | @required 103 | 104 | /** 105 | * 每个section的行数 106 | * 107 | * @param mTableView 108 | * @param section 109 | * 110 | * @return 每个section的行数 111 | */ 112 | - (NSInteger)mTableView:(XDMultTableView *)mTableView numberOfRowsInSection:(NSInteger)section; 113 | 114 | /** 115 | * Cell显示 116 | * 117 | * @param mTableView 118 | * @param indexPath 119 | * 120 | * @return Cell 121 | */ 122 | - (XDMultTableViewCell *)mTableView:(XDMultTableView *)mTableView 123 | cellForRowAtIndexPath:(NSIndexPath *)indexPath; 124 | 125 | @optional 126 | 127 | /** 128 | * section的数量 129 | * 130 | * @param mTableView 131 | * 132 | * @return section的数量 133 | */ 134 | - (NSInteger)numberOfSectionsInTableView:(XDMultTableView *)mTableView; // Default is 1 135 | 136 | /** 137 | * 头部的title 138 | * 139 | * @param tableView mTableView 140 | * @param section section 141 | * 142 | * @return 143 | */ 144 | -(NSString *)mTableView:(XDMultTableView *)mTableView titleForHeaderInSection:(NSInteger)section; 145 | 146 | //Edit 147 | 148 | /** 149 | * cell是否可以编辑 150 | * 151 | * @param mTableView 152 | * @param indexPath 153 | */ 154 | - (BOOL)mTableView:(XDMultTableView *)mTableView canEditRowAtIndexPath:(NSIndexPath *)indexPath; 155 | 156 | /** 157 | * cell编辑后回调 158 | * 159 | * @param tableView 160 | * @param editingStyle 161 | * @param indexPath 162 | */ 163 | - (void)mTableView:(XDMultTableView *)tableView commitEditingStyle:(XDMultTableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath; 164 | 165 | @end 166 | 167 | /** 168 | * 代理 169 | */ 170 | @protocol XDMultTableViewDelegate 171 | 172 | @optional 173 | /** 174 | * 每个Cell的高度 175 | * 176 | * @param mTableView 177 | * @param indexPath 178 | * 179 | * @return 每个Cell的高度 180 | */ 181 | - (CGFloat)mTableView:(XDMultTableView *)mTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath; 182 | 183 | /** 184 | * 每个section的高度 185 | * 186 | * @param mTableView 187 | * @param section 188 | * 189 | * @return 每个section的高度 190 | */ 191 | - (CGFloat)mTableView:(XDMultTableView *)mTableView heightForHeaderInSection:(NSInteger)section; 192 | 193 | /** 194 | * section View 195 | * 196 | * @param mTableView 197 | * @param section 198 | * 199 | * @return section View 200 | */ 201 | - (UIView *)mTableView:(XDMultTableView *)mTableView viewForHeaderInSection:(NSInteger)section; 202 | 203 | /** 204 | * 即将打开指定列表回调 205 | * 206 | * @param mTableView 207 | * @param section 208 | */ 209 | - (void)mTableView:(XDMultTableView *)mTableView willOpenHeaderAtSection:(NSInteger)section; 210 | 211 | /** 212 | * 213 | * 即将关闭列表回调 214 | * @param mTableView 215 | * @param section 216 | */ 217 | - (void)mTableView:(XDMultTableView *)mTableView willCloseHeaderAtSection:(NSInteger)section; 218 | 219 | /** 220 | * 点击Cell回调 221 | * 222 | * @param mTableView 223 | * @param indexPath 224 | */ 225 | - (void)mTableView:(XDMultTableView *)mTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; 226 | 227 | //Edit 228 | 229 | /** 230 | * 231 | * 设置cell的编辑类型 232 | * @param mTableView 233 | * @param indexPath 234 | * 235 | * @return 236 | */ 237 | - (XDMultTableViewCellEditingStyle)mTableView:(XDMultTableView *)mTableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath; 238 | 239 | /** 240 | * 设置cell编辑状态之删除的文本 241 | * 242 | * @param mTableView 243 | * @param indexPath 244 | 245 | * @return 246 | */ 247 | - (NSString *)mTableView:(XDMultTableView *)mTableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath; 248 | 249 | 250 | /** 251 | * ...易拓展出你想要的tableview的功能,写法可以参照上面的定义 252 | */ 253 | 254 | @end 255 | 256 | -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4EA4A1FC1D39D95A00AC649C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EA4A1FB1D39D95A00AC649C /* main.m */; }; 11 | 4EA4A1FF1D39D95A00AC649C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EA4A1FE1D39D95A00AC649C /* AppDelegate.m */; }; 12 | 4EA4A2021D39D95A00AC649C /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EA4A2011D39D95A00AC649C /* ViewController.m */; }; 13 | 4EA4A2051D39D95A00AC649C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4EA4A2031D39D95A00AC649C /* Main.storyboard */; }; 14 | 4EA4A2071D39D95A00AC649C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4EA4A2061D39D95A00AC649C /* Assets.xcassets */; }; 15 | 4EA4A20A1D39D95A00AC649C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4EA4A2081D39D95A00AC649C /* LaunchScreen.storyboard */; }; 16 | 4EA4A2141D39D9C500AC649C /* XDMultTableView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4EA4A2131D39D9C500AC649C /* XDMultTableView.m */; }; 17 | 4EA4A2161D39D9D700AC649C /* down_blue@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 4EA4A2151D39D9D700AC649C /* down_blue@2x.png */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 4EA4A1F71D39D95A00AC649C /* XDMultTableView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XDMultTableView.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | 4EA4A1FB1D39D95A00AC649C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 23 | 4EA4A1FD1D39D95A00AC649C /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 24 | 4EA4A1FE1D39D95A00AC649C /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 25 | 4EA4A2001D39D95A00AC649C /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 26 | 4EA4A2011D39D95A00AC649C /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 27 | 4EA4A2041D39D95A00AC649C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 28 | 4EA4A2061D39D95A00AC649C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 29 | 4EA4A2091D39D95A00AC649C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 30 | 4EA4A20B1D39D95A00AC649C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 31 | 4EA4A2121D39D9C500AC649C /* XDMultTableView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XDMultTableView.h; sourceTree = ""; }; 32 | 4EA4A2131D39D9C500AC649C /* XDMultTableView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XDMultTableView.m; sourceTree = ""; }; 33 | 4EA4A2151D39D9D700AC649C /* down_blue@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "down_blue@2x.png"; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | 4EA4A1F41D39D95A00AC649C /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 4EA4A1EE1D39D95A00AC649C = { 48 | isa = PBXGroup; 49 | children = ( 50 | 4EA4A1F91D39D95A00AC649C /* XDMultTableView */, 51 | 4EA4A1F81D39D95A00AC649C /* Products */, 52 | ); 53 | sourceTree = ""; 54 | }; 55 | 4EA4A1F81D39D95A00AC649C /* Products */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | 4EA4A1F71D39D95A00AC649C /* XDMultTableView.app */, 59 | ); 60 | name = Products; 61 | sourceTree = ""; 62 | }; 63 | 4EA4A1F91D39D95A00AC649C /* XDMultTableView */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 4EA4A2111D39D9A800AC649C /* XDMultTableView */, 67 | 4EA4A1FD1D39D95A00AC649C /* AppDelegate.h */, 68 | 4EA4A1FE1D39D95A00AC649C /* AppDelegate.m */, 69 | 4EA4A2001D39D95A00AC649C /* ViewController.h */, 70 | 4EA4A2011D39D95A00AC649C /* ViewController.m */, 71 | 4EA4A2031D39D95A00AC649C /* Main.storyboard */, 72 | 4EA4A2061D39D95A00AC649C /* Assets.xcassets */, 73 | 4EA4A2081D39D95A00AC649C /* LaunchScreen.storyboard */, 74 | 4EA4A20B1D39D95A00AC649C /* Info.plist */, 75 | 4EA4A1FA1D39D95A00AC649C /* Supporting Files */, 76 | ); 77 | path = XDMultTableView; 78 | sourceTree = ""; 79 | }; 80 | 4EA4A1FA1D39D95A00AC649C /* Supporting Files */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 4EA4A1FB1D39D95A00AC649C /* main.m */, 84 | ); 85 | name = "Supporting Files"; 86 | sourceTree = ""; 87 | }; 88 | 4EA4A2111D39D9A800AC649C /* XDMultTableView */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 4EA4A2151D39D9D700AC649C /* down_blue@2x.png */, 92 | 4EA4A2121D39D9C500AC649C /* XDMultTableView.h */, 93 | 4EA4A2131D39D9C500AC649C /* XDMultTableView.m */, 94 | ); 95 | path = XDMultTableView; 96 | sourceTree = ""; 97 | }; 98 | /* End PBXGroup section */ 99 | 100 | /* Begin PBXNativeTarget section */ 101 | 4EA4A1F61D39D95A00AC649C /* XDMultTableView */ = { 102 | isa = PBXNativeTarget; 103 | buildConfigurationList = 4EA4A20E1D39D95A00AC649C /* Build configuration list for PBXNativeTarget "XDMultTableView" */; 104 | buildPhases = ( 105 | 4EA4A1F31D39D95A00AC649C /* Sources */, 106 | 4EA4A1F41D39D95A00AC649C /* Frameworks */, 107 | 4EA4A1F51D39D95A00AC649C /* Resources */, 108 | ); 109 | buildRules = ( 110 | ); 111 | dependencies = ( 112 | ); 113 | name = XDMultTableView; 114 | productName = XDMultTableView; 115 | productReference = 4EA4A1F71D39D95A00AC649C /* XDMultTableView.app */; 116 | productType = "com.apple.product-type.application"; 117 | }; 118 | /* End PBXNativeTarget section */ 119 | 120 | /* Begin PBXProject section */ 121 | 4EA4A1EF1D39D95A00AC649C /* Project object */ = { 122 | isa = PBXProject; 123 | attributes = { 124 | LastUpgradeCheck = 0730; 125 | ORGANIZATIONNAME = "蔡欣东"; 126 | TargetAttributes = { 127 | 4EA4A1F61D39D95A00AC649C = { 128 | CreatedOnToolsVersion = 7.3.1; 129 | }; 130 | }; 131 | }; 132 | buildConfigurationList = 4EA4A1F21D39D95A00AC649C /* Build configuration list for PBXProject "XDMultTableView" */; 133 | compatibilityVersion = "Xcode 3.2"; 134 | developmentRegion = English; 135 | hasScannedForEncodings = 0; 136 | knownRegions = ( 137 | en, 138 | Base, 139 | ); 140 | mainGroup = 4EA4A1EE1D39D95A00AC649C; 141 | productRefGroup = 4EA4A1F81D39D95A00AC649C /* Products */; 142 | projectDirPath = ""; 143 | projectRoot = ""; 144 | targets = ( 145 | 4EA4A1F61D39D95A00AC649C /* XDMultTableView */, 146 | ); 147 | }; 148 | /* End PBXProject section */ 149 | 150 | /* Begin PBXResourcesBuildPhase section */ 151 | 4EA4A1F51D39D95A00AC649C /* Resources */ = { 152 | isa = PBXResourcesBuildPhase; 153 | buildActionMask = 2147483647; 154 | files = ( 155 | 4EA4A2161D39D9D700AC649C /* down_blue@2x.png in Resources */, 156 | 4EA4A20A1D39D95A00AC649C /* LaunchScreen.storyboard in Resources */, 157 | 4EA4A2071D39D95A00AC649C /* Assets.xcassets in Resources */, 158 | 4EA4A2051D39D95A00AC649C /* Main.storyboard in Resources */, 159 | ); 160 | runOnlyForDeploymentPostprocessing = 0; 161 | }; 162 | /* End PBXResourcesBuildPhase section */ 163 | 164 | /* Begin PBXSourcesBuildPhase section */ 165 | 4EA4A1F31D39D95A00AC649C /* Sources */ = { 166 | isa = PBXSourcesBuildPhase; 167 | buildActionMask = 2147483647; 168 | files = ( 169 | 4EA4A2021D39D95A00AC649C /* ViewController.m in Sources */, 170 | 4EA4A2141D39D9C500AC649C /* XDMultTableView.m in Sources */, 171 | 4EA4A1FF1D39D95A00AC649C /* AppDelegate.m in Sources */, 172 | 4EA4A1FC1D39D95A00AC649C /* main.m in Sources */, 173 | ); 174 | runOnlyForDeploymentPostprocessing = 0; 175 | }; 176 | /* End PBXSourcesBuildPhase section */ 177 | 178 | /* Begin PBXVariantGroup section */ 179 | 4EA4A2031D39D95A00AC649C /* Main.storyboard */ = { 180 | isa = PBXVariantGroup; 181 | children = ( 182 | 4EA4A2041D39D95A00AC649C /* Base */, 183 | ); 184 | name = Main.storyboard; 185 | sourceTree = ""; 186 | }; 187 | 4EA4A2081D39D95A00AC649C /* LaunchScreen.storyboard */ = { 188 | isa = PBXVariantGroup; 189 | children = ( 190 | 4EA4A2091D39D95A00AC649C /* Base */, 191 | ); 192 | name = LaunchScreen.storyboard; 193 | sourceTree = ""; 194 | }; 195 | /* End PBXVariantGroup section */ 196 | 197 | /* Begin XCBuildConfiguration section */ 198 | 4EA4A20C1D39D95A00AC649C /* Debug */ = { 199 | isa = XCBuildConfiguration; 200 | buildSettings = { 201 | ALWAYS_SEARCH_USER_PATHS = NO; 202 | CLANG_ANALYZER_NONNULL = YES; 203 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 204 | CLANG_CXX_LIBRARY = "libc++"; 205 | CLANG_ENABLE_MODULES = YES; 206 | CLANG_ENABLE_OBJC_ARC = YES; 207 | CLANG_WARN_BOOL_CONVERSION = YES; 208 | CLANG_WARN_CONSTANT_CONVERSION = YES; 209 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 210 | CLANG_WARN_EMPTY_BODY = YES; 211 | CLANG_WARN_ENUM_CONVERSION = YES; 212 | CLANG_WARN_INT_CONVERSION = YES; 213 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 214 | CLANG_WARN_UNREACHABLE_CODE = YES; 215 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 216 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 217 | COPY_PHASE_STRIP = NO; 218 | DEBUG_INFORMATION_FORMAT = dwarf; 219 | ENABLE_STRICT_OBJC_MSGSEND = YES; 220 | ENABLE_TESTABILITY = YES; 221 | GCC_C_LANGUAGE_STANDARD = gnu99; 222 | GCC_DYNAMIC_NO_PIC = NO; 223 | GCC_NO_COMMON_BLOCKS = YES; 224 | GCC_OPTIMIZATION_LEVEL = 0; 225 | GCC_PREPROCESSOR_DEFINITIONS = ( 226 | "DEBUG=1", 227 | "$(inherited)", 228 | ); 229 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 230 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 231 | GCC_WARN_UNDECLARED_SELECTOR = YES; 232 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 233 | GCC_WARN_UNUSED_FUNCTION = YES; 234 | GCC_WARN_UNUSED_VARIABLE = YES; 235 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 236 | MTL_ENABLE_DEBUG_INFO = YES; 237 | ONLY_ACTIVE_ARCH = YES; 238 | SDKROOT = iphoneos; 239 | }; 240 | name = Debug; 241 | }; 242 | 4EA4A20D1D39D95A00AC649C /* Release */ = { 243 | isa = XCBuildConfiguration; 244 | buildSettings = { 245 | ALWAYS_SEARCH_USER_PATHS = NO; 246 | CLANG_ANALYZER_NONNULL = YES; 247 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 248 | CLANG_CXX_LIBRARY = "libc++"; 249 | CLANG_ENABLE_MODULES = YES; 250 | CLANG_ENABLE_OBJC_ARC = YES; 251 | CLANG_WARN_BOOL_CONVERSION = YES; 252 | CLANG_WARN_CONSTANT_CONVERSION = YES; 253 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 254 | CLANG_WARN_EMPTY_BODY = YES; 255 | CLANG_WARN_ENUM_CONVERSION = YES; 256 | CLANG_WARN_INT_CONVERSION = YES; 257 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 258 | CLANG_WARN_UNREACHABLE_CODE = YES; 259 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 260 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 261 | COPY_PHASE_STRIP = NO; 262 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 263 | ENABLE_NS_ASSERTIONS = NO; 264 | ENABLE_STRICT_OBJC_MSGSEND = YES; 265 | GCC_C_LANGUAGE_STANDARD = gnu99; 266 | GCC_NO_COMMON_BLOCKS = YES; 267 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 268 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 269 | GCC_WARN_UNDECLARED_SELECTOR = YES; 270 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 271 | GCC_WARN_UNUSED_FUNCTION = YES; 272 | GCC_WARN_UNUSED_VARIABLE = YES; 273 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 274 | MTL_ENABLE_DEBUG_INFO = NO; 275 | SDKROOT = iphoneos; 276 | VALIDATE_PRODUCT = YES; 277 | }; 278 | name = Release; 279 | }; 280 | 4EA4A20F1D39D95A00AC649C /* Debug */ = { 281 | isa = XCBuildConfiguration; 282 | buildSettings = { 283 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 284 | INFOPLIST_FILE = XDMultTableView/Info.plist; 285 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 286 | PRODUCT_BUNDLE_IDENTIFIER = com.xindong.XDMultTableView; 287 | PRODUCT_NAME = "$(TARGET_NAME)"; 288 | }; 289 | name = Debug; 290 | }; 291 | 4EA4A2101D39D95A00AC649C /* Release */ = { 292 | isa = XCBuildConfiguration; 293 | buildSettings = { 294 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 295 | INFOPLIST_FILE = XDMultTableView/Info.plist; 296 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 297 | PRODUCT_BUNDLE_IDENTIFIER = com.xindong.XDMultTableView; 298 | PRODUCT_NAME = "$(TARGET_NAME)"; 299 | }; 300 | name = Release; 301 | }; 302 | /* End XCBuildConfiguration section */ 303 | 304 | /* Begin XCConfigurationList section */ 305 | 4EA4A1F21D39D95A00AC649C /* Build configuration list for PBXProject "XDMultTableView" */ = { 306 | isa = XCConfigurationList; 307 | buildConfigurations = ( 308 | 4EA4A20C1D39D95A00AC649C /* Debug */, 309 | 4EA4A20D1D39D95A00AC649C /* Release */, 310 | ); 311 | defaultConfigurationIsVisible = 0; 312 | defaultConfigurationName = Release; 313 | }; 314 | 4EA4A20E1D39D95A00AC649C /* Build configuration list for PBXNativeTarget "XDMultTableView" */ = { 315 | isa = XCConfigurationList; 316 | buildConfigurations = ( 317 | 4EA4A20F1D39D95A00AC649C /* Debug */, 318 | 4EA4A2101D39D95A00AC649C /* Release */, 319 | ); 320 | defaultConfigurationIsVisible = 0; 321 | }; 322 | /* End XCConfigurationList section */ 323 | }; 324 | rootObject = 4EA4A1EF1D39D95A00AC649C /* Project object */; 325 | } 326 | -------------------------------------------------------------------------------- /XDMultTableView/XDMultTableView/XDMultTableView/XDMultTableView.m: -------------------------------------------------------------------------------- 1 | // 2 | // XDMultTableView.m 3 | // XDMultTableView 4 | // 5 | // Created by 蔡欣东 on 2016/7/16. 6 | // Copyright © 2016年 蔡欣东. All rights reserved. 7 | // 8 | 9 | #import "XDMultTableView.h" 10 | 11 | static const CGFloat CELLHEIGHT = 44.0f; 12 | 13 | #define DEFAULTHEADVIEWCOLOR [UIColor colorWithRed:229/255.f green:229/255.f blue:229/255.f alpha:1] 14 | 15 | @interface XDMultTableView() 16 | 17 | @property (nonatomic, strong, readwrite) NSMutableArray *multopenSectionArray; 18 | 19 | @end 20 | 21 | @implementation XDMultTableView 22 | 23 | - (instancetype)initWithFrame:(CGRect)frame{ 24 | if ([super initWithFrame:frame]) { 25 | _multopenSectionArray = [NSMutableArray arrayWithCapacity:10]; 26 | _autoAdjustOpenAndClose = YES; 27 | 28 | _tableView = [[UITableView alloc] initWithFrame:self.bounds]; 29 | _tableView.delegate = self; 30 | _tableView.dataSource = self; 31 | _tableView.backgroundColor = [UIColor clearColor]; 32 | _tableView.separatorStyle = UITableViewCellSeparatorStyleNone; 33 | 34 | _tableView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; 35 | 36 | [self addSubview:_tableView]; 37 | 38 | } 39 | return self; 40 | } 41 | 42 | - (XDMultTableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier{ 43 | 44 | return [self.tableView dequeueReusableCellWithIdentifier:identifier]; 45 | } 46 | 47 | - (XDMultTableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath{ 48 | return [self.tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath]; 49 | } 50 | 51 | - (void)reloadData{ 52 | [_tableView reloadData]; 53 | } 54 | 55 | - (void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier{ 56 | [self.tableView registerNib:nib forCellReuseIdentifier:identifier]; 57 | } 58 | 59 | - (void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier{ 60 | [self.tableView registerClass:cellClass forCellReuseIdentifier:identifier]; 61 | } 62 | 63 | - (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(XDMultTableViewRowAnimation)animation{ 64 | [self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:animation]; 65 | } 66 | 67 | #pragma mark - UITableViewDataSource 68 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 69 | if (![_multopenSectionArray containsObject:[NSNumber numberWithInteger:section]]) { 70 | return 0; 71 | } 72 | return [self invoke_numberOfRowsInSection:section]; 73 | } 74 | 75 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 76 | return [self invoke_cellForRowAtIndexPath:indexPath]; 77 | } 78 | 79 | 80 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ 81 | return [self invoke_numberOfSections]; 82 | } 83 | 84 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 85 | return [self invode_canEditRowAtIndexPath:indexPath]; 86 | } 87 | 88 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{ 89 | [self invode_commitEditingStyle:editingStyle forRowAtIndexPath:indexPath]; 90 | } 91 | 92 | #pragma mark - UITableViewDelegate 93 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 94 | return [self invoke_heightForRowAtIndexPath:indexPath]; 95 | 96 | } 97 | 98 | - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ 99 | if (self.datasource && [self.datasource respondsToSelector:@selector(numberOfSectionsInTableView:)]) 100 | { 101 | return [self invoke_heightForHeaderInSection:section]; 102 | 103 | }else { 104 | return 0; 105 | } 106 | } 107 | 108 | - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ 109 | UIView* view = [self invoke_viewForHeaderInSection:section]; 110 | CGFloat height = [self invoke_heightForHeaderInSection:section]; 111 | CGFloat width = self.tableView.bounds.size.width; 112 | CGRect frame = CGRectMake(0, 0, width, height); 113 | if (view) { 114 | view.frame = frame; 115 | }else{ 116 | view = [[UIView alloc] init]; 117 | view.backgroundColor = DEFAULTHEADVIEWCOLOR; 118 | view.layer.borderColor = [UIColor whiteColor].CGColor; 119 | view.layer.borderWidth = 0.5; 120 | NSString *title = [self invoke_titleForHeaderInSection:section]; 121 | view.frame = frame; 122 | CGFloat labelW = 200; 123 | CGFloat labelH = 20; 124 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, (height-labelH)/2, labelW, labelH)]; 125 | label.text = title; 126 | [view addSubview:label]; 127 | } 128 | view.tag = section; 129 | CGFloat imgH = height-20; 130 | CGFloat imgW = imgH; 131 | UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(width-imgW-10, (height-imgH)/2, imgW, imgH)]; 132 | imageView.contentMode = UIViewContentModeScaleAspectFit; 133 | imageView.image = [UIImage imageNamed:@"down_blue"]; 134 | NSNumber *sectionObj = [NSNumber numberWithInteger:section]; 135 | if ([_multopenSectionArray containsObject:sectionObj]) { 136 | imageView.transform = CGAffineTransformMakeRotation(0); 137 | }else{ 138 | imageView.transform = CGAffineTransformMakeRotation(-M_PI/2); 139 | } 140 | imageView.tag = 100; 141 | [view addSubview:imageView]; 142 | UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapHeader:)]; 143 | [view addGestureRecognizer:tap]; 144 | return view; 145 | } 146 | 147 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 148 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 149 | [self invoke_didSelectRowAtIndexPath:indexPath]; 150 | } 151 | 152 | - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{ 153 | return [self invoke_editingStyleForRowAtIndexPath:indexPath]; 154 | } 155 | 156 | - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{ 157 | return [self invoke_titleForDeleteConfirmationButtonForRowAtIndexPath:indexPath]; 158 | } 159 | 160 | #pragma mark - add or delete NSIndexPaths 161 | 162 | - (NSMutableArray *)buildInsertRowWithSection:(NSInteger)section 163 | { 164 | NSInteger insert = [self invoke_numberOfRowsInSection:section]; 165 | 166 | if (insert != 0) 167 | { 168 | [self invoke_willOpenHeaderAtSection:section]; 169 | } 170 | 171 | NSMutableArray *indexPaths = [[NSMutableArray alloc] init]; 172 | 173 | for (int i = 0; i < insert; i++) 174 | { 175 | [indexPaths addObject: [NSIndexPath indexPathForRow:i inSection:section]]; 176 | } 177 | 178 | return indexPaths; 179 | } 180 | 181 | - (NSMutableArray *)buildDeleteRowWithSection:(NSInteger)section 182 | { 183 | NSInteger delete = [self invoke_numberOfRowsInSection:section];; 184 | if (delete != 0) 185 | { 186 | [self invoke_willCloseHeaderAtSection:section]; 187 | } 188 | NSMutableArray *indexPaths = [[NSMutableArray alloc] init]; 189 | 190 | for (int i = 0; i < delete; i++) 191 | { 192 | [indexPaths addObject: [NSIndexPath indexPathForRow:i inSection:section]]; 193 | } 194 | 195 | return indexPaths; 196 | } 197 | 198 | #pragma mark - UITapGestureRecognizer response 199 | - (void)tapHeader:(UITapGestureRecognizer *) tap { 200 | NSInteger section = tap.view.tag; 201 | NSNumber *sectionObj = [NSNumber numberWithInteger:section]; 202 | UIImageView *imageView = (UIImageView *)[tap.view viewWithTag:100]; 203 | if ([_multopenSectionArray containsObject:sectionObj]) { 204 | NSArray *deleteArray = [self buildDeleteRowWithSection:section]; 205 | [_multopenSectionArray removeObject:sectionObj]; 206 | [_tableView deleteRowsAtIndexPaths:deleteArray withRowAnimation:UITableViewRowAnimationFade]; 207 | [UIView animateWithDuration:0.3 animations:^{ 208 | imageView.transform = CGAffineTransformMakeRotation(-M_PI/2); 209 | }]; 210 | }else{ 211 | if (_autoAdjustOpenAndClose) { 212 | [[_multopenSectionArray copy] enumerateObjectsUsingBlock:^(NSNumber *obj, NSUInteger idx, BOOL * _Nonnull stop) { 213 | NSLog(@"%ld",[obj integerValue]); 214 | NSArray *otherDeleteArray = [self buildDeleteRowWithSection:[obj integerValue]]; 215 | [_multopenSectionArray removeObject:obj]; 216 | [_tableView deleteRowsAtIndexPaths:otherDeleteArray withRowAnimation:UITableViewRowAnimationFade]; 217 | UIView *otherView = [self.tableView viewWithTag:[obj integerValue]]; 218 | UIImageView *imageView = (UIImageView *)[otherView viewWithTag:100]; 219 | [UIView animateWithDuration:0.3 animations:^{ 220 | imageView.transform = CGAffineTransformMakeRotation(-M_PI/2); 221 | }]; 222 | }]; 223 | } 224 | 225 | [_multopenSectionArray addObject:sectionObj]; 226 | NSArray *insertArray = [self buildInsertRowWithSection:section]; 227 | [_tableView insertRowsAtIndexPaths:insertArray withRowAnimation:UITableViewRowAnimationFade]; 228 | [UIView animateWithDuration:0.3 animations:^{ 229 | imageView.transform = CGAffineTransformMakeRotation(0); 230 | }]; 231 | } 232 | } 233 | 234 | #pragma mark - invoke_datasource 235 | - (NSInteger)invoke_numberOfRowsInSection:(NSInteger)section{ 236 | if (self.datasource&&[self.datasource respondsToSelector:@selector(mTableView:numberOfRowsInSection:)]){ 237 | return [self.datasource mTableView:self numberOfRowsInSection:section]; 238 | } 239 | return 0; 240 | } 241 | 242 | - (NSInteger)invoke_numberOfSections{ 243 | if (self.datasource&&[self.datasource respondsToSelector:@selector(numberOfSectionsInTableView:)]) { 244 | return [self.datasource numberOfSectionsInTableView:self]; 245 | } 246 | return 1; 247 | } 248 | 249 | - (UITableViewCell *)invoke_cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 250 | UITableViewCell *cell = nil; 251 | if (self.datasource&&[self.datasource respondsToSelector:@selector(mTableView:cellForRowAtIndexPath:)]) { 252 | cell = [self.datasource mTableView:self cellForRowAtIndexPath:indexPath]; 253 | } 254 | return cell; 255 | } 256 | 257 | - (NSString *)invoke_titleForHeaderInSection:(NSInteger)section { 258 | if (self.datasource&&[self.datasource respondsToSelector:@selector(mTableView:titleForHeaderInSection:)]) { 259 | return [self.datasource mTableView:self titleForHeaderInSection:section]; 260 | } 261 | return @""; 262 | } 263 | 264 | - (BOOL)invode_canEditRowAtIndexPath:(NSIndexPath *)indexPath { 265 | if(self.datasource&&[self.datasource respondsToSelector:@selector(mTableView:canEditRowAtIndexPath:)]){ 266 | return [self.datasource mTableView:self canEditRowAtIndexPath:indexPath]; 267 | } 268 | return false; 269 | } 270 | 271 | - (void)invode_commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{ 272 | if (self.datasource&&[self.datasource respondsToSelector:@selector(mTableView:commitEditingStyle:forRowAtIndexPath:)]) { 273 | XDMultTableViewCellEditingStyle style = (XDMultTableViewCellEditingStyle)editingStyle; 274 | [self.datasource mTableView:self commitEditingStyle:style forRowAtIndexPath:indexPath]; 275 | } 276 | } 277 | 278 | #pragma mark - invoke_delegate 279 | - (CGFloat)invoke_heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 280 | CGFloat height = CELLHEIGHT; 281 | if (self.delegate&&[self.delegate respondsToSelector:@selector(mTableView:heightForRowAtIndexPath:)]) { 282 | height = [self.delegate mTableView:self heightForRowAtIndexPath:indexPath]; 283 | } 284 | return height; 285 | } 286 | 287 | - (CGFloat)invoke_heightForHeaderInSection:(NSInteger)section{ 288 | if (self.delegate&&[self.delegate respondsToSelector:@selector(mTableView:heightForHeaderInSection:)]) { 289 | return [self.delegate mTableView:self heightForHeaderInSection:section]; 290 | } 291 | return 0; 292 | } 293 | 294 | - (UIView*)invoke_viewForHeaderInSection:(NSInteger)section;{ 295 | if (self.delegate&&[self.delegate respondsToSelector:@selector(mTableView:viewForHeaderInSection:)]) { 296 | return [self.delegate mTableView:self viewForHeaderInSection:section]; 297 | } 298 | return nil; 299 | } 300 | 301 | - (void)invoke_didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 302 | if (self.delegate&&[self.delegate respondsToSelector:@selector(mTableView:didSelectRowAtIndexPath:)]) { 303 | [self.delegate mTableView:self didSelectRowAtIndexPath:indexPath]; 304 | } 305 | } 306 | 307 | - (void)invoke_willOpenHeaderAtSection:(NSInteger)section { 308 | if (self.delegate&&[self.delegate respondsToSelector:@selector(mTableView:willOpenHeaderAtSection:)]) { 309 | [self.delegate mTableView:self willOpenHeaderAtSection:section]; 310 | } 311 | } 312 | 313 | - (void)invoke_willCloseHeaderAtSection:(NSInteger)section { 314 | if (self.delegate&&[self.delegate respondsToSelector:@selector(mTableView:willCloseHeaderAtSection:)]) { 315 | [self.delegate mTableView:self willCloseHeaderAtSection:section]; 316 | } 317 | } 318 | 319 | - (UITableViewCellEditingStyle)invoke_editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { 320 | if (self.delegate&&[self.delegate respondsToSelector:@selector(mTableView:editingStyleForRowAtIndexPath:)]) { 321 | return (UITableViewCellEditingStyle)[self.delegate mTableView:self editingStyleForRowAtIndexPath:indexPath]; 322 | } 323 | return UITableViewCellEditingStyleNone; 324 | } 325 | 326 | - (NSString *)invoke_titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath{ 327 | if (self.delegate&&[self.delegate respondsToSelector:@selector(mTableView:titleForDeleteConfirmationButtonForRowAtIndexPath:)]) { 328 | return [self.delegate mTableView:self titleForDeleteConfirmationButtonForRowAtIndexPath:indexPath]; 329 | } 330 | return @"Delete"; 331 | } 332 | 333 | #pragma mark - setter and getter 334 | - (void)setOpenSectionArray:(NSArray *)openSectionArray { 335 | _multopenSectionArray = [NSMutableArray arrayWithArray:openSectionArray]; 336 | } 337 | 338 | - (void)setTableViewHeader:(UIView *)tableViewHeader { 339 | self.tableView.tableHeaderView = tableViewHeader; 340 | } 341 | 342 | 343 | @end 344 | --------------------------------------------------------------------------------