iOS 循环push同一种ViewController时,控制数
2017-07-29 本文已影响1051人
水暮竹妖
引子
新接手项目有这么个问题,商详页有推荐商品,推荐商品点进去又是商详页,用户可以无限push商详页,产品现在提出需求:只保留第一个产品和最后两个商品。
解决方案
-
该需求实际是要我们能够自己控制
UIViewController
里viewController
的顺序。 -
push或者pop实质性操作就是目标
VC
在对应UINavigationController
中viewControllers
的压栈和出栈,通过操作viewControllers
就能控制我们想要的VC
pop顺序。 -
对于该需求的解决思路是在push一个商详页的
VC
后判断是否已经超过连续的三个该VC
,如果超过了就将第二个VC
从viewControllers
移除。
代码
-
Demo:
AZCategory -
先看最终怎么使用吧:
// 1.在要限制push次数的VC里添加头文件
#import "UIViewController+PushAndPop.h"
// 2.override下面的方法,返回的即是限制的个数
+ (NSUInteger)cyclePushLimitNumber {
return 3;
}
-
我这里是新建了一个
UIViewController
的一个分类,虽然目前还只是这一个商详页的VC
有这个需求,指不定哪天又有其他什么需求了呢【笑。而且商详页这种VC
真的是很庞大,还是建议封装的粒度尽量大一点,以及用分类将不同的业务模块拆分到对应的分类中去,不要什么事情都让VC
去处理,不然到时候别人看代码以及修改起来都很痛苦【摊手。 -
代码执行的时机我觉得在
viewDidLoad
方法里就行了。 -
设置
VC
的核心代码其实就一句:
[self.navigationController setViewControllers:vcsArrM animated:YES];
-
里面的判断逻辑到时候可以根据需求拓展,分类给
VC
添加个push&pop规则的ENUM啥的... -
完整代码
// UIViewController+PushAndPop.h
#import <UIKit/UIKit.h>
@interface UIViewController (PushAndPop)
+ (NSUInteger)cyclePushLimitNumber;
@end
// UIViewController+PushAndPop.m
#import "UIViewController+PushAndPop.h"
#import <objc/runtime.h>
@implementation UIViewController (PushAndPop)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL originalSelector = @selector(viewDidLoad);
SEL swizzledSelector = @selector(az_viewDidLoad);
swizzleMethod([self class], originalSelector, swizzledSelector);
});
}
// 注意下这个 static
// 关于为啥要在C函数前加static,不知道&有兴趣的可以自己去两个不同的类创建相同的C方法试试:)
static void swizzleMethod(Class class, SEL originalSelector, SEL swizzledSelector)
{
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
}
- (void)az_viewDidLoad {
// 获取limitNum
NSUInteger limitNum = [[self class] cyclePushLimitNumber];
if (limitNum <= 0) { // 0表示不限制数量
[self az_viewDidLoad];
return;
}
NSArray *vcs = self.navigationController.viewControllers;
NSMutableArray *productDetailVCIndexArrM = [NSMutableArray array];
for (NSInteger i = vcs.count; i >= 0; i--) {
// 从数组尾开始遍历有多少连续的VC
if (![vcs[i - 1] isKindOfClass:[self class]]) {
break;
}
[productDetailVCIndexArrM addObject:@(i - 1)];
}
if (productDetailVCIndexArrM.count > limitNum) {
NSMutableArray *vcsArrM = [vcs mutableCopy];
[vcsArrM removeObjectAtIndex:[productDetailVCIndexArrM[1] integerValue]];
[self.navigationController setViewControllers:vcsArrM animated:YES];
}
[self az_viewDidLoad];
}
+ (NSUInteger)cyclePushLimitNumber {
return 0;
}
@end