iOS 11 上的 Phonegap / Cordova 选择选项后再次显示弹出窗口
Posted
技术标签:
【中文标题】iOS 11 上的 Phonegap / Cordova 选择选项后再次显示弹出窗口【英文标题】:Phonegap / Cordova on iOS 11 select displays pop-up again after selecting option 【发布时间】:2018-03-04 09:19:37 【问题描述】:我在 iPad 上的 ios 11 上使用 Phonegap 时遇到问题。如果单击选择,则会在弹出窗口中显示选项。选择一个后,弹出窗口短暂消失,选择中的选项发生变化,然后弹出窗口重新出现。以下消息在 Xcode 控制台中:
[Warning] Application tried to represent an active popover presentation: <UIPopoverPresentationController: 0x100c3e450>
编辑:弹出窗口重新出现后,单击它时没有任何反应。
如何在选择选项后让选择不重新显示弹出窗口?
这是使用最新的 Phonegap 7.0.1。
这只是一个普通的html选择:
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1 maximum-scale=1, user-scalable=no" />
<meta http-equiv="Content-Security-Policy" content="default-src * 'unsafe-inline' 'unsafe-eval'">
<script type="text/javascript" src="cordova.js"></script>
</head>
<body>
<select>
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
</body>
</html>
您可以在此处下载示例项目:
https://github.com/tomkincaid/selecttest
我通过在 Xcode 中直接打开platforms/ios/SelectTest.xcodeproj 来运行它。
编辑:两次选择,行为就更奇怪了。
<select id="select1">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<select id="select2">
<option value="4">Four</option>
<option value="5">Five</option>
<option value="6">Six</option>
</select>
单击 select1,它会弹出带有 select1 选项的弹出窗口。
选择一个选项,弹出窗口会短暂消失然后重新出现。
点击body使弹窗消失。
单击选择2。出现 select1 弹出窗口。
点击body使弹窗消失。弹出窗口短暂消失,然后再次出现空白。
点击body使弹窗消失。
再次单击 select2。现在它会显示正确的弹出窗口。
【问题讨论】:
任何解决方法?我在整个应用程序中也面临同样的问题 @Anjana-Systematix 正如其他答案中提到的 1)使用 Xcode 8 编译,但不确定 App Store 是否会接受这个或 2)拦截单击选择并显示自定义选择器。 【参考方案1】:这似乎是 iOS 11 上 UIWebVIew 的问题,适用于 iPad 上的所有应用程序,而不仅仅是 Phonegap/Cordova。由于 WKWebView 的 UIWebVIew 已贬值,Apple 不太可能修复它。在 Phonegap/Cordova 使用 WKWebView 之前,我一起破解了这个修复程序。基本上,它会在选择上放置一个 div,然后从自定义插件中打开一个选择器。
index.html
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1 maximum-scale=1, user-scalable=no" />
<meta http-equiv="Content-Security-Policy" content="default-src * 'unsafe-inline' 'unsafe-eval'">
<script type="text/javascript" src="cordova.js"></script>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="PhonegapUtility.js"></script>
<script type="text/javascript">
function onBodyLoad()
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady()
addSelectButton('#selecta');
addSelectButton('#selectb');
function addSelectButton(selectID)
var u = new PhonegapUtility();
u.isIpad(function(resp)
if (resp == 1)
var buttonID = selectID+"Button";
if($(buttonID).length == 0)
$("body").append("<div id='"+buttonID.replace("#","")+"' onclick='showPicker(\""+selectID+"\");'></div>");
$(buttonID).css("position","absolute");
$(buttonID).css("left",$(selectID).offset().left+"px");
$(buttonID).css("top",""+$(selectID).offset().top+"px");
$(buttonID).css("width",$(selectID).width()+"px");
$(buttonID).css("height",$(selectID).height()+"px");
// need to adjust this for margin and padding
);
function showPicker(selectID)
var optionArray = [];
$(selectID).find('option').each(function(index,element)
optionArray.push(element.text);
);
var u = new PhonegapUtility();
u.showPicker(optionArray.join("|||"),$(selectID).prop('selectedIndex'),function(resp)
$(selectID+" option")[resp].selected = true;
);
</script>
</head>
<body onload="onBodyLoad();">
<select id="selecta">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
<select id="selectb">
<option value="4">Option 4</option>
<option value="5">Option 5</option>
<option value="6">Option 6</option>
</select>
</body>
</html>
PhonegapUtility.h
#import <Cordova/CDV.h>
@interface PhonegapUtility : CDVPlugin <UIPickerViewDelegate,UIPickerViewDataSource>
@property (strong, nonatomic) NSString *callbackId;
@property (strong, nonatomic) UIPickerView *pickerView;
@property (strong, nonatomic) UIView *pickerWrappertView;
@property (strong, nonatomic) NSArray *pickerData;
- (void) isIpad:(CDVInvokedUrlCommand*)command;
- (void) showPicker:(CDVInvokedUrlCommand*)command;
- (void) pickerDone;
@end
PhonegapUtility.m
#import "PhonegapUtility.h"
#import "AppDelegate.h"
@implementation TomPhonegapUtility
@synthesize callbackId,pickerData,pickerView,pickerWrappertView;
- (void) isIpad:(CDVInvokedUrlCommand*)command
int iPad = 0;
if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) iPad = 1;
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:iPad];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
- (void) showPicker:(CDVInvokedUrlCommand*)command
callbackId = [[NSString alloc] initWithString: command.callbackId];
AppDelegate *appDelegate = (AppDelegate *) [[UIApplication sharedApplication] delegate];
UIViewController *rootViewController = appDelegate.window.rootViewController;
pickerData = [[command.arguments objectAtIndex:0] componentsSeparatedByString:@"|||"];
float viewWidth = rootViewController.view.bounds.size.width; //[UIScreen mainScreen].bounds.size.width;
float viewHeight = rootViewController.view.bounds.size.height; //[UIScreen mainScreen].bounds.size.height;
UIToolbar *toolBar= [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, viewWidth, 44)];
[toolBar setBarStyle:UIBarStyleDefault];
UIBarButtonItem *flex = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *barButtonDone = [[UIBarButtonItem alloc] initWithTitle:@"Done"
style:UIBarButtonItemStylePlain
target:self
action:@selector(pickerDone)];
toolBar.items = @[flex, barButtonDone];
pickerView = [[UIPickerView alloc] init];
[pickerView setDataSource: self];
[pickerView setDelegate: self];
[pickerView setFrame: CGRectMake(0, toolBar.frame.size.height, viewWidth, 180.0f)];
pickerView.showsSelectionIndicator = YES;
[pickerView selectRow:[[command.arguments objectAtIndex:1] intValue] inComponent:0 animated:NO];
pickerWrappertView = [[UIView alloc] initWithFrame:CGRectMake(0, viewHeight-toolBar.frame.size.height-pickerView.frame.size.height, viewWidth, toolBar.frame.size.height + pickerView.frame.size.height)];
pickerWrappertView.backgroundColor = [UIColor whiteColor];
[pickerWrappertView addSubview:pickerView];
[pickerWrappertView addSubview:toolBar];
[rootViewController.view addSubview:pickerWrappertView];
- (void) pickerDone
int selectedIndex = (int) [pickerView selectedRowInComponent:0];
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:selectedIndex];
[self.commandDelegate sendPluginResult:pluginResult callbackId:callbackId];
[pickerWrappertView removeFromSuperview];
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
return 1;
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
return [pickerData count];
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
return [pickerData objectAtIndex:row];
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
【讨论】:
在我的实际生产实现中,它有点复杂。我正在使用 Jquery mobile,它将选择包装在它自己的 div 中,所以我将覆盖层放在包装器中,以便它随着选择滚动。我检查是否已经出现了一个选择器,并在显示一个新的选择器之前将其删除。到目前为止,它运行良好,我实际上更喜欢 iPhone 样式选择器而不是 iPad 样式警报。 您有添加插件的链接吗?我们如何从下拉列表中选择的选项中获取回调? 代码如上。您可以根据需要自定义它。您可以通过单击“完成”按钮获得回调。【参考方案2】:您可以尝试使用发布标志构建您的应用程序吗?比如:
cordova build --release ios
我能够在没有该发布标志的情况下重现该问题,但有了它,问题就消失了。因此,我想知道这个问题的真正根源:它真的在苹果方面吗?似乎在 Cordova 方面......或者我错过了一些东西。
关于我的环境的一些信息可能有用:
iOS 11.0.1 科尔多瓦 CLI 6.5.0 Cordova-iOS 4.4.0编辑:我的错,它根本与发布版本无关,这只是因为我的发布版本是在另一台 Mac 上完成的,在 XCode 8 上运行。确实,只有在使用 XCode 9 构建应用程序时才会出现问题。从 XCode 8 为 iOS11 构建应用程序是有效的,所以我的建议是使用 XCode 8,直到我们在 Apple 或 Cordova 方面获得可靠的解决方法。
来源:https://forums.developer.apple.com/thread/88169
【讨论】:
感谢您提供有关 Xcode 8 的建议。我绝对是 Apple 的问题。我制作了一个仅包含 UIWebView 的测试应用程序,但发生了同样的问题。 任何替代解决方案?请帮忙...在我的整个应用程序中都出现了这个问题... AFAIK,唯一的替代解决方案是重写选择组件。两种选择:从原生端(iOS 平台的 Cordova 插件 - @TomKincaid 上面发布了一个示例)或从 JS 端(AngularJS 指令似乎是一种合理的方式,只需谷歌它,你会发现很多例子)【参考方案3】:刚刚遇到这个故障。我发现这个插件可能对每个人都有帮助:
https://github.com/apache/cordova-plugin-wkwebview-engine
基本上强制 Cordova 使用 WKWebView。只是一个免责声明......我在使用它后没有通过适当的浸泡测试来运行我们的应用程序,所以我不知道这是否会导致其他问题,但它确实解决了选择问题。
目前在 Cordova v.7.0.1 和 Cordova iOS 平台 4.4.0 上
【讨论】:
好的,经过大量测试,WKWebview 存在一些严重的限制。无法再在控制台中记录 JS 错误(无论发生什么,都只会在第 0 行给出一般脚本错误)。 WKWebview 也不能很好地与 dataStorage 配合使用......我似乎无法检索我在本地存储的任何图像,只是给出一个空白。另请参阅 localStorage 的一些问题。如果你们打算使用这个插件,请在发布之前对你的应用程序进行浸泡测试。我不得不回滚不使用它。以上是关于iOS 11 上的 Phonegap / Cordova 选择选项后再次显示弹出窗口的主要内容,如果未能解决你的问题,请参考以下文章
Phonegap (Cordova 2.9.0) iOS 上的地理定位
iOS 上的 PhoneGap 是不是经过硬编码以加载 www/index.html?
逐步让 Google Analytics 在 iOS 上的 PhoneGap 1.2.0 中工作(phonegapalytics)