我正在编写一个读取QR码的程序,然后使用收集的数据。我有一个奇怪的问题。我相信它可能需要对线程做些什么。基本上if语句中的所有NSLog工作正常并且每秒快速打印,但是当我尝试更新标签文本或更改背景颜色时需要大约40秒。我不明白为什么。这是代码。
#import "VerifyPassViewController.h"
#import "NewPassViewController.h"
@interface VerifyPassViewController ()
-(BOOL)startReading;
-(void)stopReading;
-(void)loadBeepSound;
@end
@implementation VerifyPassViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Initially make the captureSession object nil.
_captureSession = nil;
// Set the initial value of the flag to NO.
_isReading = NO;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - IBAction method implementation
- (IBAction)startStopReading:(id)sender {
if (!_isReading) {
// This is the case where the app should read a QR code when the start button is tapped.
if ([self startReading]) {
// If the startReading methods returns YES and the capture session is successfully
// running, then change the start button title and the status message.
[_bbITem setTitle:@"Stop"];
[_bbITem setTitle:@"Scanning for QR Code..."];
}
}
else{
// In this case the app is currently reading a QR code and it should stop doing so.
[self stopReading];
// The bar button item's title should change again.
[_bbITem setTitle:@"Start!"];
}
// Set to the flag the exact opposite value of the one that currently has.
_isReading = !_isReading;
}
#pragma mark - Private method implementation
- (BOOL)startReading {
NSError *error;
// Get an instance of the AVCaptureDevice class to initialize a device object and provide the video
// as the media type parameter.
AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
// Get an instance of the AVCaptureDeviceInput class using the previous device object.
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error];
if (!input) {
// If any error occurs, simply log the description of it and don't continue any more.
NSLog(@"%@", [error localizedDescription]);
return NO;
}
// Initialize the captureSession object.
_captureSession = [[AVCaptureSession alloc] init];
// Set the input device on the capture session.
[_captureSession addInput:input];
// Initialize a AVCaptureMetadataOutput object and set it as the output device to the capture session.
AVCaptureMetadataOutput *captureMetadataOutput = [[AVCaptureMetadataOutput alloc] init];
[_captureSession addOutput:captureMetadataOutput];
// Create a new serial dispatch queue.
dispatch_queue_t dispatchQueue;
dispatchQueue = dispatch_queue_create("myQueue", NULL);
[captureMetadataOutput setMetadataObjectsDelegate:self queue:dispatchQueue];
[captureMetadataOutput setMetadataObjectTypes:[NSArray arrayWithObject:AVMetadataObjectTypeQRCode]];
// Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.
_videoPreviewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
[_videoPreviewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[_videoPreviewLayer setFrame:_viewPreview.layer.bounds];
[_viewPreview.layer addSublayer:_videoPreviewLayer];
// Start video capture.
[_captureSession startRunning];
return YES;
}
-(void)stopReading{
// Stop video capture and make the capture session object nil.
[_captureSession stopRunning];
_captureSession = nil;
// Remove the video preview layer from the viewPreview view's layer.
[_videoPreviewLayer removeFromSuperlayer];
}
#pragma mark - AVCaptureMetadataOutputObjectsDelegate method implementation
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
for(AVMetadataObject *metadataObject in metadataObjects)
{
AVMetadataMachineReadableCodeObject *readableObject = (AVMetadataMachineReadableCodeObject *)metadataObject;
if([metadataObject.type isEqualToString:AVMetadataObjectTypeQRCode])
{
NSLog(@"QR Code = %@", readableObject.stringValue);
self.view.backgroundColor = [UIColor greenColor];
NSLog(@"If the background isnt green i might throw up");
}
else if ([metadataObject.type isEqualToString:AVMetadataObjectTypeEAN13Code])
{
NSLog(@"EAN 13 = %@", readableObject.stringValue);
}
}
}
@end
如果您有任何想法,请告诉我。谢谢
答案 0 :(得分:3)
您只能从主线程更新UI:
dispatch_async(dispatch_get_main_queue(), ^{
... update here your ui ..
});
答案 1 :(得分:1)
清楚说明其他海报提示的内容:您的代码正在设置一个在后台线程上运行的调度队列,以处理它识别的任何QR码。
您的captureOutput:didOutputMetadataObjects:fromConnection:
方法将在后台线程上运行。
必须在主线程上执行UI代码。 rafaperez发布了代码,您可以使用后台线程将UI更改分派到主线程上的队列。
您还可以使用方法performSelectorOnMainThread:withObject:waitUntilDone:
将单个方法调用发送到主线程。