iOS卡頓這個問題本身就是個問題数焊,但有這個問題避免不了萬一卡了呢挂捅。
在網(wǎng)絡(luò)少著了很多資料都感覺有些問題,下面是我根據(jù)網(wǎng)絡(luò)上的方案改良一下;
問題描述:
當(dāng)PUSH一個新的ViewController的時候状土,不管是init的過于臃腫還是耗時操作沒有處理无蜂,都有可能導(dǎo)致卡頓;
暴力的測試喜歡狂點蒙谓,這就出現(xiàn)了同一個ViewController被PUSH了多次
我通過重寫導(dǎo)航控制器的方法來解決這個問題斥季。
#import <UIKit/UIKit.h>
@interface YBRNaviViewController : UINavigationController
@end
#import "YBRNavigationController.h"
#import "Aspects.h" //一個可以Hook方法的庫
@interface YBRNavigationController ()
<
UINavigationControllerDelegate
>
{
BOOL _pushing;
id<Aspect> _aspect;
}
@end
@implementation YBRNavigationController
- (instancetype)initWithRootViewController:(UIViewController *)rootViewController
{
self = [super initWithRootViewController:rootViewController];
if (self) {
self.delegate = self; //默認(rèn)代理設(shè)置Self
}
return self;
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated {
//這個地方有個問題,initWithRootViewController會觸發(fā)pushViewController
if (self.viewControllers.count == 0) {
[super pushViewController:viewController animated:animated];
return;
}
if (_pushing == YES) {
NSLog(@"被攔截 %@",viewController);
return;
}else {
NSLog(@"PUSH %@",viewController);
_pushing = YES;
}
[super pushViewController:viewController animated:animated];
}
- (void)setDelegate:(id<UINavigationControllerDelegate>)delegate {
[super setDelegate:delegate];
//移除_aspect
if (_aspect) {
[_aspect remove];
}
if (delegate && ![self isEqual:delegate]) {
//不是Self
if ([delegate respondsToSelector:@selector(navigationController:didShowViewController:animated:)]) {
//當(dāng)delegate已經(jīng)實現(xiàn) navigationController:didShowViewController:animated: 的時候累驮,
//Hook 該方法
//當(dāng)然也可以使用 swizzleMethod 酣倾,Aspect的API更友好些
__weak __typeof(self)weakSelf = self;
_aspect = [((NSObject *)delegate) aspect_hookSelector:@selector(navigationController:didShowViewController:animated:) withOptions:AspectPositionAfter usingBlock:^(id instance, NSArray *args) {
[weakSelf navigationController:args[0] didShowViewController:args[1] animated:args[2]];
} error:nil];
}else {
//為delegate動態(tài)添加 navigationController:didShowViewController:animated:
//不知道有沒有這方面的庫可以用,只能自己寫
Class class = [delegate class];
swizzleMethod(class, @selector(navigationController:didShowViewController:animated:), @selector(navigationController:didShowViewController:animated:));
}
}
}
#pragma mark - UINavigationControllerDelegate
-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
_pushing = NO; //完成PUSH
}
@end
///黑魔法
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);
}
}