Mit Ray Wenderlich's QRCode reader from Chapter 22 of iOS7 Tutorials, ich lese erfolgreich QRCodes für meine aktuelle App. Ich erweitere es nun, dass ich nach dem erfolgreichen Lesen eines QRCodes die stringValue
der gelesenen speichern, in eine neue Ansicht wechseln und diese Daten in der neuen Ansicht verwenden möchte, mehr oder weniger genau wie die meisten QRCode Reader Apps (wie RedLaser, etc ...) verarbeiten Barcodes und QRCodes.AVCaptureSession stopRunning-Methode erstellt schrecklichen Hang
Allerdings rufe ich [captureSession stopRunning]
(so dass es nicht mehr QRCodes liest und zusätzliche Segmente auslöst) und es gibt eine 10+ Sekunde hängen. Ich habe versucht, einen async
Anruf pro this SO question zu implementieren, jedoch ohne Erfolg. Ich habe auch theseSOQuestions betrachtet und sie scheinen nicht für diesen Zweck geeignet sein.
Hat jemand eine Idee, wie man dieses Hängen entfernen kann? Hier
ist der Code:
#import "BMQRCodeReaderViewController.h"
#import "NSString+containsString.h"
#import "BMManualExperimentDataEntryViewController.h"
@import AVFoundation;
@interface BMQRCodeReaderViewController()
<AVCaptureMetadataOutputObjectsDelegate>
@end
@implementation BMQRCodeReaderViewController {
AVCaptureSession *_captureSession;
AVCaptureDevice *_videoDevice;
AVCaptureDeviceInput *_videoInput;
AVCaptureVideoPreviewLayer *_previewLayer;
BOOL _running;
AVCaptureMetadataOutput *_metadataOutput;
}
- (void)setupCaptureSession { // 1
if (_captureSession) return;
// 2
_videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if (!_videoDevice) {
NSLog(@"No video camera on this device!"); return;
}
// 3
_captureSession = [[AVCaptureSession alloc] init];
// 4
_videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:_videoDevice error:nil];
// 5
if ([_captureSession canAddInput:_videoInput]) { [_captureSession addInput:_videoInput];
}
// 6
_previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
_previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
_metadataOutput = [[AVCaptureMetadataOutput alloc] init];
dispatch_queue_t metadataQueue = dispatch_queue_create("com.razeware.ColloQR.metadata", 0);
[_metadataOutput setMetadataObjectsDelegate:self queue:metadataQueue];
if ([_captureSession canAddOutput:_metadataOutput]) { [_captureSession addOutput:_metadataOutput];
}
}
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects
fromConnection:(AVCaptureConnection *)connection {
// This fancy BOOL is just helping me fire the segue when the correct string is found
__block NSNumber *didFind = [NSNumber numberWithBool:NO];
[metadataObjects enumerateObjectsUsingBlock:^(AVMetadataObject *obj, NSUInteger idx, BOOL *stop) {
AVMetadataMachineReadableCodeObject *readableObject = (AVMetadataMachineReadableCodeObject *)obj;
NSLog(@"Metadata: %@", readableObject);
// [ containsString is a category I extended for NSString, just FYI
if ([readableObject.stringValue containsString:@"CorrectString"]) {
didFind = [NSNumber numberWithBool:YES];
NSLog(@"Found it");
_testName = @"NameOfTest";
*stop = YES;
return;
}
}];
if ([didFind boolValue]) {
NSLog(@"Confirming we found it");
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self stopRunning];
});
_labelTestName.text = _testName;
[self performSegueWithIdentifier:@"segueFromFoundQRCode" sender:self];
}
else {
NSLog(@"Did not find it");
}
}
- (void)startRunning {
if (_running)
return;
[_captureSession startRunning];
_metadataOutput.metadataObjectTypes = _metadataOutput.availableMetadataObjectTypes;
_running = YES;
}
- (void)stopRunning {
if (!_running) return;
[_captureSession stopRunning];
_running = NO;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setupCaptureSession];
[self setupNavBar];
[self startRunning];
_previewLayer.frame = _previewView.bounds;
[_previewView.layer addSublayer:_previewLayer];
}
Dies ist ein Thema, das nicht sehr auf StackOverflow berührt wurde, es scheint, das hilft eine Tonne, danke. – Alioo
Eine Sache, ich bekomme jetzt einen Absturz mit der Nachricht App beenden wegen der nicht abgefangenen Ausnahme 'NSInternalInconsistencyException', Grund: 'Nur auf dem Hauptthread laufen!' Denkst du, dass meine prepareForsegue das verursacht? – Alioo
Hi @Alioo, Entschuldigung für die Verspätung, ich habe diesen Code schon eine Weile nicht mehr gelesen (wir machen keine QR), aber ich stieß auf das gleiche Problem - es könnte über das Laufen neu überdacht werden Diese Methode im Hintergrund oder nur warten, um das Segment zu feuern. Mit etwas Basteln denke ich, dass wir das mit weniger Problemen durchführen können. – Max