最近在做支付宝快捷支付和快捷登录,如果手机端装有“支付宝钱包”这个很正常,但是在手机端没有装支付宝钱包时按照支付宝提供文档应该会出现H5页面(网页版)进行操作,但是会遇到调用API:
//scheme与info.plist注册的URL Scheme保持一致
[[AlipaySDK defaultService] auth_V2WithInfo:signString
fromScheme:@"Bao"
callback:^(NSDictionary *resultDic) {
NSLog(@"result = %@",resultDic);
//授权成功后ResultStatus为9000,AuthCode会在result中,需对其做解析
NSString *resultStr = resultDic[@"result"];
if (resultStr&&resultStr.length>0) {
NSArray *resultArr = [resultStr componentsSeparatedByString:@"&"];
for (NSString *subResult in resultArr) {
NSArray *subResultArr = [subResult componentsSeparatedByString:@"="];
if ([subResultArr[0] isEqualToString:@"auth_code"]) {
NSLog(@"authCode = %@",subResultArr[1]);
_strAuthCode = [NSString stringWithFormat:@"%@",subResultArr[1]];
}
}
}
}];
发现H5页面一直不会出现,刚开始一直以为这种情况是动画冲突,或者是下载的别的第三方库的冲突,就一个一个来排查,发现并不是这个问题,用xcode-new-project 新建一个工程,将支付宝demo中相关信息导入就可以,最后发现区别是 自己项目是用代码来创建 UIWindow ,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window makeKeyAndVisible];
}
而新建project /支付宝demo 是用storyboard 来创建window,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return yes;
}
支付宝技术支持建议在调用API前 用代码:
UIWindow *firstWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:0];
firstWindow.hidden = NO;
获取到project中windows 列表最底层的window 将其可见,然后在回调成功后再隐藏,
callback:^(NSDictionary *resultDic) {firstWindow.hidden = YES;}
这种做法确实H5页面出现,如下图:但是在iOS6.0系统上点击输入框键盘不会出现,iOS7.0以后,刚开始点输入框不会出现多点几下会出现,
此处打印:
DLog(@"%@",[[UIApplication sharedApplication] windows])
DLog(@"%@",[[UIApplication sharedApplication] keyWindow]);
windows
(
"<UIWindow: 0x1dd9c090; frame = (0 0; 320 480); hidden = YES; autoresize = W+H; layer = <UIWindowLayer: 0x1dd9dec0>>",
"<UIWindow: 0x1dd9fa80; frame = (0 0; 320 480); layer = <UIWindowLayer: 0x1dd9f940>>",
"<UITextEffectsWindow: 0x1e965f20; frame = (0 0; 320 480); hidden = YES; opaque = NO; layer = <UIWindowLayer: 0x1e965e70>>"
)
keywindow <UIWindow: 0x1dd9fa80; frame = (0 0; 320 480); layer = <UIWindowLayer: 0x1dd9f940>>
会发现有两个UIWindow出现,[0] ,[1对应keywindow]但是一般project 中只会有一个window,怎么会出现两个?于是将以下代码注释掉,
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
项目还是可以正常运行,最后经排查原因是项目引用了main.storyboard ,所以在项目启动时候会自动创建一个window(0x1dd9c090),之后我们又用代码初始化一个self.window(0x1dd9fa80),并且将自己创建的self.window设置为主窗口(makekeyAndVisible),但是windows 列表中最底层的window(0x1dd9c090)并不是keywindow,所以导致H5页面出现不了(因为支付宝H5页面是show in windows[0]上而不是 show in keywindow 所以感觉支付宝SDK也需要优化),即使将windows[0].hidden = NO,H5页面出现,键盘也不会出现,输入框不能输入,因为键盘弹出一定要在keywindow上显示,之所以在>iOS7.0之后可以正常弹出键盘是因为,>iOS7.0之后,主窗口和次窗口是没有区别的
在ios7以前中有区别:哪个是主窗口,后面设置为主窗口会把之前设置的覆盖掉。(只有主窗口才能响应键盘的输入事件)
解决办法有两种:
1、将firstwindow --windows[0](0x1dd9c090) 设置为主窗口,
[firstWindow makeKeyAndVisible];
2、将firstwindow == windows[0] 去掉:也就是project不引用main.storyboard,
将
project-->Targets-->General-->Main Interface框里内容main 置空,
或者 info.plist-->Main storyboard file base name 对应内容main 置空
或者 直接删除引用main.storyboard
反正是项目中不再用main.storyboard就行。
这个时候一切都没问题了,也不用代码:
UIWindow *firstWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:0];
firstWindow.hidden = NO;
[firstWindow makeKeyAndVisible];
firstWindow.hidden = YES;
因为现在就只有一个window了并且就是keywindow,到现在H5页面也会展示,键盘也可以呼出。
当然如果项目创建UIWindow正常的话 是不会出现这个问题的。