코드 상세 iOS 영상 생방송 탄막 기능
1.탄막 의 실현 성 분석
우선,시각 적 으로 현재 탄막 이 가지 고 있 는 기능 을 명 확 히 한다.
화면 오른쪽 에서 왼쪽으로 미끄러져 완전히 사라 질 때 까지
긴 탄막 이 든 짧 은 탄막 이 든 속도 가 일치 합 니 다.
탄막 궤도 가 있 는 것 은 무 작위 로 발생 하 는 탄막 이 아니다.
탄막 은 겹 치지 않 는 다.
다음은 무엇 을 해 야 할 지 기능 적 으로 생각 하 겠 습 니 다.
재 활용 메커니즘 은 table View 와 같은 재 활용 탱크 가 있 습 니 다.모든 탄막 은 cell 입 니 다.탄막 이 있 을 때 현재 재 활용 탱크 에 컨트롤 이 없 으 면 새로운 컨트롤 을 만 듭 니 다.재 활용 탱크 에 컨트롤 이 있 으 면 이 컨트롤 을 꺼 내 애니메이션 을 시작 합 니 다.애니메이션 이 끝 난 후에 이 컨트롤 을 다시 재 활용 탱크 로 돌아 갑 니 다.
속도 가 일치 해 야 한다 면 몇 가 지 를 고려 해 야 한다.먼저 다음 그림 에서 보 듯 이 빨간색 은 탄막 의 시작 위 치 를 대표 하고 파란색 은 탄막 의 종료 위 치 를 대표 하 며 길 이 는 그들의 실제 길 이 를 대표 한다.애니메이션 을 설정 할 때[UIView animation With Duration...]이 애니메이션 을 사용 합 니 다.duration 을 3s 로 설정 하면 스크린 1 의 속 도 는(스크린 너비+스크린 1 너비)/3 이 고,스크린 2 의 속 도 는(스크린 너비+스크린 2 너비)/3 입 니 다.스크린 2 의 길이 가 스크린 1 의 길이 보다 크기 때문에 스크린 2 의 속 도 는 스크린 1 의 속도 보다 큽 니 다.(탄막 길이 에 따라 속 도 를 조절 하 는 수요 에 있어 서 여 기 는 상대 적 으로 간단 하 다.속 도 를 전문 적 으로 계산 할 필요 가 없다.유일 하 게 번 거 로 운 것 은 속도 불일치 로 인 한 중첩 문 제 를 고려 해 야 한다)
2.준비 시작
수학 공식 에 정통 하 다 V=S/t (V 는 속 도 를 나타 내 고 S 는 거 리 를 나타 내 며 t 는 시간 을 나타 낸다)(*^ ^*)
3.본 격 적 인 시작
BarrageView 라 는 이름 의 View 를 만 들 고 탄막 데 이 터 를 저장 하 는 대상 BarrageModel
다음은 Barrage Model.h 의 내용 으로 탄막 의 프로필 사진,닉네임,메시지 내용 을 저장 합 니 다.
@interface BarrageModel : NSObject
/** */
@property(nonatomic,copy)NSString *userName;
/** */
@property(nonatomic,copy)NSString *userMsg;
/** */
@property(nonatomic,copy)NSString *userHeadImageUrl;
@end
다음은 BarrageView 내용 을 편집 하고 주석 은 가능 한 한 상세 하기 때문에 소 개 를 많이 하지 않 습 니 다.파일
#import <UIKit/UIKit.h>
@class BarrageModel;
@interface BarrageView : UIView
/**
* View, View
*/
@property(nonatomic,retain) UIView *lastAnimateView;
/**
*
*
* @param msgModel Model
*/
-(void)barrageSendMsg:(BarrageModel *)msgModel;
@end
파일
#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
#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 BarrageView()
{
CGFloat _minSpaceTime; /** */
}
/** */
@property (nonatomic,retain)NSMutableArray *dataArr;
/** UI */
@property (nonatomic,retain)NSMutableArray *resuingArr;
@end
@implementation BarrageView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setInterface];
}
return self;
}
-(void)setInterface
{
// ,
self.dataArr = [NSMutableArray array];
self.resuingArr = [NSMutableArray array];
//
UIView *view = [self createUI];
[self.resuingArr addObject:view];
//
_minSpaceTime = 1;
//
[self checkStartAnimatiom];
}
-(void)checkStartAnimatiom
{
//
if (self.dataArr.count>0) {
if (self.resuingArr.count>0) { // UI
// , UI
UIView *view = [self.resuingArr firstObject];
[self.resuingArr removeObject:view];
// UI
[self startAnimationWithView:view];
}else{ // UI
// UI
UIView *view = [self createUI];
// UI
[self startAnimationWithView:view];
}
}
// , sleep()
// , ,
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_minSpaceTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self checkStartAnimatiom];
});
}
-(void)startAnimationWithView:(UIView *)view
{
//
BarrageModel *barrageModel = [self.dataArr firstObject];
//
CGSize nameSize = [barrageModel.userName boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, 14) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{ } context:nil].size;
//
CGSize msgSize = [barrageModel.userMsg boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, 14) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{ NSFontAttributeName:[UIFont systemFontOfSize:14]
} context:nil].size;
UIImageView *headImageView; //
UILabel *userNameLabel; //
UILabel *userMsgLabel; //
// ,
for (UIView *subView in view.subviews) {
if (subView.tag == 1000) {
headImageView = (UIImageView *)subView;
headImageView.image = [UIImage imageNamed:@""];
}else if (subView.tag == 1001){
userNameLabel = (UILabel *)subView;
userNameLabel.text = barrageModel.userName;
// Label
CGRect nameRect = userNameLabel.frame;
nameRect.size.width = nameSize.width;
userNameLabel.frame = nameRect;
}else{
userMsgLabel = (UILabel *)subView;
userMsgLabel.text = barrageModel.userMsg;
// Label
CGRect msgRect = userMsgLabel.frame;
msgRect.size.width = msgSize.width;
userMsgLabel.frame = msgRect;
}
}
// = + + ( , , , )
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));
// , 。 V( ) = 100( )
// S = + V = 100( )
// V( ) = S( )/t( ) -------> t( ) = S( )/V( );
CGFloat duration = (view.frame.size.width+SCREEN_WIDTH)/100;
// : +
_minSpaceTime = (view.frame.size.width + 30)/100;
// view
_lastAnimateView = view;
// UI
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
//
CGRect frame = view.frame;
view.frame = CGRectMake(-frame.size.width, 0, frame.size.width, frame.size.height);
} completion:^(BOOL finished) {
//
view.frame = CGRectMake(SCREEN_WIDTH, 0, 0, CGRectGetHeight(self.frame));
//
[self.resuingArr addObject:view];
}];
//
[self.dataArr removeObject:barrageModel];
}
#pragma mark public method
-(void)barrageSendMsg:(BarrageModel *)msgModel{
//
[self.dataArr addObject:msgModel];
}
#pragma mark
-(UIView *)createUI
{
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(SCREEN_WIDTH, 0, 0, CGRectGetHeight(self.frame))];
view.backgroundColor = [UIColor colorWithWhite:0 alpha:0.3];
UIImageView *headImageView = [[UIImageView alloc] initWithFrame:CGRectMake(2, 2, CGRectGetHeight(self.frame)-4, CGRectGetHeight(self.frame)-4)];
headImageView.layer.cornerRadius = headImageView.frame.size.width/2;
headImageView.layer.masksToBounds = YES;
headImageView.tag = 1000;
headImageView.backgroundColor = [UIColor redColor];
[view addSubview:headImageView];
UILabel *userNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(headImageView.frame) + 2, 0, 0,14)];
userNameLabel.font = [UIFont systemFontOfSize:14];
userNameLabel.tag = 1001;
[view addSubview:userNameLabel];
UILabel *userMsgLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(headImageView.frame)+2, CGRectGetMaxY(userNameLabel.frame), 0, 14)];
userMsgLabel.font = [UIFont systemFontOfSize:14];
userMsgLabel.tag = 1002;
[view addSubview:userMsgLabel];
[self addSubview:view];
return view;
}
마지막 으로 vc 에서.
#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.테스트 결론한 시간의 타이머 테스트 를 통 해 메모리 가 증가 하지 않 았 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
View의 레이아웃 방법을 AutoLayout에서 따뜻한 손 계산으로 하면 성능이 9.26배로 된 이야기이 기사는 의 15 일째 기사입니다. 어제는 에서 이었습니다. 손 계산을 권하는 의도는 없고, 특수한 상황하에서 계측한 내용입니다 화면 높이의 10 배 정도의 contentView가있는 UIScrollView 레이아...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.