0%

概述

  • 直播的现状

    • 2016年,是一个直播年。直播行业快速发展,同时也滋生了大大小小上千家相关的公司。
    • 中国互联网络信息中心发布的报告显示,截至今年6月,我国网络直播用户规模达到3.25亿,占网民总体的45.8%。
  • 直播的技术

    • 直播技术概况来说,可以分为 采集,前处理,编码,传输,解码,渲染 这几个环节

      技术整体概览

  • 图例:
    技术整体总结.png

Read more »

粒子系统介绍

  • 什么是粒子系统?
    • 粒子系统是由总体具有相同的表现规律,个体却随机表现出不同的特征的大量显示元素构成的集合。
  • 粒子定义有三要素
    • 群体性:粒子系统是由“大量显示元素”构成的(例如雪、雨、一团雾等等)
    • 统一性:粒子系统的每个元素具有相同的表现规律(例如下雨、下雪,方向都是从上向下)
    • 随机性:粒子系统的每个元素又随机表现出不同特征(例如下雪,每个雪花下落的速度会有不同,大小会有不同、方向也会有略微的不同)

粒子系统应用场景

  • 影视行业
    • 目前我们经常看的大片,比如沙尘暴、暴风雨、暴雪、烟花 等等,很多都是粒子特效做出来的。很逼真,而且相比真实世界中去实拍,成本要低很多
  • 游戏中
    • 爆炸、雨、雪、雾、烟花等等。都是粒子系统实现
  • 应用中
    • 主播房间右下角粒子动画
    • 雪花/下雨/烟花等效果
    • QQ生日快乐一堆表情的跳动

iOS粒子动画的使用

  • 步骤
    • 创建发射器
    • 创建粒子, 设置粒子属性
  • swift核心代码
    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
    47
    48
    49
    50
    51
    // 1.创建发射器
    let emitter = CAEmitterLayer()

    // 2.设置发射器的位置
    emitter.emitterPosition = point

    // 3.开启三维效果
    emitter.preservesDepth = true

    // 4.创建例子, 并且设置例子相关的属性
    var cells = [CAEmitterCell]()
    for i in 0..<10 {
    // 4.1.创建例子Cell
    let cell = CAEmitterCell()

    // 4.2.设置粒子速度
    cell.velocity = 150
    cell.velocityRange = 100

    // 4.3.设置例子的大小
    cell.scale = 0.7
    cell.scaleRange = 0.3

    // 4.4.设置粒子方向
    cell.emissionLongitude = CGFloat(-Double.pi/2)
    cell.emissionRange = CGFloat(Double.pi/2 / 6)

    // 4.5.设置例子的存活时间
    cell.lifetime = 3
    cell.lifetimeRange = 1.5

    // 4.6.设置粒子旋转
    cell.spin = CGFloat(Double.pi/2)
    cell.spinRange = CGFloat(Double.pi/2 / 2)

    // 4.6.设置例子每秒弹出的个数
    cell.birthRate = 2

    // 4.7.设置粒子展示的图片
    cell.contents = UIImage(named: "good\(i)_30x30")?.cgImage

    // 4.8.添加到数组中
    cells.append(cell)
    }

    // 5.将粒子设置到发射器中
    emitter.emitterCells = cells

    // 6.将发射器的layer添加到父layer中
    view.layer.addSublayer(emitter)

粒子动画效果展示

粒子动画.gif

源码

GitHub地址:ParticleAnimationDemo

前言

C++与Objective-C都是在1980+年代诞生,所以语法糖上面都有很多相似地方,学起来并不难。至于我用的IDE,我直接用的是Xcode,很方便。

国际惯例,打印hello world

1
cout << "hello world" << endl;

这里介绍几个关键词:

cout 输出
cin 输入
endl 换行打印

cout 语法形式:

1
2
cout << x << endl;
cout << "x + y =" << x+y << endl;

cin 语法形式:

1
2
cin >> x;
cin >> x >> y;

这样的输入、输出方式有哪些便利?
1、不用关注占位符
2、不用关注数据类型
3、不易出现问题

C++命名空间(namespace)

在C++中,名称(name)可以是符号常量、变量、宏、函数、结构、枚举、类和对象等等。为了避免,在大规模程序的设计中,以及在程序员使用各种各样的C++库时,这些标识符的命名发生冲突,标准C++引入了关键字namespace(命名空间/名字空间/名称空间/名域),可以更好地控制标识符的作用域。

