├── MCChatHUD
├── MCChatHUD.xcodeproj
│ ├── xcuserdata
│ │ └── duwei.xcuserdatad
│ │ │ └── xcschemes
│ │ │ └── xcschememanagement.plist
│ └── project.pbxproj
├── MCChatHUD
│ ├── Marco
│ │ └── HUDMarco.swift
│ ├── Info.plist
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Controller
│ │ ├── ChooseTypeViewController.swift
│ │ └── RecordViewController.swift
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ └── View
│ │ ├── MCVolumeView.swift
│ │ ├── MCRecordHUD.swift
│ │ └── MCProgressView.swift
├── MCChatHUDTests
│ ├── Info.plist
│ └── MCChatHUDTests.swift
└── MCChatHUDUITests
│ ├── Info.plist
│ └── MCChatHUDUITests.swift
└── README.md
/MCChatHUD/MCChatHUD.xcodeproj/xcuserdata/duwei.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | MCChatHUD.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUD/Marco/HUDMarco.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HUDMarco.swift
3 | // MCChatHUD
4 | //
5 | // Created by duwei on 2018/1/30.
6 | // Copyright © 2018年 Dywane. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import UIKit
11 |
12 | //MARK: - UI Marco
13 |
14 | /// 界面宽度
15 | internal let HUDWidth: CGFloat = 170
16 | /// 界面高度
17 | internal let HUDHeight: CGFloat = 78
18 | /// 界面圆角
19 | internal let HUDCornerRadius: CGFloat = 38
20 |
21 | /// 屏幕高度
22 | internal let ScreenHeight = UIScreen.main.bounds.height
23 | /// 屏幕宽度
24 | internal let ScreenWidth = UIScreen.main.bounds.width
25 |
26 | /// 音量计高度
27 | internal let VolumeViewHeight = 40
28 | /// 音量计宽度
29 | internal let VolumeViewWidth = 60
30 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUDTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUDUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
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 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUDTests/MCChatHUDTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MCChatHUDTests.swift
3 | // MCChatHUDTests
4 | //
5 | // Created by duwei on 2018/1/30.
6 | // Copyright © 2018年 Dywane. All rights reserved.
7 | //
8 |
9 | import XCTest
10 | @testable import MCChatHUD
11 |
12 | class MCChatHUDTests: XCTestCase {
13 |
14 | override func setUp() {
15 | super.setUp()
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 | }
18 |
19 | override func tearDown() {
20 | // Put teardown code here. This method is called after the invocation of each test method in the class.
21 | super.tearDown()
22 | }
23 |
24 | func testExample() {
25 | // This is an example of a functional test case.
26 | // Use XCTAssert and related functions to verify your tests produce the correct results.
27 | }
28 |
29 | func testPerformanceExample() {
30 | // This is an example of a performance test case.
31 | self.measure {
32 | // Put the code you want to measure the time of here.
33 | }
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUDUITests/MCChatHUDUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MCChatHUDUITests.swift
3 | // MCChatHUDUITests
4 | //
5 | // Created by duwei on 2018/1/30.
6 | // Copyright © 2018年 Dywane. All rights reserved.
7 | //
8 |
9 | import XCTest
10 |
11 | class MCChatHUDUITests: XCTestCase {
12 |
13 | override func setUp() {
14 | super.setUp()
15 |
16 | // Put setup code here. This method is called before the invocation of each test method in the class.
17 |
18 | // In UI tests it is usually best to stop immediately when a failure occurs.
19 | continueAfterFailure = false
20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
21 | XCUIApplication().launch()
22 |
23 | // 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.
24 | }
25 |
26 | override func tearDown() {
27 | // Put teardown code here. This method is called after the invocation of each test method in the class.
28 | super.tearDown()
29 | }
30 |
31 | func testExample() {
32 | // Use recording to get started writing UI tests.
33 | // Use XCTAssert and related functions to verify your tests produce the correct results.
34 | }
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUD/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | NSMicrophoneUsageDescription
6 | Use your microphone to test
7 | CFBundleDevelopmentRegion
8 | $(DEVELOPMENT_LANGUAGE)
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 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUD/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 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUD/Controller/ChooseTypeViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ChooseTypeViewController.swift
3 | // MCChatHUD
4 | //
5 | // Created by duwei on 2018/2/4.
6 | // Copyright © 2018年 Dywane. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class ChooseTypeViewController: UITableViewController {
12 |
13 | /// 类型数组
14 | private let typeArray = ["Bar style", "Line style"]
15 |
16 | /// 选择的类型
17 | private var selectedIndex = 0
18 |
19 | override func viewDidLoad() {
20 | super.viewDidLoad()
21 | }
22 |
23 | override func didReceiveMemoryWarning() {
24 | super.didReceiveMemoryWarning()
25 | // Dispose of any resources that can be recreated.
26 | }
27 |
28 | // MARK: - Table view data source
29 |
30 | override func numberOfSections(in tableView: UITableView) -> Int {
31 | return 1
32 | }
33 |
34 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
35 | return typeArray.count
36 | }
37 |
38 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
39 | let cell = tableView.dequeueReusableCell(withIdentifier: "ChooseTypeCellID", for: indexPath)
40 | cell.textLabel?.text = typeArray[indexPath.row]
41 | return cell
42 | }
43 |
44 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
45 | selectedIndex = indexPath.row
46 | performSegue(withIdentifier: "ShowRecordViewController", sender: self)
47 | }
48 |
49 | // MARK: - Navigation
50 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
51 | if segue.identifier == "ShowRecordViewController" {
52 | guard let type = HUDType(rawValue: selectedIndex) else {
53 | return
54 | }
55 | let recordVC = segue.destination as! RecordViewController
56 | recordVC.HUDType = type
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUD/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUD/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // MCChatHUD
4 | //
5 | // Created by duwei on 2018/1/30.
6 | // Copyright © 2018年 Dywane. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 |
14 | var window: UIWindow?
15 |
16 |
17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
18 | // Override point for customization after application launch.
19 | return true
20 | }
21 |
22 | func applicationWillResignActive(_ application: UIApplication) {
23 | // 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.
24 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
25 | }
26 |
27 | func applicationDidEnterBackground(_ application: UIApplication) {
28 | // 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.
29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
30 | }
31 |
32 | func applicationWillEnterForeground(_ application: UIApplication) {
33 | // 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.
34 | }
35 |
36 | func applicationDidBecomeActive(_ application: UIApplication) {
37 | // 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.
38 | }
39 |
40 | func applicationWillTerminate(_ application: UIApplication) {
41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
42 | }
43 |
44 |
45 | }
46 |
47 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUD/View/MCVolumeView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MCVolumeView.swift
3 | // MCChatHUD
4 | //
5 | // Created by duwei on 2018/1/30.
6 | // Copyright © 2018年 Dywane. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class MCVolumeView: UIView {
12 |
13 | //MARK: Private Properties
14 | /// 声音表数组
15 | private var soundMeters: [Float]!
16 |
17 | private var type: HUDType = .bar
18 |
19 | //MARK: Init
20 | convenience init(frame: CGRect, type: HUDType) {
21 | self.init(frame: frame)
22 | self.type = type
23 | }
24 |
25 | override init(frame: CGRect) {
26 | super.init(frame: frame)
27 | backgroundColor = UIColor.clear
28 | contentMode = .redraw //内容模式为重绘,因为需要多次重复绘制音量表
29 | NotificationCenter.default.addObserver(self, selector: #selector(updateView(notice:)), name: NSNotification.Name.init("updateMeters"), object: nil)
30 | }
31 |
32 | required init?(coder aDecoder: NSCoder) {
33 | fatalError("init(coder:) has not been implemented")
34 | }
35 |
36 | override func draw(_ rect: CGRect) {
37 | if soundMeters != nil && soundMeters.count > 0 {
38 | let context = UIGraphicsGetCurrentContext()
39 | context?.setLineCap(.round)
40 | context?.setLineJoin(.round)
41 | context?.setStrokeColor(UIColor.white.cgColor)
42 |
43 | let noVoice = -46.0 // 该值代表低于-46.0的声音都认为无声音
44 | let maxVolume = 55.0 // 该值代表最高声音为55.0
45 |
46 | switch type {
47 | case .bar:
48 | context?.setLineWidth(3)
49 | for (index,item) in soundMeters.enumerated() {
50 | let barHeight = maxVolume - (Double(item) - noVoice) //通过当前声音表计算应该显示的声音表高度
51 | context?.move(to: CGPoint(x: index * 6 + 3, y: 40))
52 | context?.addLine(to: CGPoint(x: index * 6 + 3, y: Int(barHeight)))
53 | }
54 | case .line:
55 | context?.setLineWidth(1.5)
56 | for (index, item) in soundMeters.enumerated() {
57 | let position = maxVolume - (Double(item) - noVoice) //计算对应线段高度
58 | context?.addLine(to: CGPoint(x: Double(index * 6 + 3), y: position))
59 | context?.move(to: CGPoint(x: Double(index * 6 + 3), y: position))
60 | }
61 | }
62 | context?.strokePath()
63 | }
64 | }
65 |
66 | @objc private func updateView(notice: Notification) {
67 | soundMeters = notice.object as! [Float]
68 | setNeedsDisplay()
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUD/View/MCRecordHUD.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MCRecordHUD.swift
3 | // MCChatHUD
4 | //
5 | // Created by duwei on 2018/1/30.
6 | // Copyright © 2018年 Dywane. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | /// HUD类型
12 | ///
13 | /// - bar: 条状
14 | /// - stroke: 线状
15 | enum HUDType: Int {
16 | case bar = 0
17 | case line
18 | }
19 |
20 | class MCRecordHUD: UIView {
21 |
22 | //MARK: - Public Properties
23 | /// 提示Label
24 | public let titleLabel = UILabel()
25 |
26 | //MARK: - Private Properties
27 | private let progress = MCProgressView(frame: CGRect(x: 0, y: 0, width: HUDWidth, height: HUDHeight))
28 | private var volume: MCVolumeView!
29 |
30 | //MARK: Methods
31 | public func startCounting() {
32 | progress.countingAnimate()
33 | titleLabel.text = "Slide up to cancel"
34 | }
35 |
36 | public func stopCounting() {
37 | progress.stopAnimate()
38 | }
39 |
40 | //MARK: - Init
41 |
42 | convenience init(type: HUDType) {
43 | self.init(frame: .zero)
44 | self.frame.size.width = HUDWidth
45 | self.frame.size.height = HUDHeight
46 | center = CGPoint(x: ScreenWidth/2, y: ScreenHeight/2 - 50)
47 | backgroundColor = UIColor.clear
48 | addSubview(progress)
49 |
50 | volume = MCVolumeView(frame: CGRect(x: 56, y: 0, width: VolumeViewWidth, height: VolumeViewHeight), type: type)
51 | addSubview(volume)
52 |
53 | setUpLabel()
54 | addSubview(titleLabel)
55 | setUpShadow()
56 | }
57 |
58 | override private init(frame: CGRect) {
59 | super.init(frame: frame)
60 | }
61 |
62 | required init?(coder aDecoder: NSCoder) {
63 | fatalError("init(coder:) has not been implemented")
64 | }
65 |
66 | }
67 |
68 | // MARK: - Setup
69 | extension MCRecordHUD {
70 |
71 | private func setUpLabel() {
72 | titleLabel.textColor = UIColor.white
73 | titleLabel.font = UIFont.systemFont(ofSize: 12, weight: .bold)
74 | titleLabel.textAlignment = .center
75 | titleLabel.backgroundColor = UIColor.clear
76 | titleLabel.frame = CGRect(x: 25, y: 46, width: 120, height: 14)
77 | }
78 |
79 | private func setUpShadow() {
80 |
81 | let progessViewBounds = progress.frame
82 | let shadowWidth = progessViewBounds.size.width * 0.85
83 | let shadowHeight = progessViewBounds.size.height * 0.75
84 |
85 | let shadowPath = UIBezierPath(roundedRect: CGRect(x: progessViewBounds.origin.x + (progessViewBounds.width - shadowWidth) * 0.5,
86 | y: progessViewBounds.origin.y + 20,
87 | width: shadowWidth,
88 | height: shadowHeight),
89 | cornerRadius: progress.layer.cornerRadius)
90 |
91 | layer.shadowColor = UIColor(red: 0.29, green: 0.29, blue: 0.29, alpha: 1).cgColor
92 | layer.shadowPath = shadowPath.cgPath
93 | layer.shadowOpacity = 0.5
94 | layer.shadowRadius = 8
95 | layer.shadowOffset = CGSize(width: 0, height: 10)
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUD/View/MCProgressView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MCProgressView.swift
3 | // MCChatHUD
4 | //
5 | // Created by duwei on 2018/1/30.
6 | // Copyright © 2018年 Dywane. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | class MCProgressView: UIImageView {
12 |
13 | //MARK: - Private Properties
14 | /// 进度条
15 | private var progressLayer: CAShapeLayer!
16 | /// 进度动画
17 | private var animation: CABasicAnimation!
18 | /// 高斯模糊层
19 | private var blurView: UIVisualEffectView!
20 |
21 | //MARK: - Init
22 | override init(frame: CGRect) {
23 | super.init(frame: frame)
24 | layer.cornerRadius = HUDCornerRadius
25 | clipsToBounds = true
26 | setUpBlurView()
27 | configAnimate()
28 | }
29 |
30 | required init?(coder aDecoder: NSCoder) {
31 | fatalError("init(coder:) has not been implemented")
32 | }
33 | }
34 |
35 | //MARK: - Animation
36 | extension MCProgressView {
37 |
38 | /// 开始计时动画
39 | public func countingAnimate() {
40 | progressLayer.add(animation, forKey: nil)
41 | }
42 |
43 | /// 停止计时动画
44 | public func stopAnimate() {
45 | progressLayer.removeAllAnimations()
46 | }
47 | }
48 |
49 | // MARK: - Setup
50 | extension MCProgressView {
51 |
52 | private func configAnimate() {
53 | let maskPath = UIBezierPath(roundedRect: CGRect.init(x: 0, y: 0, width: frame.width, height: frame.height), cornerRadius: HUDCornerRadius)
54 | let maskLayer = CAShapeLayer()
55 | maskLayer.backgroundColor = UIColor.clear.cgColor
56 | maskLayer.path = maskPath.cgPath
57 | maskLayer.frame = bounds
58 |
59 | // 进度路径
60 | /*
61 | 路径的中心为HUD的中心,宽度为HUD的高度,从左往右绘制
62 | */
63 | let progressPath = CGMutablePath()
64 | progressPath.move(to: CGPoint(x: 0, y: frame.height / 2))
65 | progressPath.addLine(to: CGPoint(x: frame.width, y: frame.height / 2))
66 |
67 | progressLayer = CAShapeLayer()
68 | progressLayer.frame = bounds
69 | progressLayer.fillColor = UIColor.clear.cgColor //图层背景颜色
70 | progressLayer.strokeColor = UIColor(red: 0.29, green: 0.29, blue: 0.29, alpha: 0.90).cgColor //图层绘制颜色
71 | progressLayer.lineCap = kCALineCapButt
72 | progressLayer.lineWidth = HUDHeight
73 | progressLayer.path = progressPath
74 | progressLayer.mask = maskLayer
75 |
76 | blurView.contentView.layer.addSublayer(progressLayer)
77 |
78 | animation = CABasicAnimation(keyPath: "strokeEnd")
79 | animation.duration = 60 //最大录音时长
80 | animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) //匀速前进
81 | animation.fillMode = kCAFillModeForwards
82 | animation.fromValue = 0.0
83 | animation.toValue = 1.0
84 | animation.autoreverses = false
85 | animation.repeatCount = 1
86 | }
87 |
88 | private func setUpBlurView() {
89 | let rect = CGRect(x: 0, y: 0, width: 1, height: 1)
90 | UIGraphicsBeginImageContextWithOptions(rect.size, false, 1.0)
91 | let context: CGContext? = UIGraphicsGetCurrentContext()
92 | context?.setFillColor(UIColor.black.withAlphaComponent(0.8).cgColor)
93 | context?.fill(rect)
94 | let transparentImage = UIGraphicsGetImageFromCurrentImageContext()
95 | UIGraphicsEndImageContext()
96 | image = transparentImage
97 |
98 | blurView = UIVisualEffectView(effect: UIBlurEffect(style: .regular))
99 | blurView.frame = bounds
100 | blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
101 | blurView.layer.cornerRadius = layer.cornerRadius
102 | blurView.clipsToBounds = true
103 | addSubview(blurView)
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUD/Controller/RecordViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RecordViewController.swift
3 | // MCChatHUD
4 | //
5 | // Created by duwei on 2018/1/31.
6 | // Copyright © 2018年 Dywane. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import AVFoundation
11 |
12 | class RecordViewController: UIViewController {
13 |
14 | /// HUD类型
15 | public var HUDType: HUDType = .bar
16 |
17 | @IBOutlet weak private var recordButton: UIButton!
18 |
19 | /// 录音框
20 | private var chatHUD: MCRecordHUD!
21 |
22 | /// 录音器
23 | private var recorder: AVAudioRecorder!
24 | /// 录音器设置
25 | private let recorderSetting = [AVSampleRateKey : NSNumber(value: Float(44100.0)),//声音采样率
26 | AVFormatIDKey : NSNumber(value: Int32(kAudioFormatMPEG4AAC)),//编码格式
27 | AVNumberOfChannelsKey : NSNumber(value: 1),//采集音轨
28 | AVEncoderAudioQualityKey : NSNumber(value: Int32(AVAudioQuality.medium.rawValue))]//声音质量
29 | /// 录音计时器
30 | private var timer: Timer?
31 | /// 波形更新间隔
32 | private let updateFequency = 0.05
33 | /// 声音数据数组
34 | private var soundMeters: [Float]!
35 | /// 声音数据数组容量
36 | private let soundMeterCount = 10
37 | /// 录音时间
38 | private var recordTime = 0.00
39 |
40 | override func viewDidLoad() {
41 | super.viewDidLoad()
42 | chatHUD = MCRecordHUD(type: HUDType)
43 | configRecord()
44 | setupButtonEvent()
45 | }
46 |
47 | override func didReceiveMemoryWarning() {
48 | super.didReceiveMemoryWarning()
49 | }
50 | }
51 |
52 | // MARK: - Record handlers
53 | extension RecordViewController: AVAudioRecorderDelegate {
54 |
55 | /// 开始录音
56 | @objc private func beginRecordVoice() {
57 | if recorder == nil {
58 | return
59 | }
60 | view.addSubview(chatHUD)
61 | view.isUserInteractionEnabled = false //录音时候禁止点击其他地方
62 | chatHUD.startCounting()
63 | soundMeters = [Float]()
64 | recorder.record()
65 | timer = Timer.scheduledTimer(timeInterval: updateFequency, target: self, selector: #selector(updateMeters), userInfo: nil, repeats: true)
66 | }
67 |
68 | /// 停止录音
69 | @objc private func endRecordVoice() {
70 | recorder.stop()
71 | timer?.invalidate()
72 | chatHUD.removeFromSuperview()
73 | view.isUserInteractionEnabled = true //录音完了才能点击其他地方
74 | chatHUD.stopCounting()
75 | soundMeters.removeAll()
76 | }
77 |
78 | /// 取消录音
79 | @objc private func cancelRecordVoice() {
80 | endRecordVoice()
81 | recorder.deleteRecording()
82 | }
83 |
84 | /// 上划取消录音
85 | @objc private func remindDragExit() {
86 | chatHUD.titleLabel.text = "Release to cancel"
87 | }
88 |
89 | /// 下滑继续录音
90 | @objc private func remindDragEnter() {
91 | chatHUD.titleLabel.text = "Slide up to cancel"
92 | }
93 |
94 | @objc private func updateMeters() {
95 | recorder.updateMeters()
96 | recordTime += updateFequency
97 | addSoundMeter(item: recorder.averagePower(forChannel: 0))
98 | if recordTime >= 60.0 {
99 | endRecordVoice()
100 | }
101 | }
102 |
103 | private func addSoundMeter(item: Float) {
104 | if soundMeters.count < soundMeterCount {
105 | soundMeters.append(item)
106 | } else {
107 | for (index, _) in soundMeters.enumerated() {
108 | if index < soundMeterCount - 1 {
109 | soundMeters[index] = soundMeters[index + 1]
110 | }
111 | }
112 | // 插入新数据
113 | soundMeters[soundMeterCount - 1] = item
114 | NotificationCenter.default.post(name: NSNotification.Name.init("updateMeters"), object: soundMeters)
115 | }
116 | }
117 | }
118 |
119 | //MARK: - AVAudioRecorderDelegate
120 | extension RecordViewController {
121 |
122 | func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
123 | if recordTime > 1.0 {
124 | if flag {
125 | do {
126 | let exists = try recorder.url.checkResourceIsReachable()
127 | if exists {
128 | print("finish record")
129 | }
130 | }
131 | catch { print("fail to load record")}
132 | } else {
133 | print("record failed")
134 | }
135 | }
136 | recordTime = 0
137 | }
138 | }
139 |
140 | // MARK: - Setup
141 | extension RecordViewController {
142 |
143 | private func setupButtonEvent() {
144 | recordButton.addTarget(self, action: #selector(beginRecordVoice), for: .touchDown)
145 | recordButton.addTarget(self, action: #selector(endRecordVoice), for: .touchUpInside)
146 | recordButton.addTarget(self, action: #selector(cancelRecordVoice), for: .touchUpOutside)
147 | recordButton.addTarget(self, action: #selector(cancelRecordVoice), for: .touchCancel)
148 | recordButton.addTarget(self, action: #selector(remindDragExit), for: .touchDragExit)
149 | recordButton.addTarget(self, action: #selector(remindDragEnter), for: .touchDragEnter)
150 | }
151 |
152 | private func configAVAudioSession() {
153 | let session = AVAudioSession.sharedInstance()
154 | do { try session.setCategory(AVAudioSessionCategoryRecord, with: .defaultToSpeaker) }
155 | catch { print("session config failed") }
156 | }
157 |
158 | private func configRecord() {
159 | AVAudioSession.sharedInstance().requestRecordPermission { (allowed) in
160 | if !allowed {
161 | return
162 | }
163 | }
164 | let session = AVAudioSession.sharedInstance()
165 | do { try session.setCategory(AVAudioSessionCategoryPlayAndRecord, with: .defaultToSpeaker) }
166 | catch { print("session config failed") }
167 | do {
168 | self.recorder = try AVAudioRecorder(url: self.directoryURL()!, settings: self.recorderSetting)
169 | self.recorder.delegate = self
170 | self.recorder.prepareToRecord()
171 | self.recorder.isMeteringEnabled = true
172 | } catch {
173 | print(error.localizedDescription)
174 | }
175 | do { try AVAudioSession.sharedInstance().setActive(true) }
176 | catch { print("session active failed") }
177 | }
178 |
179 | private func directoryURL() -> URL? {
180 | //定义并构建一个url来保存音频,音频文件名为recording-yyyy-MM-dd-HH-mm-ss.m4a
181 | //根据时间来设置存储文件名
182 | let format = DateFormatter()
183 | format.dateFormat="yyyy-MM-dd-HH-mm-ss"
184 | let currentFileName = "recording-\(format.string(from: Date())).m4a"
185 | print(currentFileName)
186 |
187 | let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
188 | let soundFileURL = documentsDirectory.appendingPathComponent(currentFileName)
189 | return soundFileURL
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUD/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 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MCChatHUD
2 |
3 | [MatchaSKD](https://itunes.apple.com/cn/app/matcha-schedule/id1310248785?mt=8)中录音波形图实现Demo,并增加新的样式。
4 |
5 | [文章地址](https://dywane.github.io/在iOS中绘制录音音频波形图/)
6 |
7 | # 效果图
8 | 
9 | 
10 |
11 |
12 | # 实现方式
13 | ### 配置AvAudioSession
14 | 绘制波形图前首先需要配置好`AVAudioSession`,同时需要建立一个数组去保存音量数据。
15 |
16 | #### 相关属性
17 | - **recorderSetting**用于设定录音音质等相关数据。
18 | - **timer**以及**updateFequency**用于定时更新波形图。
19 | - **soundMeter**和**soundMeterCount**用于保存音量表数组。
20 | - **recordTime**用于记录录音时间,可以用于判断录音时间是否达到要求等进一波需求。
21 |
22 |
23 | ```swift
24 | /// 录音器
25 | private var recorder: AVAudioRecorder!
26 | /// 录音器设置
27 | private let recorderSetting = [AVSampleRateKey : NSNumber(value: Float(44100.0)),//声音采样率
28 | AVFormatIDKey : NSNumber(value: Int32(kAudioFormatMPEG4AAC)),//编码格式
29 | AVNumberOfChannelsKey : NSNumber(value: 1),//采集音轨
30 | AVEncoderAudioQualityKey : NSNumber(value: Int32(AVAudioQuality.medium.rawValue))]//声音质量
31 | /// 录音计时器
32 | private var timer: Timer?
33 | /// 波形更新间隔
34 | private let updateFequency = 0.05
35 | /// 声音数据数组
36 | private var soundMeters: [Float]!
37 | /// 声音数据数组容量
38 | private let soundMeterCount = 10
39 | /// 录音时间
40 | private var recordTime = 0.00
41 |
42 | ```
43 | #### AvAudioSession相关配置
44 | - **configAVAudioSession**用于配置`AVAudioSession`,其中`AVAudioSessionCategoryRecord`是代表仅仅利用这个session进行录音操作,而需要播放操作的话是可以设置成`AVAudioSessionCategoryPlayAndRecord`或`AVAudioSessionCategoryPlayBlack`,两者区别一个是可以录音和播放,另一个是可以在后台播放(即静音后仍然可以播放语音)。
45 | - **configRecord**是用于配置整个`AVAudioRecoder`,包括权限获取、代理源设置、是否记录音量表等。
46 | - **directoryURL**是用于配置文件保存地址。
47 |
48 | ```swift
49 | private func configAVAudioSession() {
50 | let session = AVAudioSession.sharedInstance()
51 | do { try session.setCategory(AVAudioSessionCategoryPlayAndRecord, with: .defaultToSpeaker) }
52 | catch { print("session config failed") }
53 | }
54 |
55 |
56 | private func configRecord() {
57 | AVAudioSession.sharedInstance().requestRecordPermission { (allowed) in
58 | if !allowed {
59 | return
60 | }
61 | }
62 | let session = AVAudioSession.sharedInstance()
63 | do { try session.setCategory(AVAudioSessionCategoryPlayAndRecord, with: .defaultToSpeaker) }
64 | catch { print("session config failed") }
65 | do {
66 | self.recorder = try AVAudioRecorder(url: self.directoryURL()!, settings: self.recorderSetting)
67 | self.recorder.delegate = self
68 | self.recorder.prepareToRecord()
69 | self.recorder.isMeteringEnabled = true
70 | } catch {
71 | print(error.localizedDescription)
72 | }
73 | do { try AVAudioSession.sharedInstance().setActive(true) }
74 | catch { print("session active failed") }
75 | }
76 |
77 |
78 | private func directoryURL() -> URL? {
79 | // do something ...
80 | return soundFileURL
81 | }
82 | ```
83 |
84 | ### 记录音频数据
85 | 在开始录音后,利用我们刚刚配置的定时器不断获取`averagePower`,并保存到数组之中。
86 |
87 | - **updateMeters**被定时器调用,不断将recorder中记录的音量数据保存到soundMeter数组中。
88 | - **addSoundMeter**用于完成添加数据的工作。
89 |
90 | ```swift
91 | private func updateMeters() {
92 | recorder.updateMeters()
93 | recordTime += updateFequency
94 | addSoundMeter(item: recorder.averagePower(forChannel: 0))
95 | }
96 |
97 |
98 | private func addSoundMeter(item: Float) {
99 | if soundMeters.count < soundMeterCount {
100 | soundMeters.append(item)
101 | } else {
102 | for (index, _) in soundMeters.enumerated() {
103 | if index < soundMeterCount - 1 {
104 | soundMeters[index] = soundMeters[index + 1]
105 | }
106 | }
107 | // 插入新数据
108 | soundMeters[soundMeterCount - 1] = item
109 | NotificationCenter.default.post(name: NSNotification.Name.init("updateMeters"), object: soundMeters)
110 | }
111 | }
112 | ```
113 |
114 | ### 开始绘制波形图
115 | 现在我们已经获取了我们需要的所有数据,可以开始绘制波形图了。这时候让我们转到`MCVolumeView.swift`文件中,在上一个步骤中,我们发送了一条叫做`updateMeters`的通知,目的就是为了通知`MCVolumeView`进行波形图的更新。
116 |
117 | ```swift
118 | override init(frame: CGRect) {
119 | super.init(frame: frame)
120 | backgroundColor = UIColor.clear
121 | contentMode = .redraw //内容模式为重绘,因为需要多次重复绘制音量表
122 | NotificationCenter.default.addObserver(self, selector: #selector(updateView(notice:)), name: NSNotification.Name.init("updateMeters"), object: nil)
123 | }
124 |
125 | @objc private func updateView(notice: Notification) {
126 | soundMeters = notice.object as! [Float]
127 | setNeedsDisplay()
128 | }
129 | ```
130 |
131 | 当`setNeedsDisplay`被调用之后,就会调用`drawRect`方法,在这里我们可以进行绘制波形图的操作。
132 |
133 | - **noVoice**和**maxVolume**是用于确保声音的显示范围
134 | - 波形图的绘制使用CGContext进行绘制,当然也可以使用UIBezierPath进行绘制。
135 |
136 | ```swift
137 | override func draw(_ rect: CGRect) {
138 | if soundMeters != nil && soundMeters.count > 0 {
139 | let context = UIGraphicsGetCurrentContext()
140 | context?.setLineCap(.round)
141 | context?.setLineJoin(.round)
142 | context?.setStrokeColor(UIColor.white.cgColor)
143 |
144 | let noVoice = -46.0 // 该值代表低于-46.0的声音都认为无声音
145 | let maxVolume = 55.0 // 该值代表最高声音为55.0
146 |
147 | // draw the volume...
148 |
149 | context?.strokePath()
150 | }
151 | }
152 | ```
153 |
154 | ### 柱状波形图的绘制
155 |
156 | - 根据`maxVolume`和`noVoice`计算出每一条柱状的高度,并移动context所在的点进行绘制
157 | - 另外需要注意的是`CGContext`中坐标点时反转的,所以在进行计算时需要将坐标轴进行反转来计算。
158 |
159 | ```swift
160 | case .bar:
161 | context?.setLineWidth(3)
162 | for (index,item) in soundMeters.enumerated() {
163 | let barHeight = maxVolume - (Double(item) - noVoice) //通过当前声音表计算应该显示的声音表高度
164 | context?.move(to: CGPoint(x: index * 6 + 3, y: 40))
165 | context?.addLine(to: CGPoint(x: index * 6 + 3, y: Int(barHeight)))
166 | }
167 | ```
168 |
169 | ### 线状波形图的绘制
170 |
171 | - 线状与条状一样使用同样的方法计算“高度”,但是在绘制条状波形图时,是先画线,再移动,而绘制条状波形图时是先移动再画线。
172 |
173 | ```swift
174 | case .line:
175 | context?.setLineWidth(1.5)
176 | for (index, item) in soundMeters.enumerated() {
177 | let position = maxVolume - (Double(item) - noVoice) //计算对应线段高度
178 | context?.addLine(to: CGPoint(x: Double(index * 6 + 3), y: position))
179 | context?.move(to: CGPoint(x: Double(index * 6 + 3), y: position))
180 | }
181 | ```
182 |
183 | ### 进一步完善我们的波形图
184 | 在很多时候,录音不单止是需要显示波形图,还需要我们展示目前录音的时间和进度,所以我们可以在波形图上添加录音的进度条,所以我们转向`MCProgressView.swift`文件进行操作。
185 |
186 | - 使用`UIBezierPath`配合`CAShapeLayer`进行绘制。
187 | - **maskPath**是作为整个进度路径的蒙版,因为我们的录音HUD不是规则的方形,所以需要使用蒙版进度路径进行裁剪。
188 | - **progressPath**为进度路径,进度的绘制方法为从左到右依次绘制。
189 | - **animation**是进度路径的绘制动画。
190 |
191 | ```swift
192 | private func configAnimate() {
193 | let maskPath = UIBezierPath(roundedRect: CGRect.init(x: 0, y: 0, width: frame.width, height: frame.height), cornerRadius: HUDCornerRadius)
194 | let maskLayer = CAShapeLayer()
195 | maskLayer.backgroundColor = UIColor.clear.cgColor
196 | maskLayer.path = maskPath.cgPath
197 | maskLayer.frame = bounds
198 |
199 | // 进度路径
200 | /*
201 | 路径的中心为HUD的中心,宽度为HUD的高度,从左往右绘制
202 | */
203 | let progressPath = CGMutablePath()
204 | progressPath.move(to: CGPoint(x: 0, y: frame.height / 2))
205 | progressPath.addLine(to: CGPoint(x: frame.width, y: frame.height / 2))
206 |
207 | progressLayer = CAShapeLayer()
208 | progressLayer.frame = bounds
209 | progressLayer.fillColor = UIColor.clear.cgColor //图层背景颜色
210 | progressLayer.strokeColor = UIColor(red: 0.29, green: 0.29, blue: 0.29, alpha: 0.90).cgColor //图层绘制颜色
211 | progressLayer.lineCap = kCALineCapButt
212 | progressLayer.lineWidth = HUDHeight
213 | progressLayer.path = progressPath
214 | progressLayer.mask = maskLayer
215 |
216 | animation = CABasicAnimation(keyPath: "strokeEnd")
217 | animation.duration = 60 //最大录音时长
218 | animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) //匀速前进
219 | animation.fillMode = kCAFillModeForwards
220 | animation.fromValue = 0.0
221 | animation.toValue = 1.0
222 | animation.autoreverses = false
223 | animation.repeatCount = 1
224 | }
225 |
226 | ```
227 |
228 | # 需求环境
229 | - iOS 10.0
230 | - Swift 4.0
231 |
232 | # Contribution
233 | You are welcome to contribute to the project by forking the repo, modifying the code and opening issues or pull requests.
234 |
--------------------------------------------------------------------------------
/MCChatHUD/MCChatHUD.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 48;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 5B1A80CC202708FD0065F21B /* ChooseTypeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B1A80CB202708FD0065F21B /* ChooseTypeViewController.swift */; };
11 | 5B2DA023202050C7008AF29B /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2DA022202050C7008AF29B /* AppDelegate.swift */; };
12 | 5B2DA028202050C7008AF29B /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5B2DA026202050C7008AF29B /* Main.storyboard */; };
13 | 5B2DA02A202050C7008AF29B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5B2DA029202050C7008AF29B /* Assets.xcassets */; };
14 | 5B2DA02D202050C7008AF29B /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5B2DA02B202050C7008AF29B /* LaunchScreen.storyboard */; };
15 | 5B2DA038202050C7008AF29B /* MCChatHUDTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2DA037202050C7008AF29B /* MCChatHUDTests.swift */; };
16 | 5B2DA043202050C7008AF29B /* MCChatHUDUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2DA042202050C7008AF29B /* MCChatHUDUITests.swift */; };
17 | 5B2DA05220205141008AF29B /* MCRecordHUD.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2DA05120205141008AF29B /* MCRecordHUD.swift */; };
18 | 5B2DA05420205167008AF29B /* MCProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2DA05320205167008AF29B /* MCProgressView.swift */; };
19 | 5B2DA0562020517D008AF29B /* MCVolumeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2DA0552020517D008AF29B /* MCVolumeView.swift */; };
20 | 5B2DA059202053D0008AF29B /* HUDMarco.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B2DA058202053D0008AF29B /* HUDMarco.swift */; };
21 | 5B6A6CEB2021E07E00F16718 /* RecordViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6A6CEA2021E07E00F16718 /* RecordViewController.swift */; };
22 | /* End PBXBuildFile section */
23 |
24 | /* Begin PBXContainerItemProxy section */
25 | 5B2DA034202050C7008AF29B /* PBXContainerItemProxy */ = {
26 | isa = PBXContainerItemProxy;
27 | containerPortal = 5B2DA017202050C7008AF29B /* Project object */;
28 | proxyType = 1;
29 | remoteGlobalIDString = 5B2DA01E202050C7008AF29B;
30 | remoteInfo = MCChatHUD;
31 | };
32 | 5B2DA03F202050C7008AF29B /* PBXContainerItemProxy */ = {
33 | isa = PBXContainerItemProxy;
34 | containerPortal = 5B2DA017202050C7008AF29B /* Project object */;
35 | proxyType = 1;
36 | remoteGlobalIDString = 5B2DA01E202050C7008AF29B;
37 | remoteInfo = MCChatHUD;
38 | };
39 | /* End PBXContainerItemProxy section */
40 |
41 | /* Begin PBXFileReference section */
42 | 5B1A80CB202708FD0065F21B /* ChooseTypeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChooseTypeViewController.swift; sourceTree = ""; };
43 | 5B2DA01F202050C7008AF29B /* MCChatHUD.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MCChatHUD.app; sourceTree = BUILT_PRODUCTS_DIR; };
44 | 5B2DA022202050C7008AF29B /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
45 | 5B2DA027202050C7008AF29B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
46 | 5B2DA029202050C7008AF29B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
47 | 5B2DA02C202050C7008AF29B /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
48 | 5B2DA02E202050C7008AF29B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
49 | 5B2DA033202050C7008AF29B /* MCChatHUDTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MCChatHUDTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
50 | 5B2DA037202050C7008AF29B /* MCChatHUDTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCChatHUDTests.swift; sourceTree = ""; };
51 | 5B2DA039202050C7008AF29B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
52 | 5B2DA03E202050C7008AF29B /* MCChatHUDUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MCChatHUDUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
53 | 5B2DA042202050C7008AF29B /* MCChatHUDUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCChatHUDUITests.swift; sourceTree = ""; };
54 | 5B2DA044202050C7008AF29B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
55 | 5B2DA05120205141008AF29B /* MCRecordHUD.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCRecordHUD.swift; sourceTree = ""; };
56 | 5B2DA05320205167008AF29B /* MCProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCProgressView.swift; sourceTree = ""; };
57 | 5B2DA0552020517D008AF29B /* MCVolumeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MCVolumeView.swift; sourceTree = ""; };
58 | 5B2DA058202053D0008AF29B /* HUDMarco.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HUDMarco.swift; sourceTree = ""; };
59 | 5B6A6CEA2021E07E00F16718 /* RecordViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordViewController.swift; sourceTree = ""; };
60 | /* End PBXFileReference section */
61 |
62 | /* Begin PBXFrameworksBuildPhase section */
63 | 5B2DA01C202050C7008AF29B /* Frameworks */ = {
64 | isa = PBXFrameworksBuildPhase;
65 | buildActionMask = 2147483647;
66 | files = (
67 | );
68 | runOnlyForDeploymentPostprocessing = 0;
69 | };
70 | 5B2DA030202050C7008AF29B /* Frameworks */ = {
71 | isa = PBXFrameworksBuildPhase;
72 | buildActionMask = 2147483647;
73 | files = (
74 | );
75 | runOnlyForDeploymentPostprocessing = 0;
76 | };
77 | 5B2DA03B202050C7008AF29B /* Frameworks */ = {
78 | isa = PBXFrameworksBuildPhase;
79 | buildActionMask = 2147483647;
80 | files = (
81 | );
82 | runOnlyForDeploymentPostprocessing = 0;
83 | };
84 | /* End PBXFrameworksBuildPhase section */
85 |
86 | /* Begin PBXGroup section */
87 | 5B2DA016202050C7008AF29B = {
88 | isa = PBXGroup;
89 | children = (
90 | 5B2DA021202050C7008AF29B /* MCChatHUD */,
91 | 5B2DA036202050C7008AF29B /* MCChatHUDTests */,
92 | 5B2DA041202050C7008AF29B /* MCChatHUDUITests */,
93 | 5B2DA020202050C7008AF29B /* Products */,
94 | );
95 | sourceTree = "";
96 | };
97 | 5B2DA020202050C7008AF29B /* Products */ = {
98 | isa = PBXGroup;
99 | children = (
100 | 5B2DA01F202050C7008AF29B /* MCChatHUD.app */,
101 | 5B2DA033202050C7008AF29B /* MCChatHUDTests.xctest */,
102 | 5B2DA03E202050C7008AF29B /* MCChatHUDUITests.xctest */,
103 | );
104 | name = Products;
105 | sourceTree = "";
106 | };
107 | 5B2DA021202050C7008AF29B /* MCChatHUD */ = {
108 | isa = PBXGroup;
109 | children = (
110 | 5B6A6CE92021DF6F00F16718 /* Controller */,
111 | 5B2DA05020205122008AF29B /* View */,
112 | 5B2DA057202053B6008AF29B /* Marco */,
113 | 5B2DA022202050C7008AF29B /* AppDelegate.swift */,
114 | 5B2DA026202050C7008AF29B /* Main.storyboard */,
115 | 5B2DA029202050C7008AF29B /* Assets.xcassets */,
116 | 5B2DA02B202050C7008AF29B /* LaunchScreen.storyboard */,
117 | 5B2DA02E202050C7008AF29B /* Info.plist */,
118 | );
119 | path = MCChatHUD;
120 | sourceTree = "";
121 | };
122 | 5B2DA036202050C7008AF29B /* MCChatHUDTests */ = {
123 | isa = PBXGroup;
124 | children = (
125 | 5B2DA037202050C7008AF29B /* MCChatHUDTests.swift */,
126 | 5B2DA039202050C7008AF29B /* Info.plist */,
127 | );
128 | path = MCChatHUDTests;
129 | sourceTree = "";
130 | };
131 | 5B2DA041202050C7008AF29B /* MCChatHUDUITests */ = {
132 | isa = PBXGroup;
133 | children = (
134 | 5B2DA042202050C7008AF29B /* MCChatHUDUITests.swift */,
135 | 5B2DA044202050C7008AF29B /* Info.plist */,
136 | );
137 | path = MCChatHUDUITests;
138 | sourceTree = "";
139 | };
140 | 5B2DA05020205122008AF29B /* View */ = {
141 | isa = PBXGroup;
142 | children = (
143 | 5B2DA05120205141008AF29B /* MCRecordHUD.swift */,
144 | 5B2DA05320205167008AF29B /* MCProgressView.swift */,
145 | 5B2DA0552020517D008AF29B /* MCVolumeView.swift */,
146 | );
147 | path = View;
148 | sourceTree = "";
149 | };
150 | 5B2DA057202053B6008AF29B /* Marco */ = {
151 | isa = PBXGroup;
152 | children = (
153 | 5B2DA058202053D0008AF29B /* HUDMarco.swift */,
154 | );
155 | path = Marco;
156 | sourceTree = "";
157 | };
158 | 5B6A6CE92021DF6F00F16718 /* Controller */ = {
159 | isa = PBXGroup;
160 | children = (
161 | 5B6A6CEA2021E07E00F16718 /* RecordViewController.swift */,
162 | 5B1A80CB202708FD0065F21B /* ChooseTypeViewController.swift */,
163 | );
164 | path = Controller;
165 | sourceTree = "";
166 | };
167 | /* End PBXGroup section */
168 |
169 | /* Begin PBXNativeTarget section */
170 | 5B2DA01E202050C7008AF29B /* MCChatHUD */ = {
171 | isa = PBXNativeTarget;
172 | buildConfigurationList = 5B2DA047202050C7008AF29B /* Build configuration list for PBXNativeTarget "MCChatHUD" */;
173 | buildPhases = (
174 | 5B2DA01B202050C7008AF29B /* Sources */,
175 | 5B2DA01C202050C7008AF29B /* Frameworks */,
176 | 5B2DA01D202050C7008AF29B /* Resources */,
177 | );
178 | buildRules = (
179 | );
180 | dependencies = (
181 | );
182 | name = MCChatHUD;
183 | productName = MCChatHUD;
184 | productReference = 5B2DA01F202050C7008AF29B /* MCChatHUD.app */;
185 | productType = "com.apple.product-type.application";
186 | };
187 | 5B2DA032202050C7008AF29B /* MCChatHUDTests */ = {
188 | isa = PBXNativeTarget;
189 | buildConfigurationList = 5B2DA04A202050C7008AF29B /* Build configuration list for PBXNativeTarget "MCChatHUDTests" */;
190 | buildPhases = (
191 | 5B2DA02F202050C7008AF29B /* Sources */,
192 | 5B2DA030202050C7008AF29B /* Frameworks */,
193 | 5B2DA031202050C7008AF29B /* Resources */,
194 | );
195 | buildRules = (
196 | );
197 | dependencies = (
198 | 5B2DA035202050C7008AF29B /* PBXTargetDependency */,
199 | );
200 | name = MCChatHUDTests;
201 | productName = MCChatHUDTests;
202 | productReference = 5B2DA033202050C7008AF29B /* MCChatHUDTests.xctest */;
203 | productType = "com.apple.product-type.bundle.unit-test";
204 | };
205 | 5B2DA03D202050C7008AF29B /* MCChatHUDUITests */ = {
206 | isa = PBXNativeTarget;
207 | buildConfigurationList = 5B2DA04D202050C7008AF29B /* Build configuration list for PBXNativeTarget "MCChatHUDUITests" */;
208 | buildPhases = (
209 | 5B2DA03A202050C7008AF29B /* Sources */,
210 | 5B2DA03B202050C7008AF29B /* Frameworks */,
211 | 5B2DA03C202050C7008AF29B /* Resources */,
212 | );
213 | buildRules = (
214 | );
215 | dependencies = (
216 | 5B2DA040202050C7008AF29B /* PBXTargetDependency */,
217 | );
218 | name = MCChatHUDUITests;
219 | productName = MCChatHUDUITests;
220 | productReference = 5B2DA03E202050C7008AF29B /* MCChatHUDUITests.xctest */;
221 | productType = "com.apple.product-type.bundle.ui-testing";
222 | };
223 | /* End PBXNativeTarget section */
224 |
225 | /* Begin PBXProject section */
226 | 5B2DA017202050C7008AF29B /* Project object */ = {
227 | isa = PBXProject;
228 | attributes = {
229 | LastSwiftUpdateCheck = 0920;
230 | LastUpgradeCheck = 0920;
231 | ORGANIZATIONNAME = Dywane;
232 | TargetAttributes = {
233 | 5B2DA01E202050C7008AF29B = {
234 | CreatedOnToolsVersion = 9.2;
235 | ProvisioningStyle = Automatic;
236 | };
237 | 5B2DA032202050C7008AF29B = {
238 | CreatedOnToolsVersion = 9.2;
239 | ProvisioningStyle = Automatic;
240 | TestTargetID = 5B2DA01E202050C7008AF29B;
241 | };
242 | 5B2DA03D202050C7008AF29B = {
243 | CreatedOnToolsVersion = 9.2;
244 | ProvisioningStyle = Automatic;
245 | TestTargetID = 5B2DA01E202050C7008AF29B;
246 | };
247 | };
248 | };
249 | buildConfigurationList = 5B2DA01A202050C7008AF29B /* Build configuration list for PBXProject "MCChatHUD" */;
250 | compatibilityVersion = "Xcode 8.0";
251 | developmentRegion = en;
252 | hasScannedForEncodings = 0;
253 | knownRegions = (
254 | en,
255 | Base,
256 | );
257 | mainGroup = 5B2DA016202050C7008AF29B;
258 | productRefGroup = 5B2DA020202050C7008AF29B /* Products */;
259 | projectDirPath = "";
260 | projectRoot = "";
261 | targets = (
262 | 5B2DA01E202050C7008AF29B /* MCChatHUD */,
263 | 5B2DA032202050C7008AF29B /* MCChatHUDTests */,
264 | 5B2DA03D202050C7008AF29B /* MCChatHUDUITests */,
265 | );
266 | };
267 | /* End PBXProject section */
268 |
269 | /* Begin PBXResourcesBuildPhase section */
270 | 5B2DA01D202050C7008AF29B /* Resources */ = {
271 | isa = PBXResourcesBuildPhase;
272 | buildActionMask = 2147483647;
273 | files = (
274 | 5B2DA02D202050C7008AF29B /* LaunchScreen.storyboard in Resources */,
275 | 5B2DA02A202050C7008AF29B /* Assets.xcassets in Resources */,
276 | 5B2DA028202050C7008AF29B /* Main.storyboard in Resources */,
277 | );
278 | runOnlyForDeploymentPostprocessing = 0;
279 | };
280 | 5B2DA031202050C7008AF29B /* Resources */ = {
281 | isa = PBXResourcesBuildPhase;
282 | buildActionMask = 2147483647;
283 | files = (
284 | );
285 | runOnlyForDeploymentPostprocessing = 0;
286 | };
287 | 5B2DA03C202050C7008AF29B /* Resources */ = {
288 | isa = PBXResourcesBuildPhase;
289 | buildActionMask = 2147483647;
290 | files = (
291 | );
292 | runOnlyForDeploymentPostprocessing = 0;
293 | };
294 | /* End PBXResourcesBuildPhase section */
295 |
296 | /* Begin PBXSourcesBuildPhase section */
297 | 5B2DA01B202050C7008AF29B /* Sources */ = {
298 | isa = PBXSourcesBuildPhase;
299 | buildActionMask = 2147483647;
300 | files = (
301 | 5B2DA0562020517D008AF29B /* MCVolumeView.swift in Sources */,
302 | 5B1A80CC202708FD0065F21B /* ChooseTypeViewController.swift in Sources */,
303 | 5B2DA05220205141008AF29B /* MCRecordHUD.swift in Sources */,
304 | 5B2DA059202053D0008AF29B /* HUDMarco.swift in Sources */,
305 | 5B6A6CEB2021E07E00F16718 /* RecordViewController.swift in Sources */,
306 | 5B2DA023202050C7008AF29B /* AppDelegate.swift in Sources */,
307 | 5B2DA05420205167008AF29B /* MCProgressView.swift in Sources */,
308 | );
309 | runOnlyForDeploymentPostprocessing = 0;
310 | };
311 | 5B2DA02F202050C7008AF29B /* Sources */ = {
312 | isa = PBXSourcesBuildPhase;
313 | buildActionMask = 2147483647;
314 | files = (
315 | 5B2DA038202050C7008AF29B /* MCChatHUDTests.swift in Sources */,
316 | );
317 | runOnlyForDeploymentPostprocessing = 0;
318 | };
319 | 5B2DA03A202050C7008AF29B /* Sources */ = {
320 | isa = PBXSourcesBuildPhase;
321 | buildActionMask = 2147483647;
322 | files = (
323 | 5B2DA043202050C7008AF29B /* MCChatHUDUITests.swift in Sources */,
324 | );
325 | runOnlyForDeploymentPostprocessing = 0;
326 | };
327 | /* End PBXSourcesBuildPhase section */
328 |
329 | /* Begin PBXTargetDependency section */
330 | 5B2DA035202050C7008AF29B /* PBXTargetDependency */ = {
331 | isa = PBXTargetDependency;
332 | target = 5B2DA01E202050C7008AF29B /* MCChatHUD */;
333 | targetProxy = 5B2DA034202050C7008AF29B /* PBXContainerItemProxy */;
334 | };
335 | 5B2DA040202050C7008AF29B /* PBXTargetDependency */ = {
336 | isa = PBXTargetDependency;
337 | target = 5B2DA01E202050C7008AF29B /* MCChatHUD */;
338 | targetProxy = 5B2DA03F202050C7008AF29B /* PBXContainerItemProxy */;
339 | };
340 | /* End PBXTargetDependency section */
341 |
342 | /* Begin PBXVariantGroup section */
343 | 5B2DA026202050C7008AF29B /* Main.storyboard */ = {
344 | isa = PBXVariantGroup;
345 | children = (
346 | 5B2DA027202050C7008AF29B /* Base */,
347 | );
348 | name = Main.storyboard;
349 | sourceTree = "";
350 | };
351 | 5B2DA02B202050C7008AF29B /* LaunchScreen.storyboard */ = {
352 | isa = PBXVariantGroup;
353 | children = (
354 | 5B2DA02C202050C7008AF29B /* Base */,
355 | );
356 | name = LaunchScreen.storyboard;
357 | sourceTree = "";
358 | };
359 | /* End PBXVariantGroup section */
360 |
361 | /* Begin XCBuildConfiguration section */
362 | 5B2DA045202050C7008AF29B /* Debug */ = {
363 | isa = XCBuildConfiguration;
364 | buildSettings = {
365 | ALWAYS_SEARCH_USER_PATHS = NO;
366 | CLANG_ANALYZER_NONNULL = YES;
367 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
368 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
369 | CLANG_CXX_LIBRARY = "libc++";
370 | CLANG_ENABLE_MODULES = YES;
371 | CLANG_ENABLE_OBJC_ARC = YES;
372 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
373 | CLANG_WARN_BOOL_CONVERSION = YES;
374 | CLANG_WARN_COMMA = YES;
375 | CLANG_WARN_CONSTANT_CONVERSION = YES;
376 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
377 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
378 | CLANG_WARN_EMPTY_BODY = YES;
379 | CLANG_WARN_ENUM_CONVERSION = YES;
380 | CLANG_WARN_INFINITE_RECURSION = YES;
381 | CLANG_WARN_INT_CONVERSION = YES;
382 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
383 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
384 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
385 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
386 | CLANG_WARN_STRICT_PROTOTYPES = YES;
387 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
388 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
389 | CLANG_WARN_UNREACHABLE_CODE = YES;
390 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
391 | CODE_SIGN_IDENTITY = "iPhone Developer";
392 | COPY_PHASE_STRIP = NO;
393 | DEBUG_INFORMATION_FORMAT = dwarf;
394 | ENABLE_STRICT_OBJC_MSGSEND = YES;
395 | ENABLE_TESTABILITY = YES;
396 | GCC_C_LANGUAGE_STANDARD = gnu11;
397 | GCC_DYNAMIC_NO_PIC = NO;
398 | GCC_NO_COMMON_BLOCKS = YES;
399 | GCC_OPTIMIZATION_LEVEL = 0;
400 | GCC_PREPROCESSOR_DEFINITIONS = (
401 | "DEBUG=1",
402 | "$(inherited)",
403 | );
404 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
405 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
406 | GCC_WARN_UNDECLARED_SELECTOR = YES;
407 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
408 | GCC_WARN_UNUSED_FUNCTION = YES;
409 | GCC_WARN_UNUSED_VARIABLE = YES;
410 | IPHONEOS_DEPLOYMENT_TARGET = 11.2;
411 | MTL_ENABLE_DEBUG_INFO = YES;
412 | ONLY_ACTIVE_ARCH = YES;
413 | SDKROOT = iphoneos;
414 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
415 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
416 | };
417 | name = Debug;
418 | };
419 | 5B2DA046202050C7008AF29B /* Release */ = {
420 | isa = XCBuildConfiguration;
421 | buildSettings = {
422 | ALWAYS_SEARCH_USER_PATHS = NO;
423 | CLANG_ANALYZER_NONNULL = YES;
424 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
425 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
426 | CLANG_CXX_LIBRARY = "libc++";
427 | CLANG_ENABLE_MODULES = YES;
428 | CLANG_ENABLE_OBJC_ARC = YES;
429 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
430 | CLANG_WARN_BOOL_CONVERSION = YES;
431 | CLANG_WARN_COMMA = YES;
432 | CLANG_WARN_CONSTANT_CONVERSION = YES;
433 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
434 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
435 | CLANG_WARN_EMPTY_BODY = YES;
436 | CLANG_WARN_ENUM_CONVERSION = YES;
437 | CLANG_WARN_INFINITE_RECURSION = YES;
438 | CLANG_WARN_INT_CONVERSION = YES;
439 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
440 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
441 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
442 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
443 | CLANG_WARN_STRICT_PROTOTYPES = YES;
444 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
445 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
446 | CLANG_WARN_UNREACHABLE_CODE = YES;
447 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
448 | CODE_SIGN_IDENTITY = "iPhone Developer";
449 | COPY_PHASE_STRIP = NO;
450 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
451 | ENABLE_NS_ASSERTIONS = NO;
452 | ENABLE_STRICT_OBJC_MSGSEND = YES;
453 | GCC_C_LANGUAGE_STANDARD = gnu11;
454 | GCC_NO_COMMON_BLOCKS = YES;
455 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
456 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
457 | GCC_WARN_UNDECLARED_SELECTOR = YES;
458 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
459 | GCC_WARN_UNUSED_FUNCTION = YES;
460 | GCC_WARN_UNUSED_VARIABLE = YES;
461 | IPHONEOS_DEPLOYMENT_TARGET = 11.2;
462 | MTL_ENABLE_DEBUG_INFO = NO;
463 | SDKROOT = iphoneos;
464 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
465 | VALIDATE_PRODUCT = YES;
466 | };
467 | name = Release;
468 | };
469 | 5B2DA048202050C7008AF29B /* Debug */ = {
470 | isa = XCBuildConfiguration;
471 | buildSettings = {
472 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
473 | CODE_SIGN_STYLE = Automatic;
474 | DEVELOPMENT_TEAM = 55F5T35K6E;
475 | INFOPLIST_FILE = MCChatHUD/Info.plist;
476 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
477 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
478 | PRODUCT_BUNDLE_IDENTIFIER = dywane.MCChatHUD;
479 | PRODUCT_NAME = "$(TARGET_NAME)";
480 | SWIFT_VERSION = 4.0;
481 | TARGETED_DEVICE_FAMILY = "1,2";
482 | };
483 | name = Debug;
484 | };
485 | 5B2DA049202050C7008AF29B /* Release */ = {
486 | isa = XCBuildConfiguration;
487 | buildSettings = {
488 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
489 | CODE_SIGN_STYLE = Automatic;
490 | DEVELOPMENT_TEAM = 55F5T35K6E;
491 | INFOPLIST_FILE = MCChatHUD/Info.plist;
492 | IPHONEOS_DEPLOYMENT_TARGET = 10.0;
493 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
494 | PRODUCT_BUNDLE_IDENTIFIER = dywane.MCChatHUD;
495 | PRODUCT_NAME = "$(TARGET_NAME)";
496 | SWIFT_VERSION = 4.0;
497 | TARGETED_DEVICE_FAMILY = "1,2";
498 | };
499 | name = Release;
500 | };
501 | 5B2DA04B202050C7008AF29B /* Debug */ = {
502 | isa = XCBuildConfiguration;
503 | buildSettings = {
504 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
505 | BUNDLE_LOADER = "$(TEST_HOST)";
506 | CODE_SIGN_STYLE = Automatic;
507 | DEVELOPMENT_TEAM = 55F5T35K6E;
508 | INFOPLIST_FILE = MCChatHUDTests/Info.plist;
509 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
510 | PRODUCT_BUNDLE_IDENTIFIER = dywane.MCChatHUDTests;
511 | PRODUCT_NAME = "$(TARGET_NAME)";
512 | SWIFT_VERSION = 4.0;
513 | TARGETED_DEVICE_FAMILY = "1,2";
514 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MCChatHUD.app/MCChatHUD";
515 | };
516 | name = Debug;
517 | };
518 | 5B2DA04C202050C7008AF29B /* Release */ = {
519 | isa = XCBuildConfiguration;
520 | buildSettings = {
521 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
522 | BUNDLE_LOADER = "$(TEST_HOST)";
523 | CODE_SIGN_STYLE = Automatic;
524 | DEVELOPMENT_TEAM = 55F5T35K6E;
525 | INFOPLIST_FILE = MCChatHUDTests/Info.plist;
526 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
527 | PRODUCT_BUNDLE_IDENTIFIER = dywane.MCChatHUDTests;
528 | PRODUCT_NAME = "$(TARGET_NAME)";
529 | SWIFT_VERSION = 4.0;
530 | TARGETED_DEVICE_FAMILY = "1,2";
531 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MCChatHUD.app/MCChatHUD";
532 | };
533 | name = Release;
534 | };
535 | 5B2DA04E202050C7008AF29B /* Debug */ = {
536 | isa = XCBuildConfiguration;
537 | buildSettings = {
538 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
539 | CODE_SIGN_STYLE = Automatic;
540 | DEVELOPMENT_TEAM = 55F5T35K6E;
541 | INFOPLIST_FILE = MCChatHUDUITests/Info.plist;
542 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
543 | PRODUCT_BUNDLE_IDENTIFIER = dywane.MCChatHUDUITests;
544 | PRODUCT_NAME = "$(TARGET_NAME)";
545 | SWIFT_VERSION = 4.0;
546 | TARGETED_DEVICE_FAMILY = "1,2";
547 | TEST_TARGET_NAME = MCChatHUD;
548 | };
549 | name = Debug;
550 | };
551 | 5B2DA04F202050C7008AF29B /* Release */ = {
552 | isa = XCBuildConfiguration;
553 | buildSettings = {
554 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
555 | CODE_SIGN_STYLE = Automatic;
556 | DEVELOPMENT_TEAM = 55F5T35K6E;
557 | INFOPLIST_FILE = MCChatHUDUITests/Info.plist;
558 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
559 | PRODUCT_BUNDLE_IDENTIFIER = dywane.MCChatHUDUITests;
560 | PRODUCT_NAME = "$(TARGET_NAME)";
561 | SWIFT_VERSION = 4.0;
562 | TARGETED_DEVICE_FAMILY = "1,2";
563 | TEST_TARGET_NAME = MCChatHUD;
564 | };
565 | name = Release;
566 | };
567 | /* End XCBuildConfiguration section */
568 |
569 | /* Begin XCConfigurationList section */
570 | 5B2DA01A202050C7008AF29B /* Build configuration list for PBXProject "MCChatHUD" */ = {
571 | isa = XCConfigurationList;
572 | buildConfigurations = (
573 | 5B2DA045202050C7008AF29B /* Debug */,
574 | 5B2DA046202050C7008AF29B /* Release */,
575 | );
576 | defaultConfigurationIsVisible = 0;
577 | defaultConfigurationName = Release;
578 | };
579 | 5B2DA047202050C7008AF29B /* Build configuration list for PBXNativeTarget "MCChatHUD" */ = {
580 | isa = XCConfigurationList;
581 | buildConfigurations = (
582 | 5B2DA048202050C7008AF29B /* Debug */,
583 | 5B2DA049202050C7008AF29B /* Release */,
584 | );
585 | defaultConfigurationIsVisible = 0;
586 | defaultConfigurationName = Release;
587 | };
588 | 5B2DA04A202050C7008AF29B /* Build configuration list for PBXNativeTarget "MCChatHUDTests" */ = {
589 | isa = XCConfigurationList;
590 | buildConfigurations = (
591 | 5B2DA04B202050C7008AF29B /* Debug */,
592 | 5B2DA04C202050C7008AF29B /* Release */,
593 | );
594 | defaultConfigurationIsVisible = 0;
595 | defaultConfigurationName = Release;
596 | };
597 | 5B2DA04D202050C7008AF29B /* Build configuration list for PBXNativeTarget "MCChatHUDUITests" */ = {
598 | isa = XCConfigurationList;
599 | buildConfigurations = (
600 | 5B2DA04E202050C7008AF29B /* Debug */,
601 | 5B2DA04F202050C7008AF29B /* Release */,
602 | );
603 | defaultConfigurationIsVisible = 0;
604 | defaultConfigurationName = Release;
605 | };
606 | /* End XCConfigurationList section */
607 | };
608 | rootObject = 5B2DA017202050C7008AF29B /* Project object */;
609 | }
610 |
--------------------------------------------------------------------------------