{"id":240,"date":"2015-05-12T14:16:19","date_gmt":"2015-05-12T06:16:19","guid":{"rendered":"http:\/\/www.yusian.com\/blog\/?p=240"},"modified":"2016-07-14T22:52:53","modified_gmt":"2016-07-14T14:52:53","slug":"240","status":"publish","type":"post","link":"https:\/\/www.yusian.com\/blog\/project\/2015\/05\/12\/141619240.html","title":{"rendered":"\u4f7f\u7528AVFoundation\u81ea\u5b9a\u4e49\u76f8\u673a\u5982\u4f55\u8c03\u6574\u76f8\u673a\u7126\u8ddd"},"content":{"rendered":"<p>1\u3001\u5982\u4f55\u4f7f\u7528AVFoundation\u6846\u67b6\u81ea\u5b9a\u4e49\u76f8\u673a\u8bf7\u5148\u53c2\u7167<a href=\"http:\/\/www.yusian.com\/blog\/experience\/2015\/04\/21\/130926.html\" target=\"_blank\">iOS\u9879\u76ee\u5b9e\u6218\u4e4b\u81ea\u5b9a\u4e49\u76f8\u673a<\/a><\/p>\n<p>2.1\u3001\u4e0a\u8ff0\u5e16\u5b50\u4e2d\u6709\u8bb2\u5230\uff0c\u5982\u679c\u9700\u8981\u5bf9\u7126\uff0c\u53ef\u4ee5\u901a\u8fc7<strong>AVCaptureDevice<\/strong>\u7684<strong><span style=\"color: red;\"><span style=\"font-family: Arial;\">setFocusPointOfInterest:<\/span><\/span><\/strong>\u65b9\u6cd5\u6765\u5b9e\u73b0\uff0c\u4f20\u5165\u4e00\u4e2aCGPoint\u503c\uff0c\u4f46\u8fd9\u91cc\u7684CGPoint\u4e0d\u662fView\u4e0a\u9762\u7684\u70b9\uff0c\u800c\u662f\u8303\u56f4\u76840~1\u7684\u76f8\u5bf9\u767e\u5206\u70b9\uff1b<\/p>\n<p>2.2\u3001\u8fd9\u4e2aCGPoint\u5982\u4f55\u5f97\u6765\u5462\uff0c\u6211\u4eec\u5728\u70b9\u51fb\u5c4f\u5e55\u65f6\u53ef\u4ee5\u76d1\u542c\u76f8\u5173View\u7684\u70b9\u51fb\u4e8b\u4ef6\uff0c\u6dfb\u52a0\u4e00\u4e2a<strong>UITapGestureRecognizer<\/strong>\u624b\u52bf\uff0c\u5728\u70b9\u65f6\u540e\uff0c\u53ef\u4ee5\u901a\u8fc7<strong>UITapGestureRecognizer<\/strong>\u7684<span style=\"font-family: Arial;\"><span style=\"color: #ff0000;\"><strong>locationInView:<\/strong><\/span><\/span>\u65b9\u6cd5\u5f97\u5230CGPoint\uff0c\u8fd9\u662f\u4e00\u4e2a\u7edd\u5bf9\u503c\uff0c\u5373\u70b9\u51fb\u4e86\u76f8\u5173View\u4e0a\u7684\u67d0\u4e2a\u70b9\uff0c\u6709\u4e86\u8fd9\u4e2a\u70b9\uff0c\u518d\u901a\u8fc7<strong>AVCaptureVideoPreviewLayer<\/strong>\u7684\u4e00\u4e2a\u8f6c\u6362\u65b9\u6cd5\uff1a<span style=\"font-family: Arial;\"><span style=\"color: #ff0000;\"><strong>captureDevicePointOfInterestForPoint:<\/strong><\/span><\/span>\u53ef\u4ee5\u5c06\u7edd\u5bf9\u70b9\u8f6c\u6362\u6210\u76f8\u5bf9\u70b9\u3002<!--more--><\/p>\n<p>2.3\u3001\u5f97\u5230CGPoint\u540e\uff0c\u5c31\u53ef\u4ee5\u8c03\u7528AVCaptureDevice\uff08\u5373\u6444\u50cf\u5934\uff09\u7684<strong><span style=\"color: red;\"><span style=\"font-family: Arial;\">setFocusPointOfInterest:<\/span><\/span><\/strong>\u65b9\u6cd5\u6765\u5b9e\u73b0\u4e86\uff0c\u4f46\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u8fd9\u4e2a\u65b9\u6cd5\u4e0d\u80fd\u76f4\u63a5\u8c03\u7528\uff0c\u8981\u5206\u4e09\u6b65\u66f2\u6765\u5b8c\u6210\uff1a\u9501\u5b9a<strong>AVCaptureDevice<\/strong>\uff0c\u4fee\u6539\u53c2\u6570\u503c\uff0c\u89e3\u9501<strong>AVCaptureDevice<\/strong>\u3002\u4e00\u822c\u5f62\u5f0f\u5982\uff1a<\/p>\n<pre lang=\"objc\" line=\"1\">\/\/\/ \u5bf9\u7126\u4e8b\u4ef6\n- (void)focusAtPoint:(CGPoint)point\n{\n????AVCaptureDevice *device = self.deviceInput.device;\n????NSError *error;\n????if ([device isFocusModeSupported:AVCaptureFocusModeAutoFocus] && [device isFocusPointOfInterestSupported])\n????{\n????????if ([device lockForConfiguration:&error]) {\n????????????[device setFocusPointOfInterest:point];???? \/\/ \u5bf9\u7126\u70b9\n????????????[device setExposurePointOfInterest:point];? \/\/ \u66dd\u5149\u70b9\n????????????[device setFocusMode:AVCaptureFocusModeAutoFocus];? \/\/ \u81ea\u52a8\u5bf9\u7126\u6a21\u5f0f\n????????????[device unlockForConfiguration];\n????????} else {\n????????????NSLog(@\"Error: %@\", error);\n????????}\n????}\n}<\/pre>\n<p>3\u3001\u81ea\u52a8\u5bf9\u7126\u5b9e\u73b0\u4e86\uff0c\u5982\u4f55\u8c03\u8282\u7126\u8ddd\u5462\uff1f<\/p>\n<p>3.1\u3001\u8fd9\u91cc\u6240\u8c13\u7684\u8c03\u8282\u7126\u8ddd\u4e0d\u662f\u5bf9\u7126\u7684\u610f\u601d\uff0c\u800c\u662f\u5728\u62cd\u6444\u8fdc\u666f\u65f6\u6240\u9700\u8981\u7684\u653e\u5927\uff08\u62c9\u8fd1\uff09\u5f71\u50cf<\/p>\n<p>3.2\u3001\u6709\u4e24\u79cd\u65b9\u5f0f\u6765\u5b9e\u73b0\uff0c\u7b2c\u4e00\u79cd\u65b9\u5f0f\uff0c\u901a\u8fc7\u653e\u5927AVCaptureVideoPreviewLayer\u53caAVCaptureStillImageOutput\u7684videoScaleAndCropFactor\u5c5e\u6027\u6765\u5b9e\u73b0\uff0c\u7b80\u5355\u4e00\u70b9\u8bb2\u5c31\u662f\u628a\u9884\u89c8\u56fe\u5c42\u653e\u5927\uff0c\u8fd9\u6837\u5728\u5c4f\u5e55\u4e0a\u5c31\u53ea\u80fd\u770b\u5230\u4e00\u90e8\u5206\u5f71\u50cf\u4e86\uff0c\u7136\u540e\u5728\u6355\u6349\u751f\u6210\u56fe\u7247\u65f6\u505a\u76f8\u540c\u500d\u6570\u7684\u653e\u5927\uff0c\u88c1\u526a\u8d85\u51fa\u90e8\u5206\u7684\u50cf\u7d20\u5b9e\u73b0\uff0c\u8fd9\u79cd\u65b9\u5f0f\u597d\u6bd4\u539f\u672c\u62cd\u6444\u7684\u7167\u7247\u662f4000*3000\u7684\u5206\u8fa8\u7387\uff0c\u73b0\u5728\u901a\u8fc7\u653e\u5927\u53ea\u53d6\u4e2d\u95f42000*1500\u7684\u90e8\u5206\u8f93\u51fa\u540c\u6837\u5927\u5c0f\u7684\u7167\u7247\uff0c\u6700\u7ec8\u7684\u6548\u679c\u5c31\u662f\u653e\u5927\u4e86\u56fe\u50cf\u3002<\/p>\n<p>3.3\u3001\u53e6\u4e00\u79cd\u65b9\u5f0f\uff0c\u901a\u8fc7\u8c03\u8282AVCaptureDevice\u7684videoZoomFactor\u5c5e\u6027\u6765\u5b9e\u73b0\u7126\u8ddd\u7684\u8c03\u6574\uff0c\u8fd9\u79cd\u65b9\u5f0f\u4e8b\u5b9e\u4e0a\u662f\u5728\u56fe\u50cf\u53d6\u666f\u7684\u65f6\u5019\u5c31\u8fdb\u884c\u4e86\u76f8\u5173\u8c03\u6574\uff0c\u53d6\u6444\u50cf\u5934\u7684\u90e8\u5206\u5f71\u50cf\u8fdb\u5165sesstion\uff0c\u8fd9\u6837\u66f4\u5408\u7406\uff0c\u5e76\u4e14\u524d\u9762\u90a3\u79cd\u65b9\u5f0f\u6709\u4e2a\u95ee\u9898\uff1a\u56e0\u4e3a\u662f\u901a\u8fc7\u653e\u5927\u56fe\u5c42\u6765\u6a21\u62df\u62c9\u8fd1\u7126\u8ddd\uff0c\u6240\u4ee5\u5b9e\u9645\u4e0a\u56fe\u5c42\u662f\u4e0d\u6e05\u6670\u7684\uff0c\u5bf9\u7126\u4e5f\u6ca1\u4ec0\u4e48\u6548\u679c\u3002\u7136\u800c\u7b2c\u4e8c\u79cd\u65b9\u5f0f\u4e2dvideoZoomFactor\u5c5e\u6027\u9700\u8981iOS7\u4ee5\u4e0a\u624d\u652f\u6301\u3002<\/p>\n<p>3.4\u3001\u8bbe\u7f6evideoZoomFactor\u5c5e\u6027\u4e0e\u5bf9\u7126\u4e00\u6837\u540c\u6837\u9700\u8981\u4e09\u90e8\u66f2\u6765\u5b9e\u73b0\uff0c\u9501\u5b9aDevice\u3001\u8bbe\u7f6e\u5c5e\u6027\u3001\u89e3\u9501Device<\/p>\n<pre lang=\"objc\" line=\"1\">\/\/\/ \u8c03\u6574\u6444\u50cf\u5934\u7126\u8ddd\n- (void)setDevice:(AVCaptureDevice *)device videoZoomFactor:(CGFloat)scale\n{\n????[device lockForConfiguration:nil];\n????device.videoZoomFactor = scale;\n????[device unlockForConfiguration];\n}<\/pre>\n<p>4\u3001\u5173\u952e\u4ee3\u7801<\/p>\n<pre lang=\"objc\" line=\"1\">\/\/\n\/\/? SACameraCtrl.m\n\/\/? Test\n\/\/\n\/\/? Created by \u4f59\u897f\u5b89 on 15\/4\/13.\n\/\/? Copyright (c) 2015\u5e74 Sian. All rights reserved.\n\/\/\n?\n#import \"SACameraCtrl.h\"\n#import \"SAPreview.h\"\n#import \"SAPhotoViewCtrl.h\"\n#import <AVFoundation\/AVFoundation.h>\n#import <CoreMotion\/CoreMotion.h>\n#define SourcePath [[NSBundle mainBundle] pathForResource:@\"SAImagePickerController.bundle\" ofType:nil]\n?\n@interface SACameraCtrl () <UIAccelerometerDelegate>\n{\n????CGFloat _deviceScale;\n}\n\/\/ \u8f93\u5165\u6d41\u9884\u89c8\u56fe\u5c42\n@property (nonatomic, strong)?? AVCaptureVideoPreviewLayer? *previewLayer;\n?\n@property (weak, nonatomic) IBOutlet SAPreview *preview;\n?\n\/\/ AVCaptureSession\u5bf9\u8c61\u6765\u6267\u884c\u8f93\u5165\u8bbe\u5907\u548c\u8f93\u51fa\u8bbe\u5907\u4e4b\u95f4\u7684\u6570\u636e\u4f20\u9012\n@property (nonatomic, strong)?? AVCaptureSession??????????? *session;\n?\n\/\/ \u8bbe\u5907\u8f93\u5165\u6d41\n@property (nonatomic, strong)?? AVCaptureDeviceInput??????? *deviceInput;\n?\n\/\/ \u7167\u7247\u8f93\u51fa\u6d41\n@property (nonatomic, strong)?? AVCaptureStillImageOutput?? *imageOutput;\n?\n\/\/ \u6444\u50cf\u5934\u7126\u500d\n@property (nonatomic, assign)?? CGFloat???????? deviceScale;\n?\n\/\/ \u56fe\u7247\u8f93\u51fa\u89c6\u56fe\n@property (nonatomic, strong)?? UIImageView???? *cameraShowView;\n?\n\/\/ \u6444\u50cf\u5934\u6570\u7ec4\n@property (nonatomic, strong, readonly) NSArray???? *devices;?????? \/\/ AVCaptureDevices\n?\n\/\/ \u95ea\u5149\u706f\u5207\u6362\u6309\u94ae\n@property (weak, nonatomic) IBOutlet??? UIButton??? *flashButton;\n?\n@end\n?\n@implementation SACameraCtrl\n?\n- (void)viewDidLoad\n{\n????[super viewDidLoad];\n????\/\/ \u521b\u5efa\u4ea4\u4e92\u6d41\n????self.session = [[AVCaptureSession alloc] init];\n????self.session.sessionPreset = AVCaptureSessionPresetPhoto;\n?????\n????\/\/ \u5a92\u4f53\u8f93\u5165\n????AVCaptureDevice *device = [self.devices firstObject];\n????[self setDevice:device FlashMode:AVCaptureFlashModeAuto];\n????self.deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:NULL];\n????if([self.session canAddInput:self.deviceInput])[self.session addInput:self.deviceInput];\n?\n????\/\/ \u5a92\u4f53\u8f93\u51fa\n????self.imageOutput = [[AVCaptureStillImageOutput alloc] init];\n????self.imageOutput.outputSettings = @{AVVideoCodecKey : AVVideoCodecJPEG};\n????AVCaptureConnection * connection = [self.imageOutput connectionWithMediaType:AVMediaTypeVideo];\n????connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;\n????if([self.session canAddOutput:self.imageOutput])[self.session addOutput:self.imageOutput];\n?????\n????\/\/ \u5a92\u4f53\u9884\u89c8\n????self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];\n????self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspect;\n????[self.preview.layer addSublayer:self.previewLayer];\n????[self setPreviewGesture];\n}\n?\n?\n#pragma mark - \u524d\u540e\u6444\u50cf\u5934\n- (NSArray *)devices\n{\n????return [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];\n}\n?\n- (void)viewWillAppear:(BOOL)animated\n{\n????[super viewWillAppear:animated];\n????self.deviceScale = 1.0;\n????self.previewLayer.frame = self.preview.layer.bounds;\n????self.navigationController.navigationBar.hidden = YES;\n????[self setDevice:self.deviceInput.device videoZoomFactor:self.deviceScale];\n????[self.session startRunning];\n}\n?\n- (void)viewDidAppear:(BOOL)animated\n{\n????[super viewDidAppear:animated];\n????[[UIApplication sharedApplication] setStatusBarHidden:YES];\n}\n?\n- (void)viewWillDisappear:(BOOL)animated\n{\n????[super viewWillDisappear:animated];\n????[[UIApplication sharedApplication] setStatusBarHidden:NO];\n}\n?\n- (void)viewDidDisappear:(BOOL)animated\n{\n????[super viewDidDisappear:animated];\n????[self.session stopRunning];\n}\n?\n\/\/\/ \u5a92\u4f53\u9884\u89c8\u56fe\u5c42\u624b\u52bf\u4e8b\u4ef6\n- (void)setPreviewGesture\n{\n????\/\/ \u6ce8\u518c\u4e00\u4e2a\u624b\u52bf\u4e8b\u4ef6\u6765\u5b9e\u73b0\u5bf9\u7126\u529f\u80fd\n????UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapPreview:)];\n????UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchPreview:)];\n????[self.preview addGestureRecognizer:tap];\n????if ([UIDevice currentDevice].systemVersion.floatValue >= 7.0) [self.preview addGestureRecognizer:pinch];\n}\n?\n\/\/\/ \u9884\u89c8\u56fe\u5c42\u70b9\u51fb\u4e8b\u4ef6\n- (void)tapPreview:(UITapGestureRecognizer *)gesture\n{\n????CGPoint point = [gesture locationInView:gesture.view];\n????CGPoint p = [self.previewLayer captureDevicePointOfInterestForPoint:point];\n????[self focusAtPoint:p];\n????\/\/ \u5bf9\u7126\u52a8\u753b\n????self.preview.aperture.center = point;\n????[self.preview showAperture];\n}\n?\n\/\/\/ \u7126\u8ddd\u8c03\u6574\u4e8b\u4ef6\n- (void)pinchPreview:(UIPinchGestureRecognizer *)gesture\n{\n????CGFloat scale = self.deviceScale + (gesture.scale - 1);\n????if (scale > 5) scale = 5;?? \/\/ \u6700\u59275\u500d\u7126\u8ddd\n????if (scale < 1) scale = 1;?? \/\/ \u6700\u5c0f1\u500d\u7126\u8ddd\n????[self setDevice:self.deviceInput.device videoZoomFactor:scale];\n????\/\/ \u7f29\u653e\u7ed3\u675f\u65f6\u8bb0\u5f55\u5f53\u524d\u500d\u7126\n????if (gesture.state == UIGestureRecognizerStateEnded) self.deviceScale = scale;\n}\n?\n\/\/\/ \u5bf9\u7126\u4e8b\u4ef6\n- (void)focusAtPoint:(CGPoint)point\n{\n????AVCaptureDevice *device = self.deviceInput.device;\n????NSError *error;\n????if ([device isFocusModeSupported:AVCaptureFocusModeAutoFocus] &#038;&#038; [device isFocusPointOfInterestSupported])\n????{\n????????if ([device lockForConfiguration:&#038;error]) {\n????????????[device setFocusPointOfInterest:point];???? \/\/ \u5bf9\u7126\u70b9\n????????????[device setExposurePointOfInterest:point];? \/\/ \u66dd\u5149\u70b9\n????????????[device setFocusMode:AVCaptureFocusModeAutoFocus];? \/\/ \u81ea\u52a8\u5bf9\u7126\u6a21\u5f0f\n????????????[device unlockForConfiguration];\n????????} else {\n????????????NSLog(@\"Error: %@\", error);\n????????}\n????}\n}\n?\n\/\/\/ \u6444\u50cf\u5934\u5207\u6362\u4e8b\u4ef6\n- (IBAction)switchCamera:(UIButton *)sender\n{\n????if (self.devices.count < 2) return;\n?????\n????NSInteger oldIndex = [self.devices indexOfObject:self.deviceInput.device];\n????NSInteger newIndex = (oldIndex + 1) % self.devices.count;\n????AVCaptureDevice *newDevice = [self.devices objectAtIndex:newIndex];\n????AVCaptureDeviceInput *newInput = [AVCaptureDeviceInput deviceInputWithDevice:newDevice error:NULL];\n????if (newInput) {\n????????[self.session beginConfiguration];\n????????[self.session removeInput:self.deviceInput];\n????????[self.session addInput:newInput];\n????????[self.session commitConfiguration];\n????????self.deviceInput = newInput;\n????????self.flashButton.hidden = !newDevice.isFlashAvailable;\n????}\n}\n?\n\/\/\/ \u53d6\u6d88\u4e8b\u4ef6\n- (IBAction)cancel:(UIButton *)sender\n{\n????[self dismissViewControllerAnimated:YES completion:nil];\n}\n?\n\/\/\/ \u62cd\u7167\u4e8b\u4ef6\n- (IBAction)shutter:(UIButton *)sender\n{\n????sender.userInteractionEnabled = NO;\n????AVCaptureConnection * connection = [self.imageOutput connectionWithMediaType:AVMediaTypeVideo];\n????connection.videoOrientation = AVCaptureVideoOrientationPortrait;\n????connection.videoScaleAndCropFactor = 1.0;?? \/\/ \u83b7\u53d6\u6d41\u6bd4\u4f8b\n????if (!connection) {\n????????NSLog(@\"take photo failed!\");\n????????return;\n????}\n?????\n????[self.imageOutput captureStillImageAsynchronouslyFromConnection:connection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {\n????????if (imageDataSampleBuffer == NULL) {\n????????????return;\n????????}\n????????NSData * imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];\n????????UIImage * image = [UIImage imageWithData:imageData];\n????????SAPhotoViewCtrl *photoView = [[SAPhotoViewCtrl alloc] initWithImage:image];\n????????[self.navigationController pushViewController:photoView animated:NO];\n????????sender.userInteractionEnabled = YES;\n????}];\n}\n?\n\/\/\/ \u8c03\u6574\u6444\u50cf\u5934\u7126\u8ddd\n- (void)setDevice:(AVCaptureDevice *)device videoZoomFactor:(CGFloat)scale\n{\n????[device lockForConfiguration:nil];\n????device.videoZoomFactor = scale;\n????[device unlockForConfiguration];\n}\n?\n\/\/\/ \u95ea\u5149\u706f\u5f00\u5173\u6309\u94ae\n- (IBAction)overTurn:(UIButton *)sender\n{\n????sender.tag = (sender.tag + 1) % 3;\n????NSString *imageName = [NSString stringWithFormat:@\"camera_flashlight_%d.png\", (int)sender.tag];\n????[sender setBackgroundImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];\n????[self setDevice:self.deviceInput.device FlashMode:(2 - sender.tag)];\n}\n?\n\/\/\/ \u5207\u6362\u95ea\u5149\u706f\u6a21\u5f0f\n- (void)setDevice:(AVCaptureDevice *)device FlashMode:(AVCaptureFlashMode)flashModel\n{\n????if (device.isFlashAvailable == NO) return;\n????if ([device lockForConfiguration:nil]) {\n????????device.flashMode = flashModel;\n????}\n????[device unlockForConfiguration];\n}\n?\n@end<\/pre>\n<p>5\u3001Demo\u4e0b\u8f7d <a href=\"http:\/\/www.yusian.com\/blog\/wp-content\/uploads\/2016\/07\/SAAVFoundation.zip\">SAAVFoundation<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>1\u3001\u5982\u4f55\u4f7f\u7528AVFoundation\u6846\u67b6\u81ea\u5b9a\u4e49\u76f8\u673a\u8bf7\u5148\u53c2\u7167iOS\u9879\u76ee\u5b9e\u6218\u4e4b\u81ea\u5b9a\u4e49\u76f8\u673a 2.1\u3001\u4e0a\u8ff0\u5e16\u5b50\u4e2d\u6709\u8bb2\u5230\uff0c\u5982\u679c\u9700\u8981\u5bf9\u7126\uff0c\u53ef\u4ee5\u901a\u8fc7AVCaptureDevice\u7684setFocusPointOfInterest:\u65b9\u6cd5\u6765\u5b9e\u73b0\uff0c\u4f20\u5165\u4e00\u4e2aCGPoint\u503c\uff0c\u4f46\u8fd9\u91cc\u7684CGPoint\u4e0d\u662fView\u4e0a\u9762\u7684\u70b9\uff0c\u800c\u662f\u8303\u56f4\u76840~1\u7684\u76f8\u5bf9\u767e\u5206\u70b9\uff1b 2.2\u3001\u8fd9\u4e2aCGPoint\u5982\u4f55\u5f97\u6765\u5462\uff0c\u6211\u4eec\u5728\u70b9\u51fb\u5c4f\u5e55\u65f6\u53ef\u4ee5\u76d1\u542c\u76f8\u5173View\u7684\u70b9\u51fb\u4e8b\u4ef6\uff0c\u6dfb\u52a0\u4e00\u4e2aUITapGestureRecognizer\u624b\u52bf\uff0c\u5728\u70b9\u65f6\u540e\uff0c\u53ef\u4ee5\u901a\u8fc7UITapGestureRecognizer\u7684locationInView:\u65b9\u6cd5\u5f97\u5230CGPoint\uff0c\u8fd9\u662f\u4e00\u4e2a\u7edd\u5bf9\u503c\uff0c\u5373\u70b9\u51fb\u4e86\u76f8\u5173View\u4e0a\u7684\u67d0\u4e2a\u70b9\uff0c\u6709\u4e86\u8fd9\u4e2a\u70b9\uff0c\u518d\u901a\u8fc7AVCaptureVideoPreviewLayer\u7684\u4e00\u4e2a\u8f6c\u6362\u65b9\u6cd5\uff1acaptureDevicePointOfInterestForPoint:\u53ef\u4ee5\u5c06\u7edd\u5bf9\u70b9\u8f6c\u6362\u6210\u76f8\u5bf9\u70b9\u3002<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[17],"class_list":["post-240","post","type-post","status-publish","format-standard","hentry","category-project","tag-skill"],"_links":{"self":[{"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/posts\/240","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/comments?post=240"}],"version-history":[{"count":0,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/posts\/240\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/media?parent=240"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/categories?post=240"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.yusian.com\/blog\/wp-json\/wp\/v2\/tags?post=240"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}