【问题标题】:Using AVCaptureDevice to read Barcodes, I want to show an animated ActivityIndicator immediately After the scan使用 AVCaptureDevice 读取 Barcodes,我想在扫描后立即显示动画 ActivityIndi​​cator
【发布时间】:2013-11-20 21:17:00
【问题描述】:

我在视图中有UIActivityIndicator 位置,我试图在扫描条形码后显示它(因为由于某种原因,它不会立即转到我的信息页面,该页面上有一个加载屏幕.) 我尝试在CaptureOutput 中显示指标,但[loadView setHidden:NO] 只是被忽略了。为什么会这样?有没有办法在扫描后立即进行 segue?

BRISBNScanner.h

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>

@interface BRISBNScanner : UIViewController <AVCaptureMetadataOutputObjectsDelegate>
{

    IBOutlet UIActivityIndicatorView *loadView;

}

@property (strong, nonatomic) AVCaptureDevice* device;
@property (strong, nonatomic) AVCaptureDeviceInput* input;
@property (strong, nonatomic) AVCaptureMetadataOutput* output;
@property (strong, nonatomic) AVCaptureSession* session;
@property (strong, nonatomic) AVCaptureVideoPreviewLayer* preview;
@property (strong, nonatomic) NSString *isbnText;

@end

BRISBNScanner.m

#import "BRISBNScanner.h"
#import "BRScanInfoView.h"

@interface BRISBNScanner ()

@end

@implementation BRISBNScanner

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{



    [super viewDidLoad];
    // Do any additional setup after loading the view.
    // Device
    self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    // Input
    self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:nil];

    // Output
    self.output = [[AVCaptureMetadataOutput alloc] init];
    [self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];

    // Session
    self.session = [[AVCaptureSession alloc] init];
    [self.session addInput:self.input];
    [self.session addOutput:self.output];
    self.output.metadataObjectTypes = @[AVMetadataObjectTypeEAN13Code];


    // Preview
    self.preview = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
    self.preview.videoGravity = AVLayerVideoGravityResizeAspectFill;
    self.preview.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    [self.view.layer insertSublayer:self.preview atIndex:0];



    // Start
    [self.session startRunning];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputMetadataObjects:(NSArray *)metadataObjects fromConnection:(AVCaptureConnection *)connection
{
    [loadView setHidden:NO];

    [self.session stopRunning];



    for(AVMetadataObject *metadataObject in metadataObjects)
    {

        AVMetadataMachineReadableCodeObject *readableObject = (AVMetadataMachineReadableCodeObject *)metadataObject;
        if ([metadataObject.type isEqualToString:AVMetadataObjectTypeEAN13Code])
        {
            NSLog(@"EAN 13 = %@", readableObject.stringValue);
            _isbnText = readableObject.stringValue;

            [loadView setHidden:YES];

            [self performSegueWithIdentifier:@"showInfo" sender:self];
            NSMutableArray *viewControllers = [NSMutableArray arrayWithArray: self.navigationController.viewControllers];
            [viewControllers removeObjectIdenticalTo:self];
            [self.navigationController setViewControllers: viewControllers animated: YES];

        }
    }
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"showInfo"]) {
        BRScanInfoView *scanView = (BRScanInfoView *)[segue destinationViewController];
        //The view that uses the ISBN to search for stuff
        scanView.isbnTextprop  = _isbnText;
    }
}


@end

【问题讨论】:

    标签: ios ios7 avfoundation avcapturesession avcapturedevice


    【解决方案1】:

    除非会话的 metadataObjectsCallbackQueue 设置为主队列(或设置为在其上执行的队列),否则您不会从主线程调用 [loadView setHidden:NO]。 (这可能也是 [self performSegueWithIdentifier:@"showInfo" sender:self] 不会立即转到您的信息页面的原因)。由于大多数 UIKit 都不是线程安全的,这会导致“未定义”行为,在这种情况下,不会更改任何内容或仅在延迟后更改。

    我的建议是将你所有的 ui-updates 包装在一个

    dispatch_async(dispatch_get_main_queue(), ^{
        //ui-updates
    });
    

    【讨论】:

    • +1 因为这解决了我的问题。我可能会去掉活动指示器,因为它几乎是即时运行的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-29
    • 1970-01-01
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多