├── .DS_Store ├── heart ├── .DS_Store └── abc.png ├── 摄像心率.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcuserdata │ └── xiekang.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── 摄像心率.xcscheme └── project.pbxproj ├── 摄像心率 ├── ViewController.h ├── AppDelegate.h ├── main.m ├── HeartLive.h ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── HeartBeat.h ├── Base.lproj │ ├── Main.storyboard │ └── LaunchScreen.storyboard ├── AppDelegate.m ├── HeartLive.m ├── ViewController.m └── HeartBeat.m ├── 摄像心率Tests ├── Info.plist └── ____Tests.m ├── 摄像心率UITests ├── Info.plist └── ____UITests.m └── README.md /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeenTeam1990/HeartBeat/HEAD/.DS_Store -------------------------------------------------------------------------------- /heart/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeenTeam1990/HeartBeat/HEAD/heart/.DS_Store -------------------------------------------------------------------------------- /heart/abc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KeenTeam1990/HeartBeat/HEAD/heart/abc.png -------------------------------------------------------------------------------- /摄像心率.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /摄像心率/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // 摄像心率 4 | // 5 | // Created by xiekang on 17/3/23. 6 | // Copyright © 2017年 ZM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /摄像心率/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // 摄像心率 4 | // 5 | // Created by xiekang on 17/3/23. 6 | // Copyright © 2017年 ZM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /摄像心率/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // 摄像心率 4 | // 5 | // Created by xiekang on 17/3/23. 6 | // Copyright © 2017年 ZM. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /摄像心率/HeartLive.h: -------------------------------------------------------------------------------- 1 | // 2 | // HeartLive.h 3 | // HeartBeatsPlugin 4 | // 5 | // Created by A053 on 16/9/9. 6 | // Copyright © 2016年 Yvan. All rights reserved. 7 | // 8 | /* 9 | 10 | //创建了一个心电图的View 11 | self.live = [[HeartLive alloc]initWithFrame:CGRectMake(10, 100, self.view.frame.size.width-20, 150)]; 12 | [self.view addSubview:self.live]; 13 | 14 | - (void)startHeartDelegateRatePoint:(NSDictionary *)point { 15 | NSNumber *n = [[point allValues] firstObject]; 16 | //拿到的数据传给心电图View 17 | [self.live drawRateWithPoint:n]; 18 | } 19 | */ 20 | 21 | #import 22 | @class HeartBeat; 23 | @interface HeartLive : UIView 24 | 25 | @property(assign,nonatomic) NSInteger h; 26 | 27 | 28 | - (void)drawRateWithPoint:(NSNumber *)point; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /摄像心率Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /摄像心率UITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /摄像心率/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /摄像心率.xcodeproj/xcuserdata/xiekang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | 摄像心率.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 9836551D1E83BED000723316 16 | 17 | primary 18 | 19 | 20 | 983655361E83BED000723316 21 | 22 | primary 23 | 24 | 25 | 983655411E83BED000723316 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /摄像心率Tests/____Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ____Tests.m 3 | // 摄像心率Tests 4 | // 5 | // Created by xiekang on 17/3/23. 6 | // Copyright © 2017年 ZM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ____Tests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ____Tests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HeartBeat 2 | 手机检测心率血压 3 | //创建了一个心电图的View 4 | self.live = [[HeartLive alloc]initWithFrame:CGRectMake(10, 100, self.view.frame.size.width-20, 150)]; 5 | [self.view addSubview:self.live]; 6 | 7 | - (void)startHeartDelegateRatePoint:(NSDictionary *)point { 8 | NSNumber *n = [[point allValues] firstObject]; 9 | //拿到的数据传给心电图View 10 | [self.live drawRateWithPoint:n]; 11 | } 12 | */ 13 | 14 | ![项目结构图](https://github.com/KeenTeam1990/HeartBeat/blob/master/heart/abc.png) 15 | 16 | #pragma mark - 测心率回调 17 | 18 | - (void)startHeartDelegateRatePoint:(NSDictionary *)point { 19 | NSNumber *n = [[point allValues] firstObject]; 20 | //拿到的数据传给心电图View 21 | [self.live drawRateWithPoint:n]; 22 | //NSLog(@"%@",point); 23 | } 24 | 25 | - (void)startHeartDelegateRateError:(NSError *)error { 26 | NSLog(@"%@",error); 27 | } 28 | 29 | - (void)startHeartDelegateRateFrequency:(NSInteger)frequency { 30 | NSLog(@"\n瞬时心率:%ld",frequency); 31 | dispatch_async(dispatch_get_main_queue(), ^{ 32 | self.label.text = [NSString stringWithFormat:@"%ld次/分",(long)frequency]; 33 | }); 34 | } 35 | 36 | 37 | -------------------------------------------------------------------------------- /摄像心率UITests/____UITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ____UITests.m 3 | // 摄像心率UITests 4 | // 5 | // Created by xiekang on 17/3/23. 6 | // Copyright © 2017年 ZM. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ____UITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ____UITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /摄像心率/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSCameraUsageDescription 6 | 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /摄像心率/HeartBeat.h: -------------------------------------------------------------------------------- 1 | // 2 | // HeartBeat.h 3 | // 摄像心率 4 | // 5 | // Created by xiekang on 17/3/24. 6 | // Copyright © 2017年 ZM. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | typedef enum{ 13 | heartBeatTypeHeartRate = 100, 14 | 15 | heartBeatTypeOxygen = 101, 16 | 17 | heartBeatTypeBloodPressure, 18 | 19 | heartBeatTypelungCapcity 20 | 21 | 22 | }heartBeatType; 23 | 24 | 25 | static float lastH = 0; 26 | 27 | 28 | static int count = 0; 29 | @protocol HeartBeatPluginDelegate 30 | 31 | - (void)startHeartDelegateRatePoint:(NSDictionary *)point heartType:(heartBeatType)type; 32 | @optional 33 | - (void)startHeartDelegateRateError:(NSError *)error; 34 | - (void)startHeartDelegateRateFrequency:(NSInteger)frequency; 35 | @end 36 | 37 | 38 | 39 | @interface HeartBeat : NSObject 40 | 41 | 42 | @property (assign,nonatomic) heartBeatType type; 43 | 44 | @property(copy,nonatomic) void (^backPoint)(NSDictionary *); 45 | 46 | @property(copy,nonatomic) void (^frendency)(NSInteger); 47 | 48 | @property(copy,nonatomic) void (^Error)(NSError *); 49 | 50 | @property (strong,nonatomic) AVCaptureDevice *device; 51 | 52 | @property (strong,nonatomic) AVCaptureSession *session; 53 | 54 | @property (strong,nonatomic) AVCaptureInput *input; 55 | 56 | @property (assign, nonatomic) id delegate; 57 | 58 | 59 | @property (strong,nonatomic) AVCaptureVideoDataOutput *output; 60 | 61 | 62 | @property (strong,nonatomic) NSMutableArray *points; 63 | 64 | + (instancetype)shareManager; 65 | 66 | -(void)start; 67 | 68 | 69 | -(void)stop; 70 | @end 71 | -------------------------------------------------------------------------------- /摄像心率/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /摄像心率/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /摄像心率/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // 摄像心率 4 | // 5 | // Created by xiekang on 17/3/23. 6 | // Copyright © 2017年 ZM. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /摄像心率/HeartLive.m: -------------------------------------------------------------------------------- 1 | // 2 | // HeartLive.m 3 | // HeartBeatsPlugin 4 | // 5 | // Created by A053 on 16/9/9. 6 | // Copyright © 2016年 Yvan. All rights reserved. 7 | // 8 | 9 | #import "HeartLive.h" 10 | 11 | @interface HeartLive () 12 | @property (strong, nonatomic) NSMutableArray *points; 13 | 14 | //@property (assign,nonatomic) heartBeatType type; 15 | @end 16 | 17 | static CGFloat grid_w = 30.0f; 18 | 19 | @implementation HeartLive 20 | 21 | 22 | - (void)drawRateWithPoint:(NSNumber *)point { 23 | // self.type = type; 24 | // 倒叙插入数组 25 | [self.points insertObject:point atIndex:0]; 26 | 27 | // 删除溢出屏幕数据 28 | if (self.points.count > self.frame.size.width/6) { 29 | [self.points removeLastObject]; 30 | } 31 | 32 | dispatch_async(dispatch_get_main_queue(), ^{ 33 | // 这个方法自动调取 drawRect:方法 34 | [self setNeedsDisplay]; 35 | }); 36 | } 37 | 38 | - (void)drawRate { 39 | 40 | CGFloat ww = self.frame.size.width; 41 | CGFloat hh = self.frame.size.height; 42 | CGFloat pos_x = ww; 43 | // CGFloat pos_y = hh/2; 44 | 45 | CGFloat pos_y = 0; 46 | // 获取当前画布 47 | CGContextRef context = UIGraphicsGetCurrentContext(); 48 | // 折线宽度 49 | CGContextSetLineWidth(context, 1.0); 50 | //消除锯齿 51 | //CGContextSetAllowsAntialiasing(context,false); 52 | // 折线颜色 53 | CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor); 54 | CGContextMoveToPoint(context, pos_x, pos_y); 55 | for (int i = 0; i < self.points.count; i++) { 56 | float h = [self.points[i] floatValue]; 57 | // pos_y = hh/2 + (h * hh/2) ; 58 | 59 | pos_y = 0 + ((h-0.8) * hh/2) ; 60 | CGContextAddLineToPoint(context, pos_x, pos_y); 61 | pos_x -=6; 62 | } 63 | CGContextStrokePath(context); 64 | } 65 | 66 | 67 | 68 | 69 | - (instancetype)initWithFrame:(CGRect)frame { 70 | if (self = [super initWithFrame: frame]) { 71 | self.backgroundColor = [UIColor orangeColor]; 72 | self.points = [[NSMutableArray alloc]init]; 73 | self.clearsContextBeforeDrawing = YES; 74 | } 75 | return self; 76 | } 77 | 78 | - (void)drawRect:(CGRect)rect { 79 | [self drawRate]; 80 | 81 | } 82 | 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /摄像心率/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // 摄像心率 4 | // 5 | // Created by xiekang on 17/3/23. 6 | // Copyright © 2017年 ZM. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "HeartBeat.h" 11 | #import "HeartLive.h" 12 | #import 13 | @interface ViewController () 14 | 15 | @property (strong, nonatomic) HeartLive *live; 16 | @property (strong, nonatomic) UILabel *label; 17 | 18 | @property (strong,nonatomic) NSTimer *timer; 19 | @end 20 | static int counts = 0; 21 | @implementation ViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | _timer = [NSTimer scheduledTimerWithTimeInterval:30 target:self selector:@selector(reapTime) userInfo:nil repeats:YES]; 26 | 27 | 28 | 29 | // for (int i = 0; i<3; i++) { 30 | //创建了一个心电图的View 31 | self.live = [[HeartLive alloc]initWithFrame:CGRectMake(10, 100, self.view.frame.size.width-20, 150)]; 32 | [self.view addSubview:self.live]; 33 | 34 | self.label = [[UILabel alloc]initWithFrame:CGRectMake(0, 300, self.view.frame.size.width, 30)]; 35 | self.label.layer.borderColor = [UIColor blackColor].CGColor; 36 | self.label.layer.borderWidth = 1; 37 | self.label.textColor = [UIColor blackColor]; 38 | self.label.font = [UIFont systemFontOfSize:28]; 39 | self.label.textAlignment = NSTextAlignmentCenter; 40 | [self.view addSubview:self.label]; 41 | 42 | //开启测心率方法 43 | [HeartBeat shareManager].delegate = self; 44 | [HeartBeat shareManager].type = heartBeatTypeOxygen; 45 | [[HeartBeat shareManager] start]; 46 | 47 | 48 | [[HeartBeat shareManager] stop]; 49 | 50 | //} 51 | 52 | 53 | } 54 | 55 | -(void)reapTime 56 | { 57 | 58 | counts++; 59 | 60 | 61 | 62 | } 63 | 64 | 65 | #pragma mark - 测心率回调 66 | 67 | - (void)startHeartDelegateRatePoint:(NSDictionary *)point heartType:(heartBeatType)type;{ 68 | NSNumber *n = [[point allValues] firstObject]; 69 | //拿到的数据传给心电图View 70 | [self.live drawRateWithPoint:n]; 71 | //NSLog(@"%@",point); 72 | } 73 | 74 | - (void)startHeartDelegateRateError:(NSError *)error { 75 | NSLog(@"%@",error); 76 | } 77 | 78 | - (void)startHeartDelegateRateFrequency:(NSInteger)frequency { 79 | NSLog(@"\n瞬时心率:%ld",frequency); 80 | dispatch_async(dispatch_get_main_queue(), ^{ 81 | self.label.text = [NSString stringWithFormat:@"%ld",(long)frequency]; 82 | }); 83 | } 84 | 85 | 86 | - (void)didReceiveMemoryWarning { 87 | [super didReceiveMemoryWarning]; 88 | // Dispose of any resources that can be recreated. 89 | } 90 | 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /摄像心率.xcodeproj/xcuserdata/xiekang.xcuserdatad/xcschemes/摄像心率.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /摄像心率/HeartBeat.m: -------------------------------------------------------------------------------- 1 | // 2 | // HeartBeat.m 3 | // 摄像心率 4 | // 5 | // Created by xiekang on 17/3/24. 6 | // Copyright © 2017年 ZM. All rights reserved. 7 | // 8 | 9 | #import "HeartBeat.h" 10 | static HeartBeat *plugin = nil; 11 | 12 | // 周期 13 | static float T = 10; 14 | 15 | 16 | 17 | @implementation HeartBeat 18 | 19 | - (instancetype)init { 20 | 21 | if (self = [super init]) { 22 | // 初始化 23 | self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 24 | self.session = [[AVCaptureSession alloc]init]; 25 | self.input = [[AVCaptureDeviceInput alloc]initWithDevice:self.device error:nil]; 26 | self.output = [[AVCaptureVideoDataOutput alloc]init]; 27 | self.points = [[NSMutableArray alloc]init]; 28 | } 29 | return self; 30 | } 31 | 32 | + (instancetype)shareManager { 33 | static dispatch_once_t onceToken; 34 | dispatch_once(&onceToken, ^{ 35 | plugin = [[self alloc]init]; 36 | }); 37 | return plugin; 38 | } 39 | 40 | - (void)startHeartRatePoint:(void(^)(NSDictionary *point))backPoint 41 | Frequency:(void(^)(NSInteger fre))frequency 42 | Error:(void(^)(NSError *error))error { 43 | self.backPoint = backPoint; 44 | self.frendency 45 | = frequency; 46 | self.Error = error; 47 | [self start]; 48 | } 49 | 50 | #pragma mark - 开始 51 | 52 | - (void)start { 53 | [self createDevice]; 54 | [self.session startRunning]; 55 | } 56 | 57 | #pragma mark - 结束 58 | 59 | - (void)stop { 60 | count = 0; 61 | lastH = 0; 62 | 63 | [self.points removeAllObjects]; 64 | [self.session stopRunning]; 65 | } 66 | -(void)createDevice 67 | { 68 | 69 | // self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 70 | NSString *media = AVMediaTypeVideo; 71 | 72 | AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:media]; 73 | 74 | if (authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) { 75 | NSString *error = @"相机不可用"; 76 | 77 | NSError *err = [NSError errorWithDomain:error code:100 userInfo:@{@"content":@""}]; 78 | 79 | 80 | 81 | 82 | 83 | if (self.backPoint) 84 | self.Error(err); 85 | if ([self.delegate respondsToSelector:@selector(startHeartDelegateRateError:)]) 86 | [self.delegate startHeartDelegateRateError:err]; 87 | 88 | return; 89 | } 90 | 91 | // 开启闪光灯 92 | if ([self.device isTorchModeSupported:AVCaptureTorchModeOn]) { 93 | [self.device lockForConfiguration:nil]; 94 | // 开启闪光灯 95 | self.device.torchMode=AVCaptureTorchModeOn; 96 | // 调低闪光灯亮度 97 | [self.device setTorchModeOnWithLevel:0.01 error:nil]; 98 | [self.device unlockForConfiguration]; 99 | } 100 | [self.session beginConfiguration]; 101 | 102 | // 设置像素输出格式 103 | NSNumber *BGRA32Format = [NSNumber numberWithInt:kCVPixelFormatType_32BGRA]; 104 | NSDictionary *setting =@{(id)kCVPixelBufferPixelFormatTypeKey:BGRA32Format}; 105 | [self.output setVideoSettings:setting]; 106 | // 抛弃延迟的帧 107 | [self.output setAlwaysDiscardsLateVideoFrames:YES]; 108 | //开启摄像头采集图像输出的子线程 109 | dispatch_queue_t outputQueue = dispatch_queue_create("VideoDataOutputQueue", DISPATCH_QUEUE_SERIAL); 110 | // 设置子线程执行代理方法 111 | [self.output setSampleBufferDelegate:self queue:outputQueue]; 112 | 113 | // 向session添加 114 | if ([self.session canAddInput:self.input]) [self.session addInput:self.input]; 115 | if ([self.session canAddOutput:self.output]) [self.session addOutput:self.output]; 116 | 117 | // 降低分辨率,减少采样率 118 | self.session.sessionPreset = AVCaptureSessionPreset640x480; 119 | // 设置最小的视频帧输出间隔 120 | self.device.activeVideoMinFrameDuration = CMTimeMake(1, 10); 121 | 122 | // 用当前的output 初始化connection 123 | AVCaptureConnection *connection =[self.output connectionWithMediaType:AVMediaTypeVideo]; 124 | [connection setVideoOrientation:AVCaptureVideoOrientationPortrait]; 125 | 126 | // 完成编辑 127 | [self.session commitConfiguration]; 128 | 129 | } 130 | 131 | - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection; 132 | { 133 | 134 | //获取图层缓冲 135 | CVPixelBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 136 | CVPixelBufferLockBaseAddress(imageBuffer, 0); 137 | uint8_t*buf = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer); 138 | size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 139 | size_t width = CVPixelBufferGetWidth(imageBuffer); 140 | size_t height = CVPixelBufferGetHeight(imageBuffer); 141 | 142 | float r = 0, g = 0,b = 0; 143 | float h,s,v; 144 | // 计算RGB 145 | TORGB(buf, width, height, bytesPerRow, &r, &g, &b); 146 | // RGB转HSV 147 | RGBtoHSV(r, g, b, &h, &s, &v); 148 | float p = 0; 149 | // 获取当前时间戳(精确到毫秒) 150 | double t = [[NSDate date] timeIntervalSince1970]*1000; 151 | // 返回处理后的浮点值 152 | 153 | 154 | if (_type == heartBeatTypeHeartRate) { 155 | p = HeartRate(h); 156 | } 157 | else if (_type == heartBeatTypeOxygen){ 158 | 159 | /*血氧*/ 160 | p = r; 161 | 162 | 163 | } 164 | else if (_type == heartBeatTypeBloodPressure){ 165 | 166 | 167 | 168 | } 169 | 170 | else { 171 | 172 | 173 | 174 | } 175 | 176 | 177 | 178 | 179 | // 绑定浮点和时间戳 180 | NSDictionary *point = @{[NSNumber numberWithDouble:t]:[NSNumber numberWithFloat:p]}; 181 | 182 | NSLog(@"RGB:---%f-%f-%f-%f---%f---%f-%f",r,g,b,h,s,v,p); 183 | 184 | // 范围之外 185 | if (p >= 1.0f || p<= -1.0f) { 186 | 187 | NSString *errStr = @"请将手指覆盖住后置摄像头和闪光灯"; 188 | NSError *err = [NSError errorWithDomain: errStr code:101 userInfo:@{@"content":errStr}]; 189 | if (self.Error) 190 | self.Error(err); 191 | if ([self.delegate respondsToSelector:@selector(startHeartDelegateRateError:)]) 192 | [self.delegate startHeartDelegateRateError:err]; 193 | 194 | // 清除数据 195 | count = 0; 196 | lastH = 0; 197 | [self.points removeAllObjects]; 198 | 199 | } else { 200 | 201 | // Block回调方法 202 | if (self.backPoint) 203 | self.backPoint(point); 204 | // 代理回调方法 205 | if ([self.delegate respondsToSelector:@selector(startHeartDelegateRatePoint: heartType:)]) 206 | 207 | { 208 | [self.delegate startHeartDelegateRatePoint:point heartType:_type]; 209 | } 210 | 211 | // 分析波峰波谷 212 | [self analysisPointsWith:point]; 213 | } 214 | 215 | 216 | 217 | 218 | } 219 | 220 | 221 | - (void)analysisPointsWith:(NSDictionary *)point { 222 | 223 | [self.points addObject:point]; 224 | if (self.points.count<=30) return; 225 | int count = (int)self.points.count; 226 | 227 | if (self.points.count%10 == 0) { 228 | 229 | int d_i_c = 0; //最低峰值的位置 姑且算在中间位置 c->center 230 | int d_i_l = 0; //最低峰值左面的最低峰值位置 l->left 231 | int d_i_r = 0; //最低峰值右面的最低峰值位置 r->right 232 | 233 | 234 | float trough_c = 0; //最低峰值的浮点值 235 | float trough_l = 0; //最低峰值左面的最低峰值浮点值 236 | float trough_r = 0; //最低峰值右面的最低峰值浮点值 237 | 238 | // 1.先确定数据中的最低峰值 239 | for (int i = 0; i < count; i++) { 240 | float trough = [[[self.points[i] allObjects] firstObject] floatValue]; 241 | if (trough < trough_c) { 242 | trough_c = trough; 243 | d_i_c = i; 244 | } 245 | } 246 | // 2.找到最低峰值以后 以最低峰值为中心 找到前0.5-1.5周期中的最低峰值 和后0.5-1.5周期的最低峰值 247 | if (d_i_c >= 1.5*T) { 248 | 249 | // a.如果最低峰值处在中心位置, 即距离前后都至 少有1.5个周期 250 | if (d_i_c <= count-1.5*T) { 251 | // 左面最低峰值 252 | for (int j = d_i_c - 0.5*T; j > d_i_c - 1.5*T; j--) { 253 | float trough = [[[self.points[j] allObjects] firstObject] floatValue]; 254 | if ((trough < trough_l)&&(d_i_c-j)<=T) { 255 | trough_l = trough; 256 | d_i_l = j; 257 | } 258 | } 259 | // 右面最低峰值 260 | for (int k = d_i_c + 0.5*T; k < d_i_c + 1.5*T; k++) { 261 | float trough = [[[self.points[k] allObjects] firstObject] floatValue]; 262 | if ((trough < trough_r)&&(k-d_i_c<=T)) { 263 | trough_r = trough; 264 | d_i_r = k; 265 | } 266 | } 267 | 268 | } 269 | // b.如果最低峰值右面不够1.5个周期 分两种情况 不够0.5个周期和够0.5个周期 270 | else { 271 | // b.1 够0.5个周期 272 | if (d_i_c d_i_c - 1.5*T; j--) { 275 | float trough = [[[self.points[j] allObjects] firstObject] floatValue]; 276 | if ((trough < trough_l)&&(d_i_c-j)<=T) { 277 | trough_l = trough; 278 | d_i_l = j; 279 | } 280 | } 281 | // 右面最低峰值 282 | for (int k = d_i_c + 0.5*T; k < count; k++) { 283 | float trough = [[[self.points[k] allObjects] firstObject] floatValue]; 284 | if ((trough < trough_r)&&(k-d_i_c<=T)) { 285 | trough_r = trough; 286 | d_i_r = k; 287 | } 288 | } 289 | } 290 | // b.2 不够0.5个周期 291 | else { 292 | // 左面最低峰值 293 | for (int j = d_i_c - 0.5*T; j > d_i_c - 1.5*T; j--) { 294 | float trough = [[[self.points[j] allObjects] firstObject] floatValue]; 295 | if ((trough < trough_l)&&(d_i_c-j)<=T) { 296 | trough_l = trough; 297 | d_i_l = j; 298 | } 299 | } 300 | } 301 | } 302 | 303 | } 304 | // c. 如果左面不够1.5个周期 一样分两种情况 够0.5个周期 不够0.5个周期 305 | else { 306 | // c.1 够0.5个周期 307 | if (d_i_c>0.5*T) { 308 | // 左面最低峰值 309 | for (int j = d_i_c - 0.5*T; j > 0; j--) { 310 | float trough = [[[self.points[j] allObjects] firstObject] floatValue]; 311 | if ((trough < trough_l)&&(d_i_c-j)<=T) { 312 | trough_l = trough; 313 | d_i_l = j; 314 | } 315 | } 316 | // 右面最低峰值 317 | for (int k = d_i_c + 0.5*T; k < d_i_c + 1.5*T; k++) { 318 | float trough = [[[self.points[k] allObjects] firstObject] floatValue]; 319 | if ((trough < trough_r)&&(k-d_i_c<=T)) { 320 | trough_r = trough; 321 | d_i_r = k; 322 | } 323 | } 324 | 325 | } 326 | // c.2 不够0.5个周期 327 | else { 328 | // 右面最低峰值 329 | for (int k = d_i_c + 0.5*T; k < d_i_c + 1.5*T; k++) { 330 | float trough = [[[self.points[k] allObjects] firstObject] floatValue]; 331 | if ((trough < trough_r)&&(k-d_i_c<=T)) { 332 | trough_r = trough; 333 | d_i_r = k; 334 | } 335 | } 336 | } 337 | 338 | } 339 | /* 340 | 2路信号合相加 vs sum = 红光累加 开平方 平方和 341 | ir sum 红外光 累加 342 | 343 | 110-25*R R为平均功率 344 | 345 | */ 346 | // 3. 确定哪一个与最低峰值更接近 用最接近的一个最低峰值测出瞬时心率 60*1000两个峰值的时间差------心率 发现色相H随脉搏的变化很明显 347 | if (trough_l-trough_c < trough_r-trough_c) { 348 | 349 | NSDictionary *point_c = self.points[d_i_c]; 350 | NSDictionary *point_l = self.points[d_i_l]; 351 | double t_c =0; 352 | 353 | double t_l = 0; 354 | 355 | NSInteger fre = 0; 356 | 357 | if (_type == heartBeatTypeHeartRate) { 358 | t_c = [[[point_c allKeys] firstObject] doubleValue];// 平方和开方---- 359 | t_l = [[[point_l allKeys] firstObject] doubleValue]; 360 | fre = (NSInteger)(60*1000)/(t_c - t_l);//由脉搏周期换成脉率 60000/sample_count 采样计数 361 | 362 | } 363 | else if (_type == heartBeatTypeOxygen){ 364 | 365 | t_c = [[[point_c allValues] firstObject] doubleValue];// 平方和开方---- 366 | t_l = [[[point_l allValues] firstObject] doubleValue]; 367 | fre = (NSInteger)100*t_c;//(110-(25*t_c));//由脉搏周 368 | 369 | 370 | } 371 | else if (_type == heartBeatTypeBloodPressure){ 372 | 373 | 374 | 375 | } 376 | 377 | else { 378 | 379 | 380 | 381 | } 382 | 383 | 384 | 385 | NSLog(@"t_c--%f--------%ld",t_c,(long)fre); 386 | NSLog(@"t_c--%f-----%f---%ld",t_c,100*t_c,(long)fre); 387 | 388 | 389 | if (self.frendency) 390 | self.frendency(fre); 391 | if ([self.delegate respondsToSelector:@selector(startHeartDelegateRateFrequency:)]) 392 | [self.delegate startHeartDelegateRateFrequency:fre]; 393 | } else { 394 | NSDictionary *point_c = self.points[d_i_c]; 395 | NSDictionary *point_r = self.points[d_i_r]; 396 | 397 | double t_c =0; 398 | 399 | double t_r = 0; 400 | 401 | NSInteger fre = 0; 402 | 403 | 404 | if (_type == heartBeatTypeHeartRate) { 405 | 406 | double t_c = [[[point_c allKeys] firstObject] doubleValue]; 407 | double t_r = [[[point_r allKeys] firstObject] doubleValue]; 408 | fre = (NSInteger)(60*1000)/(t_r - t_c); // 脉率的计算 409 | 410 | } 411 | else if (_type == heartBeatTypeOxygen){ 412 | 413 | t_c = [[[point_c allValues] firstObject] doubleValue]; 414 | t_r = [[[point_r allValues] firstObject] doubleValue]; 415 | fre = (NSInteger)100*t_c;//(110-(25*t_c)); // 脉率的计算 100 416 | 417 | } 418 | else if (_type == heartBeatTypeBloodPressure){ 419 | 420 | 421 | 422 | } 423 | 424 | else { 425 | 426 | 427 | 428 | } 429 | 430 | 431 | 432 | 433 | NSLog(@"t_c--%f-----%f---%ld",t_c,100*t_c,(long)fre);//t_c--1490580177917.419922--------85 434 | 435 | if (self.frendency) 436 | self.frendency(fre); 437 | if ([self.delegate respondsToSelector:@selector(startHeartDelegateRateFrequency:)]) 438 | [self.delegate startHeartDelegateRateFrequency:fre]; 439 | } 440 | // 4.删除过期数据 441 | for (int i = 0; i< 10; i++) { 442 | [self.points removeObjectAtIndex:0]; 443 | } 444 | } 445 | } 446 | #pragma mark - 根据h返回 浮点 447 | 448 | float HeartRate (float h) { 449 | float low = 0; 450 | count++; 451 | lastH = (count==1)?h:lastH; 452 | low = (h-lastH); 453 | lastH = h; 454 | return low; 455 | } 456 | 457 | #pragma mark - 计算RGB 458 | 459 | void TORGB (uint8_t *buf, float ww, float hh, size_t pr, float *r, float *g, float *b) { 460 | 461 | float wh = (float)(ww * hh ); 462 | for(int y = 0; y < hh; y++) { 463 | for(int x = 0; x < ww * 4; x += 4) { 464 | *b += buf[x]; 465 | *g += buf[x+1]; 466 | *r += buf[x+2]; 467 | } 468 | buf += pr; 469 | } 470 | *r /= 255 * wh; 471 | *g /= 255 * wh; 472 | *b /= 255 * wh; 473 | } 474 | 475 | 476 | #pragma mark --- 获取颜色变化的算法 477 | 478 | void RGBtoHSV( float r, float g, float b, float *h, float *s, float *v ) { 479 | float min, max, delta; 480 | min = MIN( r, MIN(g, b )); 481 | max = MAX( r, MAX(g, b )); 482 | *v = max; 483 | delta = max - min; 484 | if( max != 0 ) 485 | *s = delta / max; 486 | else { 487 | *s = 0; 488 | *h = -1; 489 | return; 490 | } 491 | if( r == max ) 492 | *h = ( g - b ) / delta; 493 | else if( g == max ) 494 | *h = 2 + (b - r) / delta; 495 | else 496 | *h = 4 + (r - g) / delta; 497 | *h *= 60; 498 | if( *h < 0 ) 499 | *h += 360; 500 | } 501 | @end 502 | -------------------------------------------------------------------------------- /摄像心率.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 983655231E83BED000723316 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 983655221E83BED000723316 /* main.m */; }; 11 | 983655261E83BED000723316 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 983655251E83BED000723316 /* AppDelegate.m */; }; 12 | 983655291E83BED000723316 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 983655281E83BED000723316 /* ViewController.m */; }; 13 | 9836552C1E83BED000723316 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9836552A1E83BED000723316 /* Main.storyboard */; }; 14 | 9836552E1E83BED000723316 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9836552D1E83BED000723316 /* Assets.xcassets */; }; 15 | 983655311E83BED000723316 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9836552F1E83BED000723316 /* LaunchScreen.storyboard */; }; 16 | 9836553C1E83BED000723316 /* ____Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9836553B1E83BED000723316 /* ____Tests.m */; }; 17 | 983655471E83BED000723316 /* ____UITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 983655461E83BED000723316 /* ____UITests.m */; }; 18 | 987850451E851EE70027D085 /* HeartBeat.m in Sources */ = {isa = PBXBuildFile; fileRef = 987850441E851EE70027D085 /* HeartBeat.m */; }; 19 | 9878C7D71E88EF3200E3A6DC /* HeartLive.m in Sources */ = {isa = PBXBuildFile; fileRef = 9878C7D61E88EF3200E3A6DC /* HeartLive.m */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 983655381E83BED000723316 /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 983655161E83BECF00723316 /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = 9836551D1E83BED000723316; 28 | remoteInfo = "摄像心率"; 29 | }; 30 | 983655431E83BED000723316 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 983655161E83BECF00723316 /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 9836551D1E83BED000723316; 35 | remoteInfo = "摄像心率"; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 9836551E1E83BED000723316 /* 摄像心率.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "摄像心率.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 983655221E83BED000723316 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 42 | 983655241E83BED000723316 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 43 | 983655251E83BED000723316 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 44 | 983655271E83BED000723316 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 45 | 983655281E83BED000723316 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 46 | 9836552B1E83BED000723316 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 47 | 9836552D1E83BED000723316 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 48 | 983655301E83BED000723316 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 49 | 983655321E83BED000723316 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 50 | 983655371E83BED000723316 /* 摄像心率Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "摄像心率Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | 9836553B1E83BED000723316 /* ____Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "____Tests.m"; sourceTree = ""; }; 52 | 9836553D1E83BED000723316 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | 983655421E83BED000723316 /* 摄像心率UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "摄像心率UITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 983655461E83BED000723316 /* ____UITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "____UITests.m"; sourceTree = ""; }; 55 | 983655481E83BED000723316 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 987850431E851EE70027D085 /* HeartBeat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeartBeat.h; sourceTree = ""; }; 57 | 987850441E851EE70027D085 /* HeartBeat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HeartBeat.m; sourceTree = ""; }; 58 | 9878C7D51E88EF3200E3A6DC /* HeartLive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeartLive.h; sourceTree = ""; }; 59 | 9878C7D61E88EF3200E3A6DC /* HeartLive.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HeartLive.m; sourceTree = ""; }; 60 | /* End PBXFileReference section */ 61 | 62 | /* Begin PBXFrameworksBuildPhase section */ 63 | 9836551B1E83BED000723316 /* Frameworks */ = { 64 | isa = PBXFrameworksBuildPhase; 65 | buildActionMask = 2147483647; 66 | files = ( 67 | ); 68 | runOnlyForDeploymentPostprocessing = 0; 69 | }; 70 | 983655341E83BED000723316 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | 9836553F1E83BED000723316 /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | /* End PBXFrameworksBuildPhase section */ 85 | 86 | /* Begin PBXGroup section */ 87 | 983655151E83BECF00723316 = { 88 | isa = PBXGroup; 89 | children = ( 90 | 983655201E83BED000723316 /* 摄像心率 */, 91 | 9836553A1E83BED000723316 /* 摄像心率Tests */, 92 | 983655451E83BED000723316 /* 摄像心率UITests */, 93 | 9836551F1E83BED000723316 /* Products */, 94 | ); 95 | sourceTree = ""; 96 | }; 97 | 9836551F1E83BED000723316 /* Products */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 9836551E1E83BED000723316 /* 摄像心率.app */, 101 | 983655371E83BED000723316 /* 摄像心率Tests.xctest */, 102 | 983655421E83BED000723316 /* 摄像心率UITests.xctest */, 103 | ); 104 | name = Products; 105 | sourceTree = ""; 106 | }; 107 | 983655201E83BED000723316 /* 摄像心率 */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 983655241E83BED000723316 /* AppDelegate.h */, 111 | 983655251E83BED000723316 /* AppDelegate.m */, 112 | 983655271E83BED000723316 /* ViewController.h */, 113 | 983655281E83BED000723316 /* ViewController.m */, 114 | 9878C7D51E88EF3200E3A6DC /* HeartLive.h */, 115 | 9878C7D61E88EF3200E3A6DC /* HeartLive.m */, 116 | 9836552A1E83BED000723316 /* Main.storyboard */, 117 | 9836552D1E83BED000723316 /* Assets.xcassets */, 118 | 9836552F1E83BED000723316 /* LaunchScreen.storyboard */, 119 | 983655321E83BED000723316 /* Info.plist */, 120 | 983655211E83BED000723316 /* Supporting Files */, 121 | 987850431E851EE70027D085 /* HeartBeat.h */, 122 | 987850441E851EE70027D085 /* HeartBeat.m */, 123 | ); 124 | path = "摄像心率"; 125 | sourceTree = ""; 126 | }; 127 | 983655211E83BED000723316 /* Supporting Files */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 983655221E83BED000723316 /* main.m */, 131 | ); 132 | name = "Supporting Files"; 133 | sourceTree = ""; 134 | }; 135 | 9836553A1E83BED000723316 /* 摄像心率Tests */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 9836553B1E83BED000723316 /* ____Tests.m */, 139 | 9836553D1E83BED000723316 /* Info.plist */, 140 | ); 141 | path = "摄像心率Tests"; 142 | sourceTree = ""; 143 | }; 144 | 983655451E83BED000723316 /* 摄像心率UITests */ = { 145 | isa = PBXGroup; 146 | children = ( 147 | 983655461E83BED000723316 /* ____UITests.m */, 148 | 983655481E83BED000723316 /* Info.plist */, 149 | ); 150 | path = "摄像心率UITests"; 151 | sourceTree = ""; 152 | }; 153 | /* End PBXGroup section */ 154 | 155 | /* Begin PBXNativeTarget section */ 156 | 9836551D1E83BED000723316 /* 摄像心率 */ = { 157 | isa = PBXNativeTarget; 158 | buildConfigurationList = 9836554B1E83BED000723316 /* Build configuration list for PBXNativeTarget "摄像心率" */; 159 | buildPhases = ( 160 | 9836551A1E83BED000723316 /* Sources */, 161 | 9836551B1E83BED000723316 /* Frameworks */, 162 | 9836551C1E83BED000723316 /* Resources */, 163 | ); 164 | buildRules = ( 165 | ); 166 | dependencies = ( 167 | ); 168 | name = "摄像心率"; 169 | productName = "摄像心率"; 170 | productReference = 9836551E1E83BED000723316 /* 摄像心率.app */; 171 | productType = "com.apple.product-type.application"; 172 | }; 173 | 983655361E83BED000723316 /* 摄像心率Tests */ = { 174 | isa = PBXNativeTarget; 175 | buildConfigurationList = 9836554E1E83BED000723316 /* Build configuration list for PBXNativeTarget "摄像心率Tests" */; 176 | buildPhases = ( 177 | 983655331E83BED000723316 /* Sources */, 178 | 983655341E83BED000723316 /* Frameworks */, 179 | 983655351E83BED000723316 /* Resources */, 180 | ); 181 | buildRules = ( 182 | ); 183 | dependencies = ( 184 | 983655391E83BED000723316 /* PBXTargetDependency */, 185 | ); 186 | name = "摄像心率Tests"; 187 | productName = "摄像心率Tests"; 188 | productReference = 983655371E83BED000723316 /* 摄像心率Tests.xctest */; 189 | productType = "com.apple.product-type.bundle.unit-test"; 190 | }; 191 | 983655411E83BED000723316 /* 摄像心率UITests */ = { 192 | isa = PBXNativeTarget; 193 | buildConfigurationList = 983655511E83BED000723316 /* Build configuration list for PBXNativeTarget "摄像心率UITests" */; 194 | buildPhases = ( 195 | 9836553E1E83BED000723316 /* Sources */, 196 | 9836553F1E83BED000723316 /* Frameworks */, 197 | 983655401E83BED000723316 /* Resources */, 198 | ); 199 | buildRules = ( 200 | ); 201 | dependencies = ( 202 | 983655441E83BED000723316 /* PBXTargetDependency */, 203 | ); 204 | name = "摄像心率UITests"; 205 | productName = "摄像心率UITests"; 206 | productReference = 983655421E83BED000723316 /* 摄像心率UITests.xctest */; 207 | productType = "com.apple.product-type.bundle.ui-testing"; 208 | }; 209 | /* End PBXNativeTarget section */ 210 | 211 | /* Begin PBXProject section */ 212 | 983655161E83BECF00723316 /* Project object */ = { 213 | isa = PBXProject; 214 | attributes = { 215 | LastUpgradeCheck = 0820; 216 | ORGANIZATIONNAME = ZM; 217 | TargetAttributes = { 218 | 9836551D1E83BED000723316 = { 219 | CreatedOnToolsVersion = 8.2.1; 220 | DevelopmentTeam = 9CHJPN5EEJ; 221 | ProvisioningStyle = Automatic; 222 | }; 223 | 983655361E83BED000723316 = { 224 | CreatedOnToolsVersion = 8.2.1; 225 | ProvisioningStyle = Automatic; 226 | TestTargetID = 9836551D1E83BED000723316; 227 | }; 228 | 983655411E83BED000723316 = { 229 | CreatedOnToolsVersion = 8.2.1; 230 | ProvisioningStyle = Automatic; 231 | TestTargetID = 9836551D1E83BED000723316; 232 | }; 233 | }; 234 | }; 235 | buildConfigurationList = 983655191E83BECF00723316 /* Build configuration list for PBXProject "摄像心率" */; 236 | compatibilityVersion = "Xcode 3.2"; 237 | developmentRegion = English; 238 | hasScannedForEncodings = 0; 239 | knownRegions = ( 240 | en, 241 | Base, 242 | ); 243 | mainGroup = 983655151E83BECF00723316; 244 | productRefGroup = 9836551F1E83BED000723316 /* Products */; 245 | projectDirPath = ""; 246 | projectRoot = ""; 247 | targets = ( 248 | 9836551D1E83BED000723316 /* 摄像心率 */, 249 | 983655361E83BED000723316 /* 摄像心率Tests */, 250 | 983655411E83BED000723316 /* 摄像心率UITests */, 251 | ); 252 | }; 253 | /* End PBXProject section */ 254 | 255 | /* Begin PBXResourcesBuildPhase section */ 256 | 9836551C1E83BED000723316 /* Resources */ = { 257 | isa = PBXResourcesBuildPhase; 258 | buildActionMask = 2147483647; 259 | files = ( 260 | 983655311E83BED000723316 /* LaunchScreen.storyboard in Resources */, 261 | 9836552E1E83BED000723316 /* Assets.xcassets in Resources */, 262 | 9836552C1E83BED000723316 /* Main.storyboard in Resources */, 263 | ); 264 | runOnlyForDeploymentPostprocessing = 0; 265 | }; 266 | 983655351E83BED000723316 /* Resources */ = { 267 | isa = PBXResourcesBuildPhase; 268 | buildActionMask = 2147483647; 269 | files = ( 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | }; 273 | 983655401E83BED000723316 /* Resources */ = { 274 | isa = PBXResourcesBuildPhase; 275 | buildActionMask = 2147483647; 276 | files = ( 277 | ); 278 | runOnlyForDeploymentPostprocessing = 0; 279 | }; 280 | /* End PBXResourcesBuildPhase section */ 281 | 282 | /* Begin PBXSourcesBuildPhase section */ 283 | 9836551A1E83BED000723316 /* Sources */ = { 284 | isa = PBXSourcesBuildPhase; 285 | buildActionMask = 2147483647; 286 | files = ( 287 | 9878C7D71E88EF3200E3A6DC /* HeartLive.m in Sources */, 288 | 983655291E83BED000723316 /* ViewController.m in Sources */, 289 | 987850451E851EE70027D085 /* HeartBeat.m in Sources */, 290 | 983655261E83BED000723316 /* AppDelegate.m in Sources */, 291 | 983655231E83BED000723316 /* main.m in Sources */, 292 | ); 293 | runOnlyForDeploymentPostprocessing = 0; 294 | }; 295 | 983655331E83BED000723316 /* Sources */ = { 296 | isa = PBXSourcesBuildPhase; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | 9836553C1E83BED000723316 /* ____Tests.m in Sources */, 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | }; 303 | 9836553E1E83BED000723316 /* Sources */ = { 304 | isa = PBXSourcesBuildPhase; 305 | buildActionMask = 2147483647; 306 | files = ( 307 | 983655471E83BED000723316 /* ____UITests.m in Sources */, 308 | ); 309 | runOnlyForDeploymentPostprocessing = 0; 310 | }; 311 | /* End PBXSourcesBuildPhase section */ 312 | 313 | /* Begin PBXTargetDependency section */ 314 | 983655391E83BED000723316 /* PBXTargetDependency */ = { 315 | isa = PBXTargetDependency; 316 | target = 9836551D1E83BED000723316 /* 摄像心率 */; 317 | targetProxy = 983655381E83BED000723316 /* PBXContainerItemProxy */; 318 | }; 319 | 983655441E83BED000723316 /* PBXTargetDependency */ = { 320 | isa = PBXTargetDependency; 321 | target = 9836551D1E83BED000723316 /* 摄像心率 */; 322 | targetProxy = 983655431E83BED000723316 /* PBXContainerItemProxy */; 323 | }; 324 | /* End PBXTargetDependency section */ 325 | 326 | /* Begin PBXVariantGroup section */ 327 | 9836552A1E83BED000723316 /* Main.storyboard */ = { 328 | isa = PBXVariantGroup; 329 | children = ( 330 | 9836552B1E83BED000723316 /* Base */, 331 | ); 332 | name = Main.storyboard; 333 | sourceTree = ""; 334 | }; 335 | 9836552F1E83BED000723316 /* LaunchScreen.storyboard */ = { 336 | isa = PBXVariantGroup; 337 | children = ( 338 | 983655301E83BED000723316 /* Base */, 339 | ); 340 | name = LaunchScreen.storyboard; 341 | sourceTree = ""; 342 | }; 343 | /* End PBXVariantGroup section */ 344 | 345 | /* Begin XCBuildConfiguration section */ 346 | 983655491E83BED000723316 /* Debug */ = { 347 | isa = XCBuildConfiguration; 348 | buildSettings = { 349 | ALWAYS_SEARCH_USER_PATHS = NO; 350 | CLANG_ANALYZER_NONNULL = YES; 351 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 352 | CLANG_CXX_LIBRARY = "libc++"; 353 | CLANG_ENABLE_MODULES = YES; 354 | CLANG_ENABLE_OBJC_ARC = YES; 355 | CLANG_WARN_BOOL_CONVERSION = YES; 356 | CLANG_WARN_CONSTANT_CONVERSION = YES; 357 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 358 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 359 | CLANG_WARN_EMPTY_BODY = YES; 360 | CLANG_WARN_ENUM_CONVERSION = YES; 361 | CLANG_WARN_INFINITE_RECURSION = YES; 362 | CLANG_WARN_INT_CONVERSION = YES; 363 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 364 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 365 | CLANG_WARN_UNREACHABLE_CODE = YES; 366 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 367 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 368 | COPY_PHASE_STRIP = NO; 369 | DEBUG_INFORMATION_FORMAT = dwarf; 370 | ENABLE_STRICT_OBJC_MSGSEND = YES; 371 | ENABLE_TESTABILITY = YES; 372 | GCC_C_LANGUAGE_STANDARD = gnu99; 373 | GCC_DYNAMIC_NO_PIC = NO; 374 | GCC_NO_COMMON_BLOCKS = YES; 375 | GCC_OPTIMIZATION_LEVEL = 0; 376 | GCC_PREPROCESSOR_DEFINITIONS = ( 377 | "DEBUG=1", 378 | "$(inherited)", 379 | ); 380 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 381 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 382 | GCC_WARN_UNDECLARED_SELECTOR = YES; 383 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 384 | GCC_WARN_UNUSED_FUNCTION = YES; 385 | GCC_WARN_UNUSED_VARIABLE = YES; 386 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 387 | MTL_ENABLE_DEBUG_INFO = YES; 388 | ONLY_ACTIVE_ARCH = YES; 389 | SDKROOT = iphoneos; 390 | }; 391 | name = Debug; 392 | }; 393 | 9836554A1E83BED000723316 /* Release */ = { 394 | isa = XCBuildConfiguration; 395 | buildSettings = { 396 | ALWAYS_SEARCH_USER_PATHS = NO; 397 | CLANG_ANALYZER_NONNULL = YES; 398 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 399 | CLANG_CXX_LIBRARY = "libc++"; 400 | CLANG_ENABLE_MODULES = YES; 401 | CLANG_ENABLE_OBJC_ARC = YES; 402 | CLANG_WARN_BOOL_CONVERSION = YES; 403 | CLANG_WARN_CONSTANT_CONVERSION = YES; 404 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 405 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 406 | CLANG_WARN_EMPTY_BODY = YES; 407 | CLANG_WARN_ENUM_CONVERSION = YES; 408 | CLANG_WARN_INFINITE_RECURSION = YES; 409 | CLANG_WARN_INT_CONVERSION = YES; 410 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 411 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 412 | CLANG_WARN_UNREACHABLE_CODE = YES; 413 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 414 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 415 | COPY_PHASE_STRIP = NO; 416 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 417 | ENABLE_NS_ASSERTIONS = NO; 418 | ENABLE_STRICT_OBJC_MSGSEND = YES; 419 | GCC_C_LANGUAGE_STANDARD = gnu99; 420 | GCC_NO_COMMON_BLOCKS = YES; 421 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 422 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 423 | GCC_WARN_UNDECLARED_SELECTOR = YES; 424 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 425 | GCC_WARN_UNUSED_FUNCTION = YES; 426 | GCC_WARN_UNUSED_VARIABLE = YES; 427 | IPHONEOS_DEPLOYMENT_TARGET = 10.2; 428 | MTL_ENABLE_DEBUG_INFO = NO; 429 | SDKROOT = iphoneos; 430 | VALIDATE_PRODUCT = YES; 431 | }; 432 | name = Release; 433 | }; 434 | 9836554C1E83BED000723316 /* Debug */ = { 435 | isa = XCBuildConfiguration; 436 | buildSettings = { 437 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 438 | DEVELOPMENT_TEAM = 9CHJPN5EEJ; 439 | INFOPLIST_FILE = "摄像心率/Info.plist"; 440 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 441 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 442 | PRODUCT_BUNDLE_IDENTIFIER = com.xiekang.cn.DoctorVersion; 443 | PRODUCT_NAME = "$(TARGET_NAME)"; 444 | }; 445 | name = Debug; 446 | }; 447 | 9836554D1E83BED000723316 /* Release */ = { 448 | isa = XCBuildConfiguration; 449 | buildSettings = { 450 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 451 | DEVELOPMENT_TEAM = 9CHJPN5EEJ; 452 | INFOPLIST_FILE = "摄像心率/Info.plist"; 453 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 454 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 455 | PRODUCT_BUNDLE_IDENTIFIER = com.xiekang.cn.DoctorVersion; 456 | PRODUCT_NAME = "$(TARGET_NAME)"; 457 | }; 458 | name = Release; 459 | }; 460 | 9836554F1E83BED000723316 /* Debug */ = { 461 | isa = XCBuildConfiguration; 462 | buildSettings = { 463 | BUNDLE_LOADER = "$(TEST_HOST)"; 464 | INFOPLIST_FILE = "摄像心率Tests/Info.plist"; 465 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 466 | PRODUCT_BUNDLE_IDENTIFIER = "ZhangMin.----Tests"; 467 | PRODUCT_NAME = "$(TARGET_NAME)"; 468 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/摄像心率.app/摄像心率"; 469 | }; 470 | name = Debug; 471 | }; 472 | 983655501E83BED000723316 /* Release */ = { 473 | isa = XCBuildConfiguration; 474 | buildSettings = { 475 | BUNDLE_LOADER = "$(TEST_HOST)"; 476 | INFOPLIST_FILE = "摄像心率Tests/Info.plist"; 477 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 478 | PRODUCT_BUNDLE_IDENTIFIER = "ZhangMin.----Tests"; 479 | PRODUCT_NAME = "$(TARGET_NAME)"; 480 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/摄像心率.app/摄像心率"; 481 | }; 482 | name = Release; 483 | }; 484 | 983655521E83BED000723316 /* Debug */ = { 485 | isa = XCBuildConfiguration; 486 | buildSettings = { 487 | INFOPLIST_FILE = "摄像心率UITests/Info.plist"; 488 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 489 | PRODUCT_BUNDLE_IDENTIFIER = "ZhangMin.----UITests"; 490 | PRODUCT_NAME = "$(TARGET_NAME)"; 491 | TEST_TARGET_NAME = "摄像心率"; 492 | }; 493 | name = Debug; 494 | }; 495 | 983655531E83BED000723316 /* Release */ = { 496 | isa = XCBuildConfiguration; 497 | buildSettings = { 498 | INFOPLIST_FILE = "摄像心率UITests/Info.plist"; 499 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 500 | PRODUCT_BUNDLE_IDENTIFIER = "ZhangMin.----UITests"; 501 | PRODUCT_NAME = "$(TARGET_NAME)"; 502 | TEST_TARGET_NAME = "摄像心率"; 503 | }; 504 | name = Release; 505 | }; 506 | /* End XCBuildConfiguration section */ 507 | 508 | /* Begin XCConfigurationList section */ 509 | 983655191E83BECF00723316 /* Build configuration list for PBXProject "摄像心率" */ = { 510 | isa = XCConfigurationList; 511 | buildConfigurations = ( 512 | 983655491E83BED000723316 /* Debug */, 513 | 9836554A1E83BED000723316 /* Release */, 514 | ); 515 | defaultConfigurationIsVisible = 0; 516 | defaultConfigurationName = Release; 517 | }; 518 | 9836554B1E83BED000723316 /* Build configuration list for PBXNativeTarget "摄像心率" */ = { 519 | isa = XCConfigurationList; 520 | buildConfigurations = ( 521 | 9836554C1E83BED000723316 /* Debug */, 522 | 9836554D1E83BED000723316 /* Release */, 523 | ); 524 | defaultConfigurationIsVisible = 0; 525 | defaultConfigurationName = Release; 526 | }; 527 | 9836554E1E83BED000723316 /* Build configuration list for PBXNativeTarget "摄像心率Tests" */ = { 528 | isa = XCConfigurationList; 529 | buildConfigurations = ( 530 | 9836554F1E83BED000723316 /* Debug */, 531 | 983655501E83BED000723316 /* Release */, 532 | ); 533 | defaultConfigurationIsVisible = 0; 534 | defaultConfigurationName = Release; 535 | }; 536 | 983655511E83BED000723316 /* Build configuration list for PBXNativeTarget "摄像心率UITests" */ = { 537 | isa = XCConfigurationList; 538 | buildConfigurations = ( 539 | 983655521E83BED000723316 /* Debug */, 540 | 983655531E83BED000723316 /* Release */, 541 | ); 542 | defaultConfigurationIsVisible = 0; 543 | defaultConfigurationName = Release; 544 | }; 545 | /* End XCConfigurationList section */ 546 | }; 547 | rootObject = 983655161E83BECF00723316 /* Project object */; 548 | } 549 | --------------------------------------------------------------------------------