背景:
开篇,我必须要先吐槽一番CSDN的新版块风格。好看是好看了,有点像简书的风格了。但是,你的MarkDown编辑器能不能别变来变去的。作为一个有强迫症的人,我一次性修改了20+篇博客的格式。
说回正题,有时候,我们可能封装了一个库给别人用,但是库里面可能要用到控制器(库里面,一般是不会有控制器的)。另一种情况,你的代码分层比较明显,逻辑比较清晰,那么在View层的时候,你若是想要用到控制器,怎么办?对于第二种情况,可能比较好办,那么就用通知,那么就block回调,要么就delegate代理。
不过,最近看到一个方法,能从任何一个view中拿到当前的控制器。
封装方法
+(UIViewController *)getCurrentVCWithCurrentView:(UIView *)currentView
{
for (UIView *next = currentView ; next ; next = next.superview) {
UIResponder *nextResponder = [next nextResponder];
if ([nextResponder isKindOfClass:[UIViewController class]]) {
return (UIViewController *)nextResponder;
}
}
return nil;
}
我稍微修改了一点点东西,网上另一个的版本是这样的:
//当前视图
-(UIViewController *)currentViewController{
UIViewController *vc;
for (UIView* next = [self superview]; next; next = next.superview) {
UIResponder* nextResponder = [next nextResponder];
if ([nextResponder isKindOfClass:[objc_getClass("UIViewController") class]] ) {
vc=(UIViewController*)nextResponder;
return vc;
}
}
return vc;
}
如果你细心看,你会发现,我把for
遍历的第一个参数改成了当前view
。
如果你理解他这个for
循环的意思,那么你就知道我为什么要把第一个参数改成当前的view
了。因为,如果当前的view
是控制器的自视图的话,那么这个view
根本就没有父视图。
分析方法
//第一个for循环
for (int i = 0;i < 9;i ++)
//第二个for循环
for (UIView *next = currentView ; next ; next = next.superview)
有编程基础的人,都知道我第一个for
循环的意思。
简单说一下第一个for
循环的过程:定义一个变量i
,给他赋初始值0。for
循环执行一遍代码,判断i
是否小于9,如果小于9,那么i
加一。如果i
大于9,那么终止for
循环。
那么按照第一个for
循环的套路,我们来探究第二个for
循环是什么意思:定义一个UIView
类型变量next
,给他赋初始值为当前的view
。执行一遍for
循环,判断next
是否存在,存在的话,把next
的父视图赋值给next
。如果next
不存在,那么终止for
循环。
UIResponder* nextResponder = [next nextResponder];
if ([nextResponder isKindOfClass:[objc_getClass("UIViewController") class]] ) {
vc=(UIViewController*)nextResponder;
return vc;
而这里的代码涉及到响应者对象的知识。如果next
视图的响应者的类是UIViewController
,那么表明他已经取到了当前控制器了,返回即可。