举个例子:同个年级有相同名字的同学,那样为了避免认错人,我们可以把他们分到不同班级里,这样就区分开来了。这里的班级就可以称为命名空间。

关于命名空间描述几点

1、使用namespace定义命名空间。
2、通过命名空间可以区分具有相同名字的变量。
3、通过命名空间可以区分具有相同名字的函数。

代码示例:

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
#include <iostream>
#include <stdlib.h>
using namespace std;
namespace myNum //填写命名空间的关键字
{
int x = 105;
}
int main()
{
// 使用bool类型定义isOdd,作为状态位
bool isFlag = false;

if(myNum::x % 2 == 0)
{
//改变状态位的值,使其为false
isFlag = false;
}
else
{
//改变状态位的值,使其为true
isFlag = true;
}
// 判断状态位的值
if(isFlag)
{
// 如果状态位的值为true,则打印变量x是奇数
cout << x是奇数 ;
}
else
{
// 如果状态位的值为false,则打印变量x是偶数
cout << x是偶数 ;
}
return 0;
}

C++ 引用

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;
int main(void)
{
int x = 3;
//定义引用,y是x的引用
int &y = x;
//打印x和y的值
cout << x << endl;
cout << y <<endl;
//修改y的值
y = 100;
//再次打印x和y的值
cout << x << endl;
cout << y <<endl;
return 0;
}

C++ const关键字

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//const
#include <iostream>
using namespace std;
int main(void)
{
//定义常量count
const int count = 3;
const int *p = &count;
//打印count次字符串Hello C++
for(int i = 0; i < count; i++)
{
cout << "Hello C++" << endl;
}
return 0;
}

C++函数新亮点

函数参数默认值
1
void fun( int i,int j=5,int k=10 );//有默认参数值的参数必须在参数表的最右端
函数重载

在相同作用域内
用同一个函数名定义的多个函数
参数个数和参数类型不同

内联函数

编译时将函数体代码和实参代替函数调用语句
内联函数关键字:inline

关于C++函数形参默认值的说法

1、当函数有多个形参时,可以都有默认值。
2、当函数有多个形参时,可以都没有默认值。
3、当函数有多个形参且都有默认值时,实参个数可以少于形参个数。

代码示例:

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
#include <iostream>
using namespace std;
/**
*函数功能:返回a和b的最大值
*a和b是两个整数
*/
int getMax(int a, int b)
{
return a > b ? a : b;
}

/**
* 函数功能:返回数组中的最大值
* arr:整型数组
* count:数组长度
* 该函数是对上面函数的重载
*/
int getMax(int *arr,int count)
{
//定义一个变量并获取数组的第一个元素
int maxNum = arr[0];
for(int i = 1; i < count; i++)
{
//比较变量与下一个元素的大小
if(maxNum < arr[i])
{
//如果数组中的元素比maxNum大,则获取数组中的值
maxNum = arr[i];
}
}
return maxNum;
}

int main(void)
{
//定义int数组并初始化
int numArr[3] = {3, 8, 6};

//自动调用int getMax(int a, int b)
cout << getMax(numArr, 3) << endl;

//自动调用返回数组中最大值的函数返回数组中的最大值
cout << getMax(numArr[0], numArr[2]) << endl;
return 0;
}

C++内存管理

什么是内存管理?

内存的本质是资源
操作系统掌管内存资源
对于我们开发者,我们能手动申请与归还
申请/归还内存资源就是内存管理

如图:

img

1A160E69-BD72-4B65-983B-AE17F12E7A9B.png

img

C8FEF922-5C3C-4AF6-9CD6-67F01BED98A5.png

内容总结
使用new申请内存,使用delete释放内存
申请内存需要判断是否成功,释放内存需要设空指针
new与delete配套使用

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <string.h>
#include <iostream>
using namespace std;
int main(void)
{
//在堆中申请100个char类型的内存
char *str = new char[100];
//拷贝Hello C++字符串到分配的堆中的内存中
strcpy(str, "Hello imooc");
//打印字符串
cout << str << endl;
//释放内存
delete []str;
str = NULL;
return 0;
}

前言

开发项目的时候,常常会有一些代码重复而且冗余,在用的时候需要写很长的代码或者用的地方也多,所以这个时候就需要集中起来封装,使代码复用性强,用短短的几行代码搞定。这些方法我都封装在category、tools、View,加上代码里都有写注释,用起来很方便,实用性强,读起来也易懂,可以让代码更加的简洁。里面有一些也是参考别人源码,也做了下搬运工,希望对你们开发项目有所帮助。

