WKWebView 的结构
首先看 WKWebView
的视图结构图
从上图可以看出,WKWebView
中除了还包含一个 WKScrollView
和 WKContentView
,我们加载的网页都是在 WKContent
上进行展示的。
场景
如果需要添加一个进度条来展示当前网页加载的情况,可以将进度条添加到WKWebView
和 WKScrollView
上面,这两个都能获取到,成功添加。当有个导航栏,WKWebView
和 WKScrollView
顶部有一片空白,这时候进度条的位置就需要通过设备区判断导航栏的高度,如果能够添加到 WKContentView
上的话就不需要考虑导航栏,网页怎么展示的,进度条始终都会在最顶部。但是问题是,WKContentView
不能直接获取到,怎么样才能间接获取到WKContentView
呢?
技术点
-
runtime
获取
WKWebView
所有成员变量获取
WKWebView
所有方法
获取成员变量
/**
获取到成员变量列表
*/
- (void)getIvarListWithClass:(Class)cls {
if (!cls) return;
NSLog(@"成员列表");
unsigned int count = 0;
// 获取到成员变量列表
Ivar *ivarList = class_copyIvarList(cls, &count);
// 遍历成员变量
for (int i = 0; i < count; i++) {
Ivar ivar = ivarList[i];
// 获取到成员变量名字
const char *ivarName = ivar_getName(ivar);
NSLog(@"%@, %@", [NSString stringWithUTF8String:ivarName], [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)]);
}
// 释放成员列表属性(在这里因为是C语言类型)
free(ivarList);
}
获取方法列表
/**
获取到方法列表
*/
- (void)getMethodListWithClass:(Class)cls {
if (!cls) return;
NSLog(@"方法列表");
unsigned int count = 0;
Method *methodList = class_copyMethodList(cls, &count);
for (int i = 0; i < count; i++) {
Method method = methodList[i];
SEL methodSEL = method_getName(method);
NSLog(@"%@, %@", NSStringFromSelector(methodSEL), [NSString stringWithUTF8String:method_getTypeEncoding(method)]);
}
free(methodList);
}
在通过获取 WKWebView
所有的成员变量和方法之后,经过摸索尝试之后,发现了WKWebView
有一个未公开的方法 _currentContentView
,通过这个方法我们就能拿到 WKContentView
。这时候我们可以通过WKWebView
的实例对象调用 _currentContentView
这个方法就能拿到 WKContentView
.
WKWebView *webView = [WKWebView new];
SEL currentContentViewSelector = NSSelectorFromString(@"_currentContentView");
if ([webView respondsToSelector:currentContentViewSelector]) {
id view = objc_msgSend(webView, currentContentViewSelector);
NSLog(@"[view class] : %@", [view class]); // 打印获取到的对象类名
NSLog(@"[view superclass] : %@", [view superclass]); // 打印获取到的对象父类名
NSLog(@"[[view superclass] superclass] : %@", [[view superclass] superclass]);
NSLog(@"[[[view superclass] superclass] superclass] : %@", [[[view superclass] superclass] superclass]);
}
[self.view addSubview:webView];
输出结果:
[view class] : WKContentView
[view superclass] : WKApplicationStateTrackingView
[[view superclass] superclass] : UIView
[[[view superclass] superclass] superclass] : UIResponder
既然获取到了WKContentView
,这时候我们就可以将进度条添加到获取到的 WKContentView
上去了
网友评论