├── .gitignore ├── .travis.yml ├── Example ├── Podfile ├── Tests │ ├── Tests-Info.plist │ ├── Tests-Prefix.pch │ ├── Tests.m │ └── en.lproj │ │ └── InfoPlist.strings ├── VTAntiScreenCapture.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── VTAntiScreenCapture-Example.xcscheme └── VTAntiScreenCapture │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── EncodeVC │ ├── EncodeVC.h │ └── EncodeVC.m │ ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── SimpleDRMVC │ ├── SimpleDRMVC.h │ ├── SimpleDRMVC.m │ ├── VTSimplePlayer.h │ ├── VTSimplePlayer.m │ ├── index.m3u8 │ └── text.mp4 │ ├── VTAntiScreenCapture-Info.plist │ ├── VTAntiScreenCapture-Prefix.pch │ ├── VTAppDelegate.h │ ├── VTAppDelegate.m │ ├── VTDemoTableVC.h │ ├── VTDemoTableVC.m │ ├── en.lproj │ └── InfoPlist.strings │ └── main.m ├── LICENSE ├── README.md ├── VTAntiScreenCapture.podspec ├── VTAntiScreenCapture ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ ├── UIView+antiCapture.h │ ├── UIView+antiCapture.m │ ├── VTMP4Encoder.h │ ├── VTMP4Encoder.m │ ├── VTPlayer.h │ └── VTPlayer.m └── _Pods.xcodeproj /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 26 | # Carthage/Checkouts 27 | 28 | Carthage/Build 29 | 30 | # We recommend against adding the Pods directory to your .gitignore. However 31 | # you should judge for yourself, the pros and cons are mentioned at: 32 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 33 | # 34 | # Note: if you ignore the Pods directory, make sure to uncomment 35 | # `pod install` in .travis.yml 36 | # 37 | # Pods/ 38 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * https://www.objc.io/issues/6-build-tools/travis-ci/ 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | osx_image: xcode7.3 6 | language: objective-c 7 | # cache: cocoapods 8 | # podfile: Example/Podfile 9 | # before_install: 10 | # - gem install cocoapods # Since Travis is not always on latest version 11 | # - pod install --project-directory=Example 12 | script: 13 | - set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/VTAntiScreenCapture.xcworkspace -scheme VTAntiScreenCapture-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty 14 | - pod lib lint 15 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | platform :ios, '8.0' 4 | 5 | target 'VTAntiScreenCapture_Example' do 6 | pod 'VTAntiScreenCapture', :path => '../' 7 | pod 'GCDWebServer' 8 | pod 'AFNetworking' 9 | target 'VTAntiScreenCapture_Tests' do 10 | inherit! :search_paths 11 | 12 | 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // The contents of this file are implicitly included at the beginning of every test case source file. 2 | 3 | #ifdef __OBJC__ 4 | 5 | 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /Example/Tests/Tests.m: -------------------------------------------------------------------------------- 1 | // 2 | // VTAntiScreenCaptureTests.m 3 | // VTAntiScreenCaptureTests 4 | // 5 | // Created by mightyme@qq.com on 12/31/2018. 6 | // Copyright (c) 2018 mightyme@qq.com. All rights reserved. 7 | // 8 | 9 | @import XCTest; 10 | 11 | @interface Tests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation Tests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | 36 | -------------------------------------------------------------------------------- /Example/Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 035782A6E0D2DFADCE61443A /* Pods_VTAntiScreenCapture_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E3777863D15BEADD3C31CF4D /* Pods_VTAntiScreenCapture_Example.framework */; }; 11 | 584291969AE9729FDE0EABC9 /* Pods_VTAntiScreenCapture_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C360D7C6400C52561405A303 /* Pods_VTAntiScreenCapture_Tests.framework */; }; 12 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 13 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; }; 14 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 15 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; }; 16 | 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; }; 17 | 6003F59E195388D20070C39A /* VTAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F59D195388D20070C39A /* VTAppDelegate.m */; }; 18 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; }; 19 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; }; 20 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; }; 21 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; }; 22 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; }; 23 | 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; }; 24 | 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */; }; 25 | 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */; }; 26 | B519F31821DA2226008C7F6B /* text.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = B519F31621DA2226008C7F6B /* text.mp4 */; }; 27 | B519F31921DA2226008C7F6B /* SimpleDRMVC.m in Sources */ = {isa = PBXBuildFile; fileRef = B519F31721DA2226008C7F6B /* SimpleDRMVC.m */; }; 28 | B519F31C21DA2264008C7F6B /* VTDemoTableVC.m in Sources */ = {isa = PBXBuildFile; fileRef = B519F31B21DA2264008C7F6B /* VTDemoTableVC.m */; }; 29 | B519F31F21DA2346008C7F6B /* VTSimplePlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = B519F31E21DA2346008C7F6B /* VTSimplePlayer.m */; }; 30 | B519F32F21DB0C2B008C7F6B /* EncodeVC.m in Sources */ = {isa = PBXBuildFile; fileRef = B519F32E21DB0C2B008C7F6B /* EncodeVC.m */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXContainerItemProxy section */ 34 | 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = 6003F582195388D10070C39A /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = 6003F589195388D20070C39A; 39 | remoteInfo = VTAntiScreenCapture; 40 | }; 41 | /* End PBXContainerItemProxy section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | 1C18C4D37554D27CEF37EBC4 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 45 | 2E96A21A8EDD1CD7A63226C2 /* VTAntiScreenCapture.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = VTAntiScreenCapture.podspec; path = ../VTAntiScreenCapture.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 46 | 3C5CD6229265801AC1EF7A49 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; 47 | 6003F58A195388D20070C39A /* VTAntiScreenCapture_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = VTAntiScreenCapture_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 49 | 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 50 | 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 51 | 6003F595195388D20070C39A /* VTAntiScreenCapture-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "VTAntiScreenCapture-Info.plist"; sourceTree = ""; }; 52 | 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 53 | 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 54 | 6003F59B195388D20070C39A /* VTAntiScreenCapture-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "VTAntiScreenCapture-Prefix.pch"; sourceTree = ""; }; 55 | 6003F59C195388D20070C39A /* VTAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VTAppDelegate.h; sourceTree = ""; }; 56 | 6003F59D195388D20070C39A /* VTAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VTAppDelegate.m; sourceTree = ""; }; 57 | 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 58 | 6003F5AE195388D20070C39A /* VTAntiScreenCapture_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = VTAntiScreenCapture_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 60 | 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = ""; }; 61 | 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 62 | 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = ""; }; 63 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = ""; }; 64 | 70E35D6D10B70079BA206F40 /* Pods-VTAntiScreenCapture_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VTAntiScreenCapture_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-VTAntiScreenCapture_Example/Pods-VTAntiScreenCapture_Example.debug.xcconfig"; sourceTree = ""; }; 65 | 71719F9E1E33DC2100824A3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 66 | 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 67 | B4AB297A5A8C057C83A06D72 /* Pods-VTAntiScreenCapture_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VTAntiScreenCapture_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-VTAntiScreenCapture_Tests/Pods-VTAntiScreenCapture_Tests.release.xcconfig"; sourceTree = ""; }; 68 | B519F31521DA2226008C7F6B /* SimpleDRMVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleDRMVC.h; sourceTree = ""; }; 69 | B519F31621DA2226008C7F6B /* text.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = text.mp4; sourceTree = ""; }; 70 | B519F31721DA2226008C7F6B /* SimpleDRMVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimpleDRMVC.m; sourceTree = ""; }; 71 | B519F31A21DA2264008C7F6B /* VTDemoTableVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTDemoTableVC.h; sourceTree = ""; }; 72 | B519F31B21DA2264008C7F6B /* VTDemoTableVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VTDemoTableVC.m; sourceTree = ""; }; 73 | B519F31D21DA2346008C7F6B /* VTSimplePlayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VTSimplePlayer.h; sourceTree = ""; }; 74 | B519F31E21DA2346008C7F6B /* VTSimplePlayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VTSimplePlayer.m; sourceTree = ""; }; 75 | B519F32D21DB0C2B008C7F6B /* EncodeVC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EncodeVC.h; sourceTree = ""; }; 76 | B519F32E21DB0C2B008C7F6B /* EncodeVC.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EncodeVC.m; sourceTree = ""; }; 77 | C360D7C6400C52561405A303 /* Pods_VTAntiScreenCapture_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_VTAntiScreenCapture_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 78 | DEB169BF241381E4A7CF74EB /* Pods-VTAntiScreenCapture_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VTAntiScreenCapture_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-VTAntiScreenCapture_Example/Pods-VTAntiScreenCapture_Example.release.xcconfig"; sourceTree = ""; }; 79 | E3777863D15BEADD3C31CF4D /* Pods_VTAntiScreenCapture_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_VTAntiScreenCapture_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 80 | F54844A1F1585A881352257A /* Pods-VTAntiScreenCapture_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VTAntiScreenCapture_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-VTAntiScreenCapture_Tests/Pods-VTAntiScreenCapture_Tests.debug.xcconfig"; sourceTree = ""; }; 81 | /* End PBXFileReference section */ 82 | 83 | /* Begin PBXFrameworksBuildPhase section */ 84 | 6003F587195388D20070C39A /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */, 89 | 6003F592195388D20070C39A /* UIKit.framework in Frameworks */, 90 | 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */, 91 | 035782A6E0D2DFADCE61443A /* Pods_VTAntiScreenCapture_Example.framework in Frameworks */, 92 | ); 93 | runOnlyForDeploymentPostprocessing = 0; 94 | }; 95 | 6003F5AB195388D20070C39A /* Frameworks */ = { 96 | isa = PBXFrameworksBuildPhase; 97 | buildActionMask = 2147483647; 98 | files = ( 99 | 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */, 100 | 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */, 101 | 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */, 102 | 584291969AE9729FDE0EABC9 /* Pods_VTAntiScreenCapture_Tests.framework in Frameworks */, 103 | ); 104 | runOnlyForDeploymentPostprocessing = 0; 105 | }; 106 | /* End PBXFrameworksBuildPhase section */ 107 | 108 | /* Begin PBXGroup section */ 109 | 6003F581195388D10070C39A = { 110 | isa = PBXGroup; 111 | children = ( 112 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */, 113 | 6003F593195388D20070C39A /* Example for VTAntiScreenCapture */, 114 | 6003F5B5195388D20070C39A /* Tests */, 115 | 6003F58C195388D20070C39A /* Frameworks */, 116 | 6003F58B195388D20070C39A /* Products */, 117 | D7D1DE4D7180B6B8AF359FFC /* Pods */, 118 | ); 119 | sourceTree = ""; 120 | }; 121 | 6003F58B195388D20070C39A /* Products */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 6003F58A195388D20070C39A /* VTAntiScreenCapture_Example.app */, 125 | 6003F5AE195388D20070C39A /* VTAntiScreenCapture_Tests.xctest */, 126 | ); 127 | name = Products; 128 | sourceTree = ""; 129 | }; 130 | 6003F58C195388D20070C39A /* Frameworks */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | 6003F58D195388D20070C39A /* Foundation.framework */, 134 | 6003F58F195388D20070C39A /* CoreGraphics.framework */, 135 | 6003F591195388D20070C39A /* UIKit.framework */, 136 | 6003F5AF195388D20070C39A /* XCTest.framework */, 137 | E3777863D15BEADD3C31CF4D /* Pods_VTAntiScreenCapture_Example.framework */, 138 | C360D7C6400C52561405A303 /* Pods_VTAntiScreenCapture_Tests.framework */, 139 | ); 140 | name = Frameworks; 141 | sourceTree = ""; 142 | }; 143 | 6003F593195388D20070C39A /* Example for VTAntiScreenCapture */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | B519F32C21DB0C16008C7F6B /* EncodeVC */, 147 | B519F31421DA2226008C7F6B /* SimpleDRMVC */, 148 | 6003F59C195388D20070C39A /* VTAppDelegate.h */, 149 | 6003F59D195388D20070C39A /* VTAppDelegate.m */, 150 | B519F31A21DA2264008C7F6B /* VTDemoTableVC.h */, 151 | B519F31B21DA2264008C7F6B /* VTDemoTableVC.m */, 152 | 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */, 153 | 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */, 154 | 6003F5A8195388D20070C39A /* Images.xcassets */, 155 | 6003F594195388D20070C39A /* Supporting Files */, 156 | ); 157 | name = "Example for VTAntiScreenCapture"; 158 | path = VTAntiScreenCapture; 159 | sourceTree = ""; 160 | }; 161 | 6003F594195388D20070C39A /* Supporting Files */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | 6003F595195388D20070C39A /* VTAntiScreenCapture-Info.plist */, 165 | 6003F596195388D20070C39A /* InfoPlist.strings */, 166 | 6003F599195388D20070C39A /* main.m */, 167 | 6003F59B195388D20070C39A /* VTAntiScreenCapture-Prefix.pch */, 168 | ); 169 | name = "Supporting Files"; 170 | sourceTree = ""; 171 | }; 172 | 6003F5B5195388D20070C39A /* Tests */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 6003F5BB195388D20070C39A /* Tests.m */, 176 | 6003F5B6195388D20070C39A /* Supporting Files */, 177 | ); 178 | path = Tests; 179 | sourceTree = ""; 180 | }; 181 | 6003F5B6195388D20070C39A /* Supporting Files */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 6003F5B7195388D20070C39A /* Tests-Info.plist */, 185 | 6003F5B8195388D20070C39A /* InfoPlist.strings */, 186 | 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */, 187 | ); 188 | name = "Supporting Files"; 189 | sourceTree = ""; 190 | }; 191 | 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | 2E96A21A8EDD1CD7A63226C2 /* VTAntiScreenCapture.podspec */, 195 | 1C18C4D37554D27CEF37EBC4 /* README.md */, 196 | 3C5CD6229265801AC1EF7A49 /* LICENSE */, 197 | ); 198 | name = "Podspec Metadata"; 199 | sourceTree = ""; 200 | }; 201 | B519F31421DA2226008C7F6B /* SimpleDRMVC */ = { 202 | isa = PBXGroup; 203 | children = ( 204 | B519F31621DA2226008C7F6B /* text.mp4 */, 205 | B519F31521DA2226008C7F6B /* SimpleDRMVC.h */, 206 | B519F31721DA2226008C7F6B /* SimpleDRMVC.m */, 207 | B519F31D21DA2346008C7F6B /* VTSimplePlayer.h */, 208 | B519F31E21DA2346008C7F6B /* VTSimplePlayer.m */, 209 | ); 210 | path = SimpleDRMVC; 211 | sourceTree = ""; 212 | }; 213 | B519F32C21DB0C16008C7F6B /* EncodeVC */ = { 214 | isa = PBXGroup; 215 | children = ( 216 | B519F32D21DB0C2B008C7F6B /* EncodeVC.h */, 217 | B519F32E21DB0C2B008C7F6B /* EncodeVC.m */, 218 | ); 219 | path = EncodeVC; 220 | sourceTree = ""; 221 | }; 222 | D7D1DE4D7180B6B8AF359FFC /* Pods */ = { 223 | isa = PBXGroup; 224 | children = ( 225 | 70E35D6D10B70079BA206F40 /* Pods-VTAntiScreenCapture_Example.debug.xcconfig */, 226 | DEB169BF241381E4A7CF74EB /* Pods-VTAntiScreenCapture_Example.release.xcconfig */, 227 | F54844A1F1585A881352257A /* Pods-VTAntiScreenCapture_Tests.debug.xcconfig */, 228 | B4AB297A5A8C057C83A06D72 /* Pods-VTAntiScreenCapture_Tests.release.xcconfig */, 229 | ); 230 | name = Pods; 231 | sourceTree = ""; 232 | }; 233 | /* End PBXGroup section */ 234 | 235 | /* Begin PBXNativeTarget section */ 236 | 6003F589195388D20070C39A /* VTAntiScreenCapture_Example */ = { 237 | isa = PBXNativeTarget; 238 | buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "VTAntiScreenCapture_Example" */; 239 | buildPhases = ( 240 | 8CDB88E1DBD6869D915B63AC /* [CP] Check Pods Manifest.lock */, 241 | 6003F586195388D20070C39A /* Sources */, 242 | 6003F587195388D20070C39A /* Frameworks */, 243 | 6003F588195388D20070C39A /* Resources */, 244 | F15D71A19ACFA6501D486511 /* [CP] Embed Pods Frameworks */, 245 | ); 246 | buildRules = ( 247 | ); 248 | dependencies = ( 249 | ); 250 | name = VTAntiScreenCapture_Example; 251 | productName = VTAntiScreenCapture; 252 | productReference = 6003F58A195388D20070C39A /* VTAntiScreenCapture_Example.app */; 253 | productType = "com.apple.product-type.application"; 254 | }; 255 | 6003F5AD195388D20070C39A /* VTAntiScreenCapture_Tests */ = { 256 | isa = PBXNativeTarget; 257 | buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "VTAntiScreenCapture_Tests" */; 258 | buildPhases = ( 259 | DF706BBACABE40E03F9F5EC7 /* [CP] Check Pods Manifest.lock */, 260 | 6003F5AA195388D20070C39A /* Sources */, 261 | 6003F5AB195388D20070C39A /* Frameworks */, 262 | 6003F5AC195388D20070C39A /* Resources */, 263 | ); 264 | buildRules = ( 265 | ); 266 | dependencies = ( 267 | 6003F5B4195388D20070C39A /* PBXTargetDependency */, 268 | ); 269 | name = VTAntiScreenCapture_Tests; 270 | productName = VTAntiScreenCaptureTests; 271 | productReference = 6003F5AE195388D20070C39A /* VTAntiScreenCapture_Tests.xctest */; 272 | productType = "com.apple.product-type.bundle.unit-test"; 273 | }; 274 | /* End PBXNativeTarget section */ 275 | 276 | /* Begin PBXProject section */ 277 | 6003F582195388D10070C39A /* Project object */ = { 278 | isa = PBXProject; 279 | attributes = { 280 | CLASSPREFIX = VT; 281 | LastUpgradeCheck = 0720; 282 | ORGANIZATIONNAME = "yuweishan@126.com"; 283 | TargetAttributes = { 284 | 6003F589195388D20070C39A = { 285 | DevelopmentTeam = 664M9NYFXA; 286 | ProvisioningStyle = Automatic; 287 | }; 288 | 6003F5AD195388D20070C39A = { 289 | TestTargetID = 6003F589195388D20070C39A; 290 | }; 291 | }; 292 | }; 293 | buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "VTAntiScreenCapture" */; 294 | compatibilityVersion = "Xcode 3.2"; 295 | developmentRegion = English; 296 | hasScannedForEncodings = 0; 297 | knownRegions = ( 298 | en, 299 | Base, 300 | ); 301 | mainGroup = 6003F581195388D10070C39A; 302 | productRefGroup = 6003F58B195388D20070C39A /* Products */; 303 | projectDirPath = ""; 304 | projectRoot = ""; 305 | targets = ( 306 | 6003F589195388D20070C39A /* VTAntiScreenCapture_Example */, 307 | 6003F5AD195388D20070C39A /* VTAntiScreenCapture_Tests */, 308 | ); 309 | }; 310 | /* End PBXProject section */ 311 | 312 | /* Begin PBXResourcesBuildPhase section */ 313 | 6003F588195388D20070C39A /* Resources */ = { 314 | isa = PBXResourcesBuildPhase; 315 | buildActionMask = 2147483647; 316 | files = ( 317 | 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */, 318 | 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */, 319 | 6003F5A9195388D20070C39A /* Images.xcassets in Resources */, 320 | B519F31821DA2226008C7F6B /* text.mp4 in Resources */, 321 | 6003F598195388D20070C39A /* InfoPlist.strings in Resources */, 322 | ); 323 | runOnlyForDeploymentPostprocessing = 0; 324 | }; 325 | 6003F5AC195388D20070C39A /* Resources */ = { 326 | isa = PBXResourcesBuildPhase; 327 | buildActionMask = 2147483647; 328 | files = ( 329 | 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */, 330 | ); 331 | runOnlyForDeploymentPostprocessing = 0; 332 | }; 333 | /* End PBXResourcesBuildPhase section */ 334 | 335 | /* Begin PBXShellScriptBuildPhase section */ 336 | 8CDB88E1DBD6869D915B63AC /* [CP] Check Pods Manifest.lock */ = { 337 | isa = PBXShellScriptBuildPhase; 338 | buildActionMask = 2147483647; 339 | files = ( 340 | ); 341 | inputFileListPaths = ( 342 | ); 343 | inputPaths = ( 344 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 345 | "${PODS_ROOT}/Manifest.lock", 346 | ); 347 | name = "[CP] Check Pods Manifest.lock"; 348 | outputFileListPaths = ( 349 | ); 350 | outputPaths = ( 351 | "$(DERIVED_FILE_DIR)/Pods-VTAntiScreenCapture_Example-checkManifestLockResult.txt", 352 | ); 353 | runOnlyForDeploymentPostprocessing = 0; 354 | shellPath = /bin/sh; 355 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 356 | showEnvVarsInLog = 0; 357 | }; 358 | DF706BBACABE40E03F9F5EC7 /* [CP] Check Pods Manifest.lock */ = { 359 | isa = PBXShellScriptBuildPhase; 360 | buildActionMask = 2147483647; 361 | files = ( 362 | ); 363 | inputFileListPaths = ( 364 | ); 365 | inputPaths = ( 366 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 367 | "${PODS_ROOT}/Manifest.lock", 368 | ); 369 | name = "[CP] Check Pods Manifest.lock"; 370 | outputFileListPaths = ( 371 | ); 372 | outputPaths = ( 373 | "$(DERIVED_FILE_DIR)/Pods-VTAntiScreenCapture_Tests-checkManifestLockResult.txt", 374 | ); 375 | runOnlyForDeploymentPostprocessing = 0; 376 | shellPath = /bin/sh; 377 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 378 | showEnvVarsInLog = 0; 379 | }; 380 | F15D71A19ACFA6501D486511 /* [CP] Embed Pods Frameworks */ = { 381 | isa = PBXShellScriptBuildPhase; 382 | buildActionMask = 2147483647; 383 | files = ( 384 | ); 385 | inputFileListPaths = ( 386 | ); 387 | inputPaths = ( 388 | "${SRCROOT}/Pods/Target Support Files/Pods-VTAntiScreenCapture_Example/Pods-VTAntiScreenCapture_Example-frameworks.sh", 389 | "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework", 390 | "${BUILT_PRODUCTS_DIR}/GCDWebServer/GCDWebServer.framework", 391 | "${BUILT_PRODUCTS_DIR}/VTAntiScreenCapture/VTAntiScreenCapture.framework", 392 | ); 393 | name = "[CP] Embed Pods Frameworks"; 394 | outputFileListPaths = ( 395 | ); 396 | outputPaths = ( 397 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AFNetworking.framework", 398 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GCDWebServer.framework", 399 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/VTAntiScreenCapture.framework", 400 | ); 401 | runOnlyForDeploymentPostprocessing = 0; 402 | shellPath = /bin/sh; 403 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-VTAntiScreenCapture_Example/Pods-VTAntiScreenCapture_Example-frameworks.sh\"\n"; 404 | showEnvVarsInLog = 0; 405 | }; 406 | /* End PBXShellScriptBuildPhase section */ 407 | 408 | /* Begin PBXSourcesBuildPhase section */ 409 | 6003F586195388D20070C39A /* Sources */ = { 410 | isa = PBXSourcesBuildPhase; 411 | buildActionMask = 2147483647; 412 | files = ( 413 | B519F32F21DB0C2B008C7F6B /* EncodeVC.m in Sources */, 414 | 6003F59E195388D20070C39A /* VTAppDelegate.m in Sources */, 415 | B519F31921DA2226008C7F6B /* SimpleDRMVC.m in Sources */, 416 | B519F31C21DA2264008C7F6B /* VTDemoTableVC.m in Sources */, 417 | B519F31F21DA2346008C7F6B /* VTSimplePlayer.m in Sources */, 418 | 6003F59A195388D20070C39A /* main.m in Sources */, 419 | ); 420 | runOnlyForDeploymentPostprocessing = 0; 421 | }; 422 | 6003F5AA195388D20070C39A /* Sources */ = { 423 | isa = PBXSourcesBuildPhase; 424 | buildActionMask = 2147483647; 425 | files = ( 426 | 6003F5BC195388D20070C39A /* Tests.m in Sources */, 427 | ); 428 | runOnlyForDeploymentPostprocessing = 0; 429 | }; 430 | /* End PBXSourcesBuildPhase section */ 431 | 432 | /* Begin PBXTargetDependency section */ 433 | 6003F5B4195388D20070C39A /* PBXTargetDependency */ = { 434 | isa = PBXTargetDependency; 435 | target = 6003F589195388D20070C39A /* VTAntiScreenCapture_Example */; 436 | targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */; 437 | }; 438 | /* End PBXTargetDependency section */ 439 | 440 | /* Begin PBXVariantGroup section */ 441 | 6003F596195388D20070C39A /* InfoPlist.strings */ = { 442 | isa = PBXVariantGroup; 443 | children = ( 444 | 6003F597195388D20070C39A /* en */, 445 | ); 446 | name = InfoPlist.strings; 447 | sourceTree = ""; 448 | }; 449 | 6003F5B8195388D20070C39A /* InfoPlist.strings */ = { 450 | isa = PBXVariantGroup; 451 | children = ( 452 | 6003F5B9195388D20070C39A /* en */, 453 | ); 454 | name = InfoPlist.strings; 455 | sourceTree = ""; 456 | }; 457 | 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */ = { 458 | isa = PBXVariantGroup; 459 | children = ( 460 | 71719F9E1E33DC2100824A3D /* Base */, 461 | ); 462 | name = LaunchScreen.storyboard; 463 | sourceTree = ""; 464 | }; 465 | /* End PBXVariantGroup section */ 466 | 467 | /* Begin XCBuildConfiguration section */ 468 | 6003F5BD195388D20070C39A /* Debug */ = { 469 | isa = XCBuildConfiguration; 470 | buildSettings = { 471 | ALWAYS_SEARCH_USER_PATHS = NO; 472 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 473 | CLANG_CXX_LIBRARY = "libc++"; 474 | CLANG_ENABLE_MODULES = YES; 475 | CLANG_ENABLE_OBJC_ARC = YES; 476 | CLANG_WARN_BOOL_CONVERSION = YES; 477 | CLANG_WARN_CONSTANT_CONVERSION = YES; 478 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 479 | CLANG_WARN_EMPTY_BODY = YES; 480 | CLANG_WARN_ENUM_CONVERSION = YES; 481 | CLANG_WARN_INT_CONVERSION = YES; 482 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 483 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 484 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 485 | COPY_PHASE_STRIP = NO; 486 | ENABLE_TESTABILITY = YES; 487 | GCC_C_LANGUAGE_STANDARD = gnu99; 488 | GCC_DYNAMIC_NO_PIC = NO; 489 | GCC_OPTIMIZATION_LEVEL = 0; 490 | GCC_PREPROCESSOR_DEFINITIONS = ( 491 | "DEBUG=1", 492 | "$(inherited)", 493 | ); 494 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 495 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 496 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 497 | GCC_WARN_UNDECLARED_SELECTOR = YES; 498 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 499 | GCC_WARN_UNUSED_FUNCTION = YES; 500 | GCC_WARN_UNUSED_VARIABLE = YES; 501 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 502 | ONLY_ACTIVE_ARCH = YES; 503 | SDKROOT = iphoneos; 504 | TARGETED_DEVICE_FAMILY = "1,2"; 505 | }; 506 | name = Debug; 507 | }; 508 | 6003F5BE195388D20070C39A /* Release */ = { 509 | isa = XCBuildConfiguration; 510 | buildSettings = { 511 | ALWAYS_SEARCH_USER_PATHS = NO; 512 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 513 | CLANG_CXX_LIBRARY = "libc++"; 514 | CLANG_ENABLE_MODULES = YES; 515 | CLANG_ENABLE_OBJC_ARC = YES; 516 | CLANG_WARN_BOOL_CONVERSION = YES; 517 | CLANG_WARN_CONSTANT_CONVERSION = YES; 518 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 519 | CLANG_WARN_EMPTY_BODY = YES; 520 | CLANG_WARN_ENUM_CONVERSION = YES; 521 | CLANG_WARN_INT_CONVERSION = YES; 522 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 523 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 524 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 525 | COPY_PHASE_STRIP = YES; 526 | ENABLE_NS_ASSERTIONS = NO; 527 | GCC_C_LANGUAGE_STANDARD = gnu99; 528 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 529 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 530 | GCC_WARN_UNDECLARED_SELECTOR = YES; 531 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 532 | GCC_WARN_UNUSED_FUNCTION = YES; 533 | GCC_WARN_UNUSED_VARIABLE = YES; 534 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 535 | SDKROOT = iphoneos; 536 | TARGETED_DEVICE_FAMILY = "1,2"; 537 | VALIDATE_PRODUCT = YES; 538 | }; 539 | name = Release; 540 | }; 541 | 6003F5C0195388D20070C39A /* Debug */ = { 542 | isa = XCBuildConfiguration; 543 | baseConfigurationReference = 70E35D6D10B70079BA206F40 /* Pods-VTAntiScreenCapture_Example.debug.xcconfig */; 544 | buildSettings = { 545 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 546 | CODE_SIGN_IDENTITY = "iPhone Developer"; 547 | CODE_SIGN_STYLE = Automatic; 548 | DEVELOPMENT_TEAM = 664M9NYFXA; 549 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 550 | GCC_PREFIX_HEADER = "VTAntiScreenCapture/VTAntiScreenCapture-Prefix.pch"; 551 | INFOPLIST_FILE = "VTAntiScreenCapture/VTAntiScreenCapture-Info.plist"; 552 | MODULE_NAME = ExampleApp; 553 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 554 | PRODUCT_NAME = "$(TARGET_NAME)"; 555 | PROVISIONING_PROFILE_SPECIFIER = ""; 556 | WRAPPER_EXTENSION = app; 557 | }; 558 | name = Debug; 559 | }; 560 | 6003F5C1195388D20070C39A /* Release */ = { 561 | isa = XCBuildConfiguration; 562 | baseConfigurationReference = DEB169BF241381E4A7CF74EB /* Pods-VTAntiScreenCapture_Example.release.xcconfig */; 563 | buildSettings = { 564 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 565 | CODE_SIGN_IDENTITY = "iPhone Developer"; 566 | CODE_SIGN_STYLE = Automatic; 567 | DEVELOPMENT_TEAM = 664M9NYFXA; 568 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 569 | GCC_PREFIX_HEADER = "VTAntiScreenCapture/VTAntiScreenCapture-Prefix.pch"; 570 | INFOPLIST_FILE = "VTAntiScreenCapture/VTAntiScreenCapture-Info.plist"; 571 | MODULE_NAME = ExampleApp; 572 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 573 | PRODUCT_NAME = "$(TARGET_NAME)"; 574 | PROVISIONING_PROFILE_SPECIFIER = ""; 575 | WRAPPER_EXTENSION = app; 576 | }; 577 | name = Release; 578 | }; 579 | 6003F5C3195388D20070C39A /* Debug */ = { 580 | isa = XCBuildConfiguration; 581 | baseConfigurationReference = F54844A1F1585A881352257A /* Pods-VTAntiScreenCapture_Tests.debug.xcconfig */; 582 | buildSettings = { 583 | BUNDLE_LOADER = "$(TEST_HOST)"; 584 | FRAMEWORK_SEARCH_PATHS = ( 585 | "$(SDKROOT)/Developer/Library/Frameworks", 586 | "$(inherited)", 587 | "$(DEVELOPER_FRAMEWORKS_DIR)", 588 | ); 589 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 590 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 591 | GCC_PREPROCESSOR_DEFINITIONS = ( 592 | "DEBUG=1", 593 | "$(inherited)", 594 | ); 595 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 596 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 597 | PRODUCT_NAME = "$(TARGET_NAME)"; 598 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/VTAntiScreenCapture_Example.app/VTAntiScreenCapture_Example"; 599 | WRAPPER_EXTENSION = xctest; 600 | }; 601 | name = Debug; 602 | }; 603 | 6003F5C4195388D20070C39A /* Release */ = { 604 | isa = XCBuildConfiguration; 605 | baseConfigurationReference = B4AB297A5A8C057C83A06D72 /* Pods-VTAntiScreenCapture_Tests.release.xcconfig */; 606 | buildSettings = { 607 | BUNDLE_LOADER = "$(TEST_HOST)"; 608 | FRAMEWORK_SEARCH_PATHS = ( 609 | "$(SDKROOT)/Developer/Library/Frameworks", 610 | "$(inherited)", 611 | "$(DEVELOPER_FRAMEWORKS_DIR)", 612 | ); 613 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 614 | GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch"; 615 | INFOPLIST_FILE = "Tests/Tests-Info.plist"; 616 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}"; 617 | PRODUCT_NAME = "$(TARGET_NAME)"; 618 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/VTAntiScreenCapture_Example.app/VTAntiScreenCapture_Example"; 619 | WRAPPER_EXTENSION = xctest; 620 | }; 621 | name = Release; 622 | }; 623 | /* End XCBuildConfiguration section */ 624 | 625 | /* Begin XCConfigurationList section */ 626 | 6003F585195388D10070C39A /* Build configuration list for PBXProject "VTAntiScreenCapture" */ = { 627 | isa = XCConfigurationList; 628 | buildConfigurations = ( 629 | 6003F5BD195388D20070C39A /* Debug */, 630 | 6003F5BE195388D20070C39A /* Release */, 631 | ); 632 | defaultConfigurationIsVisible = 0; 633 | defaultConfigurationName = Release; 634 | }; 635 | 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "VTAntiScreenCapture_Example" */ = { 636 | isa = XCConfigurationList; 637 | buildConfigurations = ( 638 | 6003F5C0195388D20070C39A /* Debug */, 639 | 6003F5C1195388D20070C39A /* Release */, 640 | ); 641 | defaultConfigurationIsVisible = 0; 642 | defaultConfigurationName = Release; 643 | }; 644 | 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "VTAntiScreenCapture_Tests" */ = { 645 | isa = XCConfigurationList; 646 | buildConfigurations = ( 647 | 6003F5C3195388D20070C39A /* Debug */, 648 | 6003F5C4195388D20070C39A /* Release */, 649 | ); 650 | defaultConfigurationIsVisible = 0; 651 | defaultConfigurationName = Release; 652 | }; 653 | /* End XCConfigurationList section */ 654 | }; 655 | rootObject = 6003F582195388D10070C39A /* Project object */; 656 | } 657 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture.xcodeproj/xcshareddata/xcschemes/VTAntiScreenCapture-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 189 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/EncodeVC/EncodeVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // EncodeVC.h 3 | // VTAntiScreenCapture_Example 4 | // 5 | // Created by Vincent on 2019/1/1. 6 | // Copyright © 2019 mightyme@qq.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface EncodeVC : UIViewController 14 | 15 | @property (nonatomic, strong) IBOutlet UILabel *label; 16 | 17 | @end 18 | 19 | NS_ASSUME_NONNULL_END 20 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/EncodeVC/EncodeVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // EncodeVC.m 3 | // VTAntiScreenCapture_Example 4 | // 5 | // Created by Vincent on 2019/1/1. 6 | // Copyright © 2019 mightyme@qq.com. All rights reserved. 7 | // 8 | 9 | #import "EncodeVC.h" 10 | #import 11 | 12 | @implementation EncodeVC 13 | 14 | - (IBAction)onCreateVideo:(id)sender { 15 | [VTMP4Encoder encodeViewToMP4:self.label completion:^(NSData *data) { 16 | NSLog(@"data: %@", data); 17 | }]; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/SimpleDRMVC/SimpleDRMVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleDRMVC.h 3 | // VCAntiScreenCapture_Example 4 | // 5 | // Created by Vincent on 2018/12/31. 6 | // Copyright © 2018 mightyme@qq.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface SimpleDRMVC : UIViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/SimpleDRMVC/SimpleDRMVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleDRMVC.m 3 | // VCAntiScreenCapture_Example 4 | // 5 | // Created by Vincent on 2018/12/31. 6 | // Copyright © 2018 mightyme@qq.com. All rights reserved. 7 | // 8 | 9 | #import "SimpleDRMVC.h" 10 | #import "GCDWebServer.h" 11 | #import "GCDWebServerFileResponse.h" 12 | #import "VTSimplePlayer.h" 13 | #import "AFNetworking.h" 14 | 15 | @interface SimpleDRMVC () 16 | 17 | @property (nonatomic, weak) IBOutlet UIView *labelContainer; 18 | @property (nonatomic, strong) GCDWebServer *webServer; 19 | @property (nonatomic, strong) VTSimplePlayer *player; 20 | 21 | @end 22 | 23 | @implementation SimpleDRMVC 24 | 25 | - (void)viewDidLoad { 26 | [super viewDidLoad]; 27 | // Do any additional setup after loading the view. 28 | // Create server 29 | _webServer = [[GCDWebServer alloc] init]; 30 | 31 | NSString *dir=[NSHomeDirectory() stringByAppendingPathComponent:@"tmp/www/"]; 32 | [[NSFileManager defaultManager] createDirectoryAtPath:dir withIntermediateDirectories:YES attributes:nil error:nil]; 33 | // NSString *path = [[NSBundle mainBundle] pathForResource:@"test_output" ofType:@"mp4"]; 34 | NSString *path = [[NSBundle mainBundle] pathForResource:@"text" ofType:@"mp4"]; 35 | NSString *toPath = [dir stringByAppendingPathComponent:@"text"]; 36 | if ([[NSFileManager defaultManager] fileExistsAtPath:toPath]) { 37 | [[NSFileManager defaultManager] removeItemAtPath:toPath error:nil]; 38 | } 39 | [[NSFileManager defaultManager] copyItemAtPath:path toPath:toPath error:nil]; 40 | 41 | [_webServer addGETHandlerForBasePath:@"/" directoryPath:dir indexFilename:nil cacheAge:3600 allowRangeRequests:YES]; 42 | [_webServer startWithPort:8989 bonjourName:nil]; 43 | 44 | _player = [VTSimplePlayer new]; 45 | __weak typeof(self) weakSelf = self; 46 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 47 | // [weakSelf.player playURL:@"http://localhost:8989/text.mp4" inView:self.labelContainer]; 48 | [weakSelf.player playURL:@"jedi://text.m3u8" inView:self.labelContainer]; 49 | }); 50 | 51 | return; 52 | } 53 | 54 | //- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 55 | // [self getMP4File]; 56 | //} 57 | 58 | - (void)getMP4File { 59 | NSString *url = [NSString stringWithFormat:@"http://localhost:%@/text.mp4", @(8989)]; 60 | 61 | NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url]]; 62 | NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; 63 | AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; 64 | 65 | NSURLSessionDownloadTask *_downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) { 66 | 67 | } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { 68 | 69 | NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; 70 | NSString *path = [cachesPath stringByAppendingPathComponent:response.suggestedFilename]; 71 | return [NSURL fileURLWithPath:path]; 72 | 73 | } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) { 74 | //设置下载完成操作 75 | // filePath就是你下载文件的位置,你可以解压,也可以直接拿来使用 76 | 77 | NSString *imgFilePath = [filePath path];// 将NSURL转成NSString 78 | NSData *data = [[NSData alloc]initWithContentsOfFile:imgFilePath]; 79 | NSLog(@"%@", data); 80 | }]; 81 | [_downloadTask resume]; 82 | } 83 | 84 | - (void)dealloc { 85 | [_webServer stop]; 86 | _webServer = nil; 87 | } 88 | 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/SimpleDRMVC/VTSimplePlayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // VTSimplePlayer.h 3 | // VTAntiScreenCapture_Example 4 | // 5 | // Created by Vincent on 2018/12/31. 6 | // Copyright © 2018 mightyme@qq.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VTSimplePlayer : NSObject 12 | 13 | - (void)playURL:(NSString *)url inView:(UIView *)container; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/SimpleDRMVC/VTSimplePlayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // VTSimplePlayer.m 3 | // VTAntiScreenCapture_Example 4 | // 5 | // Created by Vincent on 2018/12/31. 6 | // Copyright © 2018 mightyme@qq.com. All rights reserved. 7 | // 8 | 9 | #import "VTSimplePlayer.h" 10 | #import 11 | 12 | #pragma mark - VTSimpleResourceLoaderDelegate 13 | 14 | @interface VTSimpleResourceLoaderDelegate : NSObject 15 | 16 | @end 17 | 18 | @implementation VTSimpleResourceLoaderDelegate 19 | 20 | -(BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest{ 21 | 22 | NSString *url = loadingRequest.request.URL.absoluteString; 23 | if ([url isEqualToString:@"jedi://text.m3u8"]) { 24 | NSData *data = [[self gen_m3u8] dataUsingEncoding:NSUTF8StringEncoding]; 25 | [loadingRequest.dataRequest respondWithData:data]; 26 | [loadingRequest finishLoading]; 27 | } 28 | else if([url isEqualToString:@"jedi://text.key"]) { 29 | NSMutableData *data = [NSMutableData dataWithLength:16]; 30 | [data resetBytesInRange:NSMakeRange(0, [data length])]; 31 | [loadingRequest.dataRequest respondWithData:data]; 32 | [loadingRequest finishLoading]; 33 | } 34 | 35 | return YES; 36 | } 37 | 38 | - (NSString *)gen_m3u8 { 39 | NSString *format = @"#EXTM3U\n\ 40 | #EXT-X-PLAYLIST-TYPE:VOD\n\ 41 | #EXT-X-VERSION:5\n\ 42 | #EXT-X-TARGETDURATION:%@\n\ 43 | #EXT-X-KEY:METHOD=SAMPLE-AES,URI=\"jedi://text.key\"\n\ 44 | #EXTINF:%@,\n\ 45 | http://localhost:%@\n\ 46 | #EXT-X-ENDLIST"; 47 | NSInteger duration = 1; 48 | CGFloat EXTINF = 1/15.0; // 15 fps 49 | NSString *host = [NSString stringWithFormat:@"%@/text", @(8989)]; 50 | NSString *res = [NSString stringWithFormat:format, @(duration), @(EXTINF), host]; 51 | return res; 52 | } 53 | 54 | 55 | @end 56 | 57 | #pragma mark - VTSimplePlayer 58 | 59 | @interface VTSimplePlayer () 60 | 61 | @property(nonatomic, strong)AVURLAsset *URLAsset; 62 | @property (nonatomic, strong)AVPlayerItem *playerItem; 63 | @property (nonatomic, strong)AVPlayerLayer *playerLayer; 64 | @property (nonatomic, strong) AVPlayer *player; 65 | @property (nonatomic, weak)UIView *containerView; 66 | 67 | @property (nonatomic, strong) VTSimpleResourceLoaderDelegate *resourceLoader; 68 | 69 | @end 70 | 71 | @implementation VTSimplePlayer 72 | 73 | - (void)playURL:(NSString *)url inView:(UIView *)container { 74 | if (![url isKindOfClass:[NSString class]]) { 75 | return; 76 | } 77 | if (url.length==0) return; 78 | if (!container) return; 79 | 80 | _containerView = container; 81 | AVURLAsset *videoURLAsset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:url] options:nil]; 82 | self.URLAsset = videoURLAsset; 83 | 84 | VTSimpleResourceLoaderDelegate *loader = [VTSimpleResourceLoaderDelegate new]; 85 | self.resourceLoader = loader; 86 | [self.URLAsset.resourceLoader setDelegate:loader queue:dispatch_get_main_queue()]; 87 | 88 | AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:videoURLAsset]; 89 | self.playerItem = playerItem; 90 | 91 | self.player = [AVPlayer playerWithPlayerItem:playerItem]; 92 | self.playerLayer = [AVPlayerLayer playerLayerWithPlayer:self.player]; 93 | self.playerLayer.frame = CGRectMake(0, 0, container.bounds.size.width, container.bounds.size.height-1); 94 | } 95 | 96 | - (void)resume{ 97 | if (!self.playerItem) return; 98 | [self.player play]; 99 | } 100 | 101 | - (void)pause{ 102 | if (!self.playerItem) return; 103 | [self.player pause]; 104 | } 105 | 106 | - (void)stop{ 107 | if (!self.player) return; 108 | [self.player pause]; 109 | [self.player cancelPendingPrerolls]; 110 | if (self.playerLayer) { 111 | [self.playerLayer removeFromSuperlayer]; 112 | self.playerLayer = nil; 113 | } 114 | [self.URLAsset.resourceLoader setDelegate:nil queue:dispatch_get_main_queue()]; 115 | self.URLAsset = nil; 116 | self.playerItem = nil; 117 | self.player = nil; 118 | } 119 | 120 | -(void)handleShowViewSublayers{ 121 | for (UIView *view in _containerView.subviews) { 122 | [view removeFromSuperview]; 123 | } 124 | [_containerView.layer addSublayer:self.playerLayer]; 125 | } 126 | 127 | -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ 128 | if ([keyPath isEqualToString:@"status"]) { 129 | AVPlayerItem *playerItem = (AVPlayerItem *)object; 130 | AVPlayerItemStatus status = playerItem.status; 131 | switch (status) { 132 | case AVPlayerItemStatusUnknown:{ 133 | } 134 | break; 135 | 136 | case AVPlayerItemStatusReadyToPlay:{ 137 | [self.player play]; 138 | [self handleShowViewSublayers]; 139 | NSLog(@"duration: %@", @([self duration])); 140 | } 141 | break; 142 | 143 | case AVPlayerItemStatusFailed:{ 144 | 145 | } 146 | break; 147 | default: 148 | break; 149 | } 150 | } 151 | else if ([keyPath isEqualToString:@"playbackBufferEmpty"]){ 152 | 153 | } 154 | else if ([keyPath isEqualToString:@"playbackLikelyToKeepUp"]){ 155 | 156 | } 157 | } 158 | 159 | - (CGFloat)duration { 160 | CGFloat totalTime = CMTimeGetSeconds(self.playerItem.asset.duration); 161 | return totalTime; 162 | } 163 | 164 | 165 | -(void)setPlayerItem:(AVPlayerItem *)playerItem{ 166 | if (_playerItem) { 167 | [_playerItem removeObserver:self forKeyPath:@"status"]; 168 | [_playerItem removeObserver:self forKeyPath:@"playbackBufferEmpty"]; 169 | [_playerItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp"]; 170 | } 171 | 172 | _playerItem = playerItem; 173 | 174 | [_playerItem addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil]; 175 | [_playerItem addObserver:self forKeyPath:@"playbackBufferEmpty" options:NSKeyValueObservingOptionNew context:nil]; 176 | [_playerItem addObserver:self forKeyPath:@"playbackLikelyToKeepUp" options:NSKeyValueObservingOptionNew context:nil]; 177 | } 178 | 179 | -(void)setPlayerLayer:(AVPlayerLayer *)playerLayer{ 180 | if (_playerLayer) { 181 | [_playerLayer removeFromSuperlayer]; 182 | } 183 | _playerLayer = playerLayer; 184 | } 185 | 186 | @end 187 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/SimpleDRMVC/index.m3u8: -------------------------------------------------------------------------------- 1 | #EXTM3U 2 | #EXT-X-VERSION:3 3 | #EXT-X-TARGETDURATION:0 4 | #EXT-X-MEDIA-SEQUENCE:0 5 | #EXTINF:0.066667, 6 | index0.ts 7 | #EXT-X-ENDLIST 8 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/SimpleDRMVC/text.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohswift/VTAntiScreenCapture/5a24d29c02b70002fc6716f01ccc5b199e27f2ec/Example/VTAntiScreenCapture/SimpleDRMVC/text.mp4 -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/VTAntiScreenCapture-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | NSAppTransportSecurity 49 | 50 | NSAllowsArbitraryLoads 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/VTAntiScreenCapture-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | @import UIKit; 15 | @import Foundation; 16 | #endif 17 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/VTAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // VTAppDelegate.h 3 | // VTAntiScreenCapture 4 | // 5 | // Created by mightyme@qq.com on 12/31/2018. 6 | // Copyright (c) 2018 mightyme@qq.com. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | 11 | @interface VTAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/VTAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // VTAppDelegate.m 3 | // VTAntiScreenCapture 4 | // 5 | // Created by mightyme@qq.com on 12/31/2018. 6 | // Copyright (c) 2018 mightyme@qq.com. All rights reserved. 7 | // 8 | 9 | #import "VTAppDelegate.h" 10 | 11 | @implementation VTAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // 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. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // 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. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/VTDemoTableVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // VCDemoTableVC.h 3 | // VCAntiScreenCapture_Example 4 | // 5 | // Created by Vincent on 2018/12/31. 6 | // Copyright © 2018 mightyme@qq.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | @interface VTDemoTableVC : UITableViewController 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/VTDemoTableVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // VCDemoTableVC.m 3 | // VCAntiScreenCapture_Example 4 | // 5 | // Created by Vincent on 2018/12/31. 6 | // Copyright © 2018 mightyme@qq.com. All rights reserved. 7 | // 8 | 9 | #import "VTDemoTableVC.h" 10 | #import "SimpleDRMVC.h" 11 | 12 | @interface VTDemoTableVC () 13 | 14 | @end 15 | 16 | @implementation VTDemoTableVC 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | // Uncomment the following line to preserve selection between presentations. 22 | // self.clearsSelectionOnViewWillAppear = NO; 23 | 24 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 25 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 26 | } 27 | 28 | #pragma mark - UITableView Delegate methods 29 | 30 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 31 | UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; 32 | UIViewController *vc = nil; 33 | if (indexPath.row == 0) { 34 | vc = [storyBoard instantiateViewControllerWithIdentifier:@"SimpleDRMVC"]; 35 | } 36 | else if (indexPath.row == 1) { 37 | vc = [storyBoard instantiateViewControllerWithIdentifier:@"EncodeVC"]; 38 | } 39 | if (vc) { 40 | [self.navigationController pushViewController:vc animated:YES]; 41 | } 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/VTAntiScreenCapture/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // VTAntiScreenCapture 4 | // 5 | // Created by mightyme@qq.com on 12/31/2018. 6 | // Copyright (c) 2018 mightyme@qq.com. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import "VTAppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) 13 | { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([VTAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 mightyme@qq.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | iOS实现应用内敏感信息防截屏(附源码),查看 https://www.jianshu.com/p/86d0cfed5f4e 3 | 4 | 喜欢的话,记得给星星哦. 5 | -------------------------------------------------------------------------------- /VTAntiScreenCapture.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint VTAntiScreenCapture.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'VTAntiScreenCapture' 11 | s.version = '0.1.0' 12 | s.summary = 'A simple iOS SDK for anti screen capture' 13 | 14 | # This description is used to generate tags and improve search results. 15 | # * Think: What does it do? Why did you write it? What is the focus? 16 | # * Try to keep it short, snappy and to the point. 17 | # * Write the description between the DESC delimiters below. 18 | # * Finally, don't worry about the indent, CocoaPods strips it! 19 | 20 | s.description = <<-DESC 21 | TODO: Add long description of the pod here. 22 | DESC 23 | 24 | s.homepage = 'https://github.com/mightyme@qq.com/VTAntiScreenCapture' 25 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' 26 | s.license = { :type => 'MIT', :file => 'LICENSE' } 27 | s.author = { 'Vincent' => 'mightyme@qq.com' } 28 | s.source = { :git => 'https://github.com/mightyme@qq.com/VTAntiScreenCapture.git', :tag => s.version.to_s } 29 | # s.social_media_url = 'https://twitter.com/' 30 | 31 | s.ios.deployment_target = '8.0' 32 | 33 | s.source_files = 'VTAntiScreenCapture/Classes/**/*' 34 | 35 | # s.resource_bundles = { 36 | # 'VTAntiScreenCapture' => ['VTAntiScreenCapture/Assets/*.png'] 37 | # } 38 | 39 | # s.public_header_files = 'Pod/Classes/**/*.h' 40 | # s.frameworks = 'UIKit', 'MapKit' 41 | # s.dependency 'AFNetworking', '~> 2.3' 42 | end 43 | -------------------------------------------------------------------------------- /VTAntiScreenCapture/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohswift/VTAntiScreenCapture/5a24d29c02b70002fc6716f01ccc5b199e27f2ec/VTAntiScreenCapture/Assets/.gitkeep -------------------------------------------------------------------------------- /VTAntiScreenCapture/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ohswift/VTAntiScreenCapture/5a24d29c02b70002fc6716f01ccc5b199e27f2ec/VTAntiScreenCapture/Classes/.gitkeep -------------------------------------------------------------------------------- /VTAntiScreenCapture/Classes/UIView+antiCapture.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+antiCapture.h 3 | // AFNetworking 4 | // 5 | // Created by 俞伟山 on 2019/1/1. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | @interface UIView (antiCapture) 13 | 14 | @end 15 | 16 | NS_ASSUME_NONNULL_END 17 | -------------------------------------------------------------------------------- /VTAntiScreenCapture/Classes/UIView+antiCapture.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+antiCapture.m 3 | // AFNetworking 4 | // 5 | // Created by 俞伟山 on 2019/1/1. 6 | // 7 | 8 | #import "UIView+antiCapture.h" 9 | 10 | @implementation UIView (antiCapture) 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /VTAntiScreenCapture/Classes/VTMP4Encoder.h: -------------------------------------------------------------------------------- 1 | // 2 | // VTMP4Encoder.h 3 | // AFNetworking 4 | // 5 | // Created by Vincent on 2019/1/1. 6 | // 7 | 8 | #import 9 | 10 | @interface VTMP4Encoder : NSObject 11 | 12 | /// 根据视图内容生成mp4文件 13 | + (void)encodeViewToMP4:(UIView *)view completion:(void (^)(NSData *))handler; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /VTAntiScreenCapture/Classes/VTMP4Encoder.m: -------------------------------------------------------------------------------- 1 | // 2 | // VTMP4Encoder.m 3 | // AFNetworking 4 | // 5 | // Created by Vincent on 2019/1/1. 6 | // 7 | 8 | #import "VTMP4Encoder.h" 9 | #import 10 | 11 | @implementation VTMP4Encoder 12 | 13 | + (void)encodeViewToMP4:(UIView *)view completion:(void (^)(NSData *))handler { 14 | UIImage *img = [self viewToImage:view]; 15 | [self imageToMP4:img completion:handler]; 16 | } 17 | 18 | + (UIImage *)viewToImage:(UIView *)view { 19 | CGSize size = CGSizeMake(view.bounds.size.width, view.bounds.size.height); 20 | UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale); 21 | CGContextRef currnetContext = UIGraphicsGetCurrentContext(); 22 | [view.layer renderInContext:currnetContext]; 23 | UIImage* image = UIGraphicsGetImageFromCurrentImageContext(); 24 | UIGraphicsEndImageContext(); 25 | 26 | 27 | return image; 28 | } 29 | 30 | + (void)imageToMP4:(UIImage *)img completion:(void (^)(NSData *))handler { 31 | NSError *error = nil; 32 | 33 | NSFileManager *fileMgr = [NSFileManager defaultManager]; 34 | NSString *documentsDirectory = [NSHomeDirectory() 35 | stringByAppendingPathComponent:@"tmp"]; 36 | NSString *videoOutputPath = [documentsDirectory stringByAppendingPathComponent:@"test_output.mp4"]; 37 | if ([fileMgr removeItemAtPath:videoOutputPath error:&error] != YES) 38 | NSLog(@"Unable to delete file: %@", [error localizedDescription]); 39 | 40 | CGSize imageSize = CGSizeMake(UIScreen.mainScreen.scale*img.size.width, UIScreen.mainScreen.scale*img.size.height); 41 | NSUInteger fps = 15; 42 | NSArray *imageArray = @[img]; 43 | 44 | 45 | NSLog(@"Start building video from defined frames."); 46 | 47 | AVAssetWriter *videoWriter = [[AVAssetWriter alloc] initWithURL: 48 | [NSURL fileURLWithPath:videoOutputPath] fileType:AVFileTypeQuickTimeMovie 49 | error:&error]; 50 | /// !!!需要设置faststart 51 | videoWriter.shouldOptimizeForNetworkUse = YES; 52 | NSParameterAssert(videoWriter); 53 | 54 | NSDictionary *videoSettings = [NSDictionary dictionaryWithObjectsAndKeys: 55 | AVVideoCodecH264, AVVideoCodecKey, 56 | [NSNumber numberWithInt:imageSize.width], AVVideoWidthKey, 57 | [NSNumber numberWithInt:imageSize.height], AVVideoHeightKey, 58 | nil]; 59 | 60 | AVAssetWriterInput* videoWriterInput = [AVAssetWriterInput 61 | assetWriterInputWithMediaType:AVMediaTypeVideo 62 | outputSettings:videoSettings]; 63 | 64 | 65 | AVAssetWriterInputPixelBufferAdaptor *adaptor = [AVAssetWriterInputPixelBufferAdaptor 66 | assetWriterInputPixelBufferAdaptorWithAssetWriterInput:videoWriterInput 67 | sourcePixelBufferAttributes:nil]; 68 | 69 | NSParameterAssert(videoWriterInput); 70 | NSParameterAssert([videoWriter canAddInput:videoWriterInput]); 71 | videoWriterInput.expectsMediaDataInRealTime = YES; 72 | [videoWriter addInput:videoWriterInput]; 73 | 74 | //Start a session: 75 | [videoWriter startWriting]; 76 | [videoWriter startSessionAtSourceTime:kCMTimeZero]; 77 | 78 | CVPixelBufferRef buffer = NULL; 79 | 80 | //convert uiimage to CGImage. 81 | int frameCount = 0; 82 | double numberOfSecondsPerFrame = 1; 83 | double frameDuration = fps * numberOfSecondsPerFrame; 84 | 85 | //for(VideoFrame * frm in imageArray) 86 | NSLog(@"**************************************************"); 87 | for(UIImage * img in imageArray) 88 | { 89 | //UIImage * img = frm._imageFrame; 90 | buffer = [self pixelBufferFromCGImage:[img CGImage]]; 91 | 92 | BOOL append_ok = NO; 93 | int j = 0; 94 | while (!append_ok && j < 30) { 95 | if (adaptor.assetWriterInput.readyForMoreMediaData) { 96 | //print out status: 97 | NSLog(@"Processing video frame (%d,%d)",frameCount,[imageArray count]); 98 | 99 | CMTime frameTime = CMTimeMake(frameCount*frameDuration,(int32_t) fps); 100 | append_ok = [adaptor appendPixelBuffer:buffer withPresentationTime:frameTime]; 101 | if(!append_ok){ 102 | NSError *error = videoWriter.error; 103 | if(error!=nil) { 104 | NSLog(@"Unresolved error %@,%@.", error, [error userInfo]); 105 | } 106 | } 107 | } 108 | else { 109 | printf("adaptor not ready %d, %d\n", frameCount, j); 110 | [NSThread sleepForTimeInterval:0.1]; 111 | } 112 | j++; 113 | } 114 | if (!append_ok) { 115 | printf("error appending image %d times %d\n, with error.", frameCount, j); 116 | } 117 | frameCount++; 118 | } 119 | NSLog(@"**************************************************"); 120 | 121 | //Finish the session: 122 | [videoWriterInput markAsFinished]; 123 | [videoWriter finishWritingWithCompletionHandler:^{ 124 | if (handler) { 125 | NSData *data = [NSData dataWithContentsOfFile:videoOutputPath]; 126 | handler(data); 127 | } 128 | }]; 129 | } 130 | 131 | + (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image { 132 | 133 | CGSize size = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image)); 134 | 135 | NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys: 136 | [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, 137 | [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, 138 | nil]; 139 | CVPixelBufferRef pxbuffer = NULL; 140 | 141 | CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, 142 | size.width, 143 | size.height, 144 | kCVPixelFormatType_32ARGB, 145 | (__bridge CFDictionaryRef) options, 146 | &pxbuffer); 147 | if (status != kCVReturnSuccess){ 148 | NSLog(@"Failed to create pixel buffer"); 149 | } 150 | 151 | CVPixelBufferLockBaseAddress(pxbuffer, 0); 152 | void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer); 153 | 154 | CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB(); 155 | CGContextRef context = CGBitmapContextCreate(pxdata, size.width, 156 | size.height, 8, 4*size.width, rgbColorSpace, 157 | kCGImageAlphaPremultipliedFirst); 158 | //kCGImageAlphaNoneSkipFirst); 159 | CGContextConcatCTM(context, CGAffineTransformMakeRotation(0)); 160 | CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image), 161 | CGImageGetHeight(image)), image); 162 | CGColorSpaceRelease(rgbColorSpace); 163 | CGContextRelease(context); 164 | 165 | CVPixelBufferUnlockBaseAddress(pxbuffer, 0); 166 | 167 | return pxbuffer; 168 | } 169 | 170 | 171 | @end 172 | -------------------------------------------------------------------------------- /VTAntiScreenCapture/Classes/VTPlayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // VTPlayer.h 3 | // AFNetworking 4 | // 5 | // Created by 俞伟山 on 2019/1/1. 6 | // 7 | 8 | #import 9 | 10 | NS_ASSUME_NONNULL_BEGIN 11 | 12 | /// 简单播放器 13 | @interface VTPlayer : NSObject 14 | 15 | @end 16 | 17 | NS_ASSUME_NONNULL_END 18 | -------------------------------------------------------------------------------- /VTAntiScreenCapture/Classes/VTPlayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // VTPlayer.m 3 | // AFNetworking 4 | // 5 | // Created by 俞伟山 on 2019/1/1. 6 | // 7 | 8 | #import "VTPlayer.h" 9 | #import 10 | 11 | @implementation VTPlayer 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj --------------------------------------------------------------------------------