简介

WTSDK

WTSDK目录
看目录结构就觉得清晰易懂,反正我是这么觉得的☺️

Category(分类)

Category

NS(NS前缀的分类)

NS

UI(UI前缀的分类)

UI
class名称,它们都是对应对象的分类方法,里面扩展了很多实用性的功能,具体可以看源码。

Tool(工具类集合)

Tool
Singleton是一个单例模式的宏使用方法:
.h里写上singleton_interface(类名称).m里写上singleton_implementation(类名称)即完美支持MRC和ARC下的单例使用。
WTConst里面包括很多实用性很强的宏定义,具体看源码。
WTUtility里面定义了很多实用性很强的类方法,具体看源码。

View(UITextField与UITextView)

View
View文件夹里包括UITextFieldUITextView原生控件的封装。我一直觉得这两个原生控件每次用的时候都要加入好多的判断与代理方法,而且都是差不多一样的,所以我就针对这两个进行了封装,把常用的功能都集合在里面,比如限制文字输入长度等等,这样使用起来更加的方便和简洁。具体可以看下源码。

使用方法

你可以看下WTSDK里面有啥需要的,单独拉某个文件到你的项目里使用即可。
如果你都要使用的话,直接导入#import "WTConst.h"即可。
注意如果用到UIViewController+WT还需要项目里有MBProgressHUD这个库。

####源码在这
GitHub 如果你觉得不错的话,麻烦你点一下Star,thank you all!

前言

这一段时间比较忙,主要公司的产品需要重构与加多一个货币支付系统。说到移动端的支付,自然会牵扯到支付这一块。支付这一块主流的目前就微信、支付宝、银联。做过这些SDK集成的开发者都知道,集成相对复杂,而且要花大量的时间去阅读他们提供的开发文档,不过还好现在有很多开发者都分享了他们的集成心得,使这件事越发简单,比如:iOS支付[支付宝、银联、微信]10分钟搞定支付宝和微信支付 的 各种填坑等等,但是呢,其实还有更加简单的,Ping++

Read more »

前言

现在你准备用一个系统的类或者是你写的类,但是这个类并不能满足你的需求,你需要额外添加一个属性。
一般解决办法要么是 extends(继承),要么使用 category(类别)
而我并不推荐使用 extends ,主要是耦合性太强,一般我使用 category
我们都知道,分类中是无法设置属性的,如果在分类的声明中写@property 只能为其生成getset 方法的声明,
但是有时候使用类别也需要增加一个额外属性,
那么怎么办呢?
这个时候,runtime的关联属性就能发挥它的作用了。
一般都是key value 的存在。

Read more »

前言

记录一些代码小技巧持续更新!

Xcode12模板位置:
1
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/File Templates/iOS/Source/Cocoa Touch Class.xctemplate
Objective-C tips

1、使控件从导航栏以下开始

1
self.edgesForExtendedLayout=UIRectEdgeNone;

2、将navigation返回按钮文字position设置不在屏幕上显示

1
[[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(NSIntegerMin, NSIntegerMin) forBarMetrics:UIBarMetricsDefault];

3、解决ScrollView等在viewController无法滚动到最顶部

1
2
//自动滚动调整,默认为YES
self.automaticallyAdjustsScrollViewInsets = NO;
Read more »

1.使用UIWebView播放

1
2
3
4
5
6
7
8
9
10
#pragma clang diagnostic ignored "-Wnonnull"
NSString *path = [[NSBundle mainBundle] pathForResource:@"<#gifName#>" ofType:@"gif"];
NSData *gifData = [NSData dataWithContentsOfFile:path];
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(<#x#>, <#y#>, <#w#>, <#h#>)];
webView.scalesPageToFit = YES;
[webView loadData:gifData MIMEType:@"image/gif" textEncodingName:nil baseURL:nil];
webView.backgroundColor = [UIColor clearColor];
webView.opaque = NO;
[self.view addSubview:webView];

Read more »

前言

最近要把维护期的项目都集成极光推送,集成期间遇到一些小坑,特此在这总结!

极光推送能干嘛?

1.为 JPush Server 上报 Device Token,免除开发者管理 Device Token 的麻烦
2.支持iOS APNs推送
3.前台运行时,可接收由JPush下发的(透传的)自定义消息
4.灵活管理接收用户:Tag(标签分组)、Alias(用户别名)、RegistrationID(设备注册ID)

Read more »