如何更好的跳转,更便利的Self-Manager

我们在开发过程中总会遇到如下场景:

1.tableviewcell(view)中的控件点击需要跳转到各种页面

2.在使用app或者开打app,需要处理远程通知的跳转

跳转总是需要CurrentViewController

在app中做跳转,我们总是需要获得一个可以ViewController来做转场动画,通常的场景就是正在展示的ViewController做push或者present,特别是在Self-Manager这种思想下,因为控件的self-manager之后需要handle事件,比如跳转

@implementation FDAvatarView (FDAvatarViewSelfManager)
// 为后一个页面的创建增加了个 UID 参数
- (void)selfManagedConfigureWithAvatarURL:(NSURL *)URL VIPInfo:(id)info UID:(NSString *)UID {
    [self configureWithAvatarURL:URL VIPInfo:info tapped:^{
        // 假设 App 结构是 Root -> TabBar -> Navigation -> ViewController
        UITabBarController *tabBarControler = (id)[UIApplication.sharedApplication.delegate.window.rootViewController;
        UINavigationController *navigationController = tabBarControler.selectedViewController;
        // 创建用户信息 View Controller
        FDUserProfileViewController *profileViewController = [FDUserProfileViewController viewControllerWithUID:UID];
        [navigationController pushViewController:profileViewController animated:YES];
    }];
}
@end

然而控件可能会出现在各种各样的ViewController中,如何获得当前的ViewController

获得CurrentViewController

demo地址:https://github.com/Sdoy/CurrentViewController

写一个继承自UIViewController的子类,就叫BaseViewController

@interface BaseViewController : UIViewController

@end

然后在BaseViewController中将self绑定到Application中的currentViewController属性

@implementation BaseViewController

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [UIApplication sharedApplication].currentViewController=self;
}
@end

恩,如何绑定?
为UIApplication写一个Category

@interface UIApplication (CurrentViewController)

@property (nonatomic, weak) UIViewController *currentViewController;

@end

.m文件

#import "UIApplication+CurrentViewController.h"
#import 
@implementation UIApplication (CurrentViewController)
-(void)setCurrentViewController:(UIViewController *)currentViewController
{
    objc_setAssociatedObject(self, @selector(currentViewController), currentViewController, OBJC_ASSOCIATION_ASSIGN);
}
-(UIViewController *)currentViewController
{
    return objc_getAssociatedObject(self, _cmd);
}
@end

至此,只要你的ViewController都是继承自BaseViewController,你就可以在任何地方都能拿到CurrentViewController了,调用起来是这样的

比如收到了远程通知:

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    
    //You can esay find out which view controller is on the screen here.
    UIViewController *currentVC=[UIApplication sharedApplication].currentViewController;
   NSLog(@"%@",currentVC);
}

或者在子控件做跳转:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //if you want to go another view controller when you touch this view
    //you don't need create a delegate to let the display or some view controller to perform SEL
     NSLog(@"%@",[UIApplication sharedApplication].currentViewController);
    
    AnotherViewController *another=[[AnotherViewController alloc]init];
    [[UIApplication sharedApplication].currentViewController.navigationController pushViewController:another animated:YES];

}

而且还写了3个宏定义,用起来更方便

#define CurrentVC [UIApplication sharedApplication].currentViewController

#define PushVC(ViewController) [[UIApplication sharedApplication].currentViewController.navigationController pushViewController:ViewController animated:YES]

#define PresentVC(ViewController)\
UINavigationController *nv=[[UINavigationController alloc]initWithRootViewController:ViewController];\
[[UIApplication sharedApplication].currentViewController presentViewController:nv animated:YES completion:nil]

为什么不直接hook,UIViewController的viewWillAppear:方法?

因为很多苹果的私有组件都是继承自UIViewController的,他们也许是没有nav的

如果在一些特殊情况下,没有经过ViewWillAppear方法

可以用[UIApplication topViewControllerWithRootViewController:[UIApplication sharedApplication].keyWindow.rootViewController]方法来获取

你可能感兴趣的:(如何更好的跳转,更便利的Self-Manager)