引子
新接手項目有這么個問題,商詳頁有推薦商品,推薦商品點進去又是商詳頁,用戶可以無限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)az_cyclePushLimitNumber {
return 3;
}
我這里是新建了一個
UIViewController
的一個分類,雖然目前還只是這一個商詳頁的VC
有這個需求,指不定哪天又有其他什么需求了呢【笑。而且商詳頁這種VC
真的是很龐大,還是建議封裝的粒度盡量大一點,以及用分類將不同的業務模塊拆分到對應的分類中去,不要什么事情都讓VC
去處理,不然到時候別人看代碼以及修改起來都很痛苦【攤手。代碼執行的時機我覺得在
viewDidLoad
方法里就行了。設置
VC
的核心代碼其實就一句:
[self.navigationController setViewControllers:vcsArrM animated:YES];
里面的判斷邏輯到時候可以根據需求拓展,分類給
VC
添加個push&pop規則的ENUM啥的...完整代碼
// UIViewController+AZPushAndPop.h
#import <UIKit/UIKit.h>
@interface UIViewController (AZPushAndPop)
+ (NSUInteger)az_cyclePushLimitNumber;
@end
// UIViewController+AZPushAndPop.m
#import "UIViewController+PushAndPop.h"
#import <objc/runtime.h>
@implementation UIViewController (AZPushAndPop)
+ (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
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 - 1; i >= 0; i--) {
// 從數組尾開始遍歷有多少連續的VC
if (![vcs[i] isKindOfClass:[self class]]) {
continue;
}
[productDetailVCIndexArrM addObject:@(i)];
}
if (productDetailVCIndexArrM.count > limitNum) {
NSMutableArray *vcsArrM = [vcs mutableCopy];
[vcsArrM removeObjectAtIndex:[productDetailVCIndexArrM[1] integerValue]];
[self.navigationController setViewControllers:vcsArrM animated:YES];
}
[self az_viewDidLoad];
}
+ (NSUInteger)az_cyclePushLimitNumber {
return 0;
}
@end