我一直在开发一个具有全屏UIWebView的应用程序,其中包含一个基于HTML的应用程序。它具有使用 JS 和本机 Obj-C 代码之间的本机桥接进行工作 QR 码扫描的功能。点击一个按钮会启动这个 UIView,它的大小大约是整个显示屏的一半,作为叠加层,在其中你会看到视频源,当检测到二维码时,它会传回代码并关闭 UIView。这很有效。
然而,UIWebview随后遇到了一个奇怪的问题,任何本来在UIView下面的元素都变得无法点击。就好像UIView的幽灵仍然存在一样。
知道为什么会发生这种情况吗?
- (void)handleCall:(NSString*)functionName callbackId:(int)callbackId args:(NSArray*)args
{
if ([functionName isEqualToString:@"setBackgroundColor"]) {
....... SNIP ........
}
else if ([functionName isEqualToString:@"scanQRCode"]) {
_viewPreview = [[UIView alloc] initWithFrame:CGRectMake(256, 192, 512, 384)];
[self addSubview:self.viewPreview];
[self bringSubviewToFront:_viewPreview];
_captureSession = nil;
if (!_isReading) {
if ([self startReading]) {
NSLog(@"Read barcode: %@", @"started");
}
}
else{
[self stopReading];
[_viewPreview removeFromSuperview];
[_viewPreview release];
}
_isReading = !_isReading;
}
else
{
NSLog(@"Unimplemented method '%@'",functionName);
[uniReader requestSwipe];
[self returnResult:callbackId args:nil];
}
}
- (BOOL)startReading {
NSError *error;
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
if (!input) {
NSLog(@"%@", [error localizedDescription]);
return NO;
}
_captureSession = [[AVCaptureSession alloc] init];
[_captureSession addInput:input];
AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
[_captureSession addOutput:captureMetadataOutput];
dispatch_queue_t dispatchQueue;
dispatchQueue = dispatch_queue_create("myQueue", NULL);
[captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
[captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
_videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
[_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[_videoPreviewLayer setFrame:_viewPreview.layer.bounds];
[_viewPreview.layer addSublayer:_videoPreviewLayer];
// Since the app is landscape only, it is necessary to rotate the preview view to match
[_videoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
// Start video capture.
[_captureSession startRunning];
return YES;
}
-(void)stopReading{
[_captureSession stopRunning];
_captureSession = nil;
NSLog(@"Read barcode: %@", @"Stop scanning");
[_videoPreviewLayer removeFromSuperlayer];
}
-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection: (AVCaptureConnection *)connection{
// Check if the metadataObjects array is not nil and it contains at least one object.
if (metadataObjects != nil && [metadataObjects count] > 0) {
// Get the metadata object.
AVMetadataMachineReadableCodeObject *metadataObj = [metadataObjects objectAtIndex:0];
NSString *barcodeString = metadataObj.stringValue;
NSLog(@"Detected QR: %@", barcodeString);
NSString *javaScript = [NSString stringWithFormat:@"setQR('%@')", barcodeString];
if ([[metadataObj type] isEqualToString:AVMetadataObjectTypeQRCode]) {
// If the found metadata is equal to the QR code metadata then update the status label's text,
// stop reading and change the bar button item's title and the flag's value.
// Everything is done on the main thread.
[self performSelectorOnMainThread:@selector(stopReading) withObject:nil waitUntilDone:NO];
_isReading = NO;
[self performSelectorOnMainThread:@selector(stringByEvaluatingJavaScriptFromString:) withObject:javaScript waitUntilDone:NO];
}
} }
@end
scanQRCode 是否调用了两次:一次用于添加,一次用于删除覆盖?如果是这样,那么您总是在开始时添加新的叠加视图。任何 stopReading 都会从其超级视图(原始叠加层)中删除正在运行的视频,然后从屏幕上删除最新的叠加层。这将使原始覆盖窗口没有内容,这可能是您的问题?