在项目中遇到的一些问题和经验的分享:
先从视频播放说起,视频播放是借助于第三方的demo来做参考,cc视频的一个第三方,不过真心觉得cc视频很坑。建议不要在使用!
然后,做到最后实在是被改的做不下去,自该重新寻找新的方法,进行重新开始,
然后在网上看到了一个KrVideoPlayerController 的这个demo ,是做视频播放的,下载下来看了之后,觉得真的不错。下面来做个分享。。
视频播放器,引用与KrVideoPlayerController的第三方demo
首先在他的 里面是引用了系统的视频播放库 和导入头文件,别的地方也可以直接拿来用。里面可以根据自己的需要进行更改
#import<AVFoundation/AVFoundation.h>
#import “KrVideoPlayerController.h ”
然后他用的是系统的SDK MPMoviePlayerController
里面使用到的有 ---- 观察者模式Observer就是KVO机制,单列模式,代理delegate,通知NSNotificationCenter 等这些。。。
KrVideoPlayerController 他这里面做的不错的是,视图方法 和 执行方法 分的比较清楚,严格使用了MVC模式进
行开发。值得学习!
首先创建视频播放的视图:
这个视图是 MPMoviePlayerController 因为是继承与MPMoviePlayerController的,所有就相当于KrVideoPlayerControlView创建了视频播放控制器
- (KrVideoPlayerControlView *)videoControl
{
if (!_videoControl) {
_videoControl = [[KrVideoPlayerControlView alloc] init];
}
return _videoControl;
}
然后把要展现这个播放器,所以就把他展现出来,显示在我们的View上面,就要在初始化的时候给他加在我们的视图窗口
视图初始化
- (instancetype)initWithFrame:(CGRect)frame
{
//隐藏视频全屏播放的标题栏
self.videoControl.topBar.hidden = YES;
self = [super init];
if (self) {
self.view.frame = frame;
self.view.backgroundColor = [UIColor blackColor];
[[HudWapper shared]HUDShowText:@"视频加载中..."];
self.controlStyle = MPMovieControlStyleNone;
[self.view addSubview:self.videoControl];//加在播放器在view上面
self.videoControl.frame = self.view.bounds;//设置大小
[self configObserver];//创建KVO 观察者对视频做的一个事实观察,执行方法
[self configControlAction];//配置控件的执行方法。。
[self ListeningRotating];//监听设备旋转方向
}
return self;
}
然后在子视图中加载他的子视图,加载所有的控件到View上面显示,他的播放按钮,播放进度条
可根据CGRectGet方法来设置每个按钮的坐标位置
Note【
float float_ = CGRectGetMaxX(CGRect rect);返回矩形右边缘的坐标
CGRectGetMaxY返回矩形底部的坐标
CGRectGetMidX返回矩形中心X的坐标
CGRectGetMidY返回矩形中心Y的坐标
CGRectGetMinX返回矩形左边缘的坐标
CGRectGetMinY返回矩形顶部的坐标】
在视频下载中,自己原本也想引用外部第三方,是WHC开头的第三方,但是那个第三方要的是一个url ,
我们项目中是没有视频url可提供的,提供的视频url 。必须是点击了这个视频才可以获取这个视频的url 。
和项目中的操作步骤 相悖,所有没办法只能去除那个集成好的视频url ,
自己根据项目中的videoid 来操作获取视频下载。。。
具体操作流程是。
1 在加载全部内容列表的时候可以获取视频的全部内容,其中有视频的videoid 这个字段,我可以根据这个字段去下载我对应的视频。
2 在点击下载的时候,需要改变态度,这个当时根据存放数组,还有本地来改,
Note: 遇到问题是(但是如果没下载下来,或者下载后,删除了,这中间就出乱了 ,这个问题当时尤为头疼,最后选择
的办法是创建表
1, 我当时是建立了一个数组,存放视频的videoid ,
2 当你点击下载的时候他就把视频的videoid去数组中取出
3 然后根据这个videoid去下载视频,但是第二次来下载的时候,他还是取的数组的第一个,因为你本地存储后,他读取的时候数组被初始化,所有为空。
4 还有当你在本地存储的时候,他如果读到没有videoid的字段,他也会把这个videoid = nil 给你让你下载,这时候程序自然而然的崩溃
5 所有这个问题,当时试了好多方法,都是保存不到,要么就是为nil指针崩溃
6 最后创建了一张表数据,这三个数据,写了增删改查常用的方法
)
//视频下载中,视频id,视频下载完成三个属性
@property (nonatomic, retain) NSString * downLoad;
@property (nonatomic, retain) NSString * videoID;
@property (nonatomic, retain) NSString * downLoadFinish;
<pre name="code" class="objc">//创建视频下载的状态表 下载中,下载完成,视频ID
[db executeUpdate:@"create table DownLoadList (DownLoading text, DownLoadFinish text ,VideoID text)"];
}];
</pre><p></p><p class="p1"><span class="s1">//</span><span class="s2">插入消息数据(插入数据)</span></p><p class="p2"><span class="s2">-(</span><span class="s3">void</span><span class="s2">)insertDataToUserData:(</span><span class="s4">DownLoadModel</span><span class="s2"> *)user;</span></p><p class="p3"><span class="s2"></span></p><p class="p3"></p><p class="p1"><span class="s1">//</span><span class="s2">搜索用户(查询数据)</span></p><p class="p2"><span class="s2">-(</span><span class="s4">DownLoadModel</span><span class="s2"> *) selectUser:(</span><span class="s5">NSString</span><span class="s2"> *)userID;</span></p><p class="p2"><span class="s2"></span></p><p class="p3"><span class="s2"></span></p><p class="p1"><span class="s1">//</span><span class="s2">删除用户(删除数据)</span></p><p class="p2"><span class="s2">-(</span><span class="s3">void</span><span class="s2">)delegateUserMemberList:(</span><span class="s5">NSString</span><span class="s2"> *)userID;</span></p><p class="p2"><span class="s2"></span></p><p class="p3"><span class="s2"></span></p><p class="p1"><span class="s1">//</span><span class="s2">更新用户信息</span><span class="s1">(</span><span class="s2">修改信息</span><span class="s1">)</span></p><p class="p2"><span class="s2">-(</span><span class="s3">void</span><span class="s2">)updataUserInfor:(</span><span class="s4">DownLoadModel</span><span class="s2"> *)model;</span></p><pre name="code" class="objc">
具体实现自己可以定义自己想要执行的方法
//插入消息数据(插入数据)
//插入用户
-(void)insertDataToUserData:(DownLoadModel *)user
{
[defaultDBManager.databaseQueue inDatabase:^(FMDatabase *db) {
self.database = db;
if (user) {
[db executeUpdate:@"insert into DownLoadList (DownLoading,DownLoadFinish,VideoID) values (?,?,?)" ,user.downLoad,user.downLoadFinish,user.videoID];//playVideo_Time
}
}];
}
//查询状态
-(DownLoadModel *)selectUser:(NSString *)videoID
{
__block DownLoadModel *model=nil;
[defaultDBManager.databaseQueue inDatabase:^(FMDatabase *db) {
self.database = db;
FMResultSet * rs = [db executeQuery:@"select * from DownLoadList where VideoID = ?",videoID];
while([rs next]) {
model = [[DownLoadModel alloc]init];
model.downLoad = [rs stringForColumn:@"DownLoading"];
model.downLoadFinish = [rs stringForColumn:@"DownLoadFinish"];
model.videoID = [rs stringForColumn:@"VideoID"];
}
}];
return model;
}
//删除用户(删除数据)
-(void)delegateUserMemberList:(DownLoadModel *)videoid
{
[defaultDBManager.databaseQueue inDatabase:^(FMDatabase *db) {
self.database = db;
[db executeUpdate:@"delete from DownLoadList where VideoID = ? ",videoid];
}];
}
//更新用户信息(修改信息)
-(void)updataUserInfor:(DownLoadModel *)model
{
[defaultDBManager.databaseQueue inDatabase:^(FMDatabase *db) {
self.database = db;
if (model) {
// 更新用户的信息
[db executeUpdate:@"update DownLoadList set DownLoading = ? where VideoID = ?", model.downLoad,model.videoID];
[db executeUpdate:@"update DownLoadList set DownLoadFinish = ? where VideoID = ?", model.downLoadFinish,model.videoID];
}
}];
}
这个就是控制用户下载,下载中,下载完成这些状态。
在我的项目中,有一个列表的封装,刚开始觉得没什么用,但是现在感觉还是不错的,对分段控制器是一个不错的用法。如果使用分段控制器UISegmentedControl 进行展示列表还是不错的一个封装的。。
#import <UIKit/UIKit.h>
#pragma mark UITableViewDataSource
//- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
typedef NSInteger(^DWTableViewNumberOfRowsInSectionBlock)(UITableView *tableView, NSInteger section);
//- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
typedef UITableViewCell *(^DWTableViewCellForRowAtIndexPathBlock)(UITableView *tableView, NSIndexPath *indexPath);
//typedef id(^DWTableViewCellForRowAtIndexPath_t)(UITableView *tableView, NSIndexPath *indexPath);
//- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
typedef NSInteger (^DWNumberOfSectionsInTableViewBlock)(UITableView * tableView);
@interface DWTableView : UITableView <UITableViewDelegate, UITableViewDataSource>
@property (copy, nonatomic)DWTableViewNumberOfRowsInSectionBlock tableViewNumberOfRowsInSection;
@property (copy, nonatomic)DWTableViewCellForRowAtIndexPathBlock tableViewCellForRowAtIndexPath;
@property (copy, nonatomic)DWTableViewDidSelectRowAtIndexPathBlock tableViewDidSelectRowAtIndexPath;
具体实现的方法也是和使用UITableview的代理方法一样的使用,不过唯一就是自己可以对列表替换方便一点,不至于自己搞混。二个列表来回操作不会出现问题。