├── .gitignore ├── LYAVPlayer.xcodeproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcuserdata │ │ └── luyang.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcuserdata │ └── luyang.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── LYAVPlayer.xcscheme └── project.pbxproj ├── LYAVPlayer ├── FirstViewController.h ├── PlayerViewController.h ├── AppDelegate.h ├── SecondViewController.h ├── main.m ├── LYAVPlayer-Prefix.pch ├── SecondViewController.m ├── Info.plist ├── Base.lproj │ └── LaunchScreen.storyboard ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── FirstViewController.m ├── AppDelegate.m ├── LYAVPlayerView │ ├── LYAVPlayerView.h │ └── LYAVPlayerView.m ├── PlayerViewController.m └── PlayerViewController.storyboard ├── README.md ├── LYAVPlayerTests ├── Info.plist └── LYAVPlayerTests.m ├── LYAVPlayerUITests ├── Info.plist └── LYAVPlayerUITests.m ├── LICENSE └── LYAVPlayer.podspec /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.m 3 | -------------------------------------------------------------------------------- /LYAVPlayer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LYAVPlayer.xcodeproj/project.xcworkspace/xcuserdata/luyang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/1015857193/LYAVPlayer/HEAD/LYAVPlayer.xcodeproj/project.xcworkspace/xcuserdata/luyang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /LYAVPlayer/FirstViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewController.h 3 | // LYAVPlayer 4 | // 5 | // Created by luyang on 2017/11/29. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface FirstViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /LYAVPlayer/PlayerViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PlayerViewController.h 3 | // LYVideoPlayer 4 | // 5 | // Created by luyang on 2017/10/11. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface PlayerViewController : UIViewController 13 | 14 | 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /LYAVPlayer.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LYAVPlayer/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // LYVideoPlayer 4 | // 5 | // Created by luyang on 2017/10/11. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | 16 | 17 | 18 | @end 19 | 20 | -------------------------------------------------------------------------------- /LYAVPlayer/SecondViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController.h 3 | // LYAVPlayer 4 | // 5 | // Created by luyang on 2017/10/16. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SecondViewController : UIViewController 12 | 13 | @property (nonatomic,strong)AVURLAsset *asset; 14 | @property (nonatomic,assign)CGFloat time; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /LYAVPlayer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // LYAVPlayer 4 | // 5 | // Created by luyang on 2017/10/12. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | LYAVPlayer视频播放器,AVPlayer的封装,继承UIView.LYAVPlaye旨在封装AVPlayer,无意于写控制页面,因此用户可自定义页面。功能强大,简单易用。几行代码即可实现播放功能: 2 | ``` 3 | LYAVPlayerView *playerView =[LYAVPlayerView alloc]init]; 4 | playerView.frame =CGRectMake(0, 64, ScreenWidth,200); 5 | playerView.delegate =self;//设置代理 6 | [self.view addSubview:playerView]; 7 | [playerView setURL:[NSURL URLWithString:VideoURL]];//设置播放的URL 8 | [playerView play];//开始播放 9 | ``` 10 | 支持`cocoa pods 工程中pod 'LYAVPlayer','~> 1.0.1'` 11 | 12 | 博客地址:https://www.jianshu.com/u/e36a07f5dc7b 13 | -------------------------------------------------------------------------------- /LYAVPlayer.xcodeproj/xcuserdata/luyang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /LYAVPlayerTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /LYAVPlayer/LYAVPlayer-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // LYAVPlayer-Prefix.pch 3 | // LYAVPlayer 4 | // 5 | // Created by luyang on 2017/10/16. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #ifndef LYAVPlayer_Prefix_pch 10 | #define LYAVPlayer_Prefix_pch 11 | 12 | #import "LYAVPlayerView.h" 13 | 14 | #define ScreenWidth [UIScreen mainScreen].bounds.size.width 15 | #define ScreenHeight [UIScreen mainScreen].bounds.size.height 16 | 17 | #define VideoURL @"http://wvideo.spriteapp.cn/video/2016/0328/56f8ec01d9bfe_wpd.mp4" 18 | 19 | // Include any system framework and library headers here that should be included in all compilation units. 20 | // You will also need to set the Prefix Header build setting of one or more of your targets to reference this file. 21 | 22 | #endif /* LYAVPlayer_Prefix_pch */ 23 | -------------------------------------------------------------------------------- /LYAVPlayerUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /LYAVPlayer.xcodeproj/xcuserdata/luyang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | LYAVPlayer.xcscheme 8 | 9 | orderHint 10 | 8 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 355894441F8F5DF0000F7DF6 16 | 17 | primary 18 | 19 | 20 | 3558945C1F8F5DF0000F7DF6 21 | 22 | primary 23 | 24 | 25 | 355894671F8F5DF0000F7DF6 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /LYAVPlayerTests/LYAVPlayerTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // LYAVPlayerTests.m 3 | // LYAVPlayerTests 4 | // 5 | // Created by luyang on 2017/10/12. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LYAVPlayerTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation LYAVPlayerTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This project is licensed under the MIT license. 2 | 3 | Copyright (c) 2013 - 2018 卢洋 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /LYAVPlayerUITests/LYAVPlayerUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // LYAVPlayerUITests.m 3 | // LYAVPlayerUITests 4 | // 5 | // Created by luyang on 2017/10/12. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LYAVPlayerUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation LYAVPlayerUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /LYAVPlayer/SecondViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SecondViewController.m 3 | // LYAVPlayer 4 | // 5 | // Created by luyang on 2017/10/16. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #import "SecondViewController.h" 10 | 11 | @interface SecondViewController () 12 | 13 | @property (nonatomic,strong)LYAVPlayerView *playerView; 14 | 15 | @end 16 | 17 | @implementation SecondViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | // Do any additional setup after loading the view. 22 | 23 | self.playerView =[[LYAVPlayerView alloc]init]; 24 | self.playerView.frame =CGRectMake(0, 64, ScreenWidth,200); 25 | // self.playerView.delegate =self; 26 | [self.view addSubview:self.playerView]; 27 | [self.playerView setAsset:_asset]; 28 | 29 | [self.playerView seekToTime:_time]; 30 | [self.playerView play]; 31 | 32 | 33 | 34 | 35 | 36 | } 37 | 38 | - (void)didReceiveMemoryWarning { 39 | [super didReceiveMemoryWarning]; 40 | // Dispose of any resources that can be recreated. 41 | } 42 | 43 | /* 44 | #pragma mark - Navigation 45 | 46 | // In a storyboard-based application, you will often want to do a little preparation before navigation 47 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 48 | // Get the new view controller using [segue destinationViewController]. 49 | // Pass the selected object to the new view controller. 50 | } 51 | */ 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /LYAVPlayer/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | NSAppTransportSecurity 24 | 25 | NSAllowsArbitraryLoads 26 | 27 | 28 | UIBackgroundModes 29 | 30 | audio 31 | 32 | UILaunchStoryboardName 33 | LaunchScreen 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /LYAVPlayer/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 | -------------------------------------------------------------------------------- /LYAVPlayer/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /LYAVPlayer/FirstViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // FirstViewController.m 3 | // LYAVPlayer 4 | // 5 | // Created by luyang on 2017/11/29. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #import "FirstViewController.h" 10 | #import "PlayerViewController.h" 11 | 12 | @interface FirstViewController () 13 | 14 | @end 15 | 16 | @implementation FirstViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | UIButton *btn =[UIButton buttonWithType:UIButtonTypeCustom]; 22 | btn.frame =CGRectMake(100, 100, 60, 60); 23 | btn.layer.cornerRadius =5; 24 | btn.layer.masksToBounds =YES; 25 | [btn setTitle:@"播放" forState:UIControlStateNormal]; 26 | [btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; 27 | btn.titleLabel.font =[UIFont systemFontOfSize:18]; 28 | [btn addTarget:self action:@selector(inputDeviceAction) forControlEvents:UIControlEventTouchUpInside]; 29 | [self.view addSubview:btn]; 30 | 31 | } 32 | 33 | - (void)inputDeviceAction{ 34 | 35 | PlayerViewController *playerViewCtrl =(PlayerViewController *)[[UIStoryboard storyboardWithName:@"PlayerViewController" bundle:nil] instantiateViewControllerWithIdentifier:@"PlayerView"]; 36 | 37 | [self.navigationController pushViewController:playerViewCtrl animated:NO]; 38 | 39 | 40 | } 41 | 42 | - (void)viewWillDisappear:(BOOL)animated{ 43 | 44 | [super viewWillDisappear:animated]; 45 | 46 | NSLog(@"test1%@",[self description]); 47 | 48 | } 49 | 50 | - (void)viewDidDisappear:(BOOL)animated{ 51 | 52 | [super viewDidDisappear:animated]; 53 | 54 | NSLog(@"test2%@",[self description]); 55 | 56 | } 57 | 58 | - (void)didReceiveMemoryWarning { 59 | [super didReceiveMemoryWarning]; 60 | // Dispose of any resources that can be recreated. 61 | } 62 | 63 | /* 64 | #pragma mark - Navigation 65 | 66 | // In a storyboard-based application, you will often want to do a little preparation before navigation 67 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 68 | // Get the new view controller using [segue destinationViewController]. 69 | // Pass the selected object to the new view controller. 70 | } 71 | */ 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /LYAVPlayer/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // LYVideoPlayer 4 | // 5 | // Created by luyang on 2017/10/11. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "PlayerViewController.h" 11 | #import "FirstViewController.h" 12 | 13 | 14 | #import "LYAVPlayerView.h" 15 | 16 | @interface AppDelegate () 17 | 18 | 19 | 20 | @end 21 | 22 | @implementation AppDelegate 23 | 24 | 25 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 26 | 27 | //NSURLCache 28 | NSURLCache *URLCache =[[NSURLCache alloc]initWithMemoryCapacity:4*1024*1024 diskCapacity:20*1024*1024 diskPath:nil]; 29 | [NSURLCache setSharedURLCache:URLCache]; 30 | 31 | 32 | // Override point for customization after application launch. 33 | // 后台播放音频设置,需要在Capabilities->Background Modes中勾选Audio,Airplay,and Picture in Picture 34 | AVAudioSession *session = [AVAudioSession sharedInstance]; 35 | 36 | [session setCategory:AVAudioSessionCategoryPlayback error:nil]; 37 | [session setActive:YES error:nil]; 38 | 39 | self.window =[[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds]; 40 | self.window.backgroundColor = [UIColor whiteColor]; 41 | 42 | FirstViewController *first =[[FirstViewController alloc]init]; 43 | 44 | UINavigationController *nav =[[UINavigationController alloc]initWithRootViewController:first]; 45 | 46 | self.window.rootViewController = nav; 47 | [self.window makeKeyAndVisible]; 48 | 49 | return YES; 50 | } 51 | 52 | 53 | - (void)applicationWillResignActive:(UIApplication *)application { 54 | 55 | 56 | 57 | 58 | } 59 | 60 | //已经进入后台 61 | - (void)applicationDidEnterBackground:(UIApplication *)application { 62 | 63 | LYAVPlayerView *playerView =[LYAVPlayerView sharedInstance]; 64 | [playerView.playerLayer setPlayer:nil]; 65 | 66 | } 67 | 68 | 69 | - (void)applicationWillEnterForeground:(UIApplication *)application { 70 | // 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. 71 | } 72 | 73 | //已经激活 74 | - (void)applicationDidBecomeActive:(UIApplication *)application { 75 | 76 | LYAVPlayerView *playerView =[LYAVPlayerView sharedInstance]; 77 | AVPlayer *player =playerView.player; 78 | [playerView.playerLayer setPlayer:player]; 79 | 80 | } 81 | 82 | 83 | - (void)applicationWillTerminate:(UIApplication *)application { 84 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 85 | } 86 | 87 | 88 | @end 89 | -------------------------------------------------------------------------------- /LYAVPlayer/LYAVPlayerView/LYAVPlayerView.h: -------------------------------------------------------------------------------- 1 | // 2 | // LYPlayerView.h 3 | // LYPlayer 4 | // 5 | // Created by luyang on 2017/10/10. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class LYAVPlayerView; 13 | 14 | @protocol LYVideoPlayerDelegate 15 | 16 | @optional 17 | 18 | /* 19 | * 20 | *AVPlayerItem的三种状态 21 | *AVPlayerItemStatusUnknown, 22 | *AVPlayerItemStatusReadyToPlay, 23 | *AVPlayerItemStatusFailed 24 | */ 25 | 26 | //所有的代理方法均已回到主线程 可直接刷新UI 27 | // 可播放/播放中 28 | - (void)videoPlayerIsReadyToPlayVideo:(LYAVPlayerView *)playerView; 29 | //播放完毕 30 | - (void)videoPlayerDidReachEnd:(LYAVPlayerView *)playerView; 31 | //当前播放时间 32 | - (void)videoPlayer:(LYAVPlayerView *)playerView timeDidChange:(CGFloat )time; 33 | //duration 当前缓冲的长度 34 | - (void)videoPlayer:(LYAVPlayerView *)playerView loadedTimeRangeDidChange:(CGFloat )duration; 35 | //进行跳转后没数据 即播放卡顿 36 | - (void)videoPlayerPlaybackBufferEmpty:(LYAVPlayerView *)playerView; 37 | // 进行跳转后有数据 能够继续播放 38 | - (void)videoPlayerPlaybackLikelyToKeepUp:(LYAVPlayerView *)playerView; 39 | //加载失败 40 | - (void)videoPlayer:(LYAVPlayerView *)playerView didFailWithError:(NSError *)error; 41 | 42 | @end 43 | 44 | 45 | @interface LYAVPlayerView : UIView 46 | 47 | /** 48 | 49 | AVPlayerLayer的videoGravity属性设置 50 | AVLayerVideoGravityResize, // 非均匀模式。两个维度完全填充至整个视图区域 51 | AVLayerVideoGravityResizeAspect, // 等比例填充,直到一个维度到达区域边界 52 | AVLayerVideoGravityResizeAspectFill, // 等比例填充,直到填充满整个视图区域,其中一个维度的部分区域会被裁剪 53 | */ 54 | @property (nonatomic, copy) NSString *videoGravity; 55 | 56 | //播放时为YES 暂停时为NO 57 | @property (nonatomic, assign,readonly) BOOL isPlaying; 58 | 59 | //播放属性 60 | @property (nonatomic, strong,readonly) AVPlayer *player; 61 | @property (nonatomic, strong,readonly) AVPlayerItem *item; 62 | @property (nonatomic, strong,readonly) AVURLAsset *urlAsset; 63 | @property (nonatomic, strong,readonly) AVPlayerLayer *playerLayer; 64 | 65 | @property (nonatomic,weak) id delegate; 66 | 67 | //单例 68 | + (instancetype)sharedInstance; 69 | 70 | //设置播放URL 71 | - (void)setURL:(NSURL *)URL; 72 | 73 | - (void)setAsset:(AVURLAsset *)asset; 74 | 75 | //跳到xx秒播放视频 76 | - (void)seekToTime:(CGFloat )time; 77 | 78 | //播放 79 | - (void)play; 80 | 81 | //暂停 82 | - (void)pause; 83 | 84 | //停止播放 85 | - (void)stop; 86 | 87 | //设置播放倍速 0.5-2.0 88 | - (void)setPlayerRate:(CGFloat )rate; 89 | 90 | //获取当前播放的时间 91 | - (CGFloat )getCurrentPlayTime; 92 | 93 | //获取视频的总时间长 94 | - (CGFloat)getTotalPlayTime; 95 | 96 | //获取视频宽高比 97 | - (CGFloat )getVideoScale:(NSURL *)URL; 98 | 99 | //获取网络视频的缩略图 100 | - (UIImage *)getThumbnailImageFromVideoURL:(NSURL *)URL time:(NSTimeInterval )videoTime; 101 | //获取本地视频缩略图 102 | - (UIImage *)getThumbnailImageFromFilePath:(NSString *)videoPath time:(NSTimeInterval )videoTime; 103 | 104 | @end 105 | -------------------------------------------------------------------------------- /LYAVPlayer.xcodeproj/xcuserdata/luyang.xcuserdatad/xcschemes/LYAVPlayer.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /LYAVPlayer.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod spec lint LYAVPlayer.podspec' to ensure this is a 3 | # valid spec and to remove all comments including this before submitting the spec. 4 | # 5 | # To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html 6 | # To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/ 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | 11 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 12 | # 13 | # These will help people to find your library, and whilst it 14 | # can feel like a chore to fill in it's definitely to your advantage. The 15 | # summary should be tweet-length, and the description more in depth. 16 | # 17 | s.name = "LYAVPlayer" 18 | s.version = "1.0.1" 19 | s.summary = "支持cocoa pods" 20 | 21 | # This description is used to generate tags and improve search results. 22 | # * Think: What does it do? Why did you write it? What is the focus? 23 | # * Try to keep it short, snappy and to the point. # * Write the description between the DESC delimiters below. 24 | # * Finally, don't worry about the indent, CocoaPods strips it! 25 | s.description = <<-DESC 26 | Cocoa Pods组件化实践视频播放器 27 | DESC 28 | s.homepage = "https://github.com/1015857193/LYAVPlayer" 29 | # s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif" 30 | 31 | 32 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 33 | # 34 | # Licensing your code is important. See http://choosealicense.com for more info. 35 | # CocoaPods will detect a license file if there is a named LICENSE* 36 | # Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'. 37 | # 38 | 39 | s.license = "MIT" 40 | # s.license = { :type => "MIT", :file => "FILE_LICENSE" } 41 | 42 | 43 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 44 | # 45 | # Specify the authors of the library, with email addresses. Email addresses 46 | # of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also 47 | # accepts just a name if you'd rather not provide an email address. 48 | # 49 | # Specify a social_media_url where others can refer to, for example a twitter 50 | # profile URL. 51 | # 52 | 53 | s.author = { "卢洋" => "15210899805@163.com" } 54 | # Or just: s.author = "卢洋" 55 | # s.authors = { "卢洋" => "15210899805@163.com" } 56 | # s.social_media_url = "https://juejin.im/user/585b4586128fe1006b95bd7b" 57 | 58 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 59 | # 60 | # If this Pod runs only on iOS or OS X, then specify the platform and 61 | # the deployment target. You can optionally include the target after the platform. 62 | # 63 | 64 | # s.platform = :ios 65 | # s.platform = :ios, "8.0" 66 | s.ios.deployment_target = '8.0' 67 | # When using multiple platforms 68 | # s.ios.deployment_target = "5.0" 69 | # s.osx.deployment_target = "10.7" 70 | # s.watchos.deployment_target = "2.0" 71 | # s.tvos.deployment_target = "9.0" 72 | 73 | 74 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 75 | # 76 | # Specify the location from where the source should be retrieved. 77 | # Supports git, hg, bzr, svn and HTTP. 78 | # 79 | 80 | s.source = { :git => "https://github.com/1015857193/LYAVPlayer.git", :tag => "#{s.version}" } 81 | 82 | 83 | # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 84 | # 85 | # CocoaPods is smart about how it includes source code. For source files 86 | # giving a folder will include any swift, h, m, mm, c & cpp files. 87 | # For header files it will include any header in the folder. 88 | # Not including the public_header_files will make all headers public. 89 | # 90 | 91 | s.source_files = "LYAVPlayer/LYAVPlayerView", "LYAVPlayerView/**/*.{h.m}" 92 | s.exclude_files = "Classes/Exclude" 93 | 94 | # s.public_header_files = "Classes/**/*.h" 95 | 96 | 97 | # ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 98 | # 99 | # A list of resources included with the Pod. These are copied into the 100 | # target bundle with a build phase script. Anything else will be cleaned. 101 | # You can preserve files from being cleaned, please don't preserve 102 | # non-essential files like tests, examples and documentation. 103 | # 104 | 105 | # s.resource = "icon.png" 106 | # s.resources = "Resources/*.png" 107 | 108 | # s.preserve_paths = "FilesToSave", "MoreFilesToSave" 109 | 110 | 111 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 112 | # 113 | # Link your library with frameworks, or libraries. Libraries do not include 114 | # the lib prefix of their name. 115 | # 116 | 117 | # s.framework = "AVFoundation" 118 | # s.frameworks = "UIKit", "AVFoundation" 119 | 120 | # s.library = "iconv" 121 | # s.libraries = "iconv", "xml2" 122 | 123 | 124 | # ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 125 | # 126 | # If your library depends on compiler flags you can set them in the xcconfig hash 127 | # where they will only apply to your library. If you depend on other Podspecs 128 | # you can include multiple dependencies to ensure it works. 129 | 130 | # s.requires_arc = true 131 | 132 | # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } 133 | # s.dependency "JSONKit", "~> 1.4" 134 | 135 | end 136 | -------------------------------------------------------------------------------- /LYAVPlayer/PlayerViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PlayerViewController.m 3 | // LYVideoPlayer 4 | // 5 | // Created by luyang on 2017/10/11. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #import "PlayerViewController.h" 10 | #import "SecondViewController.h" 11 | 12 | 13 | 14 | 15 | 16 | @interface PlayerViewController () 17 | 18 | @property (weak, nonatomic) IBOutlet UIButton *playBtn; 19 | 20 | @property (weak, nonatomic) IBOutlet UIButton *pauseBtn; 21 | 22 | 23 | @property (weak, nonatomic) IBOutlet UISlider *slider; 24 | 25 | 26 | @property (nonatomic,assign)BOOL isSlidering; 27 | 28 | @property (nonatomic,strong)LYAVPlayerView *playerView; 29 | 30 | @property (nonatomic,strong)AVURLAsset *asset; 31 | 32 | @property (nonatomic,strong)UIImageView *imageView; 33 | 34 | 35 | @property (nonatomic,assign)CGFloat switchTime; 36 | @property (nonatomic,assign)BOOL isSwitch; 37 | 38 | @property (nonatomic,assign)BOOL isChange; 39 | 40 | 41 | 42 | @end 43 | 44 | @implementation PlayerViewController 45 | 46 | - (void)viewWillAppear:(BOOL)animated{ 47 | 48 | [super viewWillAppear:animated]; 49 | 50 | 51 | NSLog(@"test3%@",[self description]); 52 | 53 | } 54 | 55 | - (void)viewDidAppear:(BOOL)animated{ 56 | 57 | [super viewDidAppear:animated]; 58 | 59 | NSLog(@"test4%@",[self description]); 60 | 61 | } 62 | 63 | - (void)viewDidLoad { 64 | [super viewDidLoad]; 65 | 66 | //想实现后台播放使用sharedInstance 67 | self.playerView =[[LYAVPlayerView alloc]init]; 68 | //先获取视频的宽高比 69 | // CGFloat scale =[self.playerView getVideoScale:[NSURL URLWithString:VideoURL]]; 70 | self.playerView.frame =CGRectMake(0,64,ScreenWidth,ScreenWidth/2); 71 | 72 | self.playerView.delegate =self; 73 | [self.view addSubview:self.playerView]; 74 | [self.playerView setURL:[NSURL URLWithString:VideoURL]]; 75 | [self.playerView play]; 76 | 77 | // _imageView =[UIImageView new]; 78 | // _imageView.hidden =YES; 79 | // _imageView.frame =CGRectMake(0,64,ScreenWidth,ScreenWidth*scale); 80 | // _imageView.image =[self.playerView getThumbnailImageFromVideoURL:[NSURL URLWithString:VideoURL] time:5]; 81 | // [self.view addSubview:_imageView]; 82 | 83 | 84 | } 85 | 86 | 87 | 88 | 89 | - (IBAction)playAction:(id)sender { 90 | 91 | [self.playerView play]; 92 | 93 | } 94 | 95 | 96 | - (IBAction)pauseAction:(id)sender { 97 | 98 | [self.playerView pause]; 99 | // [self.playerView stop]; 100 | 101 | 102 | 103 | } 104 | 105 | - (IBAction)valueChange:(id)sender { 106 | 107 | CGFloat seconds =_slider.value; 108 | 109 | CGFloat totalTime =[self.playerView getTotalPlayTime]; 110 | 111 | CGFloat time =seconds*totalTime; 112 | 113 | [self.playerView seekToTime:time]; 114 | 115 | } 116 | - (IBAction)qualityAction:(id)sender { 117 | 118 | _switchTime =[self.playerView getCurrentPlayTime]; 119 | 120 | _isSwitch =YES; 121 | _isChange =NO; 122 | [self.playerView pause]; 123 | 124 | _imageView.image =[self.playerView getThumbnailImageFromVideoURL:[NSURL URLWithString:VideoURL] time:_switchTime]; 125 | _imageView.hidden =NO; 126 | [self.playerView setURL:[NSURL URLWithString:VideoURL]]; 127 | 128 | } 129 | 130 | - (IBAction)valueEnd:(id)sender { 131 | 132 | _isSlidering =NO; 133 | 134 | } 135 | - (IBAction)valueBegin:(id)sender { 136 | 137 | _isSlidering =YES; 138 | 139 | 140 | } 141 | - (IBAction)turnAction:(id)sender { 142 | 143 | [self.playerView pause]; 144 | 145 | CGFloat time =[self.playerView getCurrentPlayTime]; 146 | 147 | SecondViewController *viewCtrl =[[SecondViewController alloc]init]; 148 | viewCtrl.asset =self.playerView.urlAsset; 149 | viewCtrl.time =time; 150 | [self.navigationController pushViewController:viewCtrl animated:NO]; 151 | 152 | } 153 | 154 | #pragma mark-----LYVideoPlayerDelegate------- 155 | // 可播放/播放中 156 | - (void)videoPlayerIsReadyToPlayVideo:(LYAVPlayerView *)playerView{ 157 | 158 | NSLog(@"可播放"); 159 | 160 | } 161 | 162 | //播放完毕 163 | - (void)videoPlayerDidReachEnd:(LYAVPlayerView *)playerView{ 164 | 165 | NSLog(@"播放完毕"); 166 | 167 | [self.playerView setURL:[NSURL URLWithString:VideoURL]]; 168 | [self.playerView play]; 169 | 170 | } 171 | //当前播放时间 172 | - (void)videoPlayer:(LYAVPlayerView *)playerView timeDidChange:(CGFloat )time{ 173 | 174 | NSLog(@"当前播放时间:%f",time); 175 | 176 | if(!_isSlidering){ 177 | 178 | _slider.value =[self.playerView getCurrentPlayTime]/[self.playerView getTotalPlayTime]; 179 | } 180 | } 181 | 182 | 183 | //duration 当前缓冲的长度 184 | - (void)videoPlayer:(LYAVPlayerView *)playerView loadedTimeRangeDidChange:(CGFloat )duration{ 185 | 186 | NSLog(@"当前缓冲的长度%f",duration); 187 | 188 | if (_isChange) return; 189 | 190 | if (duration >= _switchTime && _isSwitch) { 191 | _imageView.hidden =YES; 192 | [self.playerView seekToTime:_switchTime]; 193 | [self.playerView play]; 194 | _isChange =YES; 195 | 196 | } 197 | 198 | } 199 | 200 | //进行跳转后没数据 即播放卡顿 201 | - (void)videoPlayerPlaybackBufferEmpty:(LYAVPlayerView *)playerView{ 202 | 203 | NSLog(@"卡顿了"); 204 | 205 | } 206 | 207 | // 进行跳转后有数据 能够继续播放 208 | - (void)videoPlayerPlaybackLikelyToKeepUp:(LYAVPlayerView *)playerView{ 209 | 210 | NSLog(@"能够继续播放"); 211 | 212 | } 213 | 214 | //加载失败 215 | - (void)videoPlayer:(LYAVPlayerView *)playerView didFailWithError:(NSError *)error{ 216 | 217 | NSLog(@"加载失败"); 218 | 219 | } 220 | 221 | 222 | 223 | 224 | - (void)didReceiveMemoryWarning { 225 | [super didReceiveMemoryWarning]; 226 | // Dispose of any resources that can be recreated. 227 | } 228 | 229 | /* 230 | #pragma mark - Navigation 231 | 232 | // In a storyboard-based application, you will often want to do a little preparation before navigation 233 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 234 | // Get the new view controller using [segue destinationViewController]. 235 | // Pass the selected object to the new view controller. 236 | } 237 | */ 238 | 239 | @end 240 | -------------------------------------------------------------------------------- /LYAVPlayer/PlayerViewController.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 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 53 | 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 | 101 | -------------------------------------------------------------------------------- /LYAVPlayer/LYAVPlayerView/LYAVPlayerView.m: -------------------------------------------------------------------------------- 1 | // 2 | // LYPlayerView.m 3 | // LYPlayer 4 | // 5 | // Created by luyang on 2017/10/10. 6 | // Copyright © 2017年 Myself. All rights reserved. 7 | // 8 | 9 | #import "LYAVPlayerView.h" 10 | 11 | static const CGFloat TimeObserverInterval = 0.01f; 12 | 13 | static void *VideoPlayer_PlayerItemStatusContext = &VideoPlayer_PlayerItemStatusContext; 14 | 15 | static void *VideoPlayer_PlayerItemPlaybackLikelyToKeepUp = &VideoPlayer_PlayerItemPlaybackLikelyToKeepUp; 16 | static void *VideoPlayer_PlayerItemPlaybackBufferEmpty = &VideoPlayer_PlayerItemPlaybackBufferEmpty; 17 | static void *VideoPlayer_PlayerItemLoadedTimeRangesContext = &VideoPlayer_PlayerItemLoadedTimeRangesContext; 18 | 19 | NSString * const LYVideoPlayerErrorDomain = @"VideoPlayerErrorDomain"; 20 | 21 | @interface LYAVPlayerView() 22 | 23 | //播放时为YES 暂停时为NO 24 | @property (nonatomic, assign) BOOL isPlaying; 25 | 26 | //播放属性 27 | @property (nonatomic, strong) AVPlayer *player; 28 | @property (nonatomic, strong) AVPlayerItem *item; 29 | @property (nonatomic, strong) AVURLAsset *urlAsset; 30 | @property (nonatomic, strong) AVPlayerLayer *playerLayer; 31 | 32 | @property (nonatomic, strong) id timeObserverToken; 33 | 34 | @property (nonatomic,assign)CGFloat rate; 35 | 36 | 37 | @end 38 | 39 | 40 | @implementation LYAVPlayerView 41 | 42 | -(void)dealloc{ 43 | 44 | NSLog(@"LYPlayerView销毁了"); 45 | 46 | [self resetPlayerItemIfNecessary]; 47 | 48 | } 49 | 50 | + (instancetype)sharedInstance{ 51 | 52 | static id sharedInstance =nil; 53 | static dispatch_once_t onceToken; 54 | dispatch_once(&onceToken, ^{ 55 | 56 | sharedInstance =[[self alloc] init]; 57 | }); 58 | return sharedInstance; 59 | 60 | } 61 | 62 | - (instancetype)initWithCoder:(NSCoder *)aDecoder{ 63 | 64 | self =[super initWithCoder:aDecoder]; 65 | if (self) 66 | { 67 | 68 | [self setupAudioSession]; 69 | } 70 | 71 | return self; 72 | 73 | 74 | } 75 | 76 | - (void)awakeFromNib{ 77 | 78 | [super awakeFromNib]; 79 | 80 | [self setupAudioSession]; 81 | 82 | } 83 | 84 | - (instancetype)initWithFrame:(CGRect)frame{ 85 | 86 | self =[super initWithFrame:frame]; 87 | 88 | if (self) { 89 | 90 | [self setupAudioSession]; 91 | } 92 | 93 | return self; 94 | } 95 | 96 | - (instancetype)init 97 | { 98 | self = [super init]; 99 | if (self) 100 | { 101 | 102 | [self setupAudioSession]; 103 | } 104 | 105 | return self; 106 | } 107 | 108 | - (void)setupAudioSession 109 | { 110 | //先设置rate为1.0 111 | _rate =1.0f; 112 | 113 | NSError *categoryError = nil; 114 | BOOL success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&categoryError]; 115 | if (!success) 116 | { 117 | NSLog(@"Error setting audio session category: %@", categoryError); 118 | } 119 | 120 | NSError *activeError = nil; 121 | success = [[AVAudioSession sharedInstance] setActive:YES error:&activeError]; 122 | if (!success) 123 | { 124 | NSLog(@"Error setting audio session active: %@", activeError); 125 | } 126 | } 127 | 128 | //懒加载 129 | - (NSString *)videoGravity{ 130 | 131 | if(!_videoGravity){ 132 | 133 | _videoGravity =AVLayerVideoGravityResizeAspect; 134 | } 135 | 136 | return _videoGravity; 137 | 138 | } 139 | 140 | - (void)layoutSubviews{ 141 | [super layoutSubviews]; 142 | 143 | if(self.playerLayer){ 144 | 145 | self.playerLayer.frame =self.bounds; 146 | 147 | } 148 | 149 | } 150 | 151 | //跳到xx秒播放视频 152 | - (void)seekToTime:(CGFloat )time{ 153 | 154 | if (self.player){ 155 | 156 | [self.player.currentItem cancelPendingSeeks]; 157 | 158 | CMTime cmTime =CMTimeMakeWithSeconds(time, 1); 159 | if (CMTIME_IS_INVALID(cmTime) || self.player.currentItem.status != AVPlayerStatusReadyToPlay){ 160 | 161 | return; 162 | } 163 | 164 | 165 | [self.player seekToTime:cmTime toleranceBefore:CMTimeMake(1,1) toleranceAfter:CMTimeMake(1,1) completionHandler:^(BOOL finished) { 166 | 167 | 168 | 169 | }]; 170 | 171 | } 172 | 173 | } 174 | 175 | 176 | 177 | //设置播放URL 178 | - (void)setURL:(NSURL *)URL{ 179 | 180 | //如果有正在播放的视频 先释放掉 181 | [self resetPlayerItemIfNecessary]; 182 | 183 | self.urlAsset =[AVURLAsset assetWithURL:URL]; 184 | 185 | [self creatPlayerWithAsset:self.urlAsset]; 186 | 187 | } 188 | 189 | - (void)setAsset:(AVURLAsset *)asset{ 190 | 191 | //如果有正在播放的视频 先释放掉 192 | [self resetPlayerItemIfNecessary]; 193 | 194 | [self creatPlayerWithAsset:asset]; 195 | 196 | 197 | } 198 | 199 | - (void)creatPlayerWithAsset:(AVURLAsset *)urlAsset{ 200 | 201 | // 初始化playerItem 202 | self.item =[AVPlayerItem playerItemWithAsset:urlAsset]; 203 | 204 | if (@available(iOS 10.0, *)) { 205 | 206 | self.item.preferredForwardBufferDuration =10.f; 207 | 208 | } else { 209 | // Fallback on earlier versions 210 | } 211 | 212 | 213 | 214 | 215 | 216 | //判断 217 | if(!self.item){ 218 | 219 | [self reportUnableToCreatePlayerItem]; 220 | 221 | return; 222 | 223 | } 224 | 225 | // 每次都重新创建Player,替换replaceCurrentItemWithPlayerItem:,该方法阻塞线程 226 | self.player =[AVPlayer playerWithPlayerItem:self.item]; 227 | 228 | self.playerLayer =[AVPlayerLayer playerLayerWithPlayer:self.player]; 229 | 230 | // 此处为默认视频填充模式 231 | self.playerLayer.videoGravity = self.videoGravity; 232 | 233 | [self setNeedsLayout]; 234 | [self layoutIfNeeded]; 235 | 236 | // 添加playerLayer到self.layer 237 | [self.layer insertSublayer:self.playerLayer atIndex:0]; 238 | 239 | //添加播放时间观察 240 | [self enableTimeUpdates]; 241 | //添加观察 242 | [self preparePlayerItem:self.item]; 243 | 244 | 245 | 246 | } 247 | 248 | - (void)preparePlayerItem:(AVPlayerItem *)playerItem{ 249 | 250 | [self addPlayerItemObservers:playerItem]; 251 | } 252 | 253 | - (void)addPlayerItemObservers:(AVPlayerItem *)playerItem 254 | { 255 | [playerItem addObserver:self 256 | forKeyPath:@"status" 257 | options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew 258 | context:VideoPlayer_PlayerItemStatusContext]; 259 | 260 | [playerItem addObserver:self 261 | forKeyPath:@"playbackLikelyToKeepUp" 262 | options:NSKeyValueObservingOptionNew 263 | context:VideoPlayer_PlayerItemPlaybackLikelyToKeepUp]; 264 | 265 | [playerItem addObserver:self 266 | forKeyPath:@"playbackBufferEmpty" 267 | options:NSKeyValueObservingOptionNew 268 | context:VideoPlayer_PlayerItemPlaybackBufferEmpty]; 269 | 270 | [playerItem addObserver:self 271 | forKeyPath:@"loadedTimeRanges" 272 | options:NSKeyValueObservingOptionNew 273 | context:VideoPlayer_PlayerItemLoadedTimeRangesContext]; 274 | 275 | //播放完毕的通知 276 | [[NSNotificationCenter defaultCenter] addObserver:self 277 | selector:@selector(playerItemDidPlayToEndTime:) 278 | name:AVPlayerItemDidPlayToEndTimeNotification 279 | object:playerItem]; 280 | 281 | //耳机插入和拔掉通知 282 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:) name:AVAudioSessionRouteChangeNotification object:nil]; 283 | 284 | 285 | 286 | } 287 | 288 | - (void)playerItemDidPlayToEndTime:(NSNotification *)notification 289 | { 290 | if ([self.delegate respondsToSelector:@selector(videoPlayerDidReachEnd:)]) 291 | { 292 | [self.delegate videoPlayerDidReachEnd:self]; 293 | } 294 | 295 | } 296 | 297 | //耳机插入、拔出事件 298 | - (void)audioRouteChangeListenerCallback:(NSNotification*)notification { 299 | NSDictionary *interuptionDict = notification.userInfo; 300 | 301 | NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue]; 302 | 303 | switch (routeChangeReason) { 304 | 305 | case AVAudioSessionRouteChangeReasonNewDeviceAvailable: 306 | // 耳机插入 307 | break; 308 | 309 | case AVAudioSessionRouteChangeReasonOldDeviceUnavailable: 310 | { 311 | 312 | // 拔掉耳机继续播放 313 | if (self.isPlaying) { 314 | 315 | [self.player play]; 316 | } 317 | 318 | } 319 | break; 320 | 321 | case AVAudioSessionRouteChangeReasonCategoryChange: 322 | // called at start - also when other audio wants to play 323 | 324 | break; 325 | } 326 | } 327 | 328 | 329 | //移除player属性观察 330 | - (void)removePlayerItemObservers:(AVPlayerItem *)playerItem 331 | { 332 | [playerItem cancelPendingSeeks]; 333 | 334 | [playerItem removeObserver:self forKeyPath:@"status" context:VideoPlayer_PlayerItemStatusContext]; 335 | [playerItem removeObserver:self forKeyPath:@"loadedTimeRanges" context:VideoPlayer_PlayerItemLoadedTimeRangesContext]; 336 | [playerItem removeObserver:self forKeyPath:@"playbackBufferEmpty" context:VideoPlayer_PlayerItemPlaybackBufferEmpty]; 337 | [playerItem removeObserver:self forKeyPath:@"playbackLikelyToKeepUp" context:VideoPlayer_PlayerItemPlaybackLikelyToKeepUp]; 338 | 339 | [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:nil]; 340 | 341 | [[NSNotificationCenter defaultCenter] removeObserver:self name:AVAudioSessionRouteChangeNotification object:nil]; 342 | } 343 | 344 | 345 | //播放时间 观察 346 | - (void)addTimeObserver{ 347 | 348 | if (self.timeObserverToken || self.player == nil) 349 | { 350 | return; 351 | } 352 | 353 | __weak typeof (self) weakSelf = self; 354 | self.timeObserverToken = [self.player addPeriodicTimeObserverForInterval:CMTimeMakeWithSeconds(1.0, 1.0) queue:dispatch_get_main_queue() usingBlock:^(CMTime time) { 355 | 356 | __strong typeof (weakSelf) strongSelf = weakSelf; 357 | if (!strongSelf) 358 | { 359 | return; 360 | } 361 | 362 | if ([strongSelf.delegate respondsToSelector:@selector(videoPlayer:timeDidChange:)]) 363 | { 364 | [strongSelf.delegate videoPlayer:strongSelf timeDidChange:CMTimeGetSeconds(time)]; 365 | } 366 | 367 | 368 | 369 | }]; 370 | 371 | 372 | 373 | } 374 | 375 | //移除时间观察 376 | - (void)removeTimeObserver{ 377 | 378 | if (!self.timeObserverToken) 379 | { 380 | return; 381 | } 382 | 383 | 384 | if (self.player) 385 | { 386 | [self.player removeTimeObserver:self.timeObserverToken]; 387 | } 388 | 389 | self.timeObserverToken = nil; 390 | 391 | 392 | } 393 | 394 | - (void)enableTimeUpdates{ 395 | 396 | [self addTimeObserver]; 397 | 398 | 399 | } 400 | 401 | - (void)disableTimeUpdates{ 402 | 403 | [self removeTimeObserver]; 404 | 405 | } 406 | 407 | - (void)reportUnableToCreatePlayerItem{ 408 | 409 | if ([self.delegate respondsToSelector:@selector(videoPlayer:didFailWithError:)]) 410 | { 411 | NSError *error = [NSError errorWithDomain:LYVideoPlayerErrorDomain 412 | code:100 413 | userInfo:@{NSLocalizedDescriptionKey : @"Unable to create AVPlayerItem."}]; 414 | 415 | [self.delegate videoPlayer:self didFailWithError:error]; 416 | } 417 | 418 | 419 | 420 | 421 | } 422 | 423 | 424 | //释放 425 | - (void)resetPlayerItemIfNecessary{ 426 | 427 | if (self.item ) 428 | { 429 | [self removePlayerItemObservers:self.item]; 430 | 431 | 432 | } 433 | 434 | //移除时间观察 435 | [self disableTimeUpdates]; 436 | 437 | if (self.playerLayer) { 438 | 439 | [self.playerLayer removeFromSuperlayer]; 440 | } 441 | 442 | 443 | if (self.item){ 444 | 445 | self.item = nil; 446 | } 447 | 448 | if (self.player) { 449 | 450 | [self.player replaceCurrentItemWithPlayerItem:nil]; 451 | self.player =nil; 452 | } 453 | 454 | if (self.urlAsset) { 455 | self.urlAsset =nil; 456 | } 457 | 458 | if (self.playerLayer) { 459 | 460 | self.playerLayer =nil; 461 | } 462 | 463 | 464 | 465 | } 466 | 467 | //播放 468 | - (void)play{ 469 | 470 | self.isPlaying =YES; 471 | self.player.rate =_rate?:1.0f; 472 | } 473 | 474 | //暂停 475 | - (void)pause{ 476 | 477 | if(self.isPlaying){ 478 | 479 | self.isPlaying =NO; 480 | // self.player.rate =0.0f; 481 | 482 | [self.player pause]; 483 | } 484 | 485 | 486 | 487 | } 488 | 489 | //停止播放 490 | - (void)stop{ 491 | 492 | [self.player pause]; 493 | 494 | //item置为nil相关 495 | [self resetPlayerItemIfNecessary]; 496 | 497 | } 498 | 499 | //设置播放倍速 0.5-2.0 500 | - (void)setPlayerRate:(CGFloat )rate{ 501 | 502 | _rate =rate; 503 | 504 | if(self.player) self.player.rate =rate; 505 | 506 | 507 | } 508 | 509 | //获取当前播放的时间 510 | - (CGFloat )getCurrentPlayTime{ 511 | 512 | if(self.player) return CMTimeGetSeconds([self.player currentTime]); 513 | 514 | return 0.0f; 515 | } 516 | 517 | //获取视频的总时间长 518 | - (CGFloat)getTotalPlayTime{ 519 | 520 | if(self.player) return CMTimeGetSeconds(self.player.currentItem.duration); 521 | 522 | return 0.0f; 523 | } 524 | 525 | //获取视频宽高比 526 | - (CGFloat )getVideoScale:(NSURL *)URL{ 527 | 528 | if (!URL) return 0.0f; 529 | //获取视频尺寸 530 | AVURLAsset *asset = [AVURLAsset assetWithURL:URL]; 531 | 532 | NSArray *array = asset.tracks; 533 | CGSize videoSize = CGSizeZero; 534 | for (AVAssetTrack *track in array) { 535 | if ([track.mediaType isEqualToString:AVMediaTypeVideo]) { 536 | videoSize = track.naturalSize; 537 | } 538 | } 539 | 540 | return videoSize.height/videoSize.width; 541 | } 542 | 543 | - (UIImage *)getThumbnailImageFromVideoURL:(NSURL *)URL time:(NSTimeInterval )videoTime{ 544 | 545 | if (!URL) return nil; 546 | 547 | UIImage *shotImage; 548 | 549 | AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:URL options:nil]; 550 | 551 | AVAssetImageGenerator *gen = [[AVAssetImageGenerator alloc] initWithAsset:asset]; 552 | 553 | gen.appliesPreferredTrackTransform = YES; 554 | 555 | CMTime time = CMTimeMakeWithSeconds(videoTime, 600); 556 | 557 | NSError *error = nil; 558 | 559 | CMTime actualTime; 560 | 561 | CGImageRef image = [gen copyCGImageAtTime:time actualTime:&actualTime error:&error]; 562 | 563 | shotImage = [[UIImage alloc] initWithCGImage:image]; 564 | 565 | CGImageRelease(image); 566 | 567 | return shotImage; 568 | } 569 | 570 | 571 | - (UIImage *)getThumbnailImageFromFilePath:(NSString *)videoPath time:(NSTimeInterval )videoTime { 572 | 573 | if (!videoPath) { 574 | return nil; 575 | } 576 | AVURLAsset *asset = [[AVURLAsset alloc] initWithURL:[[NSURL alloc] initFileURLWithPath:videoPath] options:nil]; 577 | AVAssetImageGenerator *assetImageGenerator = [[AVAssetImageGenerator alloc] initWithAsset:asset]; 578 | assetImageGenerator.appliesPreferredTrackTransform = YES; 579 | assetImageGenerator.apertureMode = AVAssetImageGeneratorApertureModeEncodedPixels; 580 | 581 | CGImageRef thumbnailImageRef = NULL; 582 | CFTimeInterval thumbnailImageTime = videoTime; 583 | thumbnailImageRef = [assetImageGenerator copyCGImageAtTime:CMTimeMake(thumbnailImageTime, 600) 584 | actualTime:NULL error:nil]; 585 | 586 | 587 | if (!thumbnailImageRef) { 588 | return nil; 589 | } 590 | 591 | UIImage *thumbnailImage = [[UIImage alloc] initWithCGImage:thumbnailImageRef]; 592 | 593 | 594 | CFRelease(thumbnailImageRef); 595 | 596 | return thumbnailImage; 597 | 598 | } 599 | 600 | 601 | 602 | #pragma mark - Observer Response 603 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 604 | { 605 | //player状态 606 | if (context == VideoPlayer_PlayerItemStatusContext){ 607 | 608 | AVPlayerStatus newStatus = [[change objectForKey:NSKeyValueChangeNewKey] integerValue]; 609 | AVPlayerStatus oldStatus = [[change objectForKey:NSKeyValueChangeOldKey] integerValue]; 610 | 611 | if (newStatus != oldStatus) { 612 | 613 | switch (newStatus) { 614 | case AVPlayerItemStatusUnknown: 615 | 616 | NSLog(@"Video player Status Unknown"); 617 | 618 | break; 619 | 620 | case AVPlayerItemStatusReadyToPlay: 621 | 622 | if ([self.delegate respondsToSelector:@selector(videoPlayerIsReadyToPlayVideo:)]) 623 | { 624 | dispatch_async(dispatch_get_main_queue(), ^{ 625 | 626 | [self.delegate videoPlayerIsReadyToPlayVideo:self]; 627 | 628 | }); 629 | 630 | 631 | } 632 | 633 | 634 | break; 635 | 636 | 637 | 638 | case AVPlayerStatusFailed:{ 639 | 640 | 641 | NSError *error = [NSError errorWithDomain:LYVideoPlayerErrorDomain code:100 userInfo:@{NSLocalizedDescriptionKey : @"unknown player error, status == AVPlayerItemStatusFailed"}]; 642 | 643 | if ([self.delegate respondsToSelector:@selector(videoPlayer:didFailWithError:)]) 644 | { 645 | dispatch_async(dispatch_get_main_queue(), ^{ 646 | [self.delegate videoPlayer:self didFailWithError:error]; 647 | }); 648 | } 649 | 650 | 651 | } 652 | break; 653 | } 654 | 655 | } 656 | 657 | 658 | 659 | }else if (context == VideoPlayer_PlayerItemPlaybackBufferEmpty){ 660 | //缓冲为空 661 | if ([keyPath isEqualToString:@"playbackBufferEmpty"]) { 662 | 663 | if (self.player.currentItem.playbackBufferEmpty) { 664 | 665 | if ([self.delegate respondsToSelector:@selector(videoPlayerPlaybackBufferEmpty:)]) 666 | { 667 | 668 | dispatch_async(dispatch_get_main_queue(), ^{ 669 | 670 | 671 | [self.delegate videoPlayerPlaybackBufferEmpty:self]; 672 | 673 | }); 674 | 675 | } 676 | 677 | } 678 | 679 | 680 | } 681 | 682 | 683 | }else if (context == VideoPlayer_PlayerItemPlaybackLikelyToKeepUp){ 684 | 685 | if([keyPath isEqualToString:@"playbackLikelyToKeepUp"]) { 686 | 687 | if (self.player.currentItem.playbackLikelyToKeepUp){ 688 | 689 | if ([self.delegate respondsToSelector:@selector(videoPlayerPlaybackLikelyToKeepUp:)]) { 690 | 691 | dispatch_async(dispatch_get_main_queue(), ^{ 692 | 693 | 694 | [self.delegate videoPlayerPlaybackLikelyToKeepUp:self]; 695 | 696 | }); 697 | 698 | } 699 | 700 | 701 | } 702 | 703 | } 704 | 705 | 706 | }else if (context == VideoPlayer_PlayerItemLoadedTimeRangesContext){ 707 | 708 | if ([keyPath isEqualToString:@"loadedTimeRanges"]) { 709 | 710 | if ([self.delegate respondsToSelector:@selector(videoPlayer:loadedTimeRangeDidChange:)]) 711 | { 712 | 713 | CGFloat loadedDuration =[self calcLoadedDuration]; 714 | dispatch_async(dispatch_get_main_queue(), ^{ 715 | 716 | 717 | [self.delegate videoPlayer:self loadedTimeRangeDidChange:loadedDuration]; 718 | 719 | }); 720 | 721 | } 722 | 723 | 724 | } 725 | 726 | 727 | 728 | }else{ 729 | 730 | [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 731 | 732 | } 733 | 734 | 735 | 736 | 737 | } 738 | 739 | - (CGFloat )calcLoadedDuration 740 | { 741 | CGFloat loadedDuration = 0.0f; 742 | 743 | if (self.player && self.player.currentItem) 744 | { 745 | NSArray *loadedTimeRanges = self.player.currentItem.loadedTimeRanges; 746 | 747 | if (loadedTimeRanges && [loadedTimeRanges count]) 748 | { 749 | CMTimeRange timeRange = [[loadedTimeRanges firstObject] CMTimeRangeValue]; 750 | CGFloat startSeconds = CMTimeGetSeconds(timeRange.start); 751 | CGFloat durationSeconds = CMTimeGetSeconds(timeRange.duration); 752 | 753 | loadedDuration = startSeconds + durationSeconds; 754 | } 755 | } 756 | 757 | return loadedDuration; 758 | } 759 | 760 | 761 | @end 762 | -------------------------------------------------------------------------------- /LYAVPlayer.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3501AC821FCE812E00F5C624 /* FirstViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3501AC811FCE812E00F5C624 /* FirstViewController.m */; }; 11 | 355894521F8F5DF0000F7DF6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 355894511F8F5DF0000F7DF6 /* Assets.xcassets */; }; 12 | 355894551F8F5DF0000F7DF6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 355894531F8F5DF0000F7DF6 /* LaunchScreen.storyboard */; }; 13 | 355894581F8F5DF0000F7DF6 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 355894571F8F5DF0000F7DF6 /* main.m */; }; 14 | 355894621F8F5DF0000F7DF6 /* LYAVPlayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 355894611F8F5DF0000F7DF6 /* LYAVPlayerTests.m */; }; 15 | 3558946D1F8F5DF0000F7DF6 /* LYAVPlayerUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3558946C1F8F5DF0000F7DF6 /* LYAVPlayerUITests.m */; }; 16 | 3558947D1F8F5E55000F7DF6 /* LYAVPlayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3558947B1F8F5E55000F7DF6 /* LYAVPlayerView.m */; }; 17 | 355894831F8F5EAD000F7DF6 /* PlayerViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3558947E1F8F5EAC000F7DF6 /* PlayerViewController.storyboard */; }; 18 | 355894841F8F5EAD000F7DF6 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 355894811F8F5EAD000F7DF6 /* AppDelegate.m */; }; 19 | 355894851F8F5EAD000F7DF6 /* PlayerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 355894821F8F5EAD000F7DF6 /* PlayerViewController.m */; }; 20 | 35B2C19B1F944D55006F31ED /* SecondViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 35B2C19A1F944D55006F31ED /* SecondViewController.m */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXContainerItemProxy section */ 24 | 3558945E1F8F5DF0000F7DF6 /* PBXContainerItemProxy */ = { 25 | isa = PBXContainerItemProxy; 26 | containerPortal = 3558943D1F8F5DF0000F7DF6 /* Project object */; 27 | proxyType = 1; 28 | remoteGlobalIDString = 355894441F8F5DF0000F7DF6; 29 | remoteInfo = LYAVPlayer; 30 | }; 31 | 355894691F8F5DF0000F7DF6 /* PBXContainerItemProxy */ = { 32 | isa = PBXContainerItemProxy; 33 | containerPortal = 3558943D1F8F5DF0000F7DF6 /* Project object */; 34 | proxyType = 1; 35 | remoteGlobalIDString = 355894441F8F5DF0000F7DF6; 36 | remoteInfo = LYAVPlayer; 37 | }; 38 | /* End PBXContainerItemProxy section */ 39 | 40 | /* Begin PBXFileReference section */ 41 | 3501AC801FCE812E00F5C624 /* FirstViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FirstViewController.h; sourceTree = ""; }; 42 | 3501AC811FCE812E00F5C624 /* FirstViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FirstViewController.m; sourceTree = ""; }; 43 | 355894451F8F5DF0000F7DF6 /* LYAVPlayer.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LYAVPlayer.app; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 355894511F8F5DF0000F7DF6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 45 | 355894541F8F5DF0000F7DF6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 46 | 355894561F8F5DF0000F7DF6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 47 | 355894571F8F5DF0000F7DF6 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 48 | 3558945D1F8F5DF0000F7DF6 /* LYAVPlayerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LYAVPlayerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 49 | 355894611F8F5DF0000F7DF6 /* LYAVPlayerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LYAVPlayerTests.m; sourceTree = ""; }; 50 | 355894631F8F5DF0000F7DF6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 51 | 355894681F8F5DF0000F7DF6 /* LYAVPlayerUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LYAVPlayerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | 3558946C1F8F5DF0000F7DF6 /* LYAVPlayerUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LYAVPlayerUITests.m; sourceTree = ""; }; 53 | 3558946E1F8F5DF0000F7DF6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 54 | 3558947B1F8F5E55000F7DF6 /* LYAVPlayerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LYAVPlayerView.m; sourceTree = ""; }; 55 | 3558947C1F8F5E55000F7DF6 /* LYAVPlayerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LYAVPlayerView.h; sourceTree = ""; }; 56 | 3558947E1F8F5EAC000F7DF6 /* PlayerViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = PlayerViewController.storyboard; sourceTree = ""; }; 57 | 3558947F1F8F5EAD000F7DF6 /* PlayerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlayerViewController.h; sourceTree = ""; }; 58 | 355894801F8F5EAD000F7DF6 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 59 | 355894811F8F5EAD000F7DF6 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 60 | 355894821F8F5EAD000F7DF6 /* PlayerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PlayerViewController.m; sourceTree = ""; }; 61 | 35B2C1991F944D55006F31ED /* SecondViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SecondViewController.h; sourceTree = ""; }; 62 | 35B2C19A1F944D55006F31ED /* SecondViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SecondViewController.m; sourceTree = ""; }; 63 | 35B2C19C1F945226006F31ED /* LYAVPlayer-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "LYAVPlayer-Prefix.pch"; sourceTree = ""; }; 64 | 719F277E04153F456DC6DFAF /* Pods-LYAVPlayer.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LYAVPlayer.release.xcconfig"; path = "Pods/Target Support Files/Pods-LYAVPlayer/Pods-LYAVPlayer.release.xcconfig"; sourceTree = ""; }; 65 | 76A72186C4432CB19046B9E4 /* Pods_LYAVPlayer.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LYAVPlayer.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 66 | E48C30709F50B91F8945C926 /* Pods-LYAVPlayer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LYAVPlayer.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LYAVPlayer/Pods-LYAVPlayer.debug.xcconfig"; sourceTree = ""; }; 67 | /* End PBXFileReference section */ 68 | 69 | /* Begin PBXFrameworksBuildPhase section */ 70 | 355894421F8F5DF0000F7DF6 /* Frameworks */ = { 71 | isa = PBXFrameworksBuildPhase; 72 | buildActionMask = 2147483647; 73 | files = ( 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | 3558945A1F8F5DF0000F7DF6 /* Frameworks */ = { 78 | isa = PBXFrameworksBuildPhase; 79 | buildActionMask = 2147483647; 80 | files = ( 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | 355894651F8F5DF0000F7DF6 /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | /* End PBXFrameworksBuildPhase section */ 92 | 93 | /* Begin PBXGroup section */ 94 | 3558943C1F8F5DF0000F7DF6 = { 95 | isa = PBXGroup; 96 | children = ( 97 | 355894471F8F5DF0000F7DF6 /* LYAVPlayer */, 98 | 355894601F8F5DF0000F7DF6 /* LYAVPlayerTests */, 99 | 3558946B1F8F5DF0000F7DF6 /* LYAVPlayerUITests */, 100 | 355894461F8F5DF0000F7DF6 /* Products */, 101 | CDE8965E88E92E99C37EBCCA /* Pods */, 102 | CA0C9D1FD19857FC11B8A3FD /* Frameworks */, 103 | ); 104 | sourceTree = ""; 105 | }; 106 | 355894461F8F5DF0000F7DF6 /* Products */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 355894451F8F5DF0000F7DF6 /* LYAVPlayer.app */, 110 | 3558945D1F8F5DF0000F7DF6 /* LYAVPlayerTests.xctest */, 111 | 355894681F8F5DF0000F7DF6 /* LYAVPlayerUITests.xctest */, 112 | ); 113 | name = Products; 114 | sourceTree = ""; 115 | }; 116 | 355894471F8F5DF0000F7DF6 /* LYAVPlayer */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 355894801F8F5EAD000F7DF6 /* AppDelegate.h */, 120 | 355894811F8F5EAD000F7DF6 /* AppDelegate.m */, 121 | 3501AC801FCE812E00F5C624 /* FirstViewController.h */, 122 | 3501AC811FCE812E00F5C624 /* FirstViewController.m */, 123 | 3558947F1F8F5EAD000F7DF6 /* PlayerViewController.h */, 124 | 355894821F8F5EAD000F7DF6 /* PlayerViewController.m */, 125 | 3558947E1F8F5EAC000F7DF6 /* PlayerViewController.storyboard */, 126 | 35B2C1991F944D55006F31ED /* SecondViewController.h */, 127 | 35B2C19A1F944D55006F31ED /* SecondViewController.m */, 128 | 3558947A1F8F5E26000F7DF6 /* LYAVPlayerView */, 129 | 355894511F8F5DF0000F7DF6 /* Assets.xcassets */, 130 | 355894531F8F5DF0000F7DF6 /* LaunchScreen.storyboard */, 131 | 355894561F8F5DF0000F7DF6 /* Info.plist */, 132 | 355894571F8F5DF0000F7DF6 /* main.m */, 133 | 35B2C19C1F945226006F31ED /* LYAVPlayer-Prefix.pch */, 134 | ); 135 | path = LYAVPlayer; 136 | sourceTree = ""; 137 | }; 138 | 355894601F8F5DF0000F7DF6 /* LYAVPlayerTests */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 355894611F8F5DF0000F7DF6 /* LYAVPlayerTests.m */, 142 | 355894631F8F5DF0000F7DF6 /* Info.plist */, 143 | ); 144 | path = LYAVPlayerTests; 145 | sourceTree = ""; 146 | }; 147 | 3558946B1F8F5DF0000F7DF6 /* LYAVPlayerUITests */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 3558946C1F8F5DF0000F7DF6 /* LYAVPlayerUITests.m */, 151 | 3558946E1F8F5DF0000F7DF6 /* Info.plist */, 152 | ); 153 | path = LYAVPlayerUITests; 154 | sourceTree = ""; 155 | }; 156 | 3558947A1F8F5E26000F7DF6 /* LYAVPlayerView */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | 3558947C1F8F5E55000F7DF6 /* LYAVPlayerView.h */, 160 | 3558947B1F8F5E55000F7DF6 /* LYAVPlayerView.m */, 161 | ); 162 | path = LYAVPlayerView; 163 | sourceTree = ""; 164 | }; 165 | CA0C9D1FD19857FC11B8A3FD /* Frameworks */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | 76A72186C4432CB19046B9E4 /* Pods_LYAVPlayer.framework */, 169 | ); 170 | name = Frameworks; 171 | sourceTree = ""; 172 | }; 173 | CDE8965E88E92E99C37EBCCA /* Pods */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | E48C30709F50B91F8945C926 /* Pods-LYAVPlayer.debug.xcconfig */, 177 | 719F277E04153F456DC6DFAF /* Pods-LYAVPlayer.release.xcconfig */, 178 | ); 179 | name = Pods; 180 | sourceTree = ""; 181 | }; 182 | /* End PBXGroup section */ 183 | 184 | /* Begin PBXNativeTarget section */ 185 | 355894441F8F5DF0000F7DF6 /* LYAVPlayer */ = { 186 | isa = PBXNativeTarget; 187 | buildConfigurationList = 355894711F8F5DF0000F7DF6 /* Build configuration list for PBXNativeTarget "LYAVPlayer" */; 188 | buildPhases = ( 189 | 355894411F8F5DF0000F7DF6 /* Sources */, 190 | 355894421F8F5DF0000F7DF6 /* Frameworks */, 191 | 355894431F8F5DF0000F7DF6 /* Resources */, 192 | ); 193 | buildRules = ( 194 | ); 195 | dependencies = ( 196 | ); 197 | name = LYAVPlayer; 198 | productName = LYAVPlayer; 199 | productReference = 355894451F8F5DF0000F7DF6 /* LYAVPlayer.app */; 200 | productType = "com.apple.product-type.application"; 201 | }; 202 | 3558945C1F8F5DF0000F7DF6 /* LYAVPlayerTests */ = { 203 | isa = PBXNativeTarget; 204 | buildConfigurationList = 355894741F8F5DF0000F7DF6 /* Build configuration list for PBXNativeTarget "LYAVPlayerTests" */; 205 | buildPhases = ( 206 | 355894591F8F5DF0000F7DF6 /* Sources */, 207 | 3558945A1F8F5DF0000F7DF6 /* Frameworks */, 208 | 3558945B1F8F5DF0000F7DF6 /* Resources */, 209 | ); 210 | buildRules = ( 211 | ); 212 | dependencies = ( 213 | 3558945F1F8F5DF0000F7DF6 /* PBXTargetDependency */, 214 | ); 215 | name = LYAVPlayerTests; 216 | productName = LYAVPlayerTests; 217 | productReference = 3558945D1F8F5DF0000F7DF6 /* LYAVPlayerTests.xctest */; 218 | productType = "com.apple.product-type.bundle.unit-test"; 219 | }; 220 | 355894671F8F5DF0000F7DF6 /* LYAVPlayerUITests */ = { 221 | isa = PBXNativeTarget; 222 | buildConfigurationList = 355894771F8F5DF0000F7DF6 /* Build configuration list for PBXNativeTarget "LYAVPlayerUITests" */; 223 | buildPhases = ( 224 | 355894641F8F5DF0000F7DF6 /* Sources */, 225 | 355894651F8F5DF0000F7DF6 /* Frameworks */, 226 | 355894661F8F5DF0000F7DF6 /* Resources */, 227 | ); 228 | buildRules = ( 229 | ); 230 | dependencies = ( 231 | 3558946A1F8F5DF0000F7DF6 /* PBXTargetDependency */, 232 | ); 233 | name = LYAVPlayerUITests; 234 | productName = LYAVPlayerUITests; 235 | productReference = 355894681F8F5DF0000F7DF6 /* LYAVPlayerUITests.xctest */; 236 | productType = "com.apple.product-type.bundle.ui-testing"; 237 | }; 238 | /* End PBXNativeTarget section */ 239 | 240 | /* Begin PBXProject section */ 241 | 3558943D1F8F5DF0000F7DF6 /* Project object */ = { 242 | isa = PBXProject; 243 | attributes = { 244 | LastUpgradeCheck = 0900; 245 | ORGANIZATIONNAME = Myself; 246 | TargetAttributes = { 247 | 355894441F8F5DF0000F7DF6 = { 248 | CreatedOnToolsVersion = 9.0; 249 | ProvisioningStyle = Automatic; 250 | SystemCapabilities = { 251 | com.apple.BackgroundModes = { 252 | enabled = 1; 253 | }; 254 | }; 255 | }; 256 | 3558945C1F8F5DF0000F7DF6 = { 257 | CreatedOnToolsVersion = 9.0; 258 | ProvisioningStyle = Automatic; 259 | TestTargetID = 355894441F8F5DF0000F7DF6; 260 | }; 261 | 355894671F8F5DF0000F7DF6 = { 262 | CreatedOnToolsVersion = 9.0; 263 | ProvisioningStyle = Automatic; 264 | TestTargetID = 355894441F8F5DF0000F7DF6; 265 | }; 266 | }; 267 | }; 268 | buildConfigurationList = 355894401F8F5DF0000F7DF6 /* Build configuration list for PBXProject "LYAVPlayer" */; 269 | compatibilityVersion = "Xcode 8.0"; 270 | developmentRegion = en; 271 | hasScannedForEncodings = 0; 272 | knownRegions = ( 273 | en, 274 | Base, 275 | ); 276 | mainGroup = 3558943C1F8F5DF0000F7DF6; 277 | productRefGroup = 355894461F8F5DF0000F7DF6 /* Products */; 278 | projectDirPath = ""; 279 | projectRoot = ""; 280 | targets = ( 281 | 355894441F8F5DF0000F7DF6 /* LYAVPlayer */, 282 | 3558945C1F8F5DF0000F7DF6 /* LYAVPlayerTests */, 283 | 355894671F8F5DF0000F7DF6 /* LYAVPlayerUITests */, 284 | ); 285 | }; 286 | /* End PBXProject section */ 287 | 288 | /* Begin PBXResourcesBuildPhase section */ 289 | 355894431F8F5DF0000F7DF6 /* Resources */ = { 290 | isa = PBXResourcesBuildPhase; 291 | buildActionMask = 2147483647; 292 | files = ( 293 | 355894831F8F5EAD000F7DF6 /* PlayerViewController.storyboard in Resources */, 294 | 355894551F8F5DF0000F7DF6 /* LaunchScreen.storyboard in Resources */, 295 | 355894521F8F5DF0000F7DF6 /* Assets.xcassets in Resources */, 296 | ); 297 | runOnlyForDeploymentPostprocessing = 0; 298 | }; 299 | 3558945B1F8F5DF0000F7DF6 /* Resources */ = { 300 | isa = PBXResourcesBuildPhase; 301 | buildActionMask = 2147483647; 302 | files = ( 303 | ); 304 | runOnlyForDeploymentPostprocessing = 0; 305 | }; 306 | 355894661F8F5DF0000F7DF6 /* Resources */ = { 307 | isa = PBXResourcesBuildPhase; 308 | buildActionMask = 2147483647; 309 | files = ( 310 | ); 311 | runOnlyForDeploymentPostprocessing = 0; 312 | }; 313 | /* End PBXResourcesBuildPhase section */ 314 | 315 | /* Begin PBXSourcesBuildPhase section */ 316 | 355894411F8F5DF0000F7DF6 /* Sources */ = { 317 | isa = PBXSourcesBuildPhase; 318 | buildActionMask = 2147483647; 319 | files = ( 320 | 35B2C19B1F944D55006F31ED /* SecondViewController.m in Sources */, 321 | 3558947D1F8F5E55000F7DF6 /* LYAVPlayerView.m in Sources */, 322 | 355894851F8F5EAD000F7DF6 /* PlayerViewController.m in Sources */, 323 | 355894581F8F5DF0000F7DF6 /* main.m in Sources */, 324 | 355894841F8F5EAD000F7DF6 /* AppDelegate.m in Sources */, 325 | 3501AC821FCE812E00F5C624 /* FirstViewController.m in Sources */, 326 | ); 327 | runOnlyForDeploymentPostprocessing = 0; 328 | }; 329 | 355894591F8F5DF0000F7DF6 /* Sources */ = { 330 | isa = PBXSourcesBuildPhase; 331 | buildActionMask = 2147483647; 332 | files = ( 333 | 355894621F8F5DF0000F7DF6 /* LYAVPlayerTests.m in Sources */, 334 | ); 335 | runOnlyForDeploymentPostprocessing = 0; 336 | }; 337 | 355894641F8F5DF0000F7DF6 /* Sources */ = { 338 | isa = PBXSourcesBuildPhase; 339 | buildActionMask = 2147483647; 340 | files = ( 341 | 3558946D1F8F5DF0000F7DF6 /* LYAVPlayerUITests.m in Sources */, 342 | ); 343 | runOnlyForDeploymentPostprocessing = 0; 344 | }; 345 | /* End PBXSourcesBuildPhase section */ 346 | 347 | /* Begin PBXTargetDependency section */ 348 | 3558945F1F8F5DF0000F7DF6 /* PBXTargetDependency */ = { 349 | isa = PBXTargetDependency; 350 | target = 355894441F8F5DF0000F7DF6 /* LYAVPlayer */; 351 | targetProxy = 3558945E1F8F5DF0000F7DF6 /* PBXContainerItemProxy */; 352 | }; 353 | 3558946A1F8F5DF0000F7DF6 /* PBXTargetDependency */ = { 354 | isa = PBXTargetDependency; 355 | target = 355894441F8F5DF0000F7DF6 /* LYAVPlayer */; 356 | targetProxy = 355894691F8F5DF0000F7DF6 /* PBXContainerItemProxy */; 357 | }; 358 | /* End PBXTargetDependency section */ 359 | 360 | /* Begin PBXVariantGroup section */ 361 | 355894531F8F5DF0000F7DF6 /* LaunchScreen.storyboard */ = { 362 | isa = PBXVariantGroup; 363 | children = ( 364 | 355894541F8F5DF0000F7DF6 /* Base */, 365 | ); 366 | name = LaunchScreen.storyboard; 367 | sourceTree = ""; 368 | }; 369 | /* End PBXVariantGroup section */ 370 | 371 | /* Begin XCBuildConfiguration section */ 372 | 3558946F1F8F5DF0000F7DF6 /* Debug */ = { 373 | isa = XCBuildConfiguration; 374 | buildSettings = { 375 | ALWAYS_SEARCH_USER_PATHS = NO; 376 | CLANG_ANALYZER_NONNULL = YES; 377 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 378 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 379 | CLANG_CXX_LIBRARY = "libc++"; 380 | CLANG_ENABLE_MODULES = YES; 381 | CLANG_ENABLE_OBJC_ARC = YES; 382 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 383 | CLANG_WARN_BOOL_CONVERSION = YES; 384 | CLANG_WARN_COMMA = YES; 385 | CLANG_WARN_CONSTANT_CONVERSION = YES; 386 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 387 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 388 | CLANG_WARN_EMPTY_BODY = YES; 389 | CLANG_WARN_ENUM_CONVERSION = YES; 390 | CLANG_WARN_INFINITE_RECURSION = YES; 391 | CLANG_WARN_INT_CONVERSION = YES; 392 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 393 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 394 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 395 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 396 | CLANG_WARN_STRICT_PROTOTYPES = YES; 397 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 398 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 399 | CLANG_WARN_UNREACHABLE_CODE = YES; 400 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 401 | CODE_SIGN_IDENTITY = "iPhone Developer"; 402 | COPY_PHASE_STRIP = NO; 403 | DEBUG_INFORMATION_FORMAT = dwarf; 404 | ENABLE_STRICT_OBJC_MSGSEND = YES; 405 | ENABLE_TESTABILITY = YES; 406 | GCC_C_LANGUAGE_STANDARD = gnu11; 407 | GCC_DYNAMIC_NO_PIC = NO; 408 | GCC_NO_COMMON_BLOCKS = YES; 409 | GCC_OPTIMIZATION_LEVEL = 0; 410 | GCC_PREPROCESSOR_DEFINITIONS = ( 411 | "DEBUG=1", 412 | "$(inherited)", 413 | ); 414 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 415 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 416 | GCC_WARN_UNDECLARED_SELECTOR = YES; 417 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 418 | GCC_WARN_UNUSED_FUNCTION = YES; 419 | GCC_WARN_UNUSED_VARIABLE = YES; 420 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 421 | MTL_ENABLE_DEBUG_INFO = YES; 422 | ONLY_ACTIVE_ARCH = YES; 423 | SDKROOT = iphoneos; 424 | }; 425 | name = Debug; 426 | }; 427 | 355894701F8F5DF0000F7DF6 /* Release */ = { 428 | isa = XCBuildConfiguration; 429 | buildSettings = { 430 | ALWAYS_SEARCH_USER_PATHS = NO; 431 | CLANG_ANALYZER_NONNULL = YES; 432 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 433 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 434 | CLANG_CXX_LIBRARY = "libc++"; 435 | CLANG_ENABLE_MODULES = YES; 436 | CLANG_ENABLE_OBJC_ARC = YES; 437 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 438 | CLANG_WARN_BOOL_CONVERSION = YES; 439 | CLANG_WARN_COMMA = YES; 440 | CLANG_WARN_CONSTANT_CONVERSION = YES; 441 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 442 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 443 | CLANG_WARN_EMPTY_BODY = YES; 444 | CLANG_WARN_ENUM_CONVERSION = YES; 445 | CLANG_WARN_INFINITE_RECURSION = YES; 446 | CLANG_WARN_INT_CONVERSION = YES; 447 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 448 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 449 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 450 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 451 | CLANG_WARN_STRICT_PROTOTYPES = YES; 452 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 453 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 454 | CLANG_WARN_UNREACHABLE_CODE = YES; 455 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 456 | CODE_SIGN_IDENTITY = "iPhone Developer"; 457 | COPY_PHASE_STRIP = NO; 458 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 459 | ENABLE_NS_ASSERTIONS = NO; 460 | ENABLE_STRICT_OBJC_MSGSEND = YES; 461 | GCC_C_LANGUAGE_STANDARD = gnu11; 462 | GCC_NO_COMMON_BLOCKS = YES; 463 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 464 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 465 | GCC_WARN_UNDECLARED_SELECTOR = YES; 466 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 467 | GCC_WARN_UNUSED_FUNCTION = YES; 468 | GCC_WARN_UNUSED_VARIABLE = YES; 469 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 470 | MTL_ENABLE_DEBUG_INFO = NO; 471 | SDKROOT = iphoneos; 472 | VALIDATE_PRODUCT = YES; 473 | }; 474 | name = Release; 475 | }; 476 | 355894721F8F5DF0000F7DF6 /* Debug */ = { 477 | isa = XCBuildConfiguration; 478 | baseConfigurationReference = E48C30709F50B91F8945C926 /* Pods-LYAVPlayer.debug.xcconfig */; 479 | buildSettings = { 480 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 481 | CODE_SIGN_STYLE = Automatic; 482 | DEVELOPMENT_TEAM = D4Q2DLFEGV; 483 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 484 | GCC_PREFIX_HEADER = "LYAVPlayer/LYAVPlayer-Prefix.pch"; 485 | INFOPLIST_FILE = LYAVPlayer/Info.plist; 486 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 487 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 488 | PRODUCT_BUNDLE_IDENTIFIER = cc.Boke.com.LYAVPlayer; 489 | PRODUCT_NAME = "$(TARGET_NAME)"; 490 | TARGETED_DEVICE_FAMILY = 1; 491 | }; 492 | name = Debug; 493 | }; 494 | 355894731F8F5DF0000F7DF6 /* Release */ = { 495 | isa = XCBuildConfiguration; 496 | baseConfigurationReference = 719F277E04153F456DC6DFAF /* Pods-LYAVPlayer.release.xcconfig */; 497 | buildSettings = { 498 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 499 | CODE_SIGN_STYLE = Automatic; 500 | DEVELOPMENT_TEAM = D4Q2DLFEGV; 501 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 502 | GCC_PREFIX_HEADER = "LYAVPlayer/LYAVPlayer-Prefix.pch"; 503 | INFOPLIST_FILE = LYAVPlayer/Info.plist; 504 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 505 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 506 | PRODUCT_BUNDLE_IDENTIFIER = cc.Boke.com.LYAVPlayer; 507 | PRODUCT_NAME = "$(TARGET_NAME)"; 508 | TARGETED_DEVICE_FAMILY = 1; 509 | }; 510 | name = Release; 511 | }; 512 | 355894751F8F5DF0000F7DF6 /* Debug */ = { 513 | isa = XCBuildConfiguration; 514 | buildSettings = { 515 | BUNDLE_LOADER = "$(TEST_HOST)"; 516 | CODE_SIGN_STYLE = Automatic; 517 | INFOPLIST_FILE = LYAVPlayerTests/Info.plist; 518 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 519 | PRODUCT_BUNDLE_IDENTIFIER = cc.Boke.com.LYAVPlayerTests; 520 | PRODUCT_NAME = "$(TARGET_NAME)"; 521 | TARGETED_DEVICE_FAMILY = "1,2"; 522 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LYAVPlayer.app/LYAVPlayer"; 523 | }; 524 | name = Debug; 525 | }; 526 | 355894761F8F5DF0000F7DF6 /* Release */ = { 527 | isa = XCBuildConfiguration; 528 | buildSettings = { 529 | BUNDLE_LOADER = "$(TEST_HOST)"; 530 | CODE_SIGN_STYLE = Automatic; 531 | INFOPLIST_FILE = LYAVPlayerTests/Info.plist; 532 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 533 | PRODUCT_BUNDLE_IDENTIFIER = cc.Boke.com.LYAVPlayerTests; 534 | PRODUCT_NAME = "$(TARGET_NAME)"; 535 | TARGETED_DEVICE_FAMILY = "1,2"; 536 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/LYAVPlayer.app/LYAVPlayer"; 537 | }; 538 | name = Release; 539 | }; 540 | 355894781F8F5DF0000F7DF6 /* Debug */ = { 541 | isa = XCBuildConfiguration; 542 | buildSettings = { 543 | CODE_SIGN_STYLE = Automatic; 544 | INFOPLIST_FILE = LYAVPlayerUITests/Info.plist; 545 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 546 | PRODUCT_BUNDLE_IDENTIFIER = cc.Boke.com.LYAVPlayerUITests; 547 | PRODUCT_NAME = "$(TARGET_NAME)"; 548 | TARGETED_DEVICE_FAMILY = "1,2"; 549 | TEST_TARGET_NAME = LYAVPlayer; 550 | }; 551 | name = Debug; 552 | }; 553 | 355894791F8F5DF0000F7DF6 /* Release */ = { 554 | isa = XCBuildConfiguration; 555 | buildSettings = { 556 | CODE_SIGN_STYLE = Automatic; 557 | INFOPLIST_FILE = LYAVPlayerUITests/Info.plist; 558 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 559 | PRODUCT_BUNDLE_IDENTIFIER = cc.Boke.com.LYAVPlayerUITests; 560 | PRODUCT_NAME = "$(TARGET_NAME)"; 561 | TARGETED_DEVICE_FAMILY = "1,2"; 562 | TEST_TARGET_NAME = LYAVPlayer; 563 | }; 564 | name = Release; 565 | }; 566 | /* End XCBuildConfiguration section */ 567 | 568 | /* Begin XCConfigurationList section */ 569 | 355894401F8F5DF0000F7DF6 /* Build configuration list for PBXProject "LYAVPlayer" */ = { 570 | isa = XCConfigurationList; 571 | buildConfigurations = ( 572 | 3558946F1F8F5DF0000F7DF6 /* Debug */, 573 | 355894701F8F5DF0000F7DF6 /* Release */, 574 | ); 575 | defaultConfigurationIsVisible = 0; 576 | defaultConfigurationName = Release; 577 | }; 578 | 355894711F8F5DF0000F7DF6 /* Build configuration list for PBXNativeTarget "LYAVPlayer" */ = { 579 | isa = XCConfigurationList; 580 | buildConfigurations = ( 581 | 355894721F8F5DF0000F7DF6 /* Debug */, 582 | 355894731F8F5DF0000F7DF6 /* Release */, 583 | ); 584 | defaultConfigurationIsVisible = 0; 585 | defaultConfigurationName = Release; 586 | }; 587 | 355894741F8F5DF0000F7DF6 /* Build configuration list for PBXNativeTarget "LYAVPlayerTests" */ = { 588 | isa = XCConfigurationList; 589 | buildConfigurations = ( 590 | 355894751F8F5DF0000F7DF6 /* Debug */, 591 | 355894761F8F5DF0000F7DF6 /* Release */, 592 | ); 593 | defaultConfigurationIsVisible = 0; 594 | defaultConfigurationName = Release; 595 | }; 596 | 355894771F8F5DF0000F7DF6 /* Build configuration list for PBXNativeTarget "LYAVPlayerUITests" */ = { 597 | isa = XCConfigurationList; 598 | buildConfigurations = ( 599 | 355894781F8F5DF0000F7DF6 /* Debug */, 600 | 355894791F8F5DF0000F7DF6 /* Release */, 601 | ); 602 | defaultConfigurationIsVisible = 0; 603 | defaultConfigurationName = Release; 604 | }; 605 | /* End XCConfigurationList section */ 606 | }; 607 | rootObject = 3558943D1F8F5DF0000F7DF6 /* Project object */; 608 | } 609 | --------------------------------------------------------------------------------