├── .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 | 
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 |
--------------------------------------------------------------------------------