在实现客户端集成微博登录功能时,点击通过新浪微博登录
按钮,此时
- 假如设备上已经安装微博客户端,会跳转到微博客户端进行授权登录
- 假如设备上尚无安装微博客户端,会在当前客户端中弹出微博的网页登录授权界面
在没有安装微博客户端的情况中,加载网页时出现了下图中的 UI 展示 BUG:蓝色进度条位置不对(原因后面会介绍)。
仔细看了一下项目中的逻辑,确定不是自己的代码问题之后,开始检查是否是 WeiBoSDK
中的问题。WeiBoSDK
不开源,不过我们可以用第三方辅助开发工具 Reveal
试着检查一下 WeiBoSDK
中的界面元素:
通过 Reveal
的分析,发现这个进度条在其 superView
的 Y
方向向下偏移 64 个点,比较敏感的开发者这时候应该能察觉出来的这一 BUG 可能与状态栏和导航栏有一定关系(在 iOS 中,statusBar.height + navigationBar.height = 64
)。在当前开发的客户端中,presentingViewController
(即弹出微博登录页面之前的那个 VC
)是没有导航栏的。
出现这种情况,可以通过Objective-C runtime
机制纠正一下进度条的垂直位置。
在项目工程中新建一个category
: UIViewController+TWWBWebViewFix
,这里的头文件中没有代码逻辑,下面展示出实现文件中的完整代码:
#import "UIViewController+TWWBWebViewFix.h"
#import <objc/runtime.h>
@implementation UIViewController (TWWBWebViewFix)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// When swizzling a class method, use the following:
// 'Class class = object_getClass((id)self);'
// or 'Class class = object_getClass([self class]);'
// Here swizzling a instance method:
Class class = [self class];
SEL originalSelector = @selector(viewWillAppear:);
SEL swizzledSelector = @selector(TW_viewWillAppear:);
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);
}
});
}
#pragma mark - Method Swizzling
- (void)TW_viewWillAppear:(BOOL)animated {
[self TW_viewWillAppear:animated];
// 下面代码中的字符串所对应的类可以查看文末图片给出的信息
if ([self isKindOfClass:NSClassFromString(@"WBSDKAuthorizeWebViewController")]) {
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:NSClassFromString(@"WBSDKWebView")]) {
for (UIView *subView in view.subviews) {
if ([subView isKindOfClass:NSClassFromString(@"WBSDKWebViewProgressView")]) {
subView.frame = CGRectMake(0, 0, kDeviceWidth, 3);
}
}
}
}
}
}
@end