From 7c03c557f0498b28f3cd60ab1713e57155da3be0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E4=BF=8A=E6=99=93?= Date: Mon, 5 Feb 2018 15:11:56 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A6=96=E6=AC=A1=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AVAudioRecorderDemo.xcodeproj/project.pbxproj | 627 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcschemes/xcschememanagement.plist | 14 + AVAudioRecorderDemo/AppDelegate.h | 17 + AVAudioRecorderDemo/AppDelegate.m | 59 ++ .../AppIcon.appiconset/Contents.json | 98 +++ .../Assets.xcassets/Contents.json | 6 + .../pause.imageset/Contents.json | 22 + .../Assets.xcassets/pause.imageset/pause.png | Bin 0 -> 2909 bytes .../pause.imageset/pause@2x.png | Bin 0 -> 3117 bytes .../record.imageset/Contents.json | 22 + .../Assets.xcassets/record.imageset/play.png | Bin 0 -> 3491 bytes .../record.imageset/play@2x.png | Bin 0 -> 4712 bytes .../stop.imageset/Contents.json | 22 + .../Assets.xcassets/stop.imageset/stop.png | Bin 0 -> 2841 bytes .../Assets.xcassets/stop.imageset/stop@2x.png | Bin 0 -> 3077 bytes .../transport_bg.imageset/Contents.json | 22 + .../transport_bg.imageset/transport_bg.png | Bin 0 -> 4447 bytes .../transport_bg.imageset/transport_bg@2x.png | Bin 0 -> 7004 bytes .../Base.lproj/LaunchScreen.storyboard | 25 + .../Base.lproj/Main.storyboard | 114 ++++ AVAudioRecorderDemo/Info.plist | 72 ++ AVAudioRecorderDemo/THLevelPair.h | 37 ++ AVAudioRecorderDemo/THLevelPair.m | 43 ++ AVAudioRecorderDemo/THMemo.h | 39 ++ AVAudioRecorderDemo/THMemo.m | 99 +++ AVAudioRecorderDemo/THMemoCell.h | 15 + AVAudioRecorderDemo/THMemoCell.m | 24 + AVAudioRecorderDemo/THMemoCell.xib | 68 ++ AVAudioRecorderDemo/THRecorderController.h | 31 + AVAudioRecorderDemo/THRecorderController.m | 146 ++++ AVAudioRecorderDemo/ViewController.h | 13 + AVAudioRecorderDemo/ViewController.m | 242 +++++++ .../leaveMeter/THLevelMeterColorThreshold.h | 36 + .../leaveMeter/THLevelMeterColorThreshold.m | 48 ++ .../leaveMeter/THLevelMeterView.h | 35 + .../leaveMeter/THLevelMeterView.m | 165 +++++ AVAudioRecorderDemo/leaveMeter/THMeterTable.h | 35 + AVAudioRecorderDemo/leaveMeter/THMeterTable.m | 76 +++ AVAudioRecorderDemo/main.m | 16 + .../AVAudioRecorderDemoTests.m | 39 ++ AVAudioRecorderDemoTests/Info.plist | 22 + .../AVAudioRecorderDemoUITests.m | 40 ++ AVAudioRecorderDemoUITests/Info.plist | 22 + 44 files changed, 2418 insertions(+) create mode 100644 AVAudioRecorderDemo.xcodeproj/project.pbxproj create mode 100644 AVAudioRecorderDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 AVAudioRecorderDemo.xcodeproj/xcuserdata/yuanjunxiao.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 AVAudioRecorderDemo/AppDelegate.h create mode 100644 AVAudioRecorderDemo/AppDelegate.m create mode 100644 AVAudioRecorderDemo/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 AVAudioRecorderDemo/Assets.xcassets/Contents.json create mode 100644 AVAudioRecorderDemo/Assets.xcassets/pause.imageset/Contents.json create mode 100644 AVAudioRecorderDemo/Assets.xcassets/pause.imageset/pause.png create mode 100644 AVAudioRecorderDemo/Assets.xcassets/pause.imageset/pause@2x.png create mode 100644 AVAudioRecorderDemo/Assets.xcassets/record.imageset/Contents.json create mode 100644 AVAudioRecorderDemo/Assets.xcassets/record.imageset/play.png create mode 100644 AVAudioRecorderDemo/Assets.xcassets/record.imageset/play@2x.png create mode 100644 AVAudioRecorderDemo/Assets.xcassets/stop.imageset/Contents.json create mode 100644 AVAudioRecorderDemo/Assets.xcassets/stop.imageset/stop.png create mode 100644 AVAudioRecorderDemo/Assets.xcassets/stop.imageset/stop@2x.png create mode 100644 AVAudioRecorderDemo/Assets.xcassets/transport_bg.imageset/Contents.json create mode 100644 AVAudioRecorderDemo/Assets.xcassets/transport_bg.imageset/transport_bg.png create mode 100644 AVAudioRecorderDemo/Assets.xcassets/transport_bg.imageset/transport_bg@2x.png create mode 100644 AVAudioRecorderDemo/Base.lproj/LaunchScreen.storyboard create mode 100644 AVAudioRecorderDemo/Base.lproj/Main.storyboard create mode 100644 AVAudioRecorderDemo/Info.plist create mode 100644 AVAudioRecorderDemo/THLevelPair.h create mode 100644 AVAudioRecorderDemo/THLevelPair.m create mode 100644 AVAudioRecorderDemo/THMemo.h create mode 100644 AVAudioRecorderDemo/THMemo.m create mode 100644 AVAudioRecorderDemo/THMemoCell.h create mode 100644 AVAudioRecorderDemo/THMemoCell.m create mode 100644 AVAudioRecorderDemo/THMemoCell.xib create mode 100644 AVAudioRecorderDemo/THRecorderController.h create mode 100644 AVAudioRecorderDemo/THRecorderController.m create mode 100644 AVAudioRecorderDemo/ViewController.h create mode 100644 AVAudioRecorderDemo/ViewController.m create mode 100644 AVAudioRecorderDemo/leaveMeter/THLevelMeterColorThreshold.h create mode 100644 AVAudioRecorderDemo/leaveMeter/THLevelMeterColorThreshold.m create mode 100644 AVAudioRecorderDemo/leaveMeter/THLevelMeterView.h create mode 100644 AVAudioRecorderDemo/leaveMeter/THLevelMeterView.m create mode 100644 AVAudioRecorderDemo/leaveMeter/THMeterTable.h create mode 100644 AVAudioRecorderDemo/leaveMeter/THMeterTable.m create mode 100644 AVAudioRecorderDemo/main.m create mode 100644 AVAudioRecorderDemoTests/AVAudioRecorderDemoTests.m create mode 100644 AVAudioRecorderDemoTests/Info.plist create mode 100644 AVAudioRecorderDemoUITests/AVAudioRecorderDemoUITests.m create mode 100644 AVAudioRecorderDemoUITests/Info.plist diff --git a/AVAudioRecorderDemo.xcodeproj/project.pbxproj b/AVAudioRecorderDemo.xcodeproj/project.pbxproj new file mode 100644 index 0000000..3fddd81 --- /dev/null +++ b/AVAudioRecorderDemo.xcodeproj/project.pbxproj @@ -0,0 +1,627 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 48; + objects = { + +/* Begin PBXBuildFile section */ + 6F1313EA2026D83000696C74 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F1313E92026D83000696C74 /* AppDelegate.m */; }; + 6F1313ED2026D83000696C74 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F1313EC2026D83000696C74 /* ViewController.m */; }; + 6F1313F02026D83000696C74 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6F1313EE2026D83000696C74 /* Main.storyboard */; }; + 6F1313F22026D83000696C74 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6F1313F12026D83000696C74 /* Assets.xcassets */; }; + 6F1313F52026D83000696C74 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6F1313F32026D83000696C74 /* LaunchScreen.storyboard */; }; + 6F1313F82026D83000696C74 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F1313F72026D83000696C74 /* main.m */; }; + 6F1314022026D83000696C74 /* AVAudioRecorderDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F1314012026D83000696C74 /* AVAudioRecorderDemoTests.m */; }; + 6F13140D2026D83000696C74 /* AVAudioRecorderDemoUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F13140C2026D83000696C74 /* AVAudioRecorderDemoUITests.m */; }; + 6F13141C202702B800696C74 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F13141B202702B800696C74 /* AVFoundation.framework */; }; + 6F13141F20272AA500696C74 /* THRecorderController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F13141E20272AA500696C74 /* THRecorderController.m */; }; + 6F1314222027F56200696C74 /* THMemo.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F1314202027F56200696C74 /* THMemo.m */; }; + 6F1314242027F5C200696C74 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F1314232027F5C200696C74 /* UIKit.framework */; }; + 6F1314262027F5D200696C74 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F1314252027F5D200696C74 /* CoreGraphics.framework */; }; + 6F131429202807B000696C74 /* THLevelPair.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F131428202807B000696C74 /* THLevelPair.m */; }; + 6F1314312028086700696C74 /* THLevelMeterView.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F13142D2028086600696C74 /* THLevelMeterView.m */; }; + 6F1314322028086700696C74 /* THMeterTable.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F13142E2028086700696C74 /* THMeterTable.m */; }; + 6F1314332028086700696C74 /* THLevelMeterColorThreshold.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F1314302028086700696C74 /* THLevelMeterColorThreshold.m */; }; + 6F13143A202825DA00696C74 /* THMemoCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F131438202825DA00696C74 /* THMemoCell.m */; }; + 6F13143B202825DA00696C74 /* THMemoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6F131439202825DA00696C74 /* THMemoCell.xib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 6F1313FE2026D83000696C74 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6F1313DD2026D83000696C74 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6F1313E42026D83000696C74; + remoteInfo = AVAudioRecorderDemo; + }; + 6F1314092026D83000696C74 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6F1313DD2026D83000696C74 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 6F1313E42026D83000696C74; + remoteInfo = AVAudioRecorderDemo; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 6F1313E52026D83000696C74 /* AVAudioRecorderDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AVAudioRecorderDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 6F1313E82026D83000696C74 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + 6F1313E92026D83000696C74 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + 6F1313EB2026D83000696C74 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + 6F1313EC2026D83000696C74 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + 6F1313EF2026D83000696C74 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 6F1313F12026D83000696C74 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 6F1313F42026D83000696C74 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 6F1313F62026D83000696C74 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6F1313F72026D83000696C74 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 6F1313FD2026D83000696C74 /* AVAudioRecorderDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AVAudioRecorderDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 6F1314012026D83000696C74 /* AVAudioRecorderDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AVAudioRecorderDemoTests.m; sourceTree = ""; }; + 6F1314032026D83000696C74 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6F1314082026D83000696C74 /* AVAudioRecorderDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AVAudioRecorderDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 6F13140C2026D83000696C74 /* AVAudioRecorderDemoUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AVAudioRecorderDemoUITests.m; sourceTree = ""; }; + 6F13140E2026D83000696C74 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6F13141B202702B800696C74 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + 6F13141D20272AA500696C74 /* THRecorderController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = THRecorderController.h; sourceTree = ""; }; + 6F13141E20272AA500696C74 /* THRecorderController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = THRecorderController.m; sourceTree = ""; }; + 6F1314202027F56200696C74 /* THMemo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = THMemo.m; sourceTree = ""; }; + 6F1314212027F56200696C74 /* THMemo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = THMemo.h; sourceTree = ""; }; + 6F1314232027F5C200696C74 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 6F1314252027F5D200696C74 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 6F131427202807B000696C74 /* THLevelPair.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = THLevelPair.h; sourceTree = ""; }; + 6F131428202807B000696C74 /* THLevelPair.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = THLevelPair.m; sourceTree = ""; }; + 6F13142B2028086600696C74 /* THMeterTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = THMeterTable.h; sourceTree = ""; }; + 6F13142C2028086600696C74 /* THLevelMeterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = THLevelMeterView.h; sourceTree = ""; }; + 6F13142D2028086600696C74 /* THLevelMeterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = THLevelMeterView.m; sourceTree = ""; }; + 6F13142E2028086700696C74 /* THMeterTable.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = THMeterTable.m; sourceTree = ""; }; + 6F13142F2028086700696C74 /* THLevelMeterColorThreshold.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = THLevelMeterColorThreshold.h; sourceTree = ""; }; + 6F1314302028086700696C74 /* THLevelMeterColorThreshold.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = THLevelMeterColorThreshold.m; sourceTree = ""; }; + 6F131437202825DA00696C74 /* THMemoCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = THMemoCell.h; sourceTree = ""; }; + 6F131438202825DA00696C74 /* THMemoCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = THMemoCell.m; sourceTree = ""; }; + 6F131439202825DA00696C74 /* THMemoCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = THMemoCell.xib; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 6F1313E22026D83000696C74 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 6F1314262027F5D200696C74 /* CoreGraphics.framework in Frameworks */, + 6F1314242027F5C200696C74 /* UIKit.framework in Frameworks */, + 6F13141C202702B800696C74 /* AVFoundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6F1313FA2026D83000696C74 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6F1314052026D83000696C74 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 6F1313DC2026D83000696C74 = { + isa = PBXGroup; + children = ( + 6F1313E72026D83000696C74 /* AVAudioRecorderDemo */, + 6F1314002026D83000696C74 /* AVAudioRecorderDemoTests */, + 6F13140B2026D83000696C74 /* AVAudioRecorderDemoUITests */, + 6F1313E62026D83000696C74 /* Products */, + 6F13141A202702B800696C74 /* Frameworks */, + ); + sourceTree = ""; + }; + 6F1313E62026D83000696C74 /* Products */ = { + isa = PBXGroup; + children = ( + 6F1313E52026D83000696C74 /* AVAudioRecorderDemo.app */, + 6F1313FD2026D83000696C74 /* AVAudioRecorderDemoTests.xctest */, + 6F1314082026D83000696C74 /* AVAudioRecorderDemoUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 6F1313E72026D83000696C74 /* AVAudioRecorderDemo */ = { + isa = PBXGroup; + children = ( + 6F13142A2028084600696C74 /* leaveMeter */, + 6F131427202807B000696C74 /* THLevelPair.h */, + 6F131428202807B000696C74 /* THLevelPair.m */, + 6F1314212027F56200696C74 /* THMemo.h */, + 6F1314202027F56200696C74 /* THMemo.m */, + 6F1313E82026D83000696C74 /* AppDelegate.h */, + 6F1313E92026D83000696C74 /* AppDelegate.m */, + 6F1313EB2026D83000696C74 /* ViewController.h */, + 6F1313EC2026D83000696C74 /* ViewController.m */, + 6F1313EE2026D83000696C74 /* Main.storyboard */, + 6F1313F12026D83000696C74 /* Assets.xcassets */, + 6F1313F32026D83000696C74 /* LaunchScreen.storyboard */, + 6F1313F62026D83000696C74 /* Info.plist */, + 6F1313F72026D83000696C74 /* main.m */, + 6F13141D20272AA500696C74 /* THRecorderController.h */, + 6F13141E20272AA500696C74 /* THRecorderController.m */, + 6F131437202825DA00696C74 /* THMemoCell.h */, + 6F131438202825DA00696C74 /* THMemoCell.m */, + 6F131439202825DA00696C74 /* THMemoCell.xib */, + ); + path = AVAudioRecorderDemo; + sourceTree = ""; + }; + 6F1314002026D83000696C74 /* AVAudioRecorderDemoTests */ = { + isa = PBXGroup; + children = ( + 6F1314012026D83000696C74 /* AVAudioRecorderDemoTests.m */, + 6F1314032026D83000696C74 /* Info.plist */, + ); + path = AVAudioRecorderDemoTests; + sourceTree = ""; + }; + 6F13140B2026D83000696C74 /* AVAudioRecorderDemoUITests */ = { + isa = PBXGroup; + children = ( + 6F13140C2026D83000696C74 /* AVAudioRecorderDemoUITests.m */, + 6F13140E2026D83000696C74 /* Info.plist */, + ); + path = AVAudioRecorderDemoUITests; + sourceTree = ""; + }; + 6F13141A202702B800696C74 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 6F1314252027F5D200696C74 /* CoreGraphics.framework */, + 6F1314232027F5C200696C74 /* UIKit.framework */, + 6F13141B202702B800696C74 /* AVFoundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 6F13142A2028084600696C74 /* leaveMeter */ = { + isa = PBXGroup; + children = ( + 6F13142F2028086700696C74 /* THLevelMeterColorThreshold.h */, + 6F1314302028086700696C74 /* THLevelMeterColorThreshold.m */, + 6F13142C2028086600696C74 /* THLevelMeterView.h */, + 6F13142D2028086600696C74 /* THLevelMeterView.m */, + 6F13142B2028086600696C74 /* THMeterTable.h */, + 6F13142E2028086700696C74 /* THMeterTable.m */, + ); + path = leaveMeter; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 6F1313E42026D83000696C74 /* AVAudioRecorderDemo */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6F1314112026D83000696C74 /* Build configuration list for PBXNativeTarget "AVAudioRecorderDemo" */; + buildPhases = ( + 6F1313E12026D83000696C74 /* Sources */, + 6F1313E22026D83000696C74 /* Frameworks */, + 6F1313E32026D83000696C74 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = AVAudioRecorderDemo; + productName = AVAudioRecorderDemo; + productReference = 6F1313E52026D83000696C74 /* AVAudioRecorderDemo.app */; + productType = "com.apple.product-type.application"; + }; + 6F1313FC2026D83000696C74 /* AVAudioRecorderDemoTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6F1314142026D83000696C74 /* Build configuration list for PBXNativeTarget "AVAudioRecorderDemoTests" */; + buildPhases = ( + 6F1313F92026D83000696C74 /* Sources */, + 6F1313FA2026D83000696C74 /* Frameworks */, + 6F1313FB2026D83000696C74 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 6F1313FF2026D83000696C74 /* PBXTargetDependency */, + ); + name = AVAudioRecorderDemoTests; + productName = AVAudioRecorderDemoTests; + productReference = 6F1313FD2026D83000696C74 /* AVAudioRecorderDemoTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 6F1314072026D83000696C74 /* AVAudioRecorderDemoUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 6F1314172026D83000696C74 /* Build configuration list for PBXNativeTarget "AVAudioRecorderDemoUITests" */; + buildPhases = ( + 6F1314042026D83000696C74 /* Sources */, + 6F1314052026D83000696C74 /* Frameworks */, + 6F1314062026D83000696C74 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 6F13140A2026D83000696C74 /* PBXTargetDependency */, + ); + name = AVAudioRecorderDemoUITests; + productName = AVAudioRecorderDemoUITests; + productReference = 6F1314082026D83000696C74 /* AVAudioRecorderDemoUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 6F1313DD2026D83000696C74 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0920; + ORGANIZATIONNAME = yuanjunxiao; + TargetAttributes = { + 6F1313E42026D83000696C74 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Automatic; + }; + 6F1313FC2026D83000696C74 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Automatic; + TestTargetID = 6F1313E42026D83000696C74; + }; + 6F1314072026D83000696C74 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Automatic; + TestTargetID = 6F1313E42026D83000696C74; + }; + }; + }; + buildConfigurationList = 6F1313E02026D83000696C74 /* Build configuration list for PBXProject "AVAudioRecorderDemo" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 6F1313DC2026D83000696C74; + productRefGroup = 6F1313E62026D83000696C74 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 6F1313E42026D83000696C74 /* AVAudioRecorderDemo */, + 6F1313FC2026D83000696C74 /* AVAudioRecorderDemoTests */, + 6F1314072026D83000696C74 /* AVAudioRecorderDemoUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 6F1313E32026D83000696C74 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6F1313F52026D83000696C74 /* LaunchScreen.storyboard in Resources */, + 6F13143B202825DA00696C74 /* THMemoCell.xib in Resources */, + 6F1313F22026D83000696C74 /* Assets.xcassets in Resources */, + 6F1313F02026D83000696C74 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6F1313FB2026D83000696C74 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6F1314062026D83000696C74 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 6F1313E12026D83000696C74 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6F1313ED2026D83000696C74 /* ViewController.m in Sources */, + 6F1313F82026D83000696C74 /* main.m in Sources */, + 6F1314322028086700696C74 /* THMeterTable.m in Sources */, + 6F13143A202825DA00696C74 /* THMemoCell.m in Sources */, + 6F1314312028086700696C74 /* THLevelMeterView.m in Sources */, + 6F131429202807B000696C74 /* THLevelPair.m in Sources */, + 6F1313EA2026D83000696C74 /* AppDelegate.m in Sources */, + 6F1314222027F56200696C74 /* THMemo.m in Sources */, + 6F13141F20272AA500696C74 /* THRecorderController.m in Sources */, + 6F1314332028086700696C74 /* THLevelMeterColorThreshold.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6F1313F92026D83000696C74 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6F1314022026D83000696C74 /* AVAudioRecorderDemoTests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 6F1314042026D83000696C74 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6F13140D2026D83000696C74 /* AVAudioRecorderDemoUITests.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 6F1313FF2026D83000696C74 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6F1313E42026D83000696C74 /* AVAudioRecorderDemo */; + targetProxy = 6F1313FE2026D83000696C74 /* PBXContainerItemProxy */; + }; + 6F13140A2026D83000696C74 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 6F1313E42026D83000696C74 /* AVAudioRecorderDemo */; + targetProxy = 6F1314092026D83000696C74 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 6F1313EE2026D83000696C74 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6F1313EF2026D83000696C74 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 6F1313F32026D83000696C74 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 6F1313F42026D83000696C74 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 6F13140F2026D83000696C74 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + }; + name = Debug; + }; + 6F1314102026D83000696C74 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 6F1314122026D83000696C74 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = KFHY8Z75E6; + INFOPLIST_FILE = AVAudioRecorderDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = yuanjunxiao.AVAudioRecorderDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 6F1314132026D83000696C74 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = KFHY8Z75E6; + INFOPLIST_FILE = AVAudioRecorderDemo/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = yuanjunxiao.AVAudioRecorderDemo; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 6F1314152026D83000696C74 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = AVAudioRecorderDemoTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = yuanjunxiao.AVAudioRecorderDemoTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AVAudioRecorderDemo.app/AVAudioRecorderDemo"; + }; + name = Debug; + }; + 6F1314162026D83000696C74 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = AVAudioRecorderDemoTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = yuanjunxiao.AVAudioRecorderDemoTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AVAudioRecorderDemo.app/AVAudioRecorderDemo"; + }; + name = Release; + }; + 6F1314182026D83000696C74 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = AVAudioRecorderDemoUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = yuanjunxiao.AVAudioRecorderDemoUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = AVAudioRecorderDemo; + }; + name = Debug; + }; + 6F1314192026D83000696C74 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + INFOPLIST_FILE = AVAudioRecorderDemoUITests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = yuanjunxiao.AVAudioRecorderDemoUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = AVAudioRecorderDemo; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 6F1313E02026D83000696C74 /* Build configuration list for PBXProject "AVAudioRecorderDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6F13140F2026D83000696C74 /* Debug */, + 6F1314102026D83000696C74 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6F1314112026D83000696C74 /* Build configuration list for PBXNativeTarget "AVAudioRecorderDemo" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6F1314122026D83000696C74 /* Debug */, + 6F1314132026D83000696C74 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6F1314142026D83000696C74 /* Build configuration list for PBXNativeTarget "AVAudioRecorderDemoTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6F1314152026D83000696C74 /* Debug */, + 6F1314162026D83000696C74 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 6F1314172026D83000696C74 /* Build configuration list for PBXNativeTarget "AVAudioRecorderDemoUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 6F1314182026D83000696C74 /* Debug */, + 6F1314192026D83000696C74 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 6F1313DD2026D83000696C74 /* Project object */; +} diff --git a/AVAudioRecorderDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/AVAudioRecorderDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..e89e42e --- /dev/null +++ b/AVAudioRecorderDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/AVAudioRecorderDemo.xcodeproj/xcuserdata/yuanjunxiao.xcuserdatad/xcschemes/xcschememanagement.plist b/AVAudioRecorderDemo.xcodeproj/xcuserdata/yuanjunxiao.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..ecc6137 --- /dev/null +++ b/AVAudioRecorderDemo.xcodeproj/xcuserdata/yuanjunxiao.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + AVAudioRecorderDemo.xcscheme + + orderHint + 0 + + + + diff --git a/AVAudioRecorderDemo/AppDelegate.h b/AVAudioRecorderDemo/AppDelegate.h new file mode 100644 index 0000000..b2e71ba --- /dev/null +++ b/AVAudioRecorderDemo/AppDelegate.h @@ -0,0 +1,17 @@ +// +// AppDelegate.h +// AVAudioRecorderDemo +// +// Created by 袁俊晓 on 2018/2/4. +// Copyright © 2018年 yuanjunxiao. All rights reserved. +// + +#import + +@interface AppDelegate : UIResponder + +@property (strong, nonatomic) UIWindow *window; + + +@end + diff --git a/AVAudioRecorderDemo/AppDelegate.m b/AVAudioRecorderDemo/AppDelegate.m new file mode 100644 index 0000000..cb26e0a --- /dev/null +++ b/AVAudioRecorderDemo/AppDelegate.m @@ -0,0 +1,59 @@ +// +// AppDelegate.m +// AVAudioRecorderDemo +// +// Created by 袁俊晓 on 2018/2/4. +// Copyright © 2018年 yuanjunxiao. All rights reserved. +// + +#import "AppDelegate.h" +#import +@interface AppDelegate () + +@end + +@implementation AppDelegate + + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + AVAudioSession *session =[AVAudioSession sharedInstance]; + NSError *error; + if (![session setCategory:AVAudioSessionCategoryPlayAndRecord error:&error]) { + NSLog(@"==="); + } + + if (![session setActive:YES error:&error]) { + NSLog(@"+++++"); + } + return YES; +} + + +- (void)applicationWillResignActive:(UIApplication *)application { + // 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. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. +} + + +- (void)applicationDidEnterBackground:(UIApplication *)application { + // 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. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. +} + + +- (void)applicationWillEnterForeground:(UIApplication *)application { + // 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. +} + + +- (void)applicationDidBecomeActive:(UIApplication *)application { + // 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. +} + + +- (void)applicationWillTerminate:(UIApplication *)application { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. +} + + +@end diff --git a/AVAudioRecorderDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/AVAudioRecorderDemo/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d8db8d6 --- /dev/null +++ b/AVAudioRecorderDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/AVAudioRecorderDemo/Assets.xcassets/Contents.json b/AVAudioRecorderDemo/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/AVAudioRecorderDemo/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/AVAudioRecorderDemo/Assets.xcassets/pause.imageset/Contents.json b/AVAudioRecorderDemo/Assets.xcassets/pause.imageset/Contents.json new file mode 100644 index 0000000..7a67263 --- /dev/null +++ b/AVAudioRecorderDemo/Assets.xcassets/pause.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "pause.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "pause@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/AVAudioRecorderDemo/Assets.xcassets/pause.imageset/pause.png b/AVAudioRecorderDemo/Assets.xcassets/pause.imageset/pause.png new file mode 100644 index 0000000000000000000000000000000000000000..80618c0e7293506e3d8d895d33b5c12ff0aa75b7 GIT binary patch literal 2909 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 Hu0mjfJF9}0 literal 0 HcmV?d00001 diff --git a/AVAudioRecorderDemo/Assets.xcassets/pause.imageset/pause@2x.png b/AVAudioRecorderDemo/Assets.xcassets/pause.imageset/pause@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..5e04b957cabd906ecf408f59dab7a04d78acbf29 GIT binary patch literal 3117 zcmV+|4AS$7P)4Tx07wm;mUmPX*B8g%%xo{TU6vwc>AklFq%OTkl_mFQv@x1^BM1TV}0C2duqR=S6Xn?LjUp6xrb&~O43j*Nv zEr418u3H3zGns$s|L;SQD-ufpfWpxLJ03rmi*g~#S@{x?OrJ!Vo{}kJ7$ajbnjp%m zGEV!%=70KpVow?KvV}a4moSaFCQKV= zXBIPnpP$8-NG!rR+)R#`$7JVZi#Wn10DSspSrkx`)s~4C+0n+?(b2-z5-tDd^^cpM zz5W?wz5V3zGUCskL5!X++LzcbT23thtSPiMTfS&1I{|204}j|3FPi>70OSh+Xzlyz zdl<5LNtZ}OE>>3g`T3RtKG#xK(9i3CI(+v0d-&=+OWAp!Ysd8Ar*foO5~i%E+?=c& zshF87;&Ay)i~kOm zCIB-Z!^JGdti+UJsxgN!t(Y#%b<8kk67vyD#cE*9urAm@Y#cTXn~yERR$}Y1E!Yd# zo7hq8Ya9;8z!~A3Z~?e@Tn26#t`xT$*Ni)h>&K1Yrto;Y8r}@=h7ZGY@Dh9xekcA2 z{tSKqKZ<`tAQQ9+wgf*y0zpVvOQ<9qCY&Y=5XJ~ILHOG0j2XwBQ%7jM`P2tv~{#P+6CGu9Y;5!2hua>CG_v;z4S?CC1rc%807-x z8s$^ULkxsr$OvR)G0GUn7`GVjR5Vq*RQM{JRGL%DRgX~5SKp(4L49HleU9rK?wsN|$L8GCfHh1tA~lw29MI^|n9|hJ z^w$(=?$kW5IibbS^3=-Es?a*EHLgw5cGnhYS7@Kne#%s4dNH$@Rm?8tq>hG8fR0pW zzfP~tjINRHeBHIW&AJctNO~;2RJ{tlPQ6KeZT(RF<@$~KcMXUJEQ54|9R}S7(}qTd zv4$HA+YFx=sTu_uEj4O1x^GN1_Ap*-Tx)#81ZToB$u!w*a?KPrbudjgtugI0gUuYx z1ZKO<`pvQC&gMe%TJu2*iiMX&o<*a@uqDGX#B!}=o8@yWeX9hktybMuAFUm%v#jf^ z@7XBX1lg>$>9G0T*3_13TVs2}j%w#;x5}>F?uEUXJ>Pzh{cQ)DL#V?BhfaqNj!uqZ z$0o;dCw-@6r(I5iEIKQkRm!^LjCJ;QUgdn!`K^nii^S!a%Wtk0u9>cfU7yS~n#-SC zH+RHM*Nx-0-)+d9>7MMq&wa>4$AjZh>+#4_&y(j_?>XjW;+5fb#Ot}YwYS*2#e16V z!d}5X>x20C`xN{1`YQR(_pSDQ=%?$K=GW*q>F?mb%>QfvHXt})YrtTjW*|4PA#gIt zDQHDdS1=_wD!4lMQHW`XIHV&K4h;(37J7f4!93x-wlEMD7`83!LAX));_x3Ma1r4V zH4%>^Z6cRPc1O{olA;bry^i*dE{nc5-*~=serJq)Okzw!%yg_zYWi`#ol25V;v^kU#wN!mA5MPH z3FFjqrcwe^cBM>m+1wr6XFN|{1#g`1#xLiOrMjh-r#?w@OWT$Wgg6&&5F%x&L(6hXP*!%2{VOVIa)adIsGCtQITk9vCHD^izmgw;`&@D zcVTY3gpU49^+=7S>!rha?s+wNZ}MaEj~6Hw2n%|am@e70WNfM5(r=exmT{MLF4tMU zX8G_6uNC`OLMu~NcCOM}Rk&(&wg2ivYe;J{*Zj2BdTsgISLt?eJQu}$~QLORDCnMIdyYynPb_W zEx0YhEw{FMY&}%2SiZD;WLxOA)(U1tamB0cN!u@1+E?z~LE0hRF;o>&)xJ}I=a!xC ztJAA*)_B)6@6y<{Y1i~_-tK`to_m`1YVIxB`);3L-|hYW`&(-bYby`n4&)tpTo+T< z{VnU;hI;k-lKKw^g$IWYMIP#EaB65ctZ}%k5pI+=jvq-pa_u{x@7kLzn)Wv{noEv? zqtc^Kzfb=D*0JDYoyS?nn|?6(VOI;SrMMMpUD7()mfkkh9^c-7BIrbChiga6kCs0k zJgIZC=9KcOveTr~g{NoFEIl)IR&;jaT-v#j&ZN$J=i|=b=!)p-y%2oi(nY_E=exbS z&s=i5bn>#xz3Ke>~2=f&N;yEFGz-^boBexUH6@}b7V+Mi8+ZXR+R zIyLMw-18{v(Y+Dw$g^K^e|bMz_?Y^*a!h-y;fd{&ljDBl*PbqTI{HlXY-Xb9SH)j< zJvV;-!*8Cy^-RW1j=m7TnEk!51Yp#Z=iODrmAaR)oj+1 zb58&1TAdFgvWDjq;1JlEuk#O|pxyu%Dd#CI6B&Yg4(tINw5}t5q%;Kgqk^Zt^I7@YW&^dAHtoY`7Y?JtrgUA=cZ$8Xo36Q1_w2FC zO+O#z+Gj{4NB=Ur{Xhd!#M0RPSRU=$55x+Vo)-fxdqvSuG~}E>d~(i#o9&_@b7anf zXvjHmvt2Y~j?7sQ4LJvHwu^?$kvR*ZA?Lu&cF~YIGG{?Fw^VQW6}^x~p{5>jC>TJ5Pq{=^a6bZC zV5_Xze!f7z2d4Tx07wm;mUmPX*B8g%%xo{TU6vwc>AklFq%OTkl_mFQv@x1^BM1TV}0C2duqR=S6Xn?LjUp6xrb&~O43j*Nv zEr418u3H3zGns$s|L;SQD-ufpfWpxLJ03rmi*g~#S@{x?OrJ!Vo{}kJ7$ajbnjp%m zGEV!%=70KpVow?KvV}a4moSaFCQKV= zXBIPnpP$8-NG!rR+)R#`$7JVZi#Wn10DSspSrkx`)s~4C+0n+?(b2-z5-tDd^^cpM zz5W?wz5V3zGUCskL5!X++LzcbT23thtSPiMTfS&1I{|204}j|3FPi>70OSh+Xzlyz zdl<5LNtZ}OE>>3g`T3RtKG#xK(9i3CI(+v0d-&=+OWAp!Ysd8Ar*foO5~i%E+?=c& zshF87;&Ay)i~kOm zCIB-Z!^JGdti+UJsxgN!t(Y#%b<8kk67vyD#cE*9urAm@Y#cTXn~yERR$}Y1E!Yd# zo7hq8Ya9;8z!~A3Z~?e@Tn26#t`xT$*Ni)h>&K1Yrto;Y8r}@=h7ZGY@Dh9xekcA2 z{tSKqKZ<`tAQQ9+wgf*y0zpVvOQ<9qCY&Y=5XJ~ILHOG0j2XwBQ%7jM`P2tv~{#P+6CGu9Y;5!2hua>CG_v;z4S?CC1rc%807-x z8s$^ULkxsr$OvR)G0GUn7`GVjR5Vq*RQM{JRGL%DRgX~5SKp(4L49HleU9rK?wsN|$L8GCfHh1tA~lw29MI^|n9|hJ z^w$(=?$kW5IibbS^3=-Es?a*EHLgw5cGnhYS7@Kne#%s4dNH$@Rm?8tq>hG8fR0pW zzfP~tjINRHeBHIW&AJctNO~;2RJ{tlPQ6KeZT(RF<@$~KcMXUJEQ54|9R}S7(}qTd zv4$HA+YFx=sTu_uEj4O1x^GN1_Ap*-Tx)#81ZToB$u!w*a?KPrbudjgtugI0gUuYx z1ZKO<`pvQC&gMe%TJu2*iiMX&o<*a@uqDGX#B!}=o8@yWeX9hktybMuAFUm%v#jf^ z@7XBX1lg>$>9G0T*3_13TVs2}j%w#;x5}>F?uEUXJ>Pzh{cQ)DL#V?BhfaqNj!uqZ z$0o;dCw-@6r(I5iEIKQkRm!^LjCJ;QUgdn!`K^nii^S!a%Wtk0u9>cfU7yS~n#-SC zH+RHM*Nx-0-)+d9>7MMq&wa>4$AjZh>+#4_&y(j_?>XjW;+5fb#Ot}YwYS*2#e16V z!d}5X>x20C`xN{1`YQR(_pSDQ=%?$K=GW*q>F?mb%>QfvHXt})YrtTjW*|4PA#gIt zDQHDdS1=_wD!4lMQHW`XIHV&K4h;(37J7f4!93x-wlEMD7`83!LAX));_x3Ma1r4V zH4%>^Z6cRPc1O{olA;bry^i*dE{nc5-*~=serJq)Okzw!%yg_zYWi`#ol25V;v^kU#wN!mA5MPH z3FFjqrcwe^cBM>m+1wr6XFN|{1#g`1#xLiOrMjh-r#?w@OWT$Wgg6&&5F%x&L(6hXP*!%2{VOVIa)adIsGCtQITk9vCHD^izmgw;`&@D zcVTY3gpU49^+=7S>!rha?s+wNZ}MaEj~6Hw2n%|am@e70WNfM5(r=exmT{MLF4tMU zX8G_6uNC`OLMu~NcCOM}Rk&(&wg2ivYe;J{*Zj2BdTsgISLt?eJQu}$~QLORDCnMIdyYynPb_W zEx0YhEw{FMY&}%2SiZD;WLxOA)(U1tamB0cN!u@1+E?z~LE0hRF;o>&)xJ}I=a!xC ztJAA*)_B)6@6y<{Y1i~_-tK`to_m`1YVIxB`);3L-|hYW`&(-bYby`n4&)tpTo+T< z{VnU;hI;k-lKKw^g$IWYMIP#EaB65ctZ}%k5pI+=jvq-pa_u{x@7kLzn)Wv{noEv? zqtc^Kzfb=D*0JDYoyS?nn|?6(VOI;SrMMMpUD7()mfkkh9^c-7BIrbChiga6kCs0k zJgIZC=9KcOveTr~g{NoFEIl)IR&;jaT-v#j&ZN$J=i|=b=!)p-y%2oi(nY_E=exbS z&s=i5bn>#xz3Ke>~2=f&N;yEFGz-^boBexUH6@}b7V+Mi8+ZXR+R zIyLMw-18{v(Y+Dw$g^K^e|bMz_?Y^*a!h-y;fd{&ljDBl*PbqTI{HlXY-Xb9SH)j< zJvV;-!*8Cy^-RW1j=m7TnEk!2)1u!>qM zLZvNuR77h*Egn2*5Ge>A6g+s-i+_VRJt%@oPo6v|B3dtk7om92hzAiBe*`K8MYPz1 z6qGh1DAM?R8NVh?Hrw5#F*^fqXEWKEd7t@)?9NPsQmG^@ry%H}jXh{T+K#rOKD73q zX32}_GkT9+qdc0BRt;$VrX&)8eh}S2MWjQKRMXVCga(`P;Cf34Ad;cO;&4It7(V-Nn5 zaRadYGW`ZoAkhFCN`5gqWZodg=)bEGL}LJv4OA?2*t|j9!AB+xA{;$THsNd!E2vIV8kQi zX0?}#T?UY|QqS_70StL&-0TkNvQXEpb11Mo^Z6fJVUA)U5#Pe07iS zGJx*c_?qT40zZ6pkME)aOe21byi8v*ypI0F`jnUUMJ6=@n%=m~yT1hkcIvWf_NNO=^-sy#DbYEEcGMgY(glQd2tJvUf%_)!m_Kq9&?pEdv; z)Vf2DMgS|gIiE6!i*>Wb4ROsB(g>*B$xNpYH=IS0Tlfh*sR@rj1)`UV&pRB6>-3)u z8+|Q{25^yB!)^CF0HJgK910zI16mruLFn$qY4jU8?)K*TKs{t8qw;tF3gJKoY4}MS zA#~KQp^Z_dtG`PIP>IG7I(e~-AZq*`8m=}M=Q=rnMZ>}DqtmNMA25_8)<^1`N1NlA z4ZFv!2Nqr|n!E^tEH!tc14!2vTTnmhLHgY4Tx07wm;mUmPX*B8g%%xo{TU6vwc>AklFq%OTkl_mFQv@x1^BM1TV}0C2duqR=S6Xn?LjUp6xrb&~O43j*Nv zEr418u3H3zGns$s|L;SQD-ufpfWpxLJ03rmi*g~#S@{x?OrJ!Vo{}kJ7$ajbnjp%m zGEV!%=70KpVow?KvV}a4moSaFCQKV= zXBIPnpP$8-NG!rR+)R#`$7JVZi#Wn10DSspSrkx`)s~4C+0n+?(b2-z5-tDd^^cpM zz5W?wz5V3zGUCskL5!X++LzcbT23thtSPiMTfS&1I{|204}j|3FPi>70OSh+Xzlyz zdl<5LNtZ}OE>>3g`T3RtKG#xK(9i3CI(+v0d-&=+OWAp!Ysd8Ar*foO5~i%E+?=c& zshF87;&Ay)i~kOm zCIB-Z!^JGdti+UJsxgN!t(Y#%b<8kk67vyD#cE*9urAm@Y#cTXn~yERR$}Y1E!Yd# zo7hq8Ya9;8z!~A3Z~?e@Tn26#t`xT$*Ni)h>&K1Yrto;Y8r}@=h7ZGY@Dh9xekcA2 z{tSKqKZ<`tAQQ9+wgf*y0zpVvOQ<9qCY&Y=5XJ~ILHOG0j2XwBQ%7jM`P2tv~{#P+6CGu9Y;5!2hua>CG_v;z4S?CC1rc%807-x z8s$^ULkxsr$OvR)G0GUn7`GVjR5Vq*RQM{JRGL%DRgX~5SKp(4L49HleU9rK?wsN|$L8GCfHh1tA~lw29MI^|n9|hJ z^w$(=?$kW5IibbS^3=-Es?a*EHLgw5cGnhYS7@Kne#%s4dNH$@Rm?8tq>hG8fR0pW zzfP~tjINRHeBHIW&AJctNO~;2RJ{tlPQ6KeZT(RF<@$~KcMXUJEQ54|9R}S7(}qTd zv4$HA+YFx=sTu_uEj4O1x^GN1_Ap*-Tx)#81ZToB$u!w*a?KPrbudjgtugI0gUuYx z1ZKO<`pvQC&gMe%TJu2*iiMX&o<*a@uqDGX#B!}=o8@yWeX9hktybMuAFUm%v#jf^ z@7XBX1lg>$>9G0T*3_13TVs2}j%w#;x5}>F?uEUXJ>Pzh{cQ)DL#V?BhfaqNj!uqZ z$0o;dCw-@6r(I5iEIKQkRm!^LjCJ;QUgdn!`K^nii^S!a%Wtk0u9>cfU7yS~n#-SC zH+RHM*Nx-0-)+d9>7MMq&wa>4$AjZh>+#4_&y(j_?>XjW;+5fb#Ot}YwYS*2#e16V z!d}5X>x20C`xN{1`YQR(_pSDQ=%?$K=GW*q>F?mb%>QfvHXt})YrtTjW*|4PA#gIt zDQHDdS1=_wD!4lMQHW`XIHV&K4h;(37J7f4!93x-wlEMD7`83!LAX));_x3Ma1r4V zH4%>^Z6cRPc1O{olA;bry^i*dE{nc5-*~=serJq)Okzw!%yg_zYWi`#ol25V;v^kU#wN!mA5MPH z3FFjqrcwe^cBM>m+1wr6XFN|{1#g`1#xLiOrMjh-r#?w@OWT$Wgg6&&5F%x&L(6hXP*!%2{VOVIa)adIsGCtQITk9vCHD^izmgw;`&@D zcVTY3gpU49^+=7S>!rha?s+wNZ}MaEj~6Hw2n%|am@e70WNfM5(r=exmT{MLF4tMU zX8G_6uNC`OLMu~NcCOM}Rk&(&wg2ivYe;J{*Zj2BdTsgISLt?eJQu}$~QLORDCnMIdyYynPb_W zEx0YhEw{FMY&}%2SiZD;WLxOA)(U1tamB0cN!u@1+E?z~LE0hRF;o>&)xJ}I=a!xC ztJAA*)_B)6@6y<{Y1i~_-tK`to_m`1YVIxB`);3L-|hYW`&(-bYby`n4&)tpTo+T< z{VnU;hI;k-lKKw^g$IWYMIP#EaB65ctZ}%k5pI+=jvq-pa_u{x@7kLzn)Wv{noEv? zqtc^Kzfb=D*0JDYoyS?nn|?6(VOI;SrMMMpUD7()mfkkh9^c-7BIrbChiga6kCs0k zJgIZC=9KcOveTr~g{NoFEIl)IR&;jaT-v#j&ZN$J=i|=b=!)p-y%2oi(nY_E=exbS z&s=i5bn>#xz3Ke>~2=f&N;yEFGz-^boBexUH6@}b7V+Mi8+ZXR+R zIyLMw-18{v(Y+Dw$g^K^e|bMz_?Y^*a!h-y;fd{&ljDBl*PbqTI{HlXY-Xb9SH)j< zJvV;-!*8Cy^-RW1j=m7TnEk!xQf(oLtC`Rxg z2q6JhF(NUdKtMn)rF?ICYnj>U>FH~_XLi3Yc~jlhRbN%T*VRW&ceNN}oT@dE3sJXv zpdWBmOIU}H@jZdAKzHCMaHIu?5gq`31$F>CTf%0?m{VA;DwC=bK;$B@GXxk4Gy+!u zN!f8Y`T_U~SOctwASV%KYS{}Q(iaR&1jYdkDYC(y@)58MSP3ysq*!)qQP~I}ayDu( z9+(CU1_a2`c*t4=%!3fy)2v9k0*IW4#?1g82Y4*6HscBLW8eh{(UeBz(h)#}C(0*) znLzI}8kRsAYvE%Sg!ncAU!`5}BwSHA&IIgMzW}`6sx_QOofiXjmEx#!@(<3xJMFJ~@Pb+~0~}$!6C(Uqys0=Q+&MtxQn>g4Q1Xkpv@xTx@T^@a7Y6SEBHiHZ zOW?+GPIbG3QHxwJSW%9PFg@ToI8*Y=G3svTg~@ze8S#kWYr%Se$S8PO3FsA%FP%jj zzd_7xI3N65w527Yd=GHPcjh6zl3$9&((yN8)03q)gH#T$`kKgGY@hC%MmPE~z+s98 z^n#zg68Q@tavd^#59sy27kk0umP3HMy^@zZ1ih%_d(jp;?k=2=Z}-Yox(A31M}}2i znKUjE0~^o_cupuVzaB8VAf>LvWnd6`!I-vAyaf;$iiCsOCf4=X3_R7=gSP->E}hys z(e=O#+=5=f;ptil2D;iF(B9r=OrOeVC7x>qI1w$s=8DUJ72rr*N18tp z1Ba~uha+XzOmP`FX$3eK*OTUt#K3+lfF6P(@fSPOJ}bcQv0bTyC=Bee0_=*CTl2(b zV3#X^F~{L*cWig+AS?sTwg)idmaw@seQXA{`Y+JqnUx&%9X=5|6 z3GWLW%NKxe^qr3FRviRoAh*Mx5x^MUjB&yxwR9NZbPolOrEq-}f7B|@z%i82#8S@m z0IoUCdv2h=6=q;HkN+&APyl1LB5r$y3s?7!^NuBA#u)@!i<#{7YeoD)bbc?LKy#B2F(iv@7E@(p>l8_XXA$q}G)<3^ZZy=L_%!=G_CB#2DTxbCM>t_zdva|FoBz z(gL`tXClb_LpNR(ud%qdu|spLt;qZZFlGmGyi}A+Bf>Di>;74#GL$|C*c|Tbl$)`7 zrH#@s6a&+-_rF>yM|lC5Q)DoHKL>Q?Eb>%Vb zVelTn)HHV{MJn4Px2`{J8CZe{epRF7aX&vp@E%}u8N(|g_5{5@u$-I;zrfW(=zam68HEz5=;uTM5^4acq0?>moAL6$W_>-$0%od`(qrgGyKU`tkA722L zXbijHKwuMBJAm=r$MK!1XnU+faQMqmKX%>E*1m!y)BKXv__n>M{}d3l=q(D(@XT%aCpd8;DzPx=GJp8g!C3+~Gw0h$4?4<=Vz+$q#^32?P% zdr;e?;*&iIm)k`oH=;To$({lFmrI_(c3#me0GkcRPcav87)r1L%|6U$zJ{ARmz*HMH< zU2X=4#3FJ;3EUpf}JH=nixRXdH_< q0r37~AHZXHGq61u8nXvs)!F~}>3~G%EY6ky0000P000>X1^@s6#OZ}&000U^X+uL$Nkc;* zP;zf(X>4Tx07wm;mUmPX*B8g%%xo{TU6vwc>AklFq%OTkl_mFQv@x1^BM1TV}0C2duqR=S6Xn?LjUp6xrb&~O43j*Nv zEr418u3H3zGns$s|L;SQD-ufpfWpxLJ03rmi*g~#S@{x?OrJ!Vo{}kJ7$ajbnjp%m zGEV!%=70KpVow?KvV}a4moSaFCQKV= zXBIPnpP$8-NG!rR+)R#`$7JVZi#Wn10DSspSrkx`)s~4C+0n+?(b2-z5-tDd^^cpM zz5W?wz5V3zGUCskL5!X++LzcbT23thtSPiMTfS&1I{|204}j|3FPi>70OSh+Xzlyz zdl<5LNtZ}OE>>3g`T3RtKG#xK(9i3CI(+v0d-&=+OWAp!Ysd8Ar*foO5~i%E+?=c& zshF87;&Ay)i~kOm zCIB-Z!^JGdti+UJsxgN!t(Y#%b<8kk67vyD#cE*9urAm@Y#cTXn~yERR$}Y1E!Yd# zo7hq8Ya9;8z!~A3Z~?e@Tn26#t`xT$*Ni)h>&K1Yrto;Y8r}@=h7ZGY@Dh9xekcA2 z{tSKqKZ<`tAQQ9+wgf*y0zpVvOQ<9qCY&Y=5XJ~ILHOG0j2XwBQ%7jM`P2tv~{#P+6CGu9Y;5!2hua>CG_v;z4S?CC1rc%807-x z8s$^ULkxsr$OvR)G0GUn7`GVjR5Vq*RQM{JRGL%DRgX~5SKp(4L49HleU9rK?wsN|$L8GCfHh1tA~lw29MI^|n9|hJ z^w$(=?$kW5IibbS^3=-Es?a*EHLgw5cGnhYS7@Kne#%s4dNH$@Rm?8tq>hG8fR0pW zzfP~tjINRHeBHIW&AJctNO~;2RJ{tlPQ6KeZT(RF<@$~KcMXUJEQ54|9R}S7(}qTd zv4$HA+YFx=sTu_uEj4O1x^GN1_Ap*-Tx)#81ZToB$u!w*a?KPrbudjgtugI0gUuYx z1ZKO<`pvQC&gMe%TJu2*iiMX&o<*a@uqDGX#B!}=o8@yWeX9hktybMuAFUm%v#jf^ z@7XBX1lg>$>9G0T*3_13TVs2}j%w#;x5}>F?uEUXJ>Pzh{cQ)DL#V?BhfaqNj!uqZ z$0o;dCw-@6r(I5iEIKQkRm!^LjCJ;QUgdn!`K^nii^S!a%Wtk0u9>cfU7yS~n#-SC zH+RHM*Nx-0-)+d9>7MMq&wa>4$AjZh>+#4_&y(j_?>XjW;+5fb#Ot}YwYS*2#e16V z!d}5X>x20C`xN{1`YQR(_pSDQ=%?$K=GW*q>F?mb%>QfvHXt})YrtTjW*|4PA#gIt zDQHDdS1=_wD!4lMQHW`XIHV&K4h;(37J7f4!93x-wlEMD7`83!LAX));_x3Ma1r4V zH4%>^Z6cRPc1O{olA;bry^i*dE{nc5-*~=serJq)Okzw!%yg_zYWi`#ol25V;v^kU#wN!mA5MPH z3FFjqrcwe^cBM>m+1wr6XFN|{1#g`1#xLiOrMjh-r#?w@OWT$Wgg6&&5F%x&L(6hXP*!%2{VOVIa)adIsGCtQITk9vCHD^izmgw;`&@D zcVTY3gpU49^+=7S>!rha?s+wNZ}MaEj~6Hw2n%|am@e70WNfM5(r=exmT{MLF4tMU zX8G_6uNC`OLMu~NcCOM}Rk&(&wg2ivYe;J{*Zj2BdTsgISLt?eJQu}$~QLORDCnMIdyYynPb_W zEx0YhEw{FMY&}%2SiZD;WLxOA)(U1tamB0cN!u@1+E?z~LE0hRF;o>&)xJ}I=a!xC ztJAA*)_B)6@6y<{Y1i~_-tK`to_m`1YVIxB`);3L-|hYW`&(-bYby`n4&)tpTo+T< z{VnU;hI;k-lKKw^g$IWYMIP#EaB65ctZ}%k5pI+=jvq-pa_u{x@7kLzn)Wv{noEv? zqtc^Kzfb=D*0JDYoyS?nn|?6(VOI;SrMMMpUD7()mfkkh9^c-7BIrbChiga6kCs0k zJgIZC=9KcOveTr~g{NoFEIl)IR&;jaT-v#j&ZN$J=i|=b=!)p-y%2oi(nY_E=exbS z&s=i5bn>#xz3Ke>~2=f&N;yEFGz-^boBexUH6@}b7V+Mi8+ZXR+R zIyLMw-18{v(Y+Dw$g^K^e|bMz_?Y^*a!h-y;fd{&ljDBl*PbqTI{HlXY-Xb9SH)j< zJvV;-!*8Cy^-RW1j=m7TnEk!<8n%r;;IqH71?Op$_S ziDtj?Rf-%K47Xu)+bH7EtZ%;lJ^11~MI=|#uCz;XKw8e%m3B!ENXvX(O}fyR8%0+A rPP$lsNh{1;SMI6|75wK1)FXGDOeopQIvAY=00000NkvXXu0mjfdaiJF literal 0 HcmV?d00001 diff --git a/AVAudioRecorderDemo/Assets.xcassets/stop.imageset/stop@2x.png b/AVAudioRecorderDemo/Assets.xcassets/stop.imageset/stop@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f241b47784f32463a925bbc0764bae7f355448f8 GIT binary patch literal 3077 zcmV+g4EpnlP)4Tx07wm;mUmPX*B8g%%xo{TU6vwc>AklFq%OTkl_mFQv@x1^BM1TV}0C2duqR=S6Xn?LjUp6xrb&~O43j*Nv zEr418u3H3zGns$s|L;SQD-ufpfWpxLJ03rmi*g~#S@{x?OrJ!Vo{}kJ7$ajbnjp%m zGEV!%=70KpVow?KvV}a4moSaFCQKV= zXBIPnpP$8-NG!rR+)R#`$7JVZi#Wn10DSspSrkx`)s~4C+0n+?(b2-z5-tDd^^cpM zz5W?wz5V3zGUCskL5!X++LzcbT23thtSPiMTfS&1I{|204}j|3FPi>70OSh+Xzlyz zdl<5LNtZ}OE>>3g`T3RtKG#xK(9i3CI(+v0d-&=+OWAp!Ysd8Ar*foO5~i%E+?=c& zshF87;&Ay)i~kOm zCIB-Z!^JGdti+UJsxgN!t(Y#%b<8kk67vyD#cE*9urAm@Y#cTXn~yERR$}Y1E!Yd# zo7hq8Ya9;8z!~A3Z~?e@Tn26#t`xT$*Ni)h>&K1Yrto;Y8r}@=h7ZGY@Dh9xekcA2 z{tSKqKZ<`tAQQ9+wgf*y0zpVvOQ<9qCY&Y=5XJ~ILHOG0j2XwBQ%7jM`P2tv~{#P+6CGu9Y;5!2hua>CG_v;z4S?CC1rc%807-x z8s$^ULkxsr$OvR)G0GUn7`GVjR5Vq*RQM{JRGL%DRgX~5SKp(4L49HleU9rK?wsN|$L8GCfHh1tA~lw29MI^|n9|hJ z^w$(=?$kW5IibbS^3=-Es?a*EHLgw5cGnhYS7@Kne#%s4dNH$@Rm?8tq>hG8fR0pW zzfP~tjINRHeBHIW&AJctNO~;2RJ{tlPQ6KeZT(RF<@$~KcMXUJEQ54|9R}S7(}qTd zv4$HA+YFx=sTu_uEj4O1x^GN1_Ap*-Tx)#81ZToB$u!w*a?KPrbudjgtugI0gUuYx z1ZKO<`pvQC&gMe%TJu2*iiMX&o<*a@uqDGX#B!}=o8@yWeX9hktybMuAFUm%v#jf^ z@7XBX1lg>$>9G0T*3_13TVs2}j%w#;x5}>F?uEUXJ>Pzh{cQ)DL#V?BhfaqNj!uqZ z$0o;dCw-@6r(I5iEIKQkRm!^LjCJ;QUgdn!`K^nii^S!a%Wtk0u9>cfU7yS~n#-SC zH+RHM*Nx-0-)+d9>7MMq&wa>4$AjZh>+#4_&y(j_?>XjW;+5fb#Ot}YwYS*2#e16V z!d}5X>x20C`xN{1`YQR(_pSDQ=%?$K=GW*q>F?mb%>QfvHXt})YrtTjW*|4PA#gIt zDQHDdS1=_wD!4lMQHW`XIHV&K4h;(37J7f4!93x-wlEMD7`83!LAX));_x3Ma1r4V zH4%>^Z6cRPc1O{olA;bry^i*dE{nc5-*~=serJq)Okzw!%yg_zYWi`#ol25V;v^kU#wN!mA5MPH z3FFjqrcwe^cBM>m+1wr6XFN|{1#g`1#xLiOrMjh-r#?w@OWT$Wgg6&&5F%x&L(6hXP*!%2{VOVIa)adIsGCtQITk9vCHD^izmgw;`&@D zcVTY3gpU49^+=7S>!rha?s+wNZ}MaEj~6Hw2n%|am@e70WNfM5(r=exmT{MLF4tMU zX8G_6uNC`OLMu~NcCOM}Rk&(&wg2ivYe;J{*Zj2BdTsgISLt?eJQu}$~QLORDCnMIdyYynPb_W zEx0YhEw{FMY&}%2SiZD;WLxOA)(U1tamB0cN!u@1+E?z~LE0hRF;o>&)xJ}I=a!xC ztJAA*)_B)6@6y<{Y1i~_-tK`to_m`1YVIxB`);3L-|hYW`&(-bYby`n4&)tpTo+T< z{VnU;hI;k-lKKw^g$IWYMIP#EaB65ctZ}%k5pI+=jvq-pa_u{x@7kLzn)Wv{noEv? zqtc^Kzfb=D*0JDYoyS?nn|?6(VOI;SrMMMpUD7()mfkkh9^c-7BIrbChiga6kCs0k zJgIZC=9KcOveTr~g{NoFEIl)IR&;jaT-v#j&ZN$J=i|=b=!)p-y%2oi(nY_E=exbS z&s=i5bn>#xz3Ke>~2=f&N;yEFGz-^boBexUH6@}b7V+Mi8+ZXR+R zIyLMw-18{v(Y+Dw$g^K^e|bMz_?Y^*a!h-y;fd{&ljDBl*PbqTI{HlXY-Xb9SH)j< zJvV;-!*8Cy^-RW1j=m7TnEk!KS~2}5QP(qcn&KY z6>ng$Q16jSPh;gj@E{TpJVC@XS_wHrnk?x0y|Al{c4>SA^Wd?+Sx9&@Up6T+!?tY) zzqChvfsgSH9$^PHgm}k~_!`ggkJL!#5!WmHf!(Ey%Bsxk{6ig(rv8A(IFp_TdxD#- zF7+kXad*yiIU=mG4@6|2>oe|~()~>OBeBh0ND3F9y*iiiP(5TS^KaTpXu!~jBwP(;Ew42mLR03k#u zB4Hc`MG-N85F!+jFb;#Fh!{W!5sF9{he1(93?PIEMI?;FpeP~+5JH3^62@Ur6cGam zA%ci#qaeGMYD8-h*|kt3+U>}$ss0Q-poZ_Lwis{4Tx07wm;mUmPX*B8g%%xo{TU6vwc>AklFq%OTkl_mFQv@x1^BM1TV}0C2duqR=S6Xn?LjUp6xrb&~O43j*Nv zEr418u3H3zGns$s|L;SQD-ufpfWpxLJ03rmi*g~#S@{x?OrJ!Vo{}kJ7$ajbnjp%m zGEV!%=70KpVow?KvV}a4moSaFCQKV= zXBIPnpP$8-NG!rR+)R#`$7JVZi#Wn10DSspSrkx`)s~4C+0n+?(b2-z5-tDd^^cpM zz5W?wz5V3zGUCskL5!X++LzcbT23thtSPiMTfS&1I{|204}j|3FPi>70OSh+Xzlyz zdl<5LNtZ}OE>>3g`T3RtKG#xK(9i3CI(+v0d-&=+OWAp!Ysd8Ar*foO5~i%E+?=c& zshF87;&Ay)i~kOm zCIB-Z!^JGdti+UJsxgN!t(Y#%b<8kk67vyD#cE*9urAm@Y#cTXn~yERR$}Y1E!Yd# zo7hq8Ya9;8z!~A3Z~?e@Tn26#t`xT$*Ni)h>&K1Yrto;Y8r}@=h7ZGY@Dh9xekcA2 z{tSKqKZ<`tAQQ9+wgf*y0zpVvOQ<9qCY&Y=5XJ~ILHOG0j2XwBQ%7jM`P2tv~{#P+6CGu9Y;5!2hua>CG_v;z4S?CC1rc%807-x z8s$^ULkxsr$OvR)G0GUn7`GVjR5Vq*RQM{JRGL%DRgX~5SKp(4L49HleU9rK?wsN|$L8GCfHh1tA~lw29MI^|n9|hJ z^w$(=?$kW5IibbS^3=-Es?a*EHLgw5cGnhYS7@Kne#%s4dNH$@Rm?8tq>hG8fR0pW zzfP~tjINRHeBHIW&AJctNO~;2RJ{tlPQ6KeZT(RF<@$~KcMXUJEQ54|9R}S7(}qTd zv4$HA+YFx=sTu_uEj4O1x^GN1_Ap*-Tx)#81ZToB$u!w*a?KPrbudjgtugI0gUuYx z1ZKO<`pvQC&gMe%TJu2*iiMX&o<*a@uqDGX#B!}=o8@yWeX9hktybMuAFUm%v#jf^ z@7XBX1lg>$>9G0T*3_13TVs2}j%w#;x5}>F?uEUXJ>Pzh{cQ)DL#V?BhfaqNj!uqZ z$0o;dCw-@6r(I5iEIKQkRm!^LjCJ;QUgdn!`K^nii^S!a%Wtk0u9>cfU7yS~n#-SC zH+RHM*Nx-0-)+d9>7MMq&wa>4$AjZh>+#4_&y(j_?>XjW;+5fb#Ot}YwYS*2#e16V z!d}5X>x20C`xN{1`YQR(_pSDQ=%?$K=GW*q>F?mb%>QfvHXt})YrtTjW*|4PA#gIt zDQHDdS1=_wD!4lMQHW`XIHV&K4h;(37J7f4!93x-wlEMD7`83!LAX));_x3Ma1r4V zH4%>^Z6cRPc1O{olA;bry^i*dE{nc5-*~=serJq)Okzw!%yg_zYWi`#ol25V;v^kU#wN!mA5MPH z3FFjqrcwe^cBM>m+1wr6XFN|{1#g`1#xLiOrMjh-r#?w@OWT$Wgg6&&5F%x&L(6hXP*!%2{VOVIa)adIsGCtQITk9vCHD^izmgw;`&@D zcVTY3gpU49^+=7S>!rha?s+wNZ}MaEj~6Hw2n%|am@e70WNfM5(r=exmT{MLF4tMU zX8G_6uNC`OLMu~NcCOM}Rk&(&wg2ivYe;J{*Zj2BdTsgISLt?eJQu}$~QLORDCnMIdyYynPb_W zEx0YhEw{FMY&}%2SiZD;WLxOA)(U1tamB0cN!u@1+E?z~LE0hRF;o>&)xJ}I=a!xC ztJAA*)_B)6@6y<{Y1i~_-tK`to_m`1YVIxB`);3L-|hYW`&(-bYby`n4&)tpTo+T< z{VnU;hI;k-lKKw^g$IWYMIP#EaB65ctZ}%k5pI+=jvq-pa_u{x@7kLzn)Wv{noEv? zqtc^Kzfb=D*0JDYoyS?nn|?6(VOI;SrMMMpUD7()mfkkh9^c-7BIrbChiga6kCs0k zJgIZC=9KcOveTr~g{NoFEIl)IR&;jaT-v#j&ZN$J=i|=b=!)p-y%2oi(nY_E=exbS z&s=i5bn>#xz3Ke>~2=f&N;yEFGz-^boBexUH6@}b7V+Mi8+ZXR+R zIyLMw-18{v(Y+Dw$g^K^e|bMz_?Y^*a!h-y;fd{&ljDBl*PbqTI{HlXY-Xb9SH)j< zJvV;-!*8Cy^-RW1j=m7TnEk!TI zUaTxjEKSXqEUk9?{jc}j&Yqp;oVk0?UC%xFz~6J`nP+C6=f87j&Y78GU1w+KX}u(M zv@;qsflj zUj^k1vOBQXfVv%g2{aSwC!yKt5ReQ24d5&=0%%4X3oZvuz*qjpa0z$<^sE*?{3-5UndQooEoLw2}0Cz(-m!x)t;X<+kHv z-%P!)10VSwqtU>p-jYq}#-pIvSHMZ~8wN8$IdxZJs~-7Il2hdG0apO;wtNkTQR#M& zBaXHc*s zrh!M|D$YpWoEZO=r9ZyOft4|oLi<(PkjKzlWwWNAXT%`2{`gaX(`Tm=<2AsNm1J1u zvZ`NT1%v)OFu)a)E11bK6=_z=+TiPo!KHg9Cay z(|ej?JJaE-)`BhqT^7$oMp$kqVG*;4yjmqjF)HwTbmNfz=pO2(4|ON?qIRR}eSu!j zJg)9qYr2<=7>}aYL{y3=+;eV(xe49aJE2&}lqqs1>c%0TICObaeQX3&*yRv8;|+t)4Sk-} zR*VHsM2_}_T%tXtyo(iMffJE4%wS-bq0f{0Fv0A11f)&HK_X|MBU7pahCXlVy+%Oi zh@9ZiP}C;ao{j4BmR9d^NrT9-&d(fimB^vainCti{NJVYq8TCLxX3Y?ix}rMY5sCV zjy1MeV^Q8nvf?}>a;#a&n#J-)juqztkz+m2SkFIsB1bOgLhR zeLE02vF{g-3iG78)CfjfIEAVg>M$j8 z-sIl3X*U}EG#TbhCJ@gYBc?Y3eb96C+OC}jmuQbXZ!+5mXb<|*uP7i#wl5n6wAife zioA$66z(^Ic@6#XQeJ4|{M12$n1ck`yjxmgt?P}(o&{Z1HJQ>NJkRi4Tg1D=d8ZC9 zonYe_7d_YQ43iTcbEMbTB@4p_k^7aTUC#y)vrHz{^Ib2Qa`q|Eg%~MI2X#VYk92Vd zCSQ!$T6JVepW1;*1$7?C%Te38#A1n#+D-+|KcrJxG(L4m+hVP#PdeVeG@*PP`PI&w zk8g2O(eZvcuWtiBife(qS3uUzCNE0xIh7AXM9?5mE1wjN#Me~`#2h4lB2a9xh|LTY z9?pH%KSsL?9}j^zN&REAfIxl5*cR7vF|W5jOq)cz>plG1i%nHNV+;stq=EN69Fa+u zK7joJf5w0y4zH`1QKV9xWUsYPr-wvh@QOS7ZdG_{_WVbSV5`6&PkWi|0Q%24wu7&V zSFNGwq=R-|`+x?Z$9(N6Y47YpFc#?W=0xBtTFqMm9tV0YDqAWcM~w{y%YeS7$Rf*wcNs0u>X}hwIp#RsE8Q(R%y>s9f64G>0mMF?Jb>O zX!AL+0%$8Y6-kqvutUuxv`#w%)Q2-tyw~EK#;+Ez7HCZ-RjC#^fs-O8_;0Bub6?Kj z9n=xN{z*cFXc2rJ=)MMnGA*e#IblCFV2=S!U=+Bxcpc1DGnCHBXok_ur5#xPJa&O^ lz&6kh+Q5Gc;3TRk{{odijU%nsj*kEU002ovPDHLkV1gPNi`oDH literal 0 HcmV?d00001 diff --git a/AVAudioRecorderDemo/Assets.xcassets/transport_bg.imageset/transport_bg@2x.png b/AVAudioRecorderDemo/Assets.xcassets/transport_bg.imageset/transport_bg@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d2e565468056e8a8e9307ed78fe08b2275c8669a GIT binary patch literal 7004 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 + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AVAudioRecorderDemo/Base.lproj/Main.storyboard b/AVAudioRecorderDemo/Base.lproj/Main.storyboard new file mode 100644 index 0000000..61b6ba6 --- /dev/null +++ b/AVAudioRecorderDemo/Base.lproj/Main.storyboard @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AVAudioRecorderDemo/Info.plist b/AVAudioRecorderDemo/Info.plist new file mode 100644 index 0000000..60b1c5c --- /dev/null +++ b/AVAudioRecorderDemo/Info.plist @@ -0,0 +1,72 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + NSBluetoothPeripheralUsageDescription + 请求访问蓝牙 + NSCalendarsUsageDescription + 请求访问日历 + NSCameraUsageDescription + 请求访问相机 + NSContactsUsageDescription + 请求访问通讯录 + NSLocationAlwaysUsageDescription + 始终访问地理位置 + NSLocationWhenInUseUsageDescription + 在使用期间访问地理位置 + NSMicrophoneUsageDescription + 请求访问麦克风 + NSPhotoLibraryUsageDescription + 请求访问相册 + NSRemindersUsageDescription + 请求访问注意事项 + UIBackgroundModes + + audio + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/AVAudioRecorderDemo/THLevelPair.h b/AVAudioRecorderDemo/THLevelPair.h new file mode 100644 index 0000000..f900f7e --- /dev/null +++ b/AVAudioRecorderDemo/THLevelPair.h @@ -0,0 +1,37 @@ +// +// MIT License +// +// Copyright (c) 2014 Bob McCune http://bobmccune.com/ +// Copyright (c) 2014 TapHarmonic, LLC http://tapharmonic.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#import +#import +#import +@interface THLevelPair : NSObject + +@property (nonatomic, readonly) float level; +@property (nonatomic, readonly) float peakLevel; + ++ (instancetype)levelsWithLevel:(float)level peakLevel:(float)peakLevel; + +- (instancetype)initWithLevel:(float)level peakLevel:(float)peakLevel; + +@end diff --git a/AVAudioRecorderDemo/THLevelPair.m b/AVAudioRecorderDemo/THLevelPair.m new file mode 100644 index 0000000..e7cd06c --- /dev/null +++ b/AVAudioRecorderDemo/THLevelPair.m @@ -0,0 +1,43 @@ +// +// MIT License +// +// Copyright (c) 2014 Bob McCune http://bobmccune.com/ +// Copyright (c) 2014 TapHarmonic, LLC http://tapharmonic.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "THLevelPair.h" + +@implementation THLevelPair + ++ (instancetype)levelsWithLevel:(float)level peakLevel:(float)peakLevel { + return [[self alloc] initWithLevel:level peakLevel:peakLevel]; +} + +- (instancetype)initWithLevel:(float)level peakLevel:(float)peakLevel { + self = [super init]; + if (self) { + _level = level; + _peakLevel = peakLevel; + } + return self; +} + +@end diff --git a/AVAudioRecorderDemo/THMemo.h b/AVAudioRecorderDemo/THMemo.h new file mode 100644 index 0000000..76d1103 --- /dev/null +++ b/AVAudioRecorderDemo/THMemo.h @@ -0,0 +1,39 @@ +// +// MIT License +// +// Copyright (c) 2014 Bob McCune http://bobmccune.com/ +// Copyright (c) 2014 TapHarmonic, LLC http://tapharmonic.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#import +#import +#import +@interface THMemo : NSObject + +@property (copy, nonatomic, readonly) NSString *title; +@property (strong, nonatomic, readonly) NSURL *url; +@property (copy, nonatomic, readonly) NSString *dateString; +@property (copy, nonatomic, readonly) NSString *timeString; + ++ (instancetype)memoWithTitle:(NSString *)title url:(NSURL *)url; + +- (BOOL)deleteMemo; + +@end diff --git a/AVAudioRecorderDemo/THMemo.m b/AVAudioRecorderDemo/THMemo.m new file mode 100644 index 0000000..39e23a5 --- /dev/null +++ b/AVAudioRecorderDemo/THMemo.m @@ -0,0 +1,99 @@ +// +// MIT License +// +// Copyright (c) 2014 Bob McCune http://bobmccune.com/ +// Copyright (c) 2014 TapHarmonic, LLC http://tapharmonic.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#import +#import +#import +#import "THMemo.h" + +#define TITLE_KEY @"title" +#define URL_KEY @"url" +#define DATE_STRING_KEY @"dateString" +#define TIME_STRING_KEY @"timeString" + +@implementation THMemo + ++ (instancetype)memoWithTitle:(NSString *)title url:(NSURL *)url { + return [[self alloc] initWithTitle:title url:url]; +} + +- (id)initWithTitle:(NSString *)title url:(NSURL *)url { + self = [super init]; + if (self) { + _title = [title copy]; + _url = url; + + NSDate *date = [NSDate date]; + _dateString = [self dateStringWithDate:date]; + _timeString = [self timeStringWithDate:date]; + } + return self; +} + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:self.title forKey:TITLE_KEY]; + [coder encodeObject:self.url forKey:URL_KEY]; + [coder encodeObject:self.dateString forKey:DATE_STRING_KEY]; + [coder encodeObject:self.timeString forKey:TIME_STRING_KEY]; +} + +- (id)initWithCoder:(NSCoder *)decoder { + self = [super init]; + if (self) { + _title = [decoder decodeObjectForKey:TITLE_KEY]; + _url = [decoder decodeObjectForKey:URL_KEY]; + _dateString = [decoder decodeObjectForKey:DATE_STRING_KEY]; + _timeString = [decoder decodeObjectForKey:TIME_STRING_KEY]; + } + return self; +} + +- (NSString *)dateStringWithDate:(NSDate *)date { + NSDateFormatter *formatter = [self formatterWithFormat:@"MMddyyyy"]; + return [formatter stringFromDate:date]; +} + +- (NSString *)timeStringWithDate:(NSDate *)date { + NSDateFormatter *formatter = [self formatterWithFormat:@"HHmmss"]; + return [formatter stringFromDate:date]; +} + +- (NSDateFormatter *)formatterWithFormat:(NSString *)template { + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; + [formatter setLocale:[NSLocale currentLocale]]; + NSString *format = [NSDateFormatter dateFormatFromTemplate:template options:0 locale:[NSLocale currentLocale]]; + [formatter setDateFormat:format]; + return formatter; +} + +- (BOOL)deleteMemo { + NSError *error; + BOOL success = [[NSFileManager defaultManager] removeItemAtURL:self.url error:&error]; + if (!success) { + NSLog(@"Unable to delete: %@", [error localizedDescription]); + } + return success; +} + +@end diff --git a/AVAudioRecorderDemo/THMemoCell.h b/AVAudioRecorderDemo/THMemoCell.h new file mode 100644 index 0000000..696ff9e --- /dev/null +++ b/AVAudioRecorderDemo/THMemoCell.h @@ -0,0 +1,15 @@ +// +// THMemoCell.h +// AVAudioRecorderDemo +// +// Created by 袁俊晓 on 2018/2/5. +// Copyright © 2018年 yuanjunxiao. All rights reserved. +// + +#import + +@interface THMemoCell : UITableViewCell +@property (weak, nonatomic) IBOutlet UILabel *titleLabel; +@property (weak, nonatomic) IBOutlet UILabel *dateLabel; +@property (weak, nonatomic) IBOutlet UILabel *timeLabel; +@end diff --git a/AVAudioRecorderDemo/THMemoCell.m b/AVAudioRecorderDemo/THMemoCell.m new file mode 100644 index 0000000..d53644d --- /dev/null +++ b/AVAudioRecorderDemo/THMemoCell.m @@ -0,0 +1,24 @@ +// +// THMemoCell.m +// AVAudioRecorderDemo +// +// Created by 袁俊晓 on 2018/2/5. +// Copyright © 2018年 yuanjunxiao. All rights reserved. +// + +#import "THMemoCell.h" + +@implementation THMemoCell + +- (void)awakeFromNib { + [super awakeFromNib]; + // Initialization code +} + +- (void)setSelected:(BOOL)selected animated:(BOOL)animated { + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state +} + +@end diff --git a/AVAudioRecorderDemo/THMemoCell.xib b/AVAudioRecorderDemo/THMemoCell.xib new file mode 100644 index 0000000..37262cd --- /dev/null +++ b/AVAudioRecorderDemo/THMemoCell.xib @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/AVAudioRecorderDemo/THRecorderController.h b/AVAudioRecorderDemo/THRecorderController.h new file mode 100644 index 0000000..310ccbc --- /dev/null +++ b/AVAudioRecorderDemo/THRecorderController.h @@ -0,0 +1,31 @@ +// +// THRecorderController.h +// AVAudioRecorderDemo +// +// Created by 袁俊晓 on 2018/2/4. +// Copyright © 2018年 yuanjunxiao. All rights reserved. +// + +#import +#import +typedef void (^THRecordingStopComletionHandler)(BOOL); +typedef void (^THRecordingSaveComletionHandler)(BOOL,id); + +@protocol THRecorderControllerDelegate +- (void)interruptionBegan; +@end + +@class THLevelPair; +@class THMemo; +@interface THRecorderController : NSObject +@property (nonatomic,readonly)NSString *formattedCurrentTime; + +@property (nonatomic,weak)id delegate; + +-(BOOL)record; +-(void)pause; +-(void)stopWithCompletionHandler:(THRecordingStopComletionHandler)hander; +-(void)saveRecordingWithName:(NSString *)name completionHander:(THRecordingSaveComletionHandler)hander; +-(BOOL)playbackMemo:(THMemo *)memo; +- (THLevelPair *)levels; +@end diff --git a/AVAudioRecorderDemo/THRecorderController.m b/AVAudioRecorderDemo/THRecorderController.m new file mode 100644 index 0000000..67a55b5 --- /dev/null +++ b/AVAudioRecorderDemo/THRecorderController.m @@ -0,0 +1,146 @@ +// +// THRecorderController.m +// AVAudioRecorderDemo +// +// Created by 袁俊晓 on 2018/2/4. +// Copyright © 2018年 yuanjunxiao. All rights reserved. +// + +#import "THRecorderController.h" +#import "THMemo.h" +#import "THLevelPair.h" +#import "THMeterTable.h" +@interface THRecorderController() + +@property (nonatomic,strong)AVAudioPlayer *Player; +@property (nonatomic,strong)AVAudioRecorder *recorder; +@property (nonatomic,strong)THRecordingStopComletionHandler completionHander; +@property (strong, nonatomic) THMeterTable *meterTable; + +@end +@implementation THRecorderController + +-(instancetype)init{ + self =[super init]; + if (self) { + // 1.写入文件的本地URL + NSString *tmpDir =NSTemporaryDirectory(); + NSString *filePath =[tmpDir stringByAppendingPathComponent:@"memo.caf"]; + NSURL *fileUrl =[NSURL fileURLWithPath:filePath]; + // 2.配置录音会话键值得NSDictionary对象 + NSDictionary *settings =@{ + // 音频格式 + AVFormatIDKey:@(kAudioFormatAppleIMA4), + // 采样率 + AVSampleRateKey:@44100.0f, + // 通道数 + AVNumberOfChannelsKey:@1, + // 位深 + AVEncoderBitDepthHintKey:@16, + // 音频质量 + AVEncoderAudioQualityKey:@(AVAudioQualityMedium) + }; + // 3.捕捉初始化阶段各种错误的NSError指针 + NSError *error; + self.recorder =[[AVAudioRecorder alloc]initWithURL:fileUrl settings:settings error:&error]; + if (self.recorder) { + self.recorder.delegate =self; + // 制作音柱效果时千万注意打开 + self.recorder.meteringEnabled = YES; + [self.recorder prepareToRecord]; + + }else{ + NSLog(@"error:%@",[error localizedDescription]); + } + _meterTable = [[THMeterTable alloc] init]; + + } + return self; +} +-(BOOL)record{ + return [self.recorder record]; +} +-(void)pause{ + return [self.recorder pause]; +} +-(void)stopWithCompletionHandler:(THRecordingStopComletionHandler)hander{ + self.completionHander = hander; + [self.recorder stop]; +} +-(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag{ + if (self.completionHander) { + self.completionHander(flag); + } +} + + +-(void)saveRecordingWithName:(NSString *)name completionHander:(THRecordingSaveComletionHandler)hander{ + NSTimeInterval timestamp =[NSDate timeIntervalSinceReferenceDate]; + NSString *filename =[NSString stringWithFormat:@"%@-%f.caf",name,timestamp]; + NSString *docDir =[self documentsDirectory]; + NSString *destpath =[docDir stringByAppendingPathComponent:filename]; + NSURL *srcUrl =self.recorder.url; + NSURL *destUrl =[NSURL fileURLWithPath:destpath]; + + NSError *error; + BOOL success =[[NSFileManager defaultManager] copyItemAtURL:srcUrl toURL:destUrl error:&error]; + + if (success) { + hander(YES,[THMemo memoWithTitle:name url:destUrl]); + [self.recorder prepareToRecord]; + } +} +-(NSString *)documentsDirectory{ + + NSArray *paths =NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + return [paths objectAtIndex:0]; + + +} +-(BOOL)playbackMemo:(THMemo *)memo{ + [self.Player stop]; + NSLog(@"memo.url=%@",memo.url); + self.Player =[[AVAudioPlayer alloc]initWithContentsOfURL:memo.url error:nil]; + if (self.Player) { + [self.Player play]; + return YES; + } + return NO; +} + + +- (void)audioRecorderBeginInterruption:(AVAudioRecorder *)recorder { + if (self.delegate) { + [self.delegate interruptionBegan]; + } +} +//时间展示 +-(NSString *)formattedCurrentTime{ + + NSUInteger time =(NSUInteger)self.recorder.currentTime; + NSInteger hours =(time / 3600); + NSInteger minutes =(time / 60)%60; + NSInteger seconds =time%60; + NSString *format =@"%02i:%02i:%02i"; + return [NSString stringWithFormat:format,hours,minutes,seconds]; + +} + +- (THLevelPair *)levels { + [self.recorder updateMeters]; + float avgPower = [self.recorder averagePowerForChannel:0]; + float peakPower = [self.recorder peakPowerForChannel:0]; + float linearLevel = [self.meterTable valueForPower:avgPower]; + float linearPeak = [self.meterTable valueForPower:peakPower]; + return [THLevelPair levelsWithLevel:linearLevel peakLevel:linearPeak]; +} + + + + + + + + + +@end diff --git a/AVAudioRecorderDemo/ViewController.h b/AVAudioRecorderDemo/ViewController.h new file mode 100644 index 0000000..1d0ad53 --- /dev/null +++ b/AVAudioRecorderDemo/ViewController.h @@ -0,0 +1,13 @@ +// +// ViewController.h +// AVAudioRecorderDemo +// +// Created by 袁俊晓 on 2018/2/4. +// Copyright © 2018年 yuanjunxiao. All rights reserved. +// + +#import +@interface ViewController : UIViewController + +@end + diff --git a/AVAudioRecorderDemo/ViewController.m b/AVAudioRecorderDemo/ViewController.m new file mode 100644 index 0000000..b6bafd3 --- /dev/null +++ b/AVAudioRecorderDemo/ViewController.m @@ -0,0 +1,242 @@ +// +// ViewController.m +// AVAudioRecorderDemo +// +// Created by 袁俊晓 on 2018/2/4. +// Copyright © 2018年 yuanjunxiao. All rights reserved. +// + +#import "ViewController.h" +#import +#import "THRecorderController.h" +#import "THMemo.h" +#import "THMemoCell.h" +#import "THLevelMeterView.h" +#import "THLevelPair.h" +#define CANCEL_BUTTON 0 +#define OK_BUTTON 1 + +#define MEMO_CELL @"memoCell" +#define MEMOS_ARCHIVE @"memos.archive" +@interface ViewController () +@property (nonatomic,strong)NSMutableArray *memos; +@property (nonatomic,strong)CADisplayLink *levelTimer; +@property (nonatomic,strong)NSTimer *timer; +@property (nonatomic,strong)THRecorderController *controller; + +@property (weak, nonatomic) IBOutlet UITableView *tableView; +@property (weak, nonatomic) IBOutlet UIButton *recordButton; +@property (weak, nonatomic) IBOutlet UIButton *stopButton; +@property (weak, nonatomic) IBOutlet UILabel *timeLabel; +@property (weak, nonatomic) IBOutlet THLevelMeterView *levelMeterView; + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + _controller = [[THRecorderController alloc] init]; + _controller.delegate = self; + self.stopButton.enabled = NO; + _memos = [NSMutableArray array]; + + UIImage *recordImage = [[UIImage imageNamed:@"record"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + UIImage *pauseImage = [[UIImage imageNamed:@"pause"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + UIImage *stopImage = [[UIImage imageNamed:@"stop"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; + + [self.recordButton setImage:recordImage forState:UIControlStateNormal]; + [self.recordButton setImage:pauseImage forState:UIControlStateSelected]; + [self.stopButton setImage:stopImage forState:UIControlStateNormal]; + + NSData *data = [NSData dataWithContentsOfURL:[self archiveURL]]; + if (!data) { + _memos = [NSMutableArray array]; + } else { + _memos = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + } + + _tableView.delegate = self; + _tableView.dataSource = self;//设置代理 + _tableView.backgroundColor = [UIColor colorWithRed:242/255.f green:242/255.f blue:242/255.f alpha:1.0]; + //允许多项选择 默认是no;默认是单选 + _tableView.allowsMultipleSelection = YES; + //取消多余的cell + _tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero];//取消多余行数 + //nib类 + [_tableView registerNib:[UINib nibWithNibName:@"THMemoCell" bundle:nil] forCellReuseIdentifier:@"THMemoCell"]; + + +} + + +- (IBAction)record:(id)sender { + //判断是否正在录音暂停 + self.stopButton.enabled = YES; + if (![sender isSelected]) { + [self startMeterTimer]; + [self startTimer]; + [self.controller record]; + } else { + [self stopMeterTimer]; + [self stopTimer]; + [self.controller pause]; + } + [sender setSelected:![sender isSelected]]; +} +- (IBAction)stopRecording:(id)sender { + [self stopMeterTimer]; + self.recordButton.selected = NO; + self.stopButton.enabled = NO; + [self.controller stopWithCompletionHandler:^(BOOL result) { + double delayInSeconds = 0.01; + dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t) (delayInSeconds * NSEC_PER_SEC)); + dispatch_after(popTime, dispatch_get_main_queue(), ^{ + [self showSaveDialog]; + }); + }]; +} + +- (void)interruptionBegan { + self.recordButton.selected = NO; + [self stopMeterTimer]; + [self stopTimer]; +} +-(void)startTimer{ + [self.timer invalidate]; + self.timer =[NSTimer timerWithTimeInterval:0.5 target:self selector:@selector(updataTimeDisplay) userInfo:nil repeats:YES]; + [[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; +} +-(void)stopTimer{ + [self.timer invalidate]; + self.timer = nil; +} +-(void)updataTimeDisplay{ + self.timeLabel.text = self.controller.formattedCurrentTime; +} + +- (void)showSaveDialog { + UIAlertController *alertController = [UIAlertController + alertControllerWithTitle:@"保存录音" + message:@"请填写本次录音的名称" + preferredStyle:UIAlertControllerStyleAlert]; + + [alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { + textField.placeholder = NSLocalizedString(@"My Recording", @"Login"); + }]; + + UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]; + UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + NSString *filename = [alertController.textFields.firstObject text]; + NSLog(@"filename:=%@=",filename); + [self.controller saveRecordingWithName:filename completionHander:^(BOOL success, id object) { + if (success) { + NSLog(@"object:=%@=",object); + [self.memos addObject:object]; + NSLog(@"memos:%@",self.memos); + [self saveMemos]; + [self.tableView reloadData]; + } else { + NSLog(@"Error saving file: %@", [object localizedDescription]); + } + }]; + }]; + + [alertController addAction:cancelAction]; + [alertController addAction:okAction]; + + [self presentViewController:alertController animated:YES completion:nil]; +} + + +#pragma mark - Memo Archiving + +- (void)saveMemos { + NSData *fileData = [NSKeyedArchiver archivedDataWithRootObject:self.memos]; + [fileData writeToURL:[self archiveURL] atomically:YES]; +} + +- (NSURL *)archiveURL { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *docsDir = [paths objectAtIndex:0]; + NSString *archivePath = [docsDir stringByAppendingPathComponent:MEMOS_ARCHIVE]; + return [NSURL fileURLWithPath:archivePath]; +} + + +#pragma mark - UITableView Datasource and Delegate + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return self.memos.count; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + THMemoCell *cell = [tableView dequeueReusableCellWithIdentifier:@"THMemoCell" forIndexPath:indexPath]; + THMemo *memo = self.memos[indexPath.row]; + cell.titleLabel.text = memo.title; + cell.dateLabel.text = memo.dateString; + cell.timeLabel.text = memo.timeString; + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + [_tableView deselectRowAtIndexPath:indexPath animated:YES]; + THMemo *memo = self.memos[indexPath.row]; + [self.controller playbackMemo:memo]; +} +-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ + return 60; + // return 400; +} +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { + return YES; +} + +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { + if (editingStyle == UITableViewCellEditingStyleDelete) { + THMemo *memo = self.memos[indexPath.row]; + [memo deleteMemo]; + [self.memos removeObjectAtIndex:indexPath.row]; + [self saveMemos]; + [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; + } +} + + +#pragma mark - Level Metering + +- (void)startMeterTimer { + [self.levelTimer invalidate]; + self.levelTimer = [CADisplayLink displayLinkWithTarget:self + selector:@selector(updateMeter)]; + self.levelTimer.frameInterval = 5; + [self.levelTimer addToRunLoop:[NSRunLoop currentRunLoop] + forMode:NSRunLoopCommonModes]; +} + +- (void)stopMeterTimer { + [self.levelTimer invalidate]; + self.levelTimer = nil; + [self.levelMeterView resetLevelMeter]; +} + +- (void)updateMeter { + THLevelPair *levels = [self.controller levels]; + self.levelMeterView.level = levels.level; + self.levelMeterView.peakLevel = levels.peakLevel; + [self.levelMeterView setNeedsDisplay]; +} +- (void)didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. +} + + + + + + + + +@end diff --git a/AVAudioRecorderDemo/leaveMeter/THLevelMeterColorThreshold.h b/AVAudioRecorderDemo/leaveMeter/THLevelMeterColorThreshold.h new file mode 100644 index 0000000..841170d --- /dev/null +++ b/AVAudioRecorderDemo/leaveMeter/THLevelMeterColorThreshold.h @@ -0,0 +1,36 @@ +// +// MIT License +// +// Copyright (c) 2014 Bob McCune http://bobmccune.com/ +// Copyright (c) 2014 TapHarmonic, LLC http://tapharmonic.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#import +#import +#import +@interface THLevelMeterColorThreshold : NSObject + +@property (nonatomic, readonly) CGFloat maxValue; +@property (nonatomic, strong, readonly) UIColor *color; +@property (nonatomic, copy, readonly) NSString *name; + ++ (instancetype)colorThresholdWithMaxValue:(CGFloat)maxValue color:(UIColor *)color name:(NSString *)name; + +@end diff --git a/AVAudioRecorderDemo/leaveMeter/THLevelMeterColorThreshold.m b/AVAudioRecorderDemo/leaveMeter/THLevelMeterColorThreshold.m new file mode 100644 index 0000000..cd35f57 --- /dev/null +++ b/AVAudioRecorderDemo/leaveMeter/THLevelMeterColorThreshold.m @@ -0,0 +1,48 @@ +// +// MIT License +// +// Copyright (c) 2014 Bob McCune http://bobmccune.com/ +// Copyright (c) 2014 TapHarmonic, LLC http://tapharmonic.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "THLevelMeterColorThreshold.h" + +@implementation THLevelMeterColorThreshold + ++ (instancetype)colorThresholdWithMaxValue:(CGFloat)maxValue color:(UIColor *)color name:(NSString *)name { + return [[self alloc] initWithMaxValue:maxValue color:color name:name]; +} + +- (instancetype)initWithMaxValue:(CGFloat)maxValue color:(UIColor *)color name:(NSString *)name { + self = [super init]; + if (self) { + _maxValue = maxValue; + _color = color; + _name = [name copy]; + } + return self; +} + +- (NSString *)description { + return self.name; +} + +@end diff --git a/AVAudioRecorderDemo/leaveMeter/THLevelMeterView.h b/AVAudioRecorderDemo/leaveMeter/THLevelMeterView.h new file mode 100644 index 0000000..4875b4b --- /dev/null +++ b/AVAudioRecorderDemo/leaveMeter/THLevelMeterView.h @@ -0,0 +1,35 @@ +// +// MIT License +// +// Copyright (c) 2014 Bob McCune http://bobmccune.com/ +// Copyright (c) 2014 TapHarmonic, LLC http://tapharmonic.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +#import +#import +#import +@interface THLevelMeterView : UIView + +@property (nonatomic) CGFloat level; +@property (nonatomic) CGFloat peakLevel; + +- (void)resetLevelMeter; + +@end diff --git a/AVAudioRecorderDemo/leaveMeter/THLevelMeterView.m b/AVAudioRecorderDemo/leaveMeter/THLevelMeterView.m new file mode 100644 index 0000000..d846ada --- /dev/null +++ b/AVAudioRecorderDemo/leaveMeter/THLevelMeterView.m @@ -0,0 +1,165 @@ +// +// MIT License +// +// Copyright (c) 2014 Bob McCune http://bobmccune.com/ +// Copyright (c) 2014 TapHarmonic, LLC http://tapharmonic.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#import "THLevelMeterView.h" +#import "THLevelMeterColorThreshold.h" + +@interface THLevelMeterView () + +@property (nonatomic) NSUInteger ledCount; +@property (strong, nonatomic) UIColor *ledBackgroundColor; +@property (strong, nonatomic) UIColor *ledBorderColor; +@property (nonatomic, strong) NSArray *colorThresholds; + +@end + +@implementation THLevelMeterView + +- (id)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + if (self) { + [self setupView]; + } + return self; +} + +- (id)initWithCoder:(NSCoder *)coder { + self = [super initWithCoder:coder]; + if (self) { + [self setupView]; + } + return self; +} + +- (void)setupView { + + self.backgroundColor = [UIColor clearColor]; + + _ledCount = 20; + + _ledBackgroundColor = [UIColor colorWithWhite:0.0f alpha:0.35f]; + _ledBorderColor = [UIColor blackColor]; + + UIColor *greenColor = [UIColor colorWithRed:0.458 green:1.000 blue:0.396 alpha:1.000]; + UIColor *yellowColor = [UIColor colorWithRed:1.000 green:0.930 blue:0.315 alpha:1.000]; + UIColor *redColor = [UIColor colorWithRed:1.000 green:0.325 blue:0.329 alpha:1.000]; + + _colorThresholds = @[[THLevelMeterColorThreshold colorThresholdWithMaxValue:0.5 color:greenColor name:@"green"], + [THLevelMeterColorThreshold colorThresholdWithMaxValue:0.8 color:yellowColor name:@"yellow"], + [THLevelMeterColorThreshold colorThresholdWithMaxValue:1.0 color:redColor name:@"red"]]; +} + +- (void)drawRect:(CGRect)rect { + + CGContextRef context = UIGraphicsGetCurrentContext(); + + CGContextTranslateCTM(context, 0, CGRectGetHeight(self.bounds)); + CGContextRotateCTM(context, (CGFloat) -M_PI_2); + CGRect bounds = CGRectMake(0., 0., [self bounds].size.height, [self bounds].size.width); + + + CGFloat lightMinValue = 0.0f; + + NSInteger peakLED = -1; + + if (self.peakLevel > 0.0f) { + peakLED = self.peakLevel * self.ledCount; + if (peakLED >= self.ledCount) { + peakLED = self.ledCount - 1; + } + } + + for (int ledIndex = 0; ledIndex < self.ledCount; ledIndex++) { + + UIColor *ledColor = [self.colorThresholds[0] color]; + + CGFloat ledMaxValue = (CGFloat) (ledIndex + 1) / self.ledCount; + + for (int colorIndex = 0; colorIndex < self.colorThresholds.count - 1; colorIndex++) { + THLevelMeterColorThreshold *currThreshold = self.colorThresholds[colorIndex]; + THLevelMeterColorThreshold *nextThreshold = self.colorThresholds[colorIndex + 1]; + if (currThreshold.maxValue <= ledMaxValue) { + ledColor = nextThreshold.color; + } + } + + CGFloat height = CGRectGetHeight(bounds); + CGFloat width = CGRectGetWidth(bounds); + + CGRect ledRect = CGRectMake(0.0f, height * ((CGFloat) ledIndex / self.ledCount), width, height * (1.0f / self.ledCount)); + + // Fill background color + CGContextSetFillColorWithColor(context, self.ledBackgroundColor.CGColor); + CGContextFillRect(context, ledRect); + + // Draw Light + CGFloat lightIntensity; + if (ledIndex == peakLED) { + lightIntensity = 1.0f; + } else { + lightIntensity = clamp((self.level - lightMinValue) / (ledMaxValue - lightMinValue)); + } + + UIColor *fillColor = nil; + if (lightIntensity == 1.0f) { + fillColor = ledColor; + } else if (lightIntensity > 0.0f) { + CGColorRef color = CGColorCreateCopyWithAlpha([ledColor CGColor], lightIntensity); + fillColor = [UIColor colorWithCGColor:color]; + CGColorRelease(color); + } + + CGContextSetFillColorWithColor(context, fillColor.CGColor); + UIBezierPath *fillPath = [UIBezierPath bezierPathWithRoundedRect:ledRect cornerRadius:2.0f]; + CGContextAddPath(context, fillPath.CGPath); + + // Stroke border + CGContextSetStrokeColorWithColor(context, self.ledBorderColor.CGColor); + UIBezierPath *strokePath = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(ledRect, 0.5, 0.5) cornerRadius:2.0f]; + CGContextAddPath(context, strokePath.CGPath); + + CGContextDrawPath(context, kCGPathFillStroke); + + lightMinValue = ledMaxValue; + } +} + +CGFloat clamp(CGFloat intensity) { + if (intensity < 0.0f) { + return 0.0f; + } else if (intensity >= 1.0) { + return 1.0f; + } else { + return intensity; + } +} + +- (void)resetLevelMeter { + self.level = 0.0f; + self.peakLevel = 0.0f; + [self setNeedsDisplay]; +} + +@end diff --git a/AVAudioRecorderDemo/leaveMeter/THMeterTable.h b/AVAudioRecorderDemo/leaveMeter/THMeterTable.h new file mode 100644 index 0000000..102c414 --- /dev/null +++ b/AVAudioRecorderDemo/leaveMeter/THMeterTable.h @@ -0,0 +1,35 @@ +// +// MIT License +// +// Copyright (c) 2014 Bob McCune http://bobmccune.com/ +// Copyright (c) 2014 TapHarmonic, LLC http://tapharmonic.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// This code is based on Apple's MeterTable.cpp code used by the avTouch and SpeakHere +// sample projects. It creates an internal table storing the precomputed db -> linear +// values. +#import +#import +#import +@interface THMeterTable : NSObject + +- (float)valueForPower:(float)power; + +@end diff --git a/AVAudioRecorderDemo/leaveMeter/THMeterTable.m b/AVAudioRecorderDemo/leaveMeter/THMeterTable.m new file mode 100644 index 0000000..efd8eaa --- /dev/null +++ b/AVAudioRecorderDemo/leaveMeter/THMeterTable.m @@ -0,0 +1,76 @@ +// +// MIT License +// +// Copyright (c) 2014 Bob McCune http://bobmccune.com/ +// Copyright (c) 2014 TapHarmonic, LLC http://tapharmonic.com/ +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// +// This code is based on Apple's MeterTable.cpp code used by the avTouch and SpeakHere +// sample projects. It creates an internal table storing the precomputed db -> linear +// values. + +#import "THMeterTable.h" + +#define MIN_DB -60.0f +#define TABLE_SIZE 300 + +@implementation THMeterTable { + float _scaleFactor; + NSMutableArray *_meterTable; +} + +- (id)init { + self = [super init]; + if (self) { + float dbResolution = MIN_DB / (TABLE_SIZE - 1); + + _meterTable = [NSMutableArray arrayWithCapacity:TABLE_SIZE]; + _scaleFactor = 1.0f / dbResolution; + + float minAmp = dbToAmp(MIN_DB); + float ampRange = 1.0 - minAmp; + float invAmpRange = 1.0 / ampRange; + + for (int i = 0; i < TABLE_SIZE; i++) { + float decibels = i * dbResolution; + float amp = dbToAmp(decibels); + float adjAmp = (amp - minAmp) * invAmpRange; + _meterTable[i] = @(adjAmp); + } + } + return self; +} + +float dbToAmp(float dB) { + return powf(10.0f, 0.05f * dB); +} + +- (float)valueForPower:(float)power { + if (power < MIN_DB) { + return 0.0f; + } else if (power >= 0.0f) { + return 1.0f; + } else { + int index = (int) (power * _scaleFactor); + return [_meterTable[index] floatValue]; + } +} + +@end diff --git a/AVAudioRecorderDemo/main.m b/AVAudioRecorderDemo/main.m new file mode 100644 index 0000000..5953e50 --- /dev/null +++ b/AVAudioRecorderDemo/main.m @@ -0,0 +1,16 @@ +// +// main.m +// AVAudioRecorderDemo +// +// Created by 袁俊晓 on 2018/2/4. +// Copyright © 2018年 yuanjunxiao. All rights reserved. +// + +#import +#import "AppDelegate.h" + +int main(int argc, char * argv[]) { + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); + } +} diff --git a/AVAudioRecorderDemoTests/AVAudioRecorderDemoTests.m b/AVAudioRecorderDemoTests/AVAudioRecorderDemoTests.m new file mode 100644 index 0000000..5f490c0 --- /dev/null +++ b/AVAudioRecorderDemoTests/AVAudioRecorderDemoTests.m @@ -0,0 +1,39 @@ +// +// AVAudioRecorderDemoTests.m +// AVAudioRecorderDemoTests +// +// Created by 袁俊晓 on 2018/2/4. +// Copyright © 2018年 yuanjunxiao. All rights reserved. +// + +#import + +@interface AVAudioRecorderDemoTests : XCTestCase + +@end + +@implementation AVAudioRecorderDemoTests + +- (void)setUp { + [super setUp]; + // Put setup code here. This method is called before the invocation of each test method in the class. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +- (void)testPerformanceExample { + // This is an example of a performance test case. + [self measureBlock:^{ + // Put the code you want to measure the time of here. + }]; +} + +@end diff --git a/AVAudioRecorderDemoTests/Info.plist b/AVAudioRecorderDemoTests/Info.plist new file mode 100644 index 0000000..6c40a6c --- /dev/null +++ b/AVAudioRecorderDemoTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/AVAudioRecorderDemoUITests/AVAudioRecorderDemoUITests.m b/AVAudioRecorderDemoUITests/AVAudioRecorderDemoUITests.m new file mode 100644 index 0000000..004a6ff --- /dev/null +++ b/AVAudioRecorderDemoUITests/AVAudioRecorderDemoUITests.m @@ -0,0 +1,40 @@ +// +// AVAudioRecorderDemoUITests.m +// AVAudioRecorderDemoUITests +// +// Created by 袁俊晓 on 2018/2/4. +// Copyright © 2018年 yuanjunxiao. All rights reserved. +// + +#import + +@interface AVAudioRecorderDemoUITests : XCTestCase + +@end + +@implementation AVAudioRecorderDemoUITests + +- (void)setUp { + [super setUp]; + + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + self.continueAfterFailure = NO; + // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. + [[[XCUIApplication alloc] init] launch]; + + // 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. +} + +- (void)tearDown { + // Put teardown code here. This method is called after the invocation of each test method in the class. + [super tearDown]; +} + +- (void)testExample { + // Use recording to get started writing UI tests. + // Use XCTAssert and related functions to verify your tests produce the correct results. +} + +@end diff --git a/AVAudioRecorderDemoUITests/Info.plist b/AVAudioRecorderDemoUITests/Info.plist new file mode 100644 index 0000000..6c40a6c --- /dev/null +++ b/AVAudioRecorderDemoUITests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + +