今天初九,也是2018年上班第一天,继续 改bug、优化代码、提升用户体验😆,真心希望旅图的产品越来越好。
MJRefresh 下拉刷新时触发taptic反馈
第一种方式:
在继承UITableView的子类中重新setMj_header:方法,并hook住mj_header的setState:方法,当state == MJRefreshStatePulling时,触发taptic反馈,
示例代码:
#import <MJRefresh.h>
#import "Aspects.h"
@interface BBTableView ()
#ifdef __IPHONE_10_0
@property (nonatomic, strong) UIImpactFeedbackGenerator *feedbackGenerator;
#endif
@property (nonatomic, strong) NSMutableArray<id<AspectToken>> *aspectArray;
@end
@implementation BBTableView
- (void)setMj_header:(MJRefreshHeader *)mj_header {
if (self.mj_header != mj_header) {
[self clearAspects];
NSError *error = nil;
__weak typeof(&*self) weakSelf = self;
id<AspectToken> asp = [mj_header aspect_hookSelector:@selector(setState:) withOptions:AspectPositionAfter usingBlock:^(id instance, MJRefreshState state){
if (state == MJRefreshStatePulling) {
__strong typeof(&*weakSelf) self = weakSelf;
// 触发taptic反馈
#ifdef __IPHONE_10_0
[self.feedbackGenerator impactOccurred];
#endif
}
} error:&error];
if (asp) {
[self.aspectArray addObject:asp];
}
}
[super setMj_header:mj_header];
}
- (void)clearAspects {
[self.aspectArray enumerateObjectsUsingBlock:^(id<AspectToken> _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj remove];
}];
[self.aspectArray removeAllObjects];
}
@end
第二种方法: 全局添加,直接给MJRefreshHeader添加分类,并交换setState:方法实现
示例代码:
@implementation MJRefreshHeader (BBFeedbackGenerator)
#ifdef __IPHONE_10_0
- (UIImpactFeedbackGenerator *)feedbackGenerator {
UIImpactFeedbackGenerator *feedbackGenerator = objc_getAssociatedObject(self, _cmd);
if (feedbackGenerator == nil) {
feedbackGenerator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
objc_setAssociatedObject(self, _cmd, feedbackGenerator, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return feedbackGenerator;
}
#endif
- (void)bb_setState:(MJRefreshState)state {
if (self.state != state) {
if (state == MJRefreshStatePulling) {
// 触发taptic反馈
#ifdef __IPHONE_10_0
[self.feedbackGenerator impactOccurred];
#endif
}
}
[self bb_setState:state];
}
+ (void)load {
[self exchangeInstanceMethod1:@selector(setState:) method2:@selector(bb_setState:)];
}
+ (void)exchangeInstanceMethod1:(SEL)method1 method2:(SEL)method2
{
method_exchangeImplementations(class_getInstanceMethod(self, method1), class_getInstanceMethod(self, method2));
}
@end