国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - IOS - 代碼詳解iOS視頻直播彈幕功能

代碼詳解iOS視頻直播彈幕功能

2021-04-08 17:37自律的自由 IOS

本篇文章通過原理分析和代碼實例講述了實現iOS視頻直播彈幕功能的方法,需要的朋友參考學習下吧。

本篇內容通過步驟詳細給大家講解了ios視頻直播彈幕的原理以及實現代碼分析,以下就是全部內容:

1.彈幕的實現性分析

首先,從視覺上明確當前彈幕所具有的功能

從屏幕右側滑入左側,直至完全消失

不管是長的彈幕,還是短的彈幕,速度一致(可能有的需求是依據彈幕長度,調整速度)

有彈幕軌道,不是隨機產生的彈幕

彈幕不會進行重疊

接下來從功能角度思考需要做什么

重用機制,類似tableview有一個重用池,每個彈幕就是一個cell,當有彈幕發送的時候,如果當前的重用池沒有控件,則創建一個新的控件,如果重用池里面有控件,則拿出這個控件,開始做動畫,在動畫結束后重新將該控件重歸重用池。

速度要求一致的話,需要考慮幾點,首先如下圖所示,紅色代表彈幕起始位置,藍色代表彈幕終止位置,長度代表它們的實際長度。當我們設定動畫的時候,采用[uiview animationwithduration.....]這個動畫,設定duration為3s的話那么彈幕1的速度為(屏幕寬度+彈幕1寬度)/3,彈幕2的速度為(屏幕寬度+彈幕2寬度)/3,因為彈幕2長度大于彈幕1的長度,所以彈幕2的速度大于彈幕1的速度。(對于依據彈幕長度調整速度的需求來說,這里相對簡單一些,不需要專門去計算速度,唯一麻煩的是需要考慮速度不一致帶來的重疊問題)

代碼詳解iOS視頻直播彈幕功能

2.開始準備

精通數學公式v=s/t (v代表速度,s代表路程,t代表時間)(*^__^*) 

3.正式開始

創建一個view,命名為barrageview,以及存儲彈幕數據的對象barragemodel

以下為barragemodel.h的內容,存儲彈幕的頭像,昵稱,和消息內容

?
1
2
3
4
5
6
7
8
@interface barragemodel : nsobject
/** 用戶昵稱 */
@property(nonatomic,copy)nsstring *username;
/** 消息內容 */
@property(nonatomic,copy)nsstring *usermsg;
/** 用戶頭像 */
@property(nonatomic,copy)nsstring *userheadimageurl;
@end

接下來對barrageview內容進行編輯,注釋已經盡可能的詳細,因此不多做介紹

在.h文件中

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#import <uikit/uikit.h>
@class barragemodel;
@interface barrageview : uiview
/**
 * 記錄當前最后一個彈幕view,通過這個view來計算是顯示在哪個彈幕軌道上
 */
@property(nonatomic,retain) uiview *lastanimateview;
/**
 * 發送彈幕
 *
 * @param msgmodel 彈幕數據model
 */
-(void)barragesendmsg:(barragemodel *)msgmodel;
@end

在.m文件中

