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