├── .gitignore ├── LICENSE ├── README.md ├── SwipeCell ├── TMSwipeCell.h └── TMSwipeCell.m ├── TMSwipeCell.podspec ├── TMSwipeCell.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── TMSwipeCell ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── 001.imageset │ │ ├── 001.jpg │ │ └── Contents.json │ ├── 002.imageset │ │ ├── 002.jpg │ │ └── Contents.json │ ├── 003.imageset │ │ ├── 003.jpg │ │ └── Contents.json │ ├── 004.imageset │ │ ├── 004.jpg │ │ └── Contents.json │ ├── 005.imageset │ │ ├── 005.jpg │ │ └── Contents.json │ ├── 006.imageset │ │ ├── 006.png │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── Delete.imageset │ │ ├── Contents.json │ │ └── Delete.png │ └── Tag.imageset │ │ ├── Contents.json │ │ └── Tag.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── ExpandCellDemo │ ├── TMCellTypeOne.h │ ├── TMCellTypeOne.m │ ├── TMCellTypeOne.xib │ ├── TMExpandCellTypeOne.h │ ├── TMExpandCellTypeOne.m │ ├── TMExpandCellTypeOne.xib │ ├── TMExpandModel.h │ ├── TMExpandModel.m │ ├── TMExpandViewController.h │ └── TMExpandViewController.m ├── Info.plist ├── SwipeCellDemo │ ├── TestModel.h │ ├── TestModel.m │ ├── TestTableViewCell.h │ ├── TestTableViewCell.m │ ├── TestViewController.h │ ├── TestViewController.m │ ├── ViewController.h │ └── ViewController.m ├── gif │ └── one.gif └── main.m ├── TMSwipeCellTests ├── Info.plist └── TMSwipeCellTests.m └── TMSwipeCellUITests ├── Info.plist └── TMSwipeCellUITests.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots/**/*.png 56 | fastlane/test_output 57 | 58 | # Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 cocomanbar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # TMSwipeCell 3 | 4 | 微信样式,支持文字和图片样式按钮,支持删除再确认效果, 兼容代码和xib创建, 屏幕翻转. 5 | 6 | #### 效果图 7 | ![image](https://github.com/cocomanbar/TMSwipeCell/blob/master/TMSwipeCell/gif/one.gif) 8 | 9 | ## pods 10 | 11 | ``` 12 | pod 'TMSwipeCell' 13 | ``` 14 | 15 | ## How to use 16 | 17 | 1.继承该类 18 | 19 | ``` 20 | @interface TMSwipeCell111 : TMSwipeCell 21 | @end 22 | ``` 23 | 24 | 2.在`tableView:cellForRowAtIndexPath:`方法中设置代理: 25 | 26 | ``` 27 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 28 | TMSwipeCell111 *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(TMSwipeCell111.class)]; 29 | if (!cell) { 30 | cell = [[TMSwipeCell111 alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NSStringFromClass(TMSwipeCell111.class)]; 31 | cell.delegate = self; 32 | } 33 | return cell; 34 | } 35 | ``` 36 | 37 | 3.实现`TMSwipeCellDelegate`协议三个方法,返回侧滑按钮事件数组、返回需要事件的cell、以及代理处理事件(当然block也ok)。 38 | 39 | 40 | 41 | 4.更多细节请看demo 42 | 43 | -------------------------------------------------------------------------------- /SwipeCell/TMSwipeCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TMSwipeCell.h 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/7/3. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, TMSwipeCellActionStyle) { 12 | TMSwipeCellActionStyleDefault = 0, 13 | TMSwipeCellActionStyleDestructive = TMSwipeCellActionStyleDefault, // 删除 红底 14 | TMSwipeCellActionStyleNormal // 正常 灰底 15 | }; 16 | 17 | typedef NS_ENUM(NSInteger, TMSwipeCellActionAnimationStyle) { 18 | TMSwipeCellActionAnimationStyleDefault = 0, // 正常 点击就执行 19 | TMSwipeCellActionAnimationStyleAnimation = 1, // 动画 点击就执行动画,寻求再次确认 : 注意 Destructive|Default 属性默认执行动画 20 | }; 21 | 22 | @interface TMSwipeCellAction : NSObject 23 | 24 | + (instancetype)rowActionWithStyle:(TMSwipeCellActionStyle)style title:(nullable NSString *)title handler:(void (^)(TMSwipeCellAction *action, NSIndexPath *indexPath))handler; 25 | 26 | @property (nonatomic, readonly) TMSwipeCellActionStyle style; 27 | @property (nonatomic, assign) TMSwipeCellActionAnimationStyle animationStyle; //是否需要执行确认动画. 默认Default 28 | //style == TMSwipeCellActionStyleDestructive || 29 | //animationStyle == TMSwipeCellActionAnimationStyleAnimation 执行动画 30 | @property (nonatomic, strong) NSString *title; // 文字内容 31 | @property (nonatomic, strong) UIImage *image; // 按钮图片. 默认无图 32 | @property (nonatomic, strong) UIColor *titleColor; // 文字颜色. 默认白色 33 | @property (nonatomic, strong) UIColor *backgroundColor; // 背景颜色. 默认透明 : 级别优先于 style 34 | @property (nonatomic, assign) CGFloat margin; // 内容左右间距. 默认15 35 | @property (nonatomic, strong) UIFont *font; // 字体大小. 默认17 36 | 37 | /* 设置需要显示confirm的text和icon */ 38 | @property (nonatomic, strong)NSString *confirmTitle; //再次确认的文字描述. 默认空 39 | @property (nonatomic, strong)NSString *confirmIcon; //再次确认的图片icon. 默认空 40 | 41 | @end 42 | 43 | #pragma mark - 44 | 45 | typedef NS_ENUM(NSInteger, TMSwipeActionButtonStyle) { 46 | TMSwipeActionButtonStyleNormal = 0, //正常状态:动画前 47 | TMSwipeActionButtonStyleSelected = 1, //选中状态:动画后 48 | }; 49 | 50 | @interface TMSwipeActionButton : UIButton 51 | 52 | /* 属性赋值来自[TMSwipeCellAction class]实例 */ 53 | @property (nonatomic, assign)TMSwipeCellActionAnimationStyle animationStyle; 54 | 55 | /* 记录当前动画状态,仅仅在有动画效果下生效 */ 56 | @property (nonatomic, assign)TMSwipeActionButtonStyle logStyle; 57 | 58 | @end 59 | 60 | #pragma mark - 61 | 62 | @class TMSwipeCell; 63 | @protocol TMSwipeCellDelegate 64 | @optional; 65 | 66 | /** 67 | 选中了侧滑按钮 68 | 69 | @param swipeCell 当前响应的cell 70 | @param indexPath cell在tableView中的位置 71 | @param index 选中的是第几个action 72 | */ 73 | - (void)swipeCell:(TMSwipeCell *)swipeCell atIndexPath:(NSIndexPath *)indexPath didSelectedAtIndex:(NSInteger)index; 74 | 75 | /** 76 | 告知当前位置的cell是否需要侧滑按钮 77 | 78 | @param swipeCell 当前响应的cell 79 | @param indexPath cell在tableView中的位置 80 | @return YES 表示当前cell可以侧滑, NO 不可以 81 | */ 82 | - (BOOL)swipeCell:(TMSwipeCell *)swipeCell canSwipeRowAtIndexPath:(NSIndexPath *)indexPath; 83 | 84 | /** 85 | 返回侧滑事件 86 | 87 | @param swipeCell 当前响应的cell 88 | @param indexPath cell在tableView中的位置 89 | @return 数组为空, 则没有侧滑事件 90 | */ 91 | - (nullable NSArray *)swipeCell:(TMSwipeCell *)swipeCell editActionsForRowAtIndexPath:(NSIndexPath *)indexPath; 92 | 93 | @end 94 | 95 | @interface TMSwipeCell : UITableViewCell 96 | 97 | @property (nonatomic, weak) id delegate; 98 | 99 | /** 100 | * 按钮容器 101 | */ 102 | @property (nonatomic, strong) UIView *btnContainView; 103 | 104 | /** 105 | * 隐藏侧滑按钮 106 | */ 107 | - (void)hiddenAllSideslip; 108 | - (void)hiddenSideslip:(BOOL)animate; 109 | 110 | @end 111 | 112 | #pragma mark - 113 | 114 | @interface UITableView (TMSwipeCell) 115 | 116 | - (void)hiddenAllSideslip; 117 | 118 | @end 119 | -------------------------------------------------------------------------------- /SwipeCell/TMSwipeCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TMSwipeCell.m 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/7/3. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import "TMSwipeCell.h" 10 | 11 | #pragma mark - TMSwipeCellAction 12 | 13 | @interface TMSwipeCellAction () 14 | @property (nonatomic, copy) void (^handler)(TMSwipeCellAction *action, NSIndexPath *indexPath); 15 | @property (nonatomic, assign) TMSwipeCellActionStyle style; 16 | @end 17 | @implementation TMSwipeCellAction 18 | + (instancetype)rowActionWithStyle:(TMSwipeCellActionStyle)style title:(NSString *)title handler:(void (^)(TMSwipeCellAction *action, NSIndexPath *indexPath))handler { 19 | TMSwipeCellAction *action = [TMSwipeCellAction new]; 20 | action.title = title; 21 | action.handler = handler; 22 | action.style = style; 23 | return action; 24 | } 25 | 26 | - (CGFloat)margin { 27 | return _margin == 0 ? 15 : _margin; 28 | } 29 | 30 | @end 31 | 32 | #pragma mark - TMSwipeActionButton 33 | 34 | @implementation TMSwipeActionButton 35 | 36 | @end 37 | 38 | #pragma mark - TMSwipeCell 39 | 40 | typedef NS_ENUM(NSInteger, TMSwipeCellState) { 41 | TMSwipeCellStateNormal, 42 | TMSwipeCellStateAnimating, 43 | TMSwipeCellStateOpen 44 | }; 45 | 46 | @interface TMSwipeCell () 47 | @property (nonatomic, assign) BOOL sideslip; 48 | @property (nonatomic, assign) TMSwipeCellState state; 49 | @end 50 | 51 | @implementation TMSwipeCell{ 52 | UITableView *_tableView; 53 | NSArray * _actions; 54 | UIPanGestureRecognizer *_panGesture; 55 | UIPanGestureRecognizer *_tableViewPan; 56 | } 57 | 58 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 59 | if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { 60 | [self setupSideslipCell]; 61 | } 62 | return self; 63 | } 64 | 65 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 66 | if (self = [super initWithCoder:aDecoder]) { 67 | [self setupSideslipCell]; 68 | } 69 | return self; 70 | } 71 | 72 | - (void)setupSideslipCell { 73 | _panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(contentViewPan:)]; 74 | _panGesture.delegate = self; 75 | [self.contentView addGestureRecognizer:_panGesture]; 76 | self.contentView.backgroundColor = [UIColor whiteColor]; 77 | } 78 | 79 | - (void)layoutSubviews { 80 | CGFloat x = 0; 81 | if (_sideslip) x = self.contentView.frame.origin.x; 82 | 83 | [super layoutSubviews]; 84 | CGFloat totalWidth = 0; 85 | for (TMSwipeActionButton *btn in _btnContainView.subviews) { 86 | btn.frame = CGRectMake(totalWidth, 0, btn.frame.size.width, self.frame.size.height); 87 | totalWidth += btn.frame.size.width; 88 | } 89 | _btnContainView.frame = CGRectMake(self.frame.size.width - totalWidth, 0, totalWidth, self.frame.size.height); 90 | 91 | // 侧滑状态旋转屏幕时, 保持侧滑 92 | if (_sideslip) [self setContentViewX:x]; 93 | 94 | CGRect frame = self.contentView.frame; 95 | frame.size.width = self.bounds.size.width; 96 | self.contentView.frame = frame; 97 | } 98 | 99 | - (void)prepareForReuse { 100 | [super prepareForReuse]; 101 | if (_sideslip) [self hiddenSideslip:NO]; 102 | } 103 | 104 | #pragma mark - UIGestureRecognizerDelegate 105 | 106 | - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { 107 | if (gestureRecognizer == _panGesture) { 108 | if (self.sideslip) { 109 | [self hiddenAllSideslip]; 110 | } 111 | UIPanGestureRecognizer *gesture = (UIPanGestureRecognizer *)gestureRecognizer; 112 | CGPoint translation = [gesture translationInView:gesture.view]; 113 | 114 | // 如果手势相对于水平方向的角度大于45°, 则不触发侧滑 115 | BOOL shouldBegin = fabs(translation.y) <= fabs(translation.x); 116 | if (!shouldBegin) return NO; 117 | 118 | // 询问代理是否需要侧滑 119 | if ([_delegate respondsToSelector:@selector(swipeCell:canSwipeRowAtIndexPath:)]) { 120 | shouldBegin = [_delegate swipeCell:self canSwipeRowAtIndexPath:self.indexPath] || _sideslip; 121 | } 122 | 123 | if (shouldBegin) { 124 | // 向代理获取侧滑展示内容数组 125 | if ([_delegate respondsToSelector:@selector(swipeCell:editActionsForRowAtIndexPath:)]) { 126 | NSArray *actions = [_delegate swipeCell:self editActionsForRowAtIndexPath:self.indexPath]; 127 | if (!actions || actions.count == 0) return NO; 128 | [self setActions:actions]; 129 | } else { 130 | return NO; 131 | } 132 | } 133 | return shouldBegin; 134 | } else if (gestureRecognizer == _tableViewPan) { 135 | if (self.tableView.scrollEnabled) { 136 | return NO; 137 | } 138 | } 139 | return YES; 140 | } 141 | 142 | /* Response Events */ 143 | - (void)tableViewPan:(UIPanGestureRecognizer *)pan { 144 | if (!self.tableView.scrollEnabled && pan.state == UIGestureRecognizerStateBegan) { 145 | [self hiddenAllSideslip]; 146 | } 147 | } 148 | 149 | - (void)contentViewPan:(UIPanGestureRecognizer *)pan { 150 | CGPoint point = [pan translationInView:pan.view]; 151 | UIGestureRecognizerState state = pan.state; 152 | [pan setTranslation:CGPointZero inView:pan.view]; 153 | 154 | if (state == UIGestureRecognizerStateChanged) { 155 | CGRect frame = self.contentView.frame; 156 | frame.origin.x += point.x; 157 | if (frame.origin.x > 15) { 158 | frame.origin.x = 15; 159 | } else if (frame.origin.x < -30 - _btnContainView.frame.size.width) { 160 | frame.origin.x = -30 - _btnContainView.frame.size.width; 161 | } 162 | self.contentView.frame = frame; 163 | 164 | } else if (state == UIGestureRecognizerStateEnded) { 165 | CGPoint velocity = [pan velocityInView:pan.view]; 166 | if (self.contentView.frame.origin.x == 0) { 167 | return; 168 | } else if (self.contentView.frame.origin.x > 5) { 169 | [self hiddenWithBounceAnimation]; 170 | } else if (fabs(self.contentView.frame.origin.x) >= 40 && velocity.x <= 0) { 171 | [self showSideslip]; 172 | } else { 173 | [self hiddenSideslip:YES]; 174 | } 175 | 176 | } else if (state == UIGestureRecognizerStateCancelled) { 177 | [self hiddenAllSideslip]; 178 | } 179 | } 180 | 181 | /* 触发事件 */ 182 | - (void)actionBtnDidClicked:(TMSwipeActionButton *)btn { 183 | 184 | TMSwipeCellAction *action = _actions[btn.tag]; 185 | if (btn.animationStyle == TMSwipeCellActionAnimationStyleAnimation) { 186 | if (btn.logStyle == TMSwipeActionButtonStyleSelected) { 187 | [self actionBtnDidClickToDule:btn.tag]; 188 | return; 189 | } 190 | 191 | if (action.confirmTitle || action.confirmIcon) { 192 | [btn setTitle:action.confirmTitle forState:UIControlStateNormal]; 193 | [btn setImage:[UIImage imageNamed:action.confirmIcon] forState:UIControlStateNormal]; 194 | }else{ 195 | [btn setTitle:@"确认删除" forState:UIControlStateNormal]; 196 | } 197 | if (_actions.count == 1) { 198 | 199 | CGFloat width = [btn.currentTitle boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : btn.titleLabel.font} context:nil].size.width; 200 | btn.frame = CGRectMake(0, 0, width + action.margin * 2, self.frame.size.height); 201 | btn.logStyle = TMSwipeActionButtonStyleSelected; 202 | [self layoutSubviews]; 203 | [self showSideslip]; 204 | }else{ 205 | 206 | CGFloat width = _btnContainView.frame.size.width; 207 | btn.frame = CGRectMake(0, 0, width, self.frame.size.height); 208 | for (TMSwipeActionButton *button in _btnContainView.subviews) { 209 | if (button.tag != btn.tag) { 210 | [button removeFromSuperview]; 211 | } 212 | } 213 | btn.logStyle = TMSwipeActionButtonStyleSelected; 214 | [self layoutSubviews]; 215 | [self showSideslip]; 216 | } 217 | }else{ 218 | [self actionBtnDidClickToDule:btn.tag]; 219 | } 220 | } 221 | 222 | - (void)actionBtnDidClickToDule:(NSInteger)tag { 223 | if ([self.delegate respondsToSelector:@selector(swipeCell:atIndexPath:didSelectedAtIndex:)]) { 224 | [self.delegate swipeCell:self atIndexPath:self.indexPath didSelectedAtIndex:tag]; 225 | } 226 | if (tag < _actions.count) { 227 | TMSwipeCellAction *action = _actions[tag]; 228 | if (action.handler) action.handler(action, self.indexPath); 229 | } 230 | [self hiddenAllSideslip]; 231 | self.state = TMSwipeCellStateNormal; 232 | } 233 | 234 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 235 | [super touchesBegan:touches withEvent:event]; 236 | if (_sideslip) { 237 | [self hiddenAllSideslip]; 238 | } 239 | } 240 | 241 | #pragma mark - Methods 242 | - (void)hiddenWithBounceAnimation { 243 | self.state = TMSwipeCellStateAnimating; 244 | [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ 245 | [self setContentViewX:-10]; 246 | } completion:^(BOOL finished) { 247 | [self hiddenSideslip:YES]; 248 | }]; 249 | } 250 | 251 | - (void)hiddenAllSideslip { 252 | [self.tableView hiddenAllSideslip]; 253 | } 254 | 255 | - (void)hiddenSideslip:(BOOL)animate { 256 | if (self.contentView.frame.origin.x == 0){ 257 | self.sideslip = NO; 258 | self.state = TMSwipeCellStateNormal; 259 | return; 260 | } 261 | 262 | self.state = TMSwipeCellStateAnimating; 263 | __weak __typeof(&*self)weakSelf = self; 264 | [UIView animateWithDuration:(animate?0.2:0) delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ 265 | [self setContentViewX:0]; 266 | } completion:^(BOOL finished) { 267 | [weakSelf.btnContainView removeFromSuperview]; 268 | weakSelf.btnContainView = nil; 269 | self.state = TMSwipeCellStateNormal; 270 | }]; 271 | } 272 | 273 | - (void)showSideslip { 274 | self.state = TMSwipeCellStateAnimating; 275 | __weak __typeof(&*self)weakSelf = self; 276 | [UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ 277 | [self setContentViewX:-weakSelf.btnContainView.frame.size.width]; 278 | } completion:^(BOOL finished) { 279 | self.state = TMSwipeCellStateOpen; 280 | }]; 281 | } 282 | 283 | #pragma mark - Setter 284 | - (void)setContentViewX:(CGFloat)x { 285 | CGRect frame = self.contentView.frame; 286 | frame.origin.x = x; 287 | self.contentView.frame = frame; 288 | } 289 | 290 | - (void)setActions:(NSArray *)actions { 291 | _actions = actions; 292 | 293 | if (_btnContainView) { 294 | [_btnContainView removeFromSuperview]; 295 | _btnContainView = nil; 296 | } 297 | _btnContainView = [UIView new]; 298 | [self insertSubview:_btnContainView belowSubview:self.contentView]; 299 | 300 | for (int i = 0; i < actions.count; i++) { 301 | TMSwipeCellAction *action = actions[i]; 302 | TMSwipeActionButton *btn = [TMSwipeActionButton buttonWithType:UIButtonTypeCustom]; 303 | btn.tag = i; 304 | btn.adjustsImageWhenHighlighted = NO; 305 | [btn setTitle:action.title?action.title:@"" forState:UIControlStateNormal]; 306 | btn.titleLabel.font = action.font ? action.font : [UIFont systemFontOfSize:17]; 307 | [btn addTarget:self action:@selector(actionBtnDidClicked:) forControlEvents:UIControlEventTouchUpInside]; 308 | 309 | if (action.backgroundColor) { 310 | btn.backgroundColor = action.backgroundColor; 311 | } else { 312 | btn.backgroundColor = action.style == TMSwipeCellActionStyleNormal?[UIColor colorWithRed:200/255.0 green:199/255.0 blue:205/255.0 alpha:1] : [UIColor redColor]; 313 | } 314 | 315 | if (action.image) { 316 | [btn setImage:action.image forState:UIControlStateNormal]; 317 | } 318 | 319 | if (action.titleColor) { 320 | [btn setTitleColor:action.titleColor forState:UIControlStateNormal]; 321 | } 322 | 323 | CGFloat width = [action.title boundingRectWithSize:CGSizeMake(MAXFLOAT, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : btn.titleLabel.font} context:nil].size.width; 324 | width += (action.image ? action.image.size.width : 0); 325 | btn.frame = CGRectMake(0, 0, width + action.margin*2, self.frame.size.height); 326 | 327 | //记录需要扩展动画的条件 328 | if (action.style == TMSwipeCellActionStyleDefault || 329 | action.animationStyle == TMSwipeCellActionAnimationStyleAnimation) { 330 | btn.animationStyle = TMSwipeCellActionAnimationStyleAnimation; 331 | } 332 | 333 | [_btnContainView addSubview:btn]; 334 | } 335 | } 336 | 337 | - (void)setState:(TMSwipeCellState)state { 338 | _state = state; 339 | 340 | if (state == TMSwipeCellStateNormal) { 341 | for (TMSwipeCell *cell in self.tableView.visibleCells) { 342 | if ([cell isKindOfClass:TMSwipeCell.class]) { 343 | cell.sideslip = NO; 344 | } 345 | } 346 | } else if (state == TMSwipeCellStateAnimating) { 347 | NSLog(@"----->>%@", self); 348 | } else if (state == TMSwipeCellStateOpen) { 349 | for (TMSwipeCell *cell in self.tableView.visibleCells) { 350 | if ([cell isKindOfClass:TMSwipeCell.class]) { 351 | cell.sideslip = YES; 352 | } 353 | } 354 | } 355 | } 356 | 357 | - (UITableView *)tableView { 358 | if (!_tableView) { 359 | id view = self.superview; 360 | while (view && [view isKindOfClass:[UITableView class]] == NO) { 361 | view = [view superview]; 362 | } 363 | _tableView = (UITableView *)view; 364 | _tableViewPan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(tableViewPan:)]; 365 | _tableViewPan.delegate = self; 366 | [_tableView addGestureRecognizer:_tableViewPan]; 367 | } 368 | return _tableView; 369 | } 370 | 371 | - (NSIndexPath *)indexPath { 372 | return [self.tableView indexPathForCell:self]; 373 | } 374 | 375 | @end 376 | 377 | #pragma mark - UITableView (TMSwipeCell) 378 | 379 | @implementation UITableView (TMSwipeCell) 380 | 381 | - (void)hiddenAllSideslip { 382 | for (TMSwipeCell *cell in self.visibleCells) { 383 | if ([cell isKindOfClass:TMSwipeCell.class]) { 384 | [cell hiddenSideslip:NO]; 385 | } 386 | } 387 | } 388 | 389 | 390 | @end 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | -------------------------------------------------------------------------------- /TMSwipeCell.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint TMSwipeCell.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | # 13 | # These will help people to find your library, and whilst it 14 | # can feel like a chore to fill in it's definitely to your advantage. The 15 | # summary should be tweet-length, and the description more in depth. 16 | # 17 | 18 | s.name = "TMSwipeCell" 19 | s.version = "0.0.1" 20 | s.summary = "A WeChat-like sliding frame" 21 | 22 | # This description is used to generate tags and improve search results. 23 | # * Think: What does it do? Why did you write it? What is the focus? 24 | # * Try to keep it short, snappy and to the point. 25 | # * Write the description between the DESC delimiters below. 26 | # * Finally, don't worry about the indent, CocoaPods strips it! 27 | 28 | s.homepage = "https://github.com/cocomanbar/TMSwipeCell" 29 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 30 | 31 | 32 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 33 | # 34 | # Licensing your code is important. See http://choosealicense.com for more info. 35 | # CocoaPods will detect a license file if there is a named LICENSE* 36 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. 37 | # 38 | 39 | s.license = "MIT" 40 | # s.license = { :type => "MIT", :file => "FILE_LICENSE" } 41 | 42 | 43 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 44 | # 45 | # Specify the authors of the library, with email addresses. Email addresses 46 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also 47 | # accepts just a name if you'd rather not provide an email address. 48 | # 49 | # Specify a social_media_url where others can refer to, for example a twitter 50 | # profile URL. 51 | # 52 | 53 | s.author = { "cocomanbar" => "125322078@qq.com" } 54 | # Or just: s.author = "cocomanbar" 55 | # s.authors = { "cocomanbar" => "125322078@qq.com" } 56 | # s.social_media_url = "http://twitter.com/cocomanbar" 57 | 58 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 59 | # 60 | # If this Pod runs only on iOS or OS X, then specify the platform and 61 | # the deployment target. You can optionally include the target after the platform. 62 | # 63 | 64 | s.platform = :ios 65 | # s.platform = :ios, "5.0" 66 | 67 | # When using multiple platforms 68 | s.ios.deployment_target = "8.0" 69 | # s.osx.deployment_target = "10.7" 70 | # s.watchos.deployment_target = "2.0" 71 | # s.tvos.deployment_target = "9.0" 72 | 73 | 74 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 75 | # 76 | # Specify the location from where the source should be retrieved. 77 | # Supports git, hg, bzr, svn and HTTP. 78 | # 79 | 80 | s.source = { :git => "https://github.com/cocomanbar/TMSwipeCell.git", :tag => "#{s.version}" } 81 | 82 | 83 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 84 | # 85 | # CocoaPods is smart about how it includes source code. For source files 86 | # giving a folder will include any swift, h, m, mm, c & cpp files. 87 | # For header files it will include any header in the folder. 88 | # Not including the public_header_files will make all headers public. 89 | # 90 | 91 | s.source_files = "TMSwipeCell", "TMSwipeCell/SwipeCell/*.{h,m}" 92 | # s.exclude_files = "Classes/Exclude" 93 | 94 | # s.public_header_files = "Classes/**/*.h" 95 | 96 | 97 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 98 | # 99 | # A list of resources included with the Pod. These are copied into the 100 | # target bundle with a build phase script. Anything else will be cleaned. 101 | # You can preserve files from being cleaned, please don't preserve 102 | # non-essential files like tests, examples and documentation. 103 | # 104 | 105 | # s.resource = "icon.png" 106 | # s.resources = "Resources/*.png" 107 | 108 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 109 | 110 | 111 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 112 | # 113 | # Link your library with frameworks, or libraries. Libraries do not include 114 | # the lib prefix of their name. 115 | # 116 | 117 | # s.framework = "SomeFramework" 118 | # s.frameworks = "SomeFramework", "AnotherFramework" 119 | 120 | # s.library = "iconv" 121 | # s.libraries = "iconv", "xml2" 122 | 123 | 124 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 125 | # 126 | # If your library depends on compiler flags you can set them in the xcconfig hash 127 | # where they will only apply to your library. If you depend on other Podspecs 128 | # you can include multiple dependencies to ensure it works. 129 | 130 | s.requires_arc = true 131 | 132 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 133 | # s.dependency "JSONKit", "~> 1.4" 134 | 135 | end 136 | -------------------------------------------------------------------------------- /TMSwipeCell.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 614A7A5F20EC9DFA007C5ADA /* TMSwipeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 614A7A5E20EC9DFA007C5ADA /* TMSwipeCell.m */; }; 11 | 61650D8E2146B03E009B60A9 /* TestTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 61650D8C2146B03E009B60A9 /* TestTableViewCell.m */; }; 12 | 61650D8F2146B03E009B60A9 /* TestModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 61650D8D2146B03E009B60A9 /* TestModel.m */; }; 13 | 61650D942146BFE8009B60A9 /* TMExpandViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 61650D932146BFE8009B60A9 /* TMExpandViewController.m */; }; 14 | 61650D972146C3AF009B60A9 /* TMExpandModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 61650D962146C3AF009B60A9 /* TMExpandModel.m */; }; 15 | 61650D9B2146C80C009B60A9 /* TMCellTypeOne.m in Sources */ = {isa = PBXBuildFile; fileRef = 61650D992146C80C009B60A9 /* TMCellTypeOne.m */; }; 16 | 61650D9C2146C80C009B60A9 /* TMCellTypeOne.xib in Resources */ = {isa = PBXBuildFile; fileRef = 61650D9A2146C80C009B60A9 /* TMCellTypeOne.xib */; }; 17 | 61650DA02146C817009B60A9 /* TMExpandCellTypeOne.m in Sources */ = {isa = PBXBuildFile; fileRef = 61650D9E2146C817009B60A9 /* TMExpandCellTypeOne.m */; }; 18 | 61650DA12146C817009B60A9 /* TMExpandCellTypeOne.xib in Resources */ = {isa = PBXBuildFile; fileRef = 61650D9F2146C817009B60A9 /* TMExpandCellTypeOne.xib */; }; 19 | 61FDD86720EB9768004BADF5 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 61FDD86620EB9768004BADF5 /* AppDelegate.m */; }; 20 | 61FDD86A20EB9768004BADF5 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 61FDD86920EB9768004BADF5 /* ViewController.m */; }; 21 | 61FDD86D20EB9768004BADF5 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 61FDD86B20EB9768004BADF5 /* Main.storyboard */; }; 22 | 61FDD86F20EB976A004BADF5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 61FDD86E20EB976A004BADF5 /* Assets.xcassets */; }; 23 | 61FDD87220EB976A004BADF5 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 61FDD87020EB976A004BADF5 /* LaunchScreen.storyboard */; }; 24 | 61FDD87520EB976A004BADF5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 61FDD87420EB976A004BADF5 /* main.m */; }; 25 | 61FDD87F20EB976A004BADF5 /* TMSwipeCellTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 61FDD87E20EB976A004BADF5 /* TMSwipeCellTests.m */; }; 26 | 61FDD88A20EB976A004BADF5 /* TMSwipeCellUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 61FDD88920EB976A004BADF5 /* TMSwipeCellUITests.m */; }; 27 | 61FDD8A620EB9A9C004BADF5 /* TestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 61FDD8A520EB9A9C004BADF5 /* TestViewController.m */; }; 28 | 61FDD8A920EBA270004BADF5 /* one.gif in Resources */ = {isa = PBXBuildFile; fileRef = 61FDD8A820EBA270004BADF5 /* one.gif */; }; 29 | /* End PBXBuildFile section */ 30 | 31 | /* Begin PBXContainerItemProxy section */ 32 | 61FDD87B20EB976A004BADF5 /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = 61FDD85A20EB9768004BADF5 /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = 61FDD86120EB9768004BADF5; 37 | remoteInfo = TMSwipeCell; 38 | }; 39 | 61FDD88620EB976A004BADF5 /* PBXContainerItemProxy */ = { 40 | isa = PBXContainerItemProxy; 41 | containerPortal = 61FDD85A20EB9768004BADF5 /* Project object */; 42 | proxyType = 1; 43 | remoteGlobalIDString = 61FDD86120EB9768004BADF5; 44 | remoteInfo = TMSwipeCell; 45 | }; 46 | /* End PBXContainerItemProxy section */ 47 | 48 | /* Begin PBXFileReference section */ 49 | 614A7A5D20EC9DFA007C5ADA /* TMSwipeCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TMSwipeCell.h; sourceTree = ""; }; 50 | 614A7A5E20EC9DFA007C5ADA /* TMSwipeCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TMSwipeCell.m; sourceTree = ""; }; 51 | 61650D8A2146B03E009B60A9 /* TestModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestModel.h; sourceTree = ""; }; 52 | 61650D8B2146B03E009B60A9 /* TestTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestTableViewCell.h; sourceTree = ""; }; 53 | 61650D8C2146B03E009B60A9 /* TestTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestTableViewCell.m; sourceTree = ""; }; 54 | 61650D8D2146B03E009B60A9 /* TestModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestModel.m; sourceTree = ""; }; 55 | 61650D922146BFE8009B60A9 /* TMExpandViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TMExpandViewController.h; sourceTree = ""; }; 56 | 61650D932146BFE8009B60A9 /* TMExpandViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TMExpandViewController.m; sourceTree = ""; }; 57 | 61650D952146C3AF009B60A9 /* TMExpandModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TMExpandModel.h; sourceTree = ""; }; 58 | 61650D962146C3AF009B60A9 /* TMExpandModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TMExpandModel.m; sourceTree = ""; }; 59 | 61650D982146C80C009B60A9 /* TMCellTypeOne.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TMCellTypeOne.h; sourceTree = ""; }; 60 | 61650D992146C80C009B60A9 /* TMCellTypeOne.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TMCellTypeOne.m; sourceTree = ""; }; 61 | 61650D9A2146C80C009B60A9 /* TMCellTypeOne.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TMCellTypeOne.xib; sourceTree = ""; }; 62 | 61650D9D2146C817009B60A9 /* TMExpandCellTypeOne.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TMExpandCellTypeOne.h; sourceTree = ""; }; 63 | 61650D9E2146C817009B60A9 /* TMExpandCellTypeOne.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TMExpandCellTypeOne.m; sourceTree = ""; }; 64 | 61650D9F2146C817009B60A9 /* TMExpandCellTypeOne.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TMExpandCellTypeOne.xib; sourceTree = ""; }; 65 | 61FDD86220EB9768004BADF5 /* TMSwipeCell.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TMSwipeCell.app; sourceTree = BUILT_PRODUCTS_DIR; }; 66 | 61FDD86520EB9768004BADF5 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 67 | 61FDD86620EB9768004BADF5 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 68 | 61FDD86820EB9768004BADF5 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 69 | 61FDD86920EB9768004BADF5 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 70 | 61FDD86C20EB9768004BADF5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 71 | 61FDD86E20EB976A004BADF5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 72 | 61FDD87120EB976A004BADF5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 73 | 61FDD87320EB976A004BADF5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 74 | 61FDD87420EB976A004BADF5 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 75 | 61FDD87A20EB976A004BADF5 /* TMSwipeCellTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TMSwipeCellTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 76 | 61FDD87E20EB976A004BADF5 /* TMSwipeCellTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TMSwipeCellTests.m; sourceTree = ""; }; 77 | 61FDD88020EB976A004BADF5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 78 | 61FDD88520EB976A004BADF5 /* TMSwipeCellUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TMSwipeCellUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 79 | 61FDD88920EB976A004BADF5 /* TMSwipeCellUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TMSwipeCellUITests.m; sourceTree = ""; }; 80 | 61FDD88B20EB976A004BADF5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 81 | 61FDD8A420EB9A9C004BADF5 /* TestViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestViewController.h; sourceTree = ""; }; 82 | 61FDD8A520EB9A9C004BADF5 /* TestViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestViewController.m; sourceTree = ""; }; 83 | 61FDD8A820EBA270004BADF5 /* one.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = one.gif; sourceTree = ""; }; 84 | /* End PBXFileReference section */ 85 | 86 | /* Begin PBXFrameworksBuildPhase section */ 87 | 61FDD85F20EB9768004BADF5 /* Frameworks */ = { 88 | isa = PBXFrameworksBuildPhase; 89 | buildActionMask = 2147483647; 90 | files = ( 91 | ); 92 | runOnlyForDeploymentPostprocessing = 0; 93 | }; 94 | 61FDD87720EB976A004BADF5 /* Frameworks */ = { 95 | isa = PBXFrameworksBuildPhase; 96 | buildActionMask = 2147483647; 97 | files = ( 98 | ); 99 | runOnlyForDeploymentPostprocessing = 0; 100 | }; 101 | 61FDD88220EB976A004BADF5 /* Frameworks */ = { 102 | isa = PBXFrameworksBuildPhase; 103 | buildActionMask = 2147483647; 104 | files = ( 105 | ); 106 | runOnlyForDeploymentPostprocessing = 0; 107 | }; 108 | /* End PBXFrameworksBuildPhase section */ 109 | 110 | /* Begin PBXGroup section */ 111 | 614A7A5C20EC9DFA007C5ADA /* SwipeCell */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 614A7A5D20EC9DFA007C5ADA /* TMSwipeCell.h */, 115 | 614A7A5E20EC9DFA007C5ADA /* TMSwipeCell.m */, 116 | ); 117 | path = SwipeCell; 118 | sourceTree = ""; 119 | }; 120 | 61650D902146BF84009B60A9 /* SwipeCellDemo */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | 61650D8A2146B03E009B60A9 /* TestModel.h */, 124 | 61650D8D2146B03E009B60A9 /* TestModel.m */, 125 | 61650D8B2146B03E009B60A9 /* TestTableViewCell.h */, 126 | 61650D8C2146B03E009B60A9 /* TestTableViewCell.m */, 127 | 61FDD86820EB9768004BADF5 /* ViewController.h */, 128 | 61FDD86920EB9768004BADF5 /* ViewController.m */, 129 | 61FDD8A420EB9A9C004BADF5 /* TestViewController.h */, 130 | 61FDD8A520EB9A9C004BADF5 /* TestViewController.m */, 131 | ); 132 | path = SwipeCellDemo; 133 | sourceTree = ""; 134 | }; 135 | 61650D912146BFC5009B60A9 /* ExpandCellDemo */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 61650D922146BFE8009B60A9 /* TMExpandViewController.h */, 139 | 61650D932146BFE8009B60A9 /* TMExpandViewController.m */, 140 | 61650D952146C3AF009B60A9 /* TMExpandModel.h */, 141 | 61650D962146C3AF009B60A9 /* TMExpandModel.m */, 142 | 61650D9D2146C817009B60A9 /* TMExpandCellTypeOne.h */, 143 | 61650D9E2146C817009B60A9 /* TMExpandCellTypeOne.m */, 144 | 61650D9F2146C817009B60A9 /* TMExpandCellTypeOne.xib */, 145 | 61650D982146C80C009B60A9 /* TMCellTypeOne.h */, 146 | 61650D992146C80C009B60A9 /* TMCellTypeOne.m */, 147 | 61650D9A2146C80C009B60A9 /* TMCellTypeOne.xib */, 148 | ); 149 | path = ExpandCellDemo; 150 | sourceTree = ""; 151 | }; 152 | 61FDD85920EB9768004BADF5 = { 153 | isa = PBXGroup; 154 | children = ( 155 | 614A7A5C20EC9DFA007C5ADA /* SwipeCell */, 156 | 61FDD86420EB9768004BADF5 /* TMSwipeCell */, 157 | 61FDD87D20EB976A004BADF5 /* TMSwipeCellTests */, 158 | 61FDD88820EB976A004BADF5 /* TMSwipeCellUITests */, 159 | 61FDD86320EB9768004BADF5 /* Products */, 160 | ); 161 | sourceTree = ""; 162 | }; 163 | 61FDD86320EB9768004BADF5 /* Products */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | 61FDD86220EB9768004BADF5 /* TMSwipeCell.app */, 167 | 61FDD87A20EB976A004BADF5 /* TMSwipeCellTests.xctest */, 168 | 61FDD88520EB976A004BADF5 /* TMSwipeCellUITests.xctest */, 169 | ); 170 | name = Products; 171 | sourceTree = ""; 172 | }; 173 | 61FDD86420EB9768004BADF5 /* TMSwipeCell */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | 61650D912146BFC5009B60A9 /* ExpandCellDemo */, 177 | 61650D902146BF84009B60A9 /* SwipeCellDemo */, 178 | 61FDD8A720EBA267004BADF5 /* gif */, 179 | 61FDD86520EB9768004BADF5 /* AppDelegate.h */, 180 | 61FDD86620EB9768004BADF5 /* AppDelegate.m */, 181 | 61FDD86B20EB9768004BADF5 /* Main.storyboard */, 182 | 61FDD86E20EB976A004BADF5 /* Assets.xcassets */, 183 | 61FDD87020EB976A004BADF5 /* LaunchScreen.storyboard */, 184 | 61FDD87320EB976A004BADF5 /* Info.plist */, 185 | 61FDD87420EB976A004BADF5 /* main.m */, 186 | ); 187 | path = TMSwipeCell; 188 | sourceTree = ""; 189 | }; 190 | 61FDD87D20EB976A004BADF5 /* TMSwipeCellTests */ = { 191 | isa = PBXGroup; 192 | children = ( 193 | 61FDD87E20EB976A004BADF5 /* TMSwipeCellTests.m */, 194 | 61FDD88020EB976A004BADF5 /* Info.plist */, 195 | ); 196 | path = TMSwipeCellTests; 197 | sourceTree = ""; 198 | }; 199 | 61FDD88820EB976A004BADF5 /* TMSwipeCellUITests */ = { 200 | isa = PBXGroup; 201 | children = ( 202 | 61FDD88920EB976A004BADF5 /* TMSwipeCellUITests.m */, 203 | 61FDD88B20EB976A004BADF5 /* Info.plist */, 204 | ); 205 | path = TMSwipeCellUITests; 206 | sourceTree = ""; 207 | }; 208 | 61FDD8A720EBA267004BADF5 /* gif */ = { 209 | isa = PBXGroup; 210 | children = ( 211 | 61FDD8A820EBA270004BADF5 /* one.gif */, 212 | ); 213 | path = gif; 214 | sourceTree = ""; 215 | }; 216 | /* End PBXGroup section */ 217 | 218 | /* Begin PBXNativeTarget section */ 219 | 61FDD86120EB9768004BADF5 /* TMSwipeCell */ = { 220 | isa = PBXNativeTarget; 221 | buildConfigurationList = 61FDD88E20EB976A004BADF5 /* Build configuration list for PBXNativeTarget "TMSwipeCell" */; 222 | buildPhases = ( 223 | 61FDD85E20EB9768004BADF5 /* Sources */, 224 | 61FDD85F20EB9768004BADF5 /* Frameworks */, 225 | 61FDD86020EB9768004BADF5 /* Resources */, 226 | ); 227 | buildRules = ( 228 | ); 229 | dependencies = ( 230 | ); 231 | name = TMSwipeCell; 232 | productName = TMSwipeCell; 233 | productReference = 61FDD86220EB9768004BADF5 /* TMSwipeCell.app */; 234 | productType = "com.apple.product-type.application"; 235 | }; 236 | 61FDD87920EB976A004BADF5 /* TMSwipeCellTests */ = { 237 | isa = PBXNativeTarget; 238 | buildConfigurationList = 61FDD89120EB976A004BADF5 /* Build configuration list for PBXNativeTarget "TMSwipeCellTests" */; 239 | buildPhases = ( 240 | 61FDD87620EB976A004BADF5 /* Sources */, 241 | 61FDD87720EB976A004BADF5 /* Frameworks */, 242 | 61FDD87820EB976A004BADF5 /* Resources */, 243 | ); 244 | buildRules = ( 245 | ); 246 | dependencies = ( 247 | 61FDD87C20EB976A004BADF5 /* PBXTargetDependency */, 248 | ); 249 | name = TMSwipeCellTests; 250 | productName = TMSwipeCellTests; 251 | productReference = 61FDD87A20EB976A004BADF5 /* TMSwipeCellTests.xctest */; 252 | productType = "com.apple.product-type.bundle.unit-test"; 253 | }; 254 | 61FDD88420EB976A004BADF5 /* TMSwipeCellUITests */ = { 255 | isa = PBXNativeTarget; 256 | buildConfigurationList = 61FDD89420EB976A004BADF5 /* Build configuration list for PBXNativeTarget "TMSwipeCellUITests" */; 257 | buildPhases = ( 258 | 61FDD88120EB976A004BADF5 /* Sources */, 259 | 61FDD88220EB976A004BADF5 /* Frameworks */, 260 | 61FDD88320EB976A004BADF5 /* Resources */, 261 | ); 262 | buildRules = ( 263 | ); 264 | dependencies = ( 265 | 61FDD88720EB976A004BADF5 /* PBXTargetDependency */, 266 | ); 267 | name = TMSwipeCellUITests; 268 | productName = TMSwipeCellUITests; 269 | productReference = 61FDD88520EB976A004BADF5 /* TMSwipeCellUITests.xctest */; 270 | productType = "com.apple.product-type.bundle.ui-testing"; 271 | }; 272 | /* End PBXNativeTarget section */ 273 | 274 | /* Begin PBXProject section */ 275 | 61FDD85A20EB9768004BADF5 /* Project object */ = { 276 | isa = PBXProject; 277 | attributes = { 278 | LastUpgradeCheck = 0940; 279 | ORGANIZATIONNAME = cocomanber; 280 | TargetAttributes = { 281 | 61FDD86120EB9768004BADF5 = { 282 | CreatedOnToolsVersion = 9.4.1; 283 | }; 284 | 61FDD87920EB976A004BADF5 = { 285 | CreatedOnToolsVersion = 9.4.1; 286 | TestTargetID = 61FDD86120EB9768004BADF5; 287 | }; 288 | 61FDD88420EB976A004BADF5 = { 289 | CreatedOnToolsVersion = 9.4.1; 290 | TestTargetID = 61FDD86120EB9768004BADF5; 291 | }; 292 | }; 293 | }; 294 | buildConfigurationList = 61FDD85D20EB9768004BADF5 /* Build configuration list for PBXProject "TMSwipeCell" */; 295 | compatibilityVersion = "Xcode 9.3"; 296 | developmentRegion = en; 297 | hasScannedForEncodings = 0; 298 | knownRegions = ( 299 | en, 300 | Base, 301 | ); 302 | mainGroup = 61FDD85920EB9768004BADF5; 303 | productRefGroup = 61FDD86320EB9768004BADF5 /* Products */; 304 | projectDirPath = ""; 305 | projectRoot = ""; 306 | targets = ( 307 | 61FDD86120EB9768004BADF5 /* TMSwipeCell */, 308 | 61FDD87920EB976A004BADF5 /* TMSwipeCellTests */, 309 | 61FDD88420EB976A004BADF5 /* TMSwipeCellUITests */, 310 | ); 311 | }; 312 | /* End PBXProject section */ 313 | 314 | /* Begin PBXResourcesBuildPhase section */ 315 | 61FDD86020EB9768004BADF5 /* Resources */ = { 316 | isa = PBXResourcesBuildPhase; 317 | buildActionMask = 2147483647; 318 | files = ( 319 | 61FDD87220EB976A004BADF5 /* LaunchScreen.storyboard in Resources */, 320 | 61650DA12146C817009B60A9 /* TMExpandCellTypeOne.xib in Resources */, 321 | 61FDD8A920EBA270004BADF5 /* one.gif in Resources */, 322 | 61FDD86F20EB976A004BADF5 /* Assets.xcassets in Resources */, 323 | 61FDD86D20EB9768004BADF5 /* Main.storyboard in Resources */, 324 | 61650D9C2146C80C009B60A9 /* TMCellTypeOne.xib in Resources */, 325 | ); 326 | runOnlyForDeploymentPostprocessing = 0; 327 | }; 328 | 61FDD87820EB976A004BADF5 /* Resources */ = { 329 | isa = PBXResourcesBuildPhase; 330 | buildActionMask = 2147483647; 331 | files = ( 332 | ); 333 | runOnlyForDeploymentPostprocessing = 0; 334 | }; 335 | 61FDD88320EB976A004BADF5 /* Resources */ = { 336 | isa = PBXResourcesBuildPhase; 337 | buildActionMask = 2147483647; 338 | files = ( 339 | ); 340 | runOnlyForDeploymentPostprocessing = 0; 341 | }; 342 | /* End PBXResourcesBuildPhase section */ 343 | 344 | /* Begin PBXSourcesBuildPhase section */ 345 | 61FDD85E20EB9768004BADF5 /* Sources */ = { 346 | isa = PBXSourcesBuildPhase; 347 | buildActionMask = 2147483647; 348 | files = ( 349 | 61650D8E2146B03E009B60A9 /* TestTableViewCell.m in Sources */, 350 | 61650D9B2146C80C009B60A9 /* TMCellTypeOne.m in Sources */, 351 | 61FDD86A20EB9768004BADF5 /* ViewController.m in Sources */, 352 | 61650D972146C3AF009B60A9 /* TMExpandModel.m in Sources */, 353 | 61650DA02146C817009B60A9 /* TMExpandCellTypeOne.m in Sources */, 354 | 61FDD8A620EB9A9C004BADF5 /* TestViewController.m in Sources */, 355 | 61650D942146BFE8009B60A9 /* TMExpandViewController.m in Sources */, 356 | 61FDD87520EB976A004BADF5 /* main.m in Sources */, 357 | 61650D8F2146B03E009B60A9 /* TestModel.m in Sources */, 358 | 614A7A5F20EC9DFA007C5ADA /* TMSwipeCell.m in Sources */, 359 | 61FDD86720EB9768004BADF5 /* AppDelegate.m in Sources */, 360 | ); 361 | runOnlyForDeploymentPostprocessing = 0; 362 | }; 363 | 61FDD87620EB976A004BADF5 /* Sources */ = { 364 | isa = PBXSourcesBuildPhase; 365 | buildActionMask = 2147483647; 366 | files = ( 367 | 61FDD87F20EB976A004BADF5 /* TMSwipeCellTests.m in Sources */, 368 | ); 369 | runOnlyForDeploymentPostprocessing = 0; 370 | }; 371 | 61FDD88120EB976A004BADF5 /* Sources */ = { 372 | isa = PBXSourcesBuildPhase; 373 | buildActionMask = 2147483647; 374 | files = ( 375 | 61FDD88A20EB976A004BADF5 /* TMSwipeCellUITests.m in Sources */, 376 | ); 377 | runOnlyForDeploymentPostprocessing = 0; 378 | }; 379 | /* End PBXSourcesBuildPhase section */ 380 | 381 | /* Begin PBXTargetDependency section */ 382 | 61FDD87C20EB976A004BADF5 /* PBXTargetDependency */ = { 383 | isa = PBXTargetDependency; 384 | target = 61FDD86120EB9768004BADF5 /* TMSwipeCell */; 385 | targetProxy = 61FDD87B20EB976A004BADF5 /* PBXContainerItemProxy */; 386 | }; 387 | 61FDD88720EB976A004BADF5 /* PBXTargetDependency */ = { 388 | isa = PBXTargetDependency; 389 | target = 61FDD86120EB9768004BADF5 /* TMSwipeCell */; 390 | targetProxy = 61FDD88620EB976A004BADF5 /* PBXContainerItemProxy */; 391 | }; 392 | /* End PBXTargetDependency section */ 393 | 394 | /* Begin PBXVariantGroup section */ 395 | 61FDD86B20EB9768004BADF5 /* Main.storyboard */ = { 396 | isa = PBXVariantGroup; 397 | children = ( 398 | 61FDD86C20EB9768004BADF5 /* Base */, 399 | ); 400 | name = Main.storyboard; 401 | sourceTree = ""; 402 | }; 403 | 61FDD87020EB976A004BADF5 /* LaunchScreen.storyboard */ = { 404 | isa = PBXVariantGroup; 405 | children = ( 406 | 61FDD87120EB976A004BADF5 /* Base */, 407 | ); 408 | name = LaunchScreen.storyboard; 409 | sourceTree = ""; 410 | }; 411 | /* End PBXVariantGroup section */ 412 | 413 | /* Begin XCBuildConfiguration section */ 414 | 61FDD88C20EB976A004BADF5 /* Debug */ = { 415 | isa = XCBuildConfiguration; 416 | buildSettings = { 417 | ALWAYS_SEARCH_USER_PATHS = NO; 418 | CLANG_ANALYZER_NONNULL = YES; 419 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 420 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 421 | CLANG_CXX_LIBRARY = "libc++"; 422 | CLANG_ENABLE_MODULES = YES; 423 | CLANG_ENABLE_OBJC_ARC = YES; 424 | CLANG_ENABLE_OBJC_WEAK = YES; 425 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 426 | CLANG_WARN_BOOL_CONVERSION = YES; 427 | CLANG_WARN_COMMA = YES; 428 | CLANG_WARN_CONSTANT_CONVERSION = YES; 429 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 430 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 431 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 432 | CLANG_WARN_EMPTY_BODY = YES; 433 | CLANG_WARN_ENUM_CONVERSION = YES; 434 | CLANG_WARN_INFINITE_RECURSION = YES; 435 | CLANG_WARN_INT_CONVERSION = YES; 436 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 437 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 438 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 439 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 440 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 441 | CLANG_WARN_STRICT_PROTOTYPES = YES; 442 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 443 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 444 | CLANG_WARN_UNREACHABLE_CODE = YES; 445 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 446 | CODE_SIGN_IDENTITY = "iPhone Developer"; 447 | COPY_PHASE_STRIP = NO; 448 | DEBUG_INFORMATION_FORMAT = dwarf; 449 | ENABLE_STRICT_OBJC_MSGSEND = YES; 450 | ENABLE_TESTABILITY = YES; 451 | GCC_C_LANGUAGE_STANDARD = gnu11; 452 | GCC_DYNAMIC_NO_PIC = NO; 453 | GCC_NO_COMMON_BLOCKS = YES; 454 | GCC_OPTIMIZATION_LEVEL = 0; 455 | GCC_PREPROCESSOR_DEFINITIONS = ( 456 | "DEBUG=1", 457 | "$(inherited)", 458 | ); 459 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 460 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 461 | GCC_WARN_UNDECLARED_SELECTOR = YES; 462 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 463 | GCC_WARN_UNUSED_FUNCTION = YES; 464 | GCC_WARN_UNUSED_VARIABLE = YES; 465 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 466 | MTL_ENABLE_DEBUG_INFO = YES; 467 | ONLY_ACTIVE_ARCH = YES; 468 | SDKROOT = iphoneos; 469 | }; 470 | name = Debug; 471 | }; 472 | 61FDD88D20EB976A004BADF5 /* Release */ = { 473 | isa = XCBuildConfiguration; 474 | buildSettings = { 475 | ALWAYS_SEARCH_USER_PATHS = NO; 476 | CLANG_ANALYZER_NONNULL = YES; 477 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 478 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 479 | CLANG_CXX_LIBRARY = "libc++"; 480 | CLANG_ENABLE_MODULES = YES; 481 | CLANG_ENABLE_OBJC_ARC = YES; 482 | CLANG_ENABLE_OBJC_WEAK = YES; 483 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 484 | CLANG_WARN_BOOL_CONVERSION = YES; 485 | CLANG_WARN_COMMA = YES; 486 | CLANG_WARN_CONSTANT_CONVERSION = YES; 487 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 488 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 489 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 490 | CLANG_WARN_EMPTY_BODY = YES; 491 | CLANG_WARN_ENUM_CONVERSION = YES; 492 | CLANG_WARN_INFINITE_RECURSION = YES; 493 | CLANG_WARN_INT_CONVERSION = YES; 494 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 495 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 496 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 497 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 498 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 499 | CLANG_WARN_STRICT_PROTOTYPES = YES; 500 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 501 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 502 | CLANG_WARN_UNREACHABLE_CODE = YES; 503 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 504 | CODE_SIGN_IDENTITY = "iPhone Developer"; 505 | COPY_PHASE_STRIP = NO; 506 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 507 | ENABLE_NS_ASSERTIONS = NO; 508 | ENABLE_STRICT_OBJC_MSGSEND = YES; 509 | GCC_C_LANGUAGE_STANDARD = gnu11; 510 | GCC_NO_COMMON_BLOCKS = YES; 511 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 512 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 513 | GCC_WARN_UNDECLARED_SELECTOR = YES; 514 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 515 | GCC_WARN_UNUSED_FUNCTION = YES; 516 | GCC_WARN_UNUSED_VARIABLE = YES; 517 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 518 | MTL_ENABLE_DEBUG_INFO = NO; 519 | SDKROOT = iphoneos; 520 | VALIDATE_PRODUCT = YES; 521 | }; 522 | name = Release; 523 | }; 524 | 61FDD88F20EB976A004BADF5 /* Debug */ = { 525 | isa = XCBuildConfiguration; 526 | buildSettings = { 527 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 528 | CODE_SIGN_STYLE = Manual; 529 | DEVELOPMENT_TEAM = ""; 530 | INFOPLIST_FILE = TMSwipeCell/Info.plist; 531 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 532 | LD_RUNPATH_SEARCH_PATHS = ( 533 | "$(inherited)", 534 | "@executable_path/Frameworks", 535 | ); 536 | PRODUCT_BUNDLE_IDENTIFIER = cocomanber.TMSwipeCell; 537 | PRODUCT_NAME = "$(TARGET_NAME)"; 538 | PROVISIONING_PROFILE_SPECIFIER = ""; 539 | TARGETED_DEVICE_FAMILY = "1,2"; 540 | }; 541 | name = Debug; 542 | }; 543 | 61FDD89020EB976A004BADF5 /* Release */ = { 544 | isa = XCBuildConfiguration; 545 | buildSettings = { 546 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 547 | CODE_SIGN_STYLE = Manual; 548 | DEVELOPMENT_TEAM = ""; 549 | INFOPLIST_FILE = TMSwipeCell/Info.plist; 550 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 551 | LD_RUNPATH_SEARCH_PATHS = ( 552 | "$(inherited)", 553 | "@executable_path/Frameworks", 554 | ); 555 | PRODUCT_BUNDLE_IDENTIFIER = cocomanber.TMSwipeCell; 556 | PRODUCT_NAME = "$(TARGET_NAME)"; 557 | PROVISIONING_PROFILE_SPECIFIER = ""; 558 | TARGETED_DEVICE_FAMILY = "1,2"; 559 | }; 560 | name = Release; 561 | }; 562 | 61FDD89220EB976A004BADF5 /* Debug */ = { 563 | isa = XCBuildConfiguration; 564 | buildSettings = { 565 | BUNDLE_LOADER = "$(TEST_HOST)"; 566 | CODE_SIGN_STYLE = Automatic; 567 | INFOPLIST_FILE = TMSwipeCellTests/Info.plist; 568 | LD_RUNPATH_SEARCH_PATHS = ( 569 | "$(inherited)", 570 | "@executable_path/Frameworks", 571 | "@loader_path/Frameworks", 572 | ); 573 | PRODUCT_BUNDLE_IDENTIFIER = cocomanber.TMSwipeCellTests; 574 | PRODUCT_NAME = "$(TARGET_NAME)"; 575 | TARGETED_DEVICE_FAMILY = "1,2"; 576 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TMSwipeCell.app/TMSwipeCell"; 577 | }; 578 | name = Debug; 579 | }; 580 | 61FDD89320EB976A004BADF5 /* Release */ = { 581 | isa = XCBuildConfiguration; 582 | buildSettings = { 583 | BUNDLE_LOADER = "$(TEST_HOST)"; 584 | CODE_SIGN_STYLE = Automatic; 585 | INFOPLIST_FILE = TMSwipeCellTests/Info.plist; 586 | LD_RUNPATH_SEARCH_PATHS = ( 587 | "$(inherited)", 588 | "@executable_path/Frameworks", 589 | "@loader_path/Frameworks", 590 | ); 591 | PRODUCT_BUNDLE_IDENTIFIER = cocomanber.TMSwipeCellTests; 592 | PRODUCT_NAME = "$(TARGET_NAME)"; 593 | TARGETED_DEVICE_FAMILY = "1,2"; 594 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/TMSwipeCell.app/TMSwipeCell"; 595 | }; 596 | name = Release; 597 | }; 598 | 61FDD89520EB976A004BADF5 /* Debug */ = { 599 | isa = XCBuildConfiguration; 600 | buildSettings = { 601 | CODE_SIGN_STYLE = Automatic; 602 | INFOPLIST_FILE = TMSwipeCellUITests/Info.plist; 603 | LD_RUNPATH_SEARCH_PATHS = ( 604 | "$(inherited)", 605 | "@executable_path/Frameworks", 606 | "@loader_path/Frameworks", 607 | ); 608 | PRODUCT_BUNDLE_IDENTIFIER = cocomanber.TMSwipeCellUITests; 609 | PRODUCT_NAME = "$(TARGET_NAME)"; 610 | TARGETED_DEVICE_FAMILY = "1,2"; 611 | TEST_TARGET_NAME = TMSwipeCell; 612 | }; 613 | name = Debug; 614 | }; 615 | 61FDD89620EB976A004BADF5 /* Release */ = { 616 | isa = XCBuildConfiguration; 617 | buildSettings = { 618 | CODE_SIGN_STYLE = Automatic; 619 | INFOPLIST_FILE = TMSwipeCellUITests/Info.plist; 620 | LD_RUNPATH_SEARCH_PATHS = ( 621 | "$(inherited)", 622 | "@executable_path/Frameworks", 623 | "@loader_path/Frameworks", 624 | ); 625 | PRODUCT_BUNDLE_IDENTIFIER = cocomanber.TMSwipeCellUITests; 626 | PRODUCT_NAME = "$(TARGET_NAME)"; 627 | TARGETED_DEVICE_FAMILY = "1,2"; 628 | TEST_TARGET_NAME = TMSwipeCell; 629 | }; 630 | name = Release; 631 | }; 632 | /* End XCBuildConfiguration section */ 633 | 634 | /* Begin XCConfigurationList section */ 635 | 61FDD85D20EB9768004BADF5 /* Build configuration list for PBXProject "TMSwipeCell" */ = { 636 | isa = XCConfigurationList; 637 | buildConfigurations = ( 638 | 61FDD88C20EB976A004BADF5 /* Debug */, 639 | 61FDD88D20EB976A004BADF5 /* Release */, 640 | ); 641 | defaultConfigurationIsVisible = 0; 642 | defaultConfigurationName = Release; 643 | }; 644 | 61FDD88E20EB976A004BADF5 /* Build configuration list for PBXNativeTarget "TMSwipeCell" */ = { 645 | isa = XCConfigurationList; 646 | buildConfigurations = ( 647 | 61FDD88F20EB976A004BADF5 /* Debug */, 648 | 61FDD89020EB976A004BADF5 /* Release */, 649 | ); 650 | defaultConfigurationIsVisible = 0; 651 | defaultConfigurationName = Release; 652 | }; 653 | 61FDD89120EB976A004BADF5 /* Build configuration list for PBXNativeTarget "TMSwipeCellTests" */ = { 654 | isa = XCConfigurationList; 655 | buildConfigurations = ( 656 | 61FDD89220EB976A004BADF5 /* Debug */, 657 | 61FDD89320EB976A004BADF5 /* Release */, 658 | ); 659 | defaultConfigurationIsVisible = 0; 660 | defaultConfigurationName = Release; 661 | }; 662 | 61FDD89420EB976A004BADF5 /* Build configuration list for PBXNativeTarget "TMSwipeCellUITests" */ = { 663 | isa = XCConfigurationList; 664 | buildConfigurations = ( 665 | 61FDD89520EB976A004BADF5 /* Debug */, 666 | 61FDD89620EB976A004BADF5 /* Release */, 667 | ); 668 | defaultConfigurationIsVisible = 0; 669 | defaultConfigurationName = Release; 670 | }; 671 | /* End XCConfigurationList section */ 672 | }; 673 | rootObject = 61FDD85A20EB9768004BADF5 /* Project object */; 674 | } 675 | -------------------------------------------------------------------------------- /TMSwipeCell.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TMSwipeCell.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TMSwipeCell/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/7/3. 6 | // Copyright © 2018年 cocomanber. 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 | -------------------------------------------------------------------------------- /TMSwipeCell/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/7/3. 6 | // Copyright © 2018年 cocomanber. 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 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/001.imageset/001.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocomanbar/TMSwipeCell/7179190c8ad3989176eaaa7b85c5fb79b52e8da4/TMSwipeCell/Assets.xcassets/001.imageset/001.jpg -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/001.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "001.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/002.imageset/002.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocomanbar/TMSwipeCell/7179190c8ad3989176eaaa7b85c5fb79b52e8da4/TMSwipeCell/Assets.xcassets/002.imageset/002.jpg -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/002.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "002.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/003.imageset/003.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocomanbar/TMSwipeCell/7179190c8ad3989176eaaa7b85c5fb79b52e8da4/TMSwipeCell/Assets.xcassets/003.imageset/003.jpg -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/003.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "003.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/004.imageset/004.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocomanbar/TMSwipeCell/7179190c8ad3989176eaaa7b85c5fb79b52e8da4/TMSwipeCell/Assets.xcassets/004.imageset/004.jpg -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/004.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "004.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/005.imageset/005.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocomanbar/TMSwipeCell/7179190c8ad3989176eaaa7b85c5fb79b52e8da4/TMSwipeCell/Assets.xcassets/005.imageset/005.jpg -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/005.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "005.jpg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/006.imageset/006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocomanbar/TMSwipeCell/7179190c8ad3989176eaaa7b85c5fb79b52e8da4/TMSwipeCell/Assets.xcassets/006.imageset/006.png -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/006.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "006.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/Delete.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Delete.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/Delete.imageset/Delete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocomanbar/TMSwipeCell/7179190c8ad3989176eaaa7b85c5fb79b52e8da4/TMSwipeCell/Assets.xcassets/Delete.imageset/Delete.png -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/Tag.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Tag.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /TMSwipeCell/Assets.xcassets/Tag.imageset/Tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocomanbar/TMSwipeCell/7179190c8ad3989176eaaa7b85c5fb79b52e8da4/TMSwipeCell/Assets.xcassets/Tag.imageset/Tag.png -------------------------------------------------------------------------------- /TMSwipeCell/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 | -------------------------------------------------------------------------------- /TMSwipeCell/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 | 49 | 50 | 51 | 60 | 69 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | -------------------------------------------------------------------------------- /TMSwipeCell/ExpandCellDemo/TMCellTypeOne.h: -------------------------------------------------------------------------------- 1 | // 2 | // TMCellTypeOne.h 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/9/10. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TMCellTypeOne : UITableViewCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /TMSwipeCell/ExpandCellDemo/TMCellTypeOne.m: -------------------------------------------------------------------------------- 1 | // 2 | // TMCellTypeOne.m 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/9/10. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import "TMCellTypeOne.h" 10 | 11 | @implementation TMCellTypeOne 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | // Initialization code 16 | } 17 | 18 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 19 | [super setSelected:selected animated:animated]; 20 | 21 | // Configure the view for the selected state 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /TMSwipeCell/ExpandCellDemo/TMCellTypeOne.xib: -------------------------------------------------------------------------------- 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 | 39 | 45 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /TMSwipeCell/ExpandCellDemo/TMExpandCellTypeOne.h: -------------------------------------------------------------------------------- 1 | // 2 | // TMExpandCellTypeOne.h 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/9/10. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TMExpandCellTypeOne : UITableViewCell 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /TMSwipeCell/ExpandCellDemo/TMExpandCellTypeOne.m: -------------------------------------------------------------------------------- 1 | // 2 | // TMExpandCellTypeOne.m 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/9/10. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import "TMExpandCellTypeOne.h" 10 | 11 | @implementation TMExpandCellTypeOne 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | // Initialization code 16 | } 17 | 18 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 19 | [super setSelected:selected animated:animated]; 20 | 21 | // Configure the view for the selected state 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /TMSwipeCell/ExpandCellDemo/TMExpandCellTypeOne.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 32 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 55 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /TMSwipeCell/ExpandCellDemo/TMExpandModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TMExpandModel.h 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/9/10. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, TMExpandType){ 12 | TMExpandTypeOne = 0, 13 | TMExpandTypeTwo = 1, 14 | }; 15 | 16 | @interface TMExpandModel : NSObject 17 | 18 | @property (nonatomic, copy)NSString *headUrl; 19 | @property (nonatomic, copy)NSString *name; 20 | @property (nonatomic, copy)NSString *content; 21 | @property (nonatomic, copy)NSString *time; 22 | 23 | @property (nonatomic, assign)TMExpandType expandType; 24 | 25 | + (NSArray *)getAllDatas; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /TMSwipeCell/ExpandCellDemo/TMExpandModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // TMExpandModel.m 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/9/10. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import "TMExpandModel.h" 10 | 11 | @implementation TMExpandModel 12 | 13 | + (NSArray *)getAllDatas{ 14 | NSMutableArray *array = @[].mutableCopy; 15 | 16 | for (int i = 0; i < 20; i ++) { 17 | TMExpandModel *model = [TMExpandModel new]; 18 | model.name = [self getNameRand][arc4random()%([[self getNameRand] count])]; 19 | model.headUrl = [self getHeadUrlRand][arc4random()%([[self getHeadUrlRand] count])]; 20 | model.content = [self getContentRand][arc4random()%([[self getContentRand] count])]; 21 | model.time = [self getTimeRand][arc4random()%([[self getTimeRand] count])]; 22 | model.expandType = (arc4random()%10) % 2 == 0; 23 | [array addObject:model]; 24 | } 25 | return array.copy; 26 | } 27 | 28 | + (NSArray *)getNameRand{ 29 | return @[@"以柔",@"惜晴",@"巧容",@"向烟",@"寒玉",@"凝薇",@"慕烟",@"凌曼"]; 30 | } 31 | 32 | + (NSArray *)getHeadUrlRand{ 33 | return @[@"001",@"002",@"003",@"004",@"005"]; 34 | } 35 | 36 | + (NSArray *)getContentRand{ 37 | return @[@"你好",@"一起吃饭吧",@"你在写什么",@"明天去哪儿玩呢,问你呢",@"今天又是星期五了呢,真好"]; 38 | } 39 | 40 | + (NSArray *)getTimeRand{ 41 | return @[@"12:31",@"02:23",@"14:56",@"17:34",@"20:56"]; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /TMSwipeCell/ExpandCellDemo/TMExpandViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TMExpandViewController.h 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/9/10. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TMExpandViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /TMSwipeCell/ExpandCellDemo/TMExpandViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TMExpandViewController.m 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/9/10. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 同一种cell expand不同状态的view 好处理? 8 | // 同一种cell expand同状态的view 好处理 9 | // 所有cell expand同状态的view 好处理 10 | 11 | #import "TMExpandViewController.h" 12 | 13 | #import "TMCellTypeOne.h" 14 | #import "TMExpandCellTypeOne.h" 15 | #import "TMExpandModel.h" 16 | 17 | @interface TMExpandViewController () 18 | 20 | { 21 | NSArray *_datas; 22 | } 23 | @property (nonatomic, strong)UITableView *tableView; 24 | @property (nonatomic, assign)BOOL isExpand; 25 | @property (nonatomic, strong)NSIndexPath *selectedIndexPath; 26 | 27 | @end 28 | 29 | @implementation TMExpandViewController 30 | 31 | - (void)viewDidLoad { 32 | [super viewDidLoad]; 33 | // Do any additional setup after loading the view. 34 | 35 | [self.view addSubview:self.tableView]; 36 | self.tableView.frame = self.view.frame; 37 | 38 | _datas = [TMExpandModel getAllDatas]; 39 | 40 | [self.tableView registerNib:[UINib nibWithNibName:@"TMExpandCellTypeOne" bundle:nil] forCellReuseIdentifier:@"TMExpandCellTypeOne"]; 41 | [self.tableView registerNib:[UINib nibWithNibName:@"TMCellTypeOne" bundle:nil] forCellReuseIdentifier:@"TMCellTypeOne"]; 42 | [self.tableView reloadData]; 43 | } 44 | 45 | #pragma mark - tableViewDelegate 46 | 47 | -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 48 | { 49 | return 1; 50 | } 51 | 52 | -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 53 | { 54 | return _datas.count; 55 | } 56 | 57 | -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 58 | { 59 | if (indexPath.row == self.selectedIndexPath.row && self.selectedIndexPath != nil ) {// 判断是否是所点击的cell 60 | if (self.isExpand == YES) { // 判断这个已点击的cell是否展开 61 | return 141; 62 | }else{ 63 | return 86; 64 | } 65 | }else{ 66 | return 86; 67 | } 68 | } 69 | 70 | -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 71 | { 72 | if (self.isExpand && [self.selectedIndexPath isEqual:indexPath]) {//如果展开并且是当前选中的cell 73 | //创建扩展的cell 74 | static NSString *expandCellID = @"TMExpandCellTypeOne"; 75 | TMExpandCellTypeOne *cell = [tableView dequeueReusableCellWithIdentifier:expandCellID]; 76 | return cell; 77 | 78 | }else{ 79 | //普通情况 80 | //创建普通cell 81 | static NSString *customCellID = @"TMCellTypeOne"; 82 | TMCellTypeOne *cell = [tableView dequeueReusableCellWithIdentifier:customCellID]; 83 | return cell; 84 | } 85 | } 86 | 87 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 88 | { 89 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 90 | 91 | if (!self.selectedIndexPath) { 92 | 93 | self.isExpand = YES; 94 | self.selectedIndexPath = indexPath; 95 | [self.tableView beginUpdates]; 96 | [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 97 | [self.tableView endUpdates]; 98 | }else{ 99 | 100 | if (self.isExpand) { 101 | if ([self.selectedIndexPath isEqual: indexPath]) { 102 | self.isExpand = NO; 103 | [self.tableView beginUpdates]; 104 | [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 105 | [self.tableView endUpdates]; 106 | self.selectedIndexPath = nil; 107 | 108 | }else{ 109 | [self.tableView beginUpdates]; 110 | [self.tableView reloadRowsAtIndexPaths:@[self.selectedIndexPath] withRowAnimation:UITableViewRowAnimationFade]; 111 | self.isExpand = YES; 112 | self.selectedIndexPath = indexPath; 113 | [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; 114 | [self.tableView endUpdates]; 115 | } 116 | } 117 | } 118 | } 119 | 120 | 121 | - (UITableView *)tableView 122 | { 123 | if (!_tableView) { 124 | _tableView = [[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStylePlain]; 125 | _tableView.delegate = self; 126 | _tableView.dataSource = self; 127 | _tableView.backgroundColor = [UIColor groupTableViewBackgroundColor]; 128 | _tableView.estimatedRowHeight = 0; 129 | _tableView.estimatedSectionFooterHeight = 0; 130 | _tableView.estimatedSectionHeaderHeight = 0; 131 | _tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero]; 132 | 133 | } 134 | return _tableView; 135 | } 136 | 137 | - (void)didReceiveMemoryWarning { 138 | [super didReceiveMemoryWarning]; 139 | // Dispose of any resources that can be recreated. 140 | } 141 | 142 | @end 143 | -------------------------------------------------------------------------------- /TMSwipeCell/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 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 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /TMSwipeCell/SwipeCellDemo/TestModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestModel.h 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/7/7. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString *const TMSWIPE_FRIEND; //备注 + 删除 12 | extern NSString *const TMSWIPE_PUBLIC; //取消关注 + 删除 13 | extern NSString *const TMSWIPE_OTHERS; //image + text 14 | 15 | @interface TestModel : NSObject 16 | 17 | @property (nonatomic, copy)NSString *headUrl; 18 | @property (nonatomic, copy)NSString *name; 19 | @property (nonatomic, copy)NSString *content; 20 | @property (nonatomic, copy)NSString *time; 21 | @property (nonatomic, copy)NSString *message_id; 22 | 23 | + (NSArray *)getAllDatas; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /TMSwipeCell/SwipeCellDemo/TestModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestModel.m 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/7/7. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import "TestModel.h" 10 | 11 | NSString *const TMSWIPE_FRIEND = @"TMSWIPE_FRIEND"; 12 | NSString *const TMSWIPE_PUBLIC = @"TMSWIPE_PUBLIC"; 13 | NSString *const TMSWIPE_OTHERS = @"TMSWIPE_OTHERS"; 14 | 15 | @implementation TestModel 16 | 17 | + (NSArray *)getAllDatas{ 18 | NSMutableArray *array = @[].mutableCopy; 19 | 20 | for (int i = 0; i < 20; i ++) { 21 | TestModel *model = [TestModel new]; 22 | model.name = [self getNameRand][arc4random()%([[self getNameRand] count])]; 23 | model.headUrl = [self getHeadUrlRand][arc4random()%([[self getHeadUrlRand] count])]; 24 | model.content = [self getContentRand][arc4random()%([[self getContentRand] count])]; 25 | model.time = [self getTimeRand][arc4random()%([[self getTimeRand] count])]; 26 | model.message_id = TMSWIPE_FRIEND; 27 | if (i % 3 == 0) { 28 | model.message_id = TMSWIPE_OTHERS; 29 | } 30 | [array addObject:model]; 31 | } 32 | 33 | TestModel *model = [TestModel new]; 34 | model.name = @"公众号消息"; 35 | model.headUrl = @"006"; 36 | model.content = @"支持XIB,只需继承,支持block和代理"; 37 | model.time = @"00:56"; 38 | model.message_id = TMSWIPE_PUBLIC; 39 | 40 | TestModel *model1 = [TestModel new]; 41 | model1.name = @"公众号"; 42 | model1.headUrl = @"006"; 43 | model1.content = @"支持XIB,只需继承,支持block和代理"; 44 | model1.time = @"13:16"; 45 | model1.message_id = TMSWIPE_PUBLIC; 46 | 47 | [array insertObject:model atIndex:2]; 48 | [array insertObject:model1 atIndex:5]; 49 | return array.copy; 50 | } 51 | 52 | + (NSArray *)getNameRand{ 53 | return @[@"以柔",@"惜晴",@"巧容",@"向烟",@"寒玉",@"凝薇",@"慕烟",@"凌曼"]; 54 | } 55 | 56 | + (NSArray *)getHeadUrlRand{ 57 | return @[@"001",@"002",@"003",@"004",@"005"]; 58 | } 59 | 60 | + (NSArray *)getContentRand{ 61 | return @[@"你好",@"一起吃饭吧",@"你在写什么",@"明天去哪儿玩呢,问你呢",@"今天又是星期五了呢,真好"]; 62 | } 63 | 64 | + (NSArray *)getTimeRand{ 65 | return @[@"12:31",@"02:23",@"14:56",@"17:34",@"20:56"]; 66 | } 67 | 68 | @end 69 | -------------------------------------------------------------------------------- /TMSwipeCell/SwipeCellDemo/TestTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestTableViewCell.h 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/7/7. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import "TMSwipeCell.h" 10 | #import "TestModel.h" 11 | 12 | @interface TestTableViewCell : TMSwipeCell 13 | 14 | @property (weak, nonatomic) IBOutlet UIImageView *imageV; 15 | @property (weak, nonatomic) IBOutlet UILabel *nameL; 16 | @property (weak, nonatomic) IBOutlet UILabel *contentL; 17 | @property (weak, nonatomic) IBOutlet UILabel *timeL; 18 | 19 | + (CGFloat)rowHeight; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /TMSwipeCell/SwipeCellDemo/TestTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestTableViewCell.m 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/7/7. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import "TestTableViewCell.h" 10 | 11 | @interface TestTableViewCell () 12 | 13 | @end 14 | 15 | @implementation TestTableViewCell 16 | 17 | - (void)awakeFromNib { 18 | [super awakeFromNib]; 19 | // Initialization code 20 | 21 | self.imageV.contentMode = UIViewContentModeScaleAspectFill; 22 | self.imageV.layer.cornerRadius = 5; 23 | self.imageV.layer.masksToBounds = YES; 24 | self.contentView.backgroundColor = [UIColor whiteColor]; 25 | } 26 | 27 | + (CGFloat)rowHeight{ 28 | return 70.f; 29 | } 30 | 31 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 32 | [super setSelected:selected animated:animated]; 33 | 34 | // Configure the view for the selected state 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /TMSwipeCell/SwipeCellDemo/TestViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController.h 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/7/3. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TestViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /TMSwipeCell/SwipeCellDemo/TestViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestViewController.m 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/7/3. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import "TestViewController.h" 10 | #import "TestTableViewCell.h" 11 | #import "TMExpandViewController.h" 12 | 13 | @interface TestViewController () 14 | 15 | 16 | @property (nonatomic, strong)NSMutableArray *datas; 17 | 18 | @end 19 | 20 | @implementation TestViewController 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | // Do any additional setup after loading the view. 25 | 26 | _datas = [NSMutableArray arrayWithArray:[TestModel getAllDatas]]; 27 | [self.tableView reloadData]; 28 | } 29 | 30 | /** 31 | 选中了侧滑按钮 32 | 33 | @param swipeCell 当前响应的cell 34 | @param indexPath cell在tableView中的位置 35 | @param index 选中的是第几个action 36 | */ 37 | - (void)swipeCell:(TMSwipeCell *)swipeCell atIndexPath:(NSIndexPath *)indexPath didSelectedAtIndex:(NSInteger)index 38 | { 39 | 40 | } 41 | 42 | /** 43 | 告知当前位置的cell是否需要侧滑按钮 44 | 45 | @param swipeCell 当前响应的cell 46 | @param indexPath cell在tableView中的位置 47 | @return YES 表示当前cell可以侧滑, NO 不可以 48 | */ 49 | - (BOOL)swipeCell:(TMSwipeCell *)swipeCell canSwipeRowAtIndexPath:(NSIndexPath *)indexPath 50 | { 51 | if (indexPath.row % 2 == 0) { 52 | return YES; 53 | } 54 | return NO; 55 | } 56 | 57 | /** 58 | 返回侧滑事件 59 | 60 | @param swipeCell 当前响应的cell 61 | @param indexPath cell在tableView中的位置 62 | @return 数组为空, 则没有侧滑事件 63 | */ 64 | - (nullable NSArray *)swipeCell:(TMSwipeCell *)swipeCell editActionsForRowAtIndexPath:(NSIndexPath *)indexPath 65 | { 66 | TestModel *model = [_datas objectAtIndex:indexPath.row]; 67 | __weak __typeof(&*self)weakSelf = self; 68 | if ([model.message_id isEqualToString:TMSWIPE_FRIEND]) { 69 | 70 | TMSwipeCellAction *action3 = [TMSwipeCellAction rowActionWithStyle:TMSwipeCellActionStyleNormal title:@"备注" handler:^(TMSwipeCellAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { 71 | NSLog(@"备注"); 72 | }]; 73 | TMSwipeCellAction *action2 = [TMSwipeCellAction rowActionWithStyle:TMSwipeCellActionStyleDestructive title:@"删除" handler:^(TMSwipeCellAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { 74 | NSLog(@"删除"); 75 | [weakSelf.datas removeObject:model]; 76 | [weakSelf.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; 77 | }]; 78 | return @[action3, action2]; 79 | 80 | }else if ([model.message_id isEqualToString:TMSWIPE_OTHERS]){ 81 | 82 | TMSwipeCellAction *tagAction = [TMSwipeCellAction rowActionWithStyle:TMSwipeCellActionStyleNormal title:nil handler:^(TMSwipeCellAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { 83 | NSLog(@"点击的打标签按钮"); 84 | }]; 85 | tagAction.backgroundColor = [UIColor lightGrayColor]; 86 | tagAction.image = [UIImage imageNamed:@"Tag"]; 87 | 88 | TMSwipeCellAction *deleteAction = [TMSwipeCellAction rowActionWithStyle:TMSwipeCellActionStyleNormal title:nil handler:^(TMSwipeCellAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { 89 | NSLog(@"点击的删除按钮"); 90 | [weakSelf.datas removeObject:model]; 91 | [weakSelf.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; 92 | }]; 93 | deleteAction.backgroundColor = [UIColor lightGrayColor]; 94 | deleteAction.image = [UIImage imageNamed:@"Delete"]; 95 | return @[tagAction, deleteAction]; 96 | 97 | }else if ([model.message_id isEqualToString:TMSWIPE_PUBLIC]){ 98 | 99 | TMSwipeCellAction *action1 = [TMSwipeCellAction rowActionWithStyle:TMSwipeCellActionStyleNormal title:@"取消关注" handler:^(TMSwipeCellAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { 100 | NSLog(@"取消关注"); 101 | }]; 102 | TMSwipeCellAction *action2 = [TMSwipeCellAction rowActionWithStyle:TMSwipeCellActionStyleDestructive title:@"删除" handler:^(TMSwipeCellAction * _Nonnull action, NSIndexPath * _Nonnull indexPath) { 103 | NSLog(@"删除"); 104 | [weakSelf.datas removeObject:model]; 105 | [weakSelf.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; 106 | }]; 107 | return @[action1, action2]; 108 | 109 | }else{ 110 | return @[]; 111 | } 112 | } 113 | 114 | #pragma mark - tableViewDelegate 115 | 116 | -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ 117 | return _datas.count; 118 | } 119 | 120 | -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ 121 | return [TestTableViewCell rowHeight]; 122 | } 123 | 124 | -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ 125 | TestModel *model = [_datas objectAtIndex:indexPath.row]; 126 | TestTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"TestTableViewCell"]; 127 | cell.imageV.image = [UIImage imageNamed:model.headUrl]; 128 | cell.nameL.text = model.name; 129 | cell.contentL.text = model.content; 130 | cell.timeL.text = model.time; 131 | cell.delegate = self; 132 | return cell; 133 | } 134 | 135 | -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{ 136 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 137 | 138 | TMExpandViewController *vc = [TMExpandViewController new]; 139 | vc.view.backgroundColor = [UIColor whiteColor]; 140 | [self.navigationController pushViewController:vc animated:YES]; 141 | } 142 | 143 | - (void)didReceiveMemoryWarning { 144 | [super didReceiveMemoryWarning]; 145 | // Dispose of any resources that can be recreated. 146 | } 147 | 148 | /* 149 | #pragma mark - Navigation 150 | 151 | // In a storyboard-based application, you will often want to do a little preparation before navigation 152 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 153 | // Get the new view controller using [segue destinationViewController]. 154 | // Pass the selected object to the new view controller. 155 | } 156 | */ 157 | 158 | @end 159 | -------------------------------------------------------------------------------- /TMSwipeCell/SwipeCellDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/7/3. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /TMSwipeCell/SwipeCellDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/7/3. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view, typically from a nib. 20 | } 21 | 22 | 23 | - (void)didReceiveMemoryWarning { 24 | [super didReceiveMemoryWarning]; 25 | // Dispose of any resources that can be recreated. 26 | } 27 | 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /TMSwipeCell/gif/one.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cocomanbar/TMSwipeCell/7179190c8ad3989176eaaa7b85c5fb79b52e8da4/TMSwipeCell/gif/one.gif -------------------------------------------------------------------------------- /TMSwipeCell/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // TMSwipeCell 4 | // 5 | // Created by cocomanber on 2018/7/3. 6 | // Copyright © 2018年 cocomanber. 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 | -------------------------------------------------------------------------------- /TMSwipeCellTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /TMSwipeCellTests/TMSwipeCellTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // TMSwipeCellTests.m 3 | // TMSwipeCellTests 4 | // 5 | // Created by cocomanber on 2018/7/3. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TMSwipeCellTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation TMSwipeCellTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /TMSwipeCellUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /TMSwipeCellUITests/TMSwipeCellUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // TMSwipeCellUITests.m 3 | // TMSwipeCellUITests 4 | // 5 | // Created by cocomanber on 2018/7/3. 6 | // Copyright © 2018年 cocomanber. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TMSwipeCellUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation TMSwipeCellUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | --------------------------------------------------------------------------------