?
1
#import <uikit/uikit.h><br>@class barragemodel;<br>@interface barrageview : uiview
?
1
/**<br> * 記錄當前最后一個彈幕view,通過這個view來計算是顯示在哪個彈幕軌道上<br> */<br>@property(nonatomic,retain) uiview *lastanimateview;<br>/**<br> * 發送彈幕<br> *<br> * @param msgmodel 彈幕數據model<br> */<br>-(void)barragesendmsg:(barragemodel *)msgmodel;<br>@end<br>在.m文件中<br>#import "barrageview.h"<br>#import "barragemodel.h"<br>//屏幕的尺寸<br>#define screen_frame  [[uiscreen mainscreen] bounds]<br>//屏幕的高度<br>#define screen_height cgrectgetheight(screen_frame)<br>//屏幕的寬度<br>#define screen_width cgrectgetwidth(screen_frame)
?
1
@interface barrageview()<br>{<br>  cgfloat _minspacetime; /** 最小間距時間 */<br>}<br>/** 數據源 */<br>@property (nonatomic,retain)nsmutablearray *dataarr;
?
1
/** 彈幕ui的重用池 */<br>@property (nonatomic,retain)nsmutablearray *resuingarr;<br>@end<br>@implementation barrageview<br>- (instancetype)initwithframe:(cgrect)frame<br>{<br>  self = [super initwithframe:frame];<br>  if (self) {<br>    [self setinterface];<br>  }<br>  return self;<br>}<br>-(void)setinterface<br>{<br>  //初始化彈幕數據源,以及重用池<br>  self.dataarr = [nsmutablearray array];<br>  self.resuingarr = [nsmutablearray array];<br>  //創建第一個彈幕加入重用池作為備用<br>  uiview *view = [self createui];<br>  [self.resuingarr addobject:view];<br>  //設置彈幕數據的初始輪詢時間<br>  _minspacetime = 1;<br>  //檢查是否可以取彈幕數據進行動畫<br>  [self checkstartanimatiom];<br>}<br>-(void)checkstartanimatiom<br>{<br>  //當有數據信息的時候<br>  if (self.dataarr.count>0) {<br>    if (self.resuingarr.count>0) { //當重用池里面有備用的彈幕ui時<br>      <br>      //在重用池中,取出第一個彈幕ui<br>      uiview *view = [self.resuingarr firstobject];<br>      [self.resuingarr removeobject:view];<br>      //取出的這個彈幕ui開始動畫<br>      [self startanimationwithview:view];<br>      <br>    }else{ //當重用池沒有備用的彈幕ui時<br>      <br>      //重新創建一個彈幕ui<br>      uiview *view = [self createui];<br>      //拿著這個彈幕ui開始動畫<br>      [self startanimationwithview:view];<br>    }<br>  }<br>  //延遲執行,在主線程中不能調用sleep()進行延遲執行<br>  //調用自身方法,構成一個無限循環,不停的輪詢檢查是否有彈幕數據<br>  dispatch_after(dispatch_time(dispatch_time_now, (int64_t)(_minspacetime * nsec_per_sec)), dispatch_get_main_queue(), ^{<br>    [self checkstartanimatiom];<br>  });<br>}<br>-(void)startanimationwithview:(uiview *)view<br>{<br>  //取出第一條數據<br>  barragemodel *barragemodel = [self.dataarr firstobject];<br>  //計算昵稱的長度<br>  cgsize namesize = [barragemodel.username boundingrectwithsize:cgsizemake(cgfloat_max, 14) options:nsstringdrawinguseslinefragmentorigin|nsstringdrawingusesfontleading attributes:@{                                                                         } context:nil].size;<br>  //計算消息的長度<br>  cgsize msgsize = [barragemodel.usermsg boundingrectwithsize:cgsizemake(cgfloat_max, 14) options:nsstringdrawinguseslinefragmentorigin|nsstringdrawingusesfontleading attributes:@{                                                               nsfontattributename:[uifont systemfontofsize:14]<br>} context:nil].size; <br>  uiimageview *headimageview; //頭像<br>  uilabel *usernamelabel;   //昵稱<br>  uilabel *usermsglabel;   //消息內容<br>  //進行賦值,寬度適應<br>  for (uiview *subview in view.subviews) {<br>    if (subview.tag == 1000) {<br>      headimageview = (uiimageview *)subview;<br>      headimageview.image = [uiimage imagenamed:@""];<br>      <br>    }else if (subview.tag == 1001){<br>      usernamelabel = (uilabel *)subview;<br>      usernamelabel.text = barragemodel.username;<br>      //重新設置名稱label寬度<br>      cgrect namerect = usernamelabel.frame;<br>      namerect.size.width = namesize.width;<br>      usernamelabel.frame = namerect;<br>    }else{<br>      usermsglabel = (uilabel *)subview;<br>      usermsglabel.text = barragemodel.usermsg;<br>      //重新設置消息內容label寬度<br>      cgrect msgrect = usermsglabel.frame;<br>      msgrect.size.width = msgsize.width;<br>      usermsglabel.frame = msgrect;<br>    }<br>  }<br>  //重新設置彈幕的總體寬度 = 頭像寬度 + 頭像左右兩側距離 + (如果名字寬度大于消息內容寬度,以名字寬度為基準,如果名字寬度小于消息內容寬度,以消息內容寬度為基準)<br>  view.frame = cgrectmake(screen_width, 0, cgrectgetwidth(headimageview.frame) + 4 + (cgrectgetwidth(usernamelabel.frame)>cgrectgetwidth(usermsglabel.frame)?cgrectgetwidth(usernamelabel.frame):cgrectgetwidth(usermsglabel.frame)), cgrectgetheight(self.frame));<br>  //不管彈幕長短,速度要求一致。 v(速度) 為固定值 = 100(可根據實際自己調整)<br>  // s = 屏幕寬度+彈幕的寬度 v = 100(可根據實際自己調整)<br>  // v(速度) = s(路程)/t(時間) -------> t(時間) = s(路程)/v(速度);<br>  cgfloat duration = (view.frame.size.width+screen_width)/100;<br>  //最小間距運行時間為:彈幕從屏幕外完全移入屏幕內的時間 + 間距的時間<br>  _minspacetime = (view.frame.size.width + 30)/100;<br>  //最后做動畫的view<br>  _lastanimateview = view;  <br>  //彈幕ui開始動畫<br>  [uiview animatewithduration:duration delay:0 options:uiviewanimationoptioncurvelinear animations:^{<br>    //運行至左側屏幕外<br>    cgrect frame = view.frame;<br>    view.frame = cgrectmake(-frame.size.width, 0, frame.size.width, frame.size.height);<br>  } completion:^(bool finished) {<br>    //動畫結束重新回到右側初始位置<br>    view.frame = cgrectmake(screen_width, 0, 0, cgrectgetheight(self.frame));<br>    //重新加入重用池<br>    [self.resuingarr addobject:view];<br>  }];  <br>  //將這個彈幕數據移除<br>  [self.dataarr removeobject:barragemodel];<br>}<br>#pragma mark public method<br>-(void)barragesendmsg:(barragemodel *)msgmodel{<br>  //添加彈幕數據<br>  [self.dataarr addobject:msgmodel];<br>}<br>#pragma mark 創建控件<br>-(uiview *)createui<br>{<br>  uiview *view = [[uiview alloc] initwithframe:cgrectmake(screen_width, 0, 0, cgrectgetheight(self.frame))];<br>  view.backgroundcolor = [uicolor colorwithwhite:0 alpha:0.3];<br>  uiimageview *headimageview = [[uiimageview alloc] initwithframe:cgrectmake(2, 2, cgrectgetheight(self.frame)-4, cgrectgetheight(self.frame)-4)];<br>  headimageview.layer.cornerradius = headimageview.frame.size.width/2;<br>  headimageview.layer.maskstobounds = yes;<br>  headimageview.tag = 1000;<br>  headimageview.backgroundcolor = [uicolor redcolor];<br>  [view addsubview:headimageview];<br>  uilabel *usernamelabel = [[uilabel alloc] initwithframe:cgrectmake(cgrectgetmaxx(headimageview.frame) + 2, 0, 0,14)];<br>  usernamelabel.font = [uifont systemfontofsize:14];<br>  usernamelabel.tag = 1001;<br>  [view addsubview:usernamelabel];<br>  uilabel *usermsglabel = [[uilabel alloc] initwithframe:cgrectmake(cgrectgetmaxx(headimageview.frame)+2, cgrectgetmaxy(usernamelabel.frame), 0, 14)];<br>  usermsglabel.font = [uifont systemfontofsize:14];<br>  usermsglabel.tag = 1002;<br>  [view addsubview:usermsglabel];<br>  [self addsubview:view];<br>  return view;<br>}<br>

最后在vc里面

?
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#import "viewcontroller.h"
#import "barrageview.h"
#import "barragemodel.h"
//屏幕的尺寸
#define screen_frame [[uiscreen mainscreen] bounds]
//屏幕的高度
#define screen_height cgrectgetheight(screen_frame)
//屏幕的寬度
#define screen_width cgrectgetwidth(screen_frame)
@interface viewcontroller ()
/** 第一個彈幕軌道 */
@property (nonatomic,retain)barrageview *barrageviewone;
/** 第二個彈幕軌道 */
@property (nonatomic,retain)barrageview *barrageviewtwo;
@end
@implementation viewcontroller
- (void)viewdidload {
 [super viewdidload];
 //創建第一個彈幕軌道
 _barrageviewone = [[barrageview alloc]initwithframe:cgrectmake(0,200, screen_width, 34)];
 [self.view addsubview:_barrageviewone];
 //創建第二個彈幕軌道
 _barrageviewtwo = [[barrageview alloc]initwithframe:cgrectmake(0,300, screen_width, 34)];
 [self.view addsubview:_barrageviewtwo];
}
-(void)touchesbegan:(nsset<uitouch *> *)touches withevent:(uievent *)event
{
 nstimer *timer = [nstimer scheduledtimerwithtimeinterval:1 target:self selector:@selector(sendmessage) userinfo:nil repeats:yes];
 [timer fire];
}
-(void)sendmessage
{
 barragemodel *model = [[barragemodel alloc]init];
 model.username = @[@"張三",@"李四",@"王五",@"趙六",@"七七",@"八八",@"九九",@"十十",@"十一",@"十二",@"十三",@"十四"][arc4random()%12];
 model.usermsg = @[@"阿達個人",@"都是vsqe12qwe",@"勝多負少的凡人歌",@"委屈翁二群二",@"12312",@"熱帖柔荑花",@"發彼此彼此",@"ok潑墨",@"人體有圖圖",@"額外熱無若無",@"微軟將圍"][arc4random()%11];
 //計算當前做動畫的彈幕ui的位置
 cgfloat onepositon = _barrageviewone.lastanimateview.layer.presentationlayer.frame.size.width + _barrageviewone.lastanimateview.layer.presentationlayer.frame.origin.x;
 //計算當前做動畫的彈幕ui的位置
 cgfloat twopositon = _barrageviewtwo.lastanimateview.layer.presentationlayer.frame.size.width + _barrageviewtwo.lastanimateview.layer.presentationlayer.frame.origin.x;
 if ( onepositon < twopositon ) {
 [_barrageviewone barragesendmsg:model];
 }else{
 [_barrageviewtwo barragesendmsg:model];
 }
}
@end

4.測試結論

經一個小時的定時器測試,內存沒有增加。

原文鏈接:http://www.cnblogs.com/ChengYing-Freedom/p/8025210.html

延伸 · 閱讀

精彩推薦
  • IOSiOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果

    iOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果

    這篇文章主要介紹了iOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果的相關資料,需要的朋友可以參考下...

    jiangamh8882021-01-11
  • IOSiOS實現控制屏幕常亮不變暗的方法示例

    iOS實現控制屏幕常亮不變暗的方法示例

    最近在工作中遇到了要將iOS屏幕保持常亮的需求,所以下面這篇文章主要給大家介紹了關于利用iOS如何實現控制屏幕常亮不變暗的方法,文中給出了詳細的...

    隨風13332021-04-02
  • IOSiOS開發之視圖切換

    iOS開發之視圖切換

    在iOS開發中視圖的切換是很頻繁的,獨立的視圖應用在實際開發過程中并不常見,除非你的應用足夠簡單。在iOS開發中常用的視圖切換有三種,今天我們將...

    執著丶執念5282021-01-16
  • IOS詳解iOS中多個網絡請求的同步問題總結

    詳解iOS中多個網絡請求的同步問題總結

    這篇文章主要介紹了詳解iOS中多個網絡請求的同步問題總結,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧...

    liang199111312021-03-15
  • IOSiOS中MD5加密算法的介紹和使用

    iOS中MD5加密算法的介紹和使用

    MD5加密是最常用的加密方法之一,是從一段字符串中通過相應特征生成一段32位的數字字母混合碼。對輸入信息生成唯一的128位散列值(32個字符)。這篇文...

    LYSNote5432021-02-04
  • IOSiOS中UILabel實現長按復制功能實例代碼

    iOS中UILabel實現長按復制功能實例代碼

    在iOS開發過程中,有時候會用到UILabel展示的內容,那么就設計到點擊UILabel復制它上面展示的內容的功能,也就是Label長按復制功能,下面這篇文章主要給大...

    devilx12792021-04-02
  • IOSiOS開發技巧之狀態欄字體顏色的設置方法

    iOS開發技巧之狀態欄字體顏色的設置方法

    有時候我們需要根據不同的背景修改狀態欄字體的顏色,下面這篇文章主要給大家介紹了關于iOS開發技巧之狀態欄字體顏色的設置方法,文中通過示例代碼...

    夢想家-mxj8922021-05-10
  • IOSiOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和Masonry簡單使用)

    iOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和

    這篇文章主要介紹了iOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和Masonry簡單使用)的相關資料,需要的朋友可以參考下...

    CodingFire13652021-02-26
主站蜘蛛池模板: 天天操天天添 | 亚洲一二三| 91精品国产综合久久小仙女陆萱萱 | 欧美日韩中 | sese综合| 久久av资源 | 蜜臀精品久久久久久蜜臀 | 免费黄色在线 | 欧美在线一区二区 | 欧美久| 黄色免费在线观看网址 | 91精品国产乱码久久久久久久久 | 日本视频免费高清一本18 | 毛片一级av | 精品成人免费 | 国产一区二区高清在线 | 国产高清在线观看 | 欧美a网 | 日韩色在线 | 欧美永久精品 | 午夜男人天堂 | 国产一区自拍视频 | 北条麻妃一区二区免费播放 | 成人av免费在线 | 日韩超碰| 国产精品久久久久久久久免费高清 | 国色天香成人网 | 91精品国产综合久久久久久 | 色婷婷综合久久久中字幕精品久久 | 中文字幕一区在线观看视频 | 午夜视频在线观看网站 | 日韩福利影院 | 在线免费观看黄色 | 一区二区av| 中文字幕免费播放 | 99re在线| 亚洲精品麻豆 | 久久九九| 免费成人在线网站 | 18.wxww.成人性视频高清 | 亚洲综合无码一区二区 |