我的GitHub
0%

写在前面

菜鸡,半个iOS开发,js了解不深入,见解不一定正确,有错指出,意会一下这个意思就行了,大牛就没必要看了、、、

背景

以下所有是基于mac的,Windows老哥只能参考着看了

cmd = ctrl , option = alt

一、环境安装

其实官方的环境安装教程很简单,但也不排除有老哥看不懂,所以还是再赘述一下,下面是mac的傻瓜式环境安装教程(安装好了的不用看,windows老哥挑着看)

打开终端,我们开始了

1.开启任意来源

1
sudo spctl --master-disable
阅读全文 »

这篇是写给原生老哥们看的,毕竟如果是做js的老哥肯定是不用说了。。。

背景:大家代码写的格式都不一样,希望统一起来,所以引入ESLint

这东西是啥应该不用我多说,至于怎么引入,说实话,看了官网教程,也看了各种博客,反正最后我是搞得一团糟。。。。万幸最后引入还是成功了。

我是打算每个项目的标准都不同(因为有的是rn,有的是h5),所以我都是局部引入,没有全局引入。所以我接下来说的都是局部引入,会让你卸掉全局的,想全局引入的同学自己注意一小下,有些步骤就不要照做了。 目前airbnb的标准是最受推崇的,我就引入它了

环境和工具:Mac,webstrom,npm,yarn

一、检查本地是否全局安装过相关的包

打开终端

1
2
npm ls -g --depth 0
复制代码

看看全局是否安装过ESLint相关的包,如果有,卸载掉。

二、进入项目根目录

阅读全文 »

背景:相信经常有这种情况,后端定义好了接口文档,但是还没开发,这时候前端或者客户端就无法进行联调,只能通过自己伪造数据进行开发。

###伪造数据这个过程,就叫做mock
但是总是因为各种各样的情况,不能总拿死数据来开发,需要一些随机数据,这样才能更好的覆盖整个用例的可能性
mock的方法其实很多:
本地写死返回值,抓包工具断点篡改返回值,本地结果替换等等。
这次介绍的是使用mock这个开源项目进行随机返回值的替换
###Mock.js虽然名字是js,不过可不限于前端哟
###部署的方式很多,比如部署专门的服务器,或者本地部署等等
但是我比较菜,也比较懒,我就直接用别人部署好的服务器进行使用,其他的部署方式就需要各位老哥自行学习了。

先介绍一个网站
###Easy Mock

登录进去以后,创建你的第一个项目
mock首页
初始化的填写
创建完毕以后就会有一个项目出现在你的首页了,点击该项目

例如我这里创建了一个wx项目,点进去就可以看到
配置

正常在开发过程中,肯定是有正式环境、开发环境这种区分的,除了域名不一样,后面的接口拼接都是一样的,在这里也是一样的。只需要将你某个环境下的域名或者ip替换成图中的baseURL即可,至于怎么替换,在接下来会讲到。

###我们举个例子来理解一下。
我们的域名为:http://www.baidu.com
有一个获取版本号的接口为:http://www.baidu.com/common/version/ios
还有一个获取helloworld的接口为:http://www.baidu.com/helloworld
可以看到,所有的请求的baseurl都是http://www.baidu.com,接口只是在后面拼接。我们先到easymock上建立获取版本号的接口。

####点击创建接口
如图
具体的返回值的语法规则这里就不说了,直接在官网能查到,没有写的必要
语法规范
这样我们就得到了一个mock接口
###接下来就是替换域名的操作了
我们需要用到的工具是Charles
因为Charles可以对子集全部代理,所以这里我们选择charles,当然,如果你可以配置node服务进行跨域也是ok的,方式有多种,目的都是一个,替换baseURL
Charles配置

image.png
通配符
注意需要使用通配符,至于啥叫通配符就百度一下吧~~
ok,至此,Charles配置完毕,让我们看看效果。
网络请求
如图,我写了一个网络请求,地址是http://www.baidu.com/common/version/ios
在抓包中得到了什么呢
地址被替换成了mock地址

###结束语
其实很简单,不过各位该锤后台的还是要锤,毕竟前台后台,相爱相杀,hhhh

阅读全文 »

没有用过其他推送,不过应该都是大同小异的,可以参考参考。
应该有不少老哥接了推送,都存在这么一种情况。推送平台只能放一个P12,肯定要放生产的,那我开发怎么测?难道真的要打包上架去TestFlight再测?那这个风险和耗时有点太大了。

###Xcode手动管理证书要是不会配置记得用自动证书管理
###其实我们只要转变一下思路就好了。创建一个测试应用即可。(读懂了这句话的老哥就不用继续往下看了)
不过如果你要是想给特定用户推送不知道怎么做的话,推荐看:
个推-iOS特定人群推送
####准备好推送证书的p12文件
推送证书的申请乱七八糟我就不说了,网上图文教程一大堆。
接下来,推送证书分两份,这个应该也不用多说了,如果这个都不知道的开发者那就有点不太称职了。。。
钥匙串截图
导出P12文件并设置密码(怎么导出也不多说了)
这时候我们得到了两份推送证书的P12文件,一份开发环境一份生产环境。
####打开个推官网
个推官网
放开发环境的p12
剩下的和正式环境的推送一模一样了。

阅读全文 »

推送嘛,集成或更新的时候肯定要各种测试,但又不可能给所有线上用户集体推送。
这时候这个测试需求就暴露出来了。
其实非常简单

###不过测试前,需要确定你的客户端能和个推平台放置的p12对应的上。
####如何看能否对应的上?
#####获取token
token绑定
打开xcode,搜索这个方法:

1
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

搜到了是不是,接下来运行起来,得到这个token,复制一下。
#####打开个推官网
个推官网
#####打开应用配置,拉到最下面
测试一下
#####点击测试一下
然后把你刚刚获得的token复制上去,监测一下看是否成功。如果成功会弹出提示,并且对应的设备会收到一条测试推送消息(走的是苹果的apns通道)

###如果是不成功,那么我猜大概率是证书环境没匹配上,你放的是生产环境但你客户端是开发环境,这时候怎么办?也有办法,看下面这篇。

好了好了,上面的准备工作已经做好,进入正题
返回注册的cid

1
- (void)GeTuiSdkDidRegisterClient:(NSString *)clientId

这里拿到cid
然后,新建一个txt文件(mac端的同学,还是拜托windows的同学新建给你吧,别问我为什么。。。因为字符集不一样啊我日)

然后把cid放到txt文件里
像这样

打开个推官网,创建推送
把你的txt文件放上去

阅读全文 »

因为公司业务关系,希望在iOS在后台的时候能存活去做某些业务操作(其实就是流氓的后台保活=。=)
最早是使用后台定位实现的,信心满满的去上架,结果被苹果爸爸锤的头都破了。连续被拒3次,申请打电话苹果代表也锤了我一顿,申请苹果审核申诉又被锤了一顿。想一想我真是头铁啊emmm
闲话不多说,开始这篇博客的主题
我们的业务其实很简单,就是后台有业务数据来了,客户端哪怕在后台也要处理。

#苹果的保活无非三种方式
###1.后台播放无声音乐
###2.后台定位
###3.推送唤醒

##播放音乐
直接被我pass了,我觉得机审都会把我拒了。。。压根不考虑

##后台定位
正好我们的业务吐过硬扯还能和业务办公场所扯上关系,头铁就是上!通过后台定位让app保活,成功实现了。不过被🍎爸爸锤了。方案二,pass

##推送唤醒
那这时候,就剩这最后一种方式了。
推送分两种,本地推送和远程推送。
####本地推送
本地推送其实类似于一个定时器,到了触发的时候就会触发。一般有很多用来做闹钟或者提示用户签到一类的场景。不过根据我的测试,当应用在后台三分钟后,被挂起以后这个本地推送就不再继续推送了。(也不知道是不是我的测试问题,反正我是没能保活成功。)

####静默推送(不用voip,有的个推运营人员是非技术,回答让你搞voip,别被忽悠了)
静默推送其实是远程推送的一种。在个推中,都属于透传消息(建议看一下这一篇)个推:什么是普通推送?什么是透传消息?
相信在看我这个前老哥们肯定也搜过其他的博客文章
无一例外肯定提到了:

1
2
3
4
5
6
{
"aps": {
"content-available": 1,
"sound": "com.gexin.ios.silence"
}
}

这个东西,不过万一有没搜到的呢emmm我还是再说一遍
content-available属性。0是非静默,1是静默
个推中,无声,sound属性:com.gexin.ios.silence(其他的推送是不是如此我就不太清楚了)
###alert,body切记不要写东西,要传值往最后看
###接下来是傻瓜式教程
###准备工作
####1.推送证书准备好
这部分太多教程了,随便搜一个搞一下就差不多了,不上图了。记得导出的p12要放到个推平台哟。
####2.打开开关
推送开关

允许后台推送

####3.代码部分
静默推送回调
就在这个里面了,当被挂起的时候,收到推送,执行这里的代码,唤醒app30s左右的时间,让你尽情的做自己想做的事😝。
我把生命周期写在下面,也好复制粘贴去搜索,我是不是很体贴=。=

阅读全文 »

写的都是自己的一些感受=。=可能都是野路子=。=大牛就别看了=。=
代码:https://github.com/XingXiaoWu/mobx-/tree/master
先声明一句话:

#MobX 会对在追踪函数执行过程中读取现存的可观察属性做出反应。
以下所有内容基于rn0.56版本以前(即低于0.56),语法是ES6语法(可能有ES7,反正我是分不清=。=)
#一、引入Mobx
首先,安装yarn(别问我为什么不用npm)

##1.在项目根目录下输入
yarn add mobx mobx-react
此命令作用:引入mobx和mobx-react
##2.在项目根目录下继续输入(看清楚你的版本选择命令)

1
2
3
4
5
6
7
//这是0.57以下的
yarn add babel-plugin-transform-decorators-legacy babel-preset-react-native-stage-0
//这是0.57及以上的
yarn add @babel/core --dev
yarn add @babel/plugin-proposal-decorators --dev
yarn add @babel/plugin-transform-runtime --dev
yarn add @babel/runtime --dev

此命令作用:能够使用@标签

##3.用IDE打开项目
打开.babelrc文件
修改为(看清楚版本)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//0.57以下
{
"presets": ["react-native"],
"plugins": ["transform-decorators-legacy"]
}

//0.57及以上
{
"presets": ["module:metro-react-native-babel-preset"],
"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/transform-runtime", {
"helpers": true,
"regenerator": false
}]
]
}

至此,如果没报错,环境配置完毕,可以正常使用mobx了
#二、mobx的常用标签
##1.定义observable
observable,顾名思义,可以被观察的,即被观察者
一般用于数据,几乎所有数据都可以被观察,无论是对象、数组、类。 循环数据结构、引用,都可以被观察,只要给他们打上@ observable的标签,他们都可以被观察。

我写了三种导出模式,相互的优劣和使用方式还需要琢磨
#ThingModel=>static定义的,导出的是ThingModel这个class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import {observable} from "mobx"

export class ThingModel {
@observable
static thing = "我是数据1"

@action
static setThing(value) {
ThingModel.thing = value
}
}

//使用
ThingModel.thing
ThingModel. setThing(xxx)
阅读全文 »

角色权限判断,这应该是大部分应用都有的功能,那么如何进行权限判断?

这里说下我们用的思路,可能会比较low,各位看官别笑。

打个比方,我现在有A,B,C,D四个功能。要对某个账户是否具有这些功能权限做判断。
我们有个list,里面存放着这个账户所有的权限。(list从哪来?当然是后台请求回来啊!)
A功能对应的权限是=>0,以此类推B=>1,C=>2,D=>3这样子。

那么如果我有一个账号拥有所有权限,list就是【0,1,2,3】,如果没有B权限就是【0,2,3,4】这样子,相信大家都应该明白我要表达的意思了。

那么要判断是否拥有某个权限,这时候肯定就会说,遍历一下list不就知道了?那如果权限比较多呢?而且你不觉得这样更low么=。=
所以这个时候,我们可以使用位运算打成这个目的:

先说我们用来判断的方法:

1
2
3
4
//判断是否存在权限,permission是所有权限展示中的某个权限,只有一个&,不是两个,别搞错了
hasPermission(permission) {
return permission & GlobalValue.authValue
}

再定义一个包含了所有权限的声明

1
2
3
4
5
6
7
8
//所有权限列表展示
export let Permission = {
A: Math.pow(2, 0), //A功能
B: Math.pow(2, 1), //B功能
C: Math.pow(2, 2), //C功能
D: Math.pow(2, 3), //D功能
...
}

在我们和后台请求拿到某个角色所包含的list的时候,对list做如下操作

阅读全文 »

背景:rn好多前端或者安卓转的旁友对iOS的打包不太熟悉,所以写个图文教程版,目前我对应的版本是0.4+版本和0.5+版本(反正我也是随便写的,参考为主)
PS:账号的申请还有各种证书的申请我就不多提了,自己百度查下。。
###1.打开项目中iOS文件夹,新建一个名为bundle的文件夹
如图
###2.打开终端,cd到整个项目根目录
如图中的catten目录
###3.输入命令行,版本不同命令不一样哟,注意看
区分标准是你是否存在index.ios.js,存在肯定是老版本,用下面这个命令

1
react-native bundle --entry-file index.ios.js --bundle-output ./ios/bundle/index.ios.jsbundle --platform ios --assets-dest ./ios/bundle --dev false

如果你是index.js,那就是新版本啦,用下面这个命令

1
react-native bundle --entry-file index.js --bundle-output ./ios/bundle/index.jsbundle --platform ios --assets-dest ./ios/bundle --dev false

###4.把上面命令输入终端并按下回车
等待时间可能要一会
如图
###4.补,差点漏了一点注意事项
可能有的旁友项目中有webview承载html页面
这时候你命令行打出来的包可能就要注意一下了
如下图,我这是bundle文件夹下assets文件夹里的资源文件夹
如图
实际上我这个html有多少文件呢
实际这么多
你会发现少了东西,这时候怎么办,很简单,去你项目中把相关缺少的文件复制到assets里就行

###5.打开Xcode项目
直接拖过去
直接拖过去
记得选下面这个哟,蓝色的物理文件夹
选下面这个
选完长这样
选完长这样
###6.这时候打开appdelegate(我改了东西,里面代码是一样的,不过我的位置不一样,你们看下就知道了)
把jsCodeLocation的来源换成你打的包的来源(其他人怎么打包、调试、开发我不清楚,反正我是这么做的,而且已经上架两个项目了,我确定是可用的)
js的地址

还是老样子,index.ios.js填

1
jsCodeLocation = [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"index.ios.jsbundle" ofType:nil]];

index.js填

1
jsCodeLocation = [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"index.jsbundle" ofType:nil]];
阅读全文 »

其实iPhone的指纹识别有很多教程,但其实有两套策略,而且好多都只写了一套,而且有的你会发现,错误码压根就试不出来啊,还以为苹果给的错误码都是瞎扯淡的。

首先,需要导入苹果的安全策略库LocalAuthentication。
导入库
这个库提供了指纹识别这一安全策略库公开发者们使用。
对于开发者来说,只需要调用几个很简单的方法便可以进行指纹识别了。至于是如何识别,这些苹果并没有公开,开发者只能获取成功或失败状态以及message。
###一.判断设备是否支持指纹识别

1
2
3
4
5
LAContext *context = [[LAContext alloc] init];
NSError *error = nil;

// 判断设置是否支持指纹识别(iPhone5s+、iOS8+支持)
BOOL support = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];

###但是注意了,这里的support如果为NO并不代表设备就不支持指纹识别了。
因为当出现:
1.设备支持TouchID但TouchId被锁时:LAErrorTouchIDLockout
2.设备支持TouchID但没有设置密码:LAErrorPasscodeNotSet(但实际上会走LAErrorTouchIDNotEnrolled)
3.设备支持TouchID,设置了密码,但没有设置TouchID:LAErrorTouchIDNotEnrolled
这几种情况统统都会报Support为NO

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
if (support) {
return AllRight;
}else{
switch (error.code) {
// 没有设置指纹(没有设置密码也会走到这),但是支持指纹识别
case LAErrorTouchIDNotEnrolled:{
return TouchOK;
}
break;
// 理论上是没有设置密码,至今没有尝试出什么情况下走这个,希望有试出来场景的兄弟告知一下我
case LAErrorPasscodeNotSet:{
return TouchOK;
}
break;
// 在使用touchID的场景中,错误太多次(根据策略不同为5次到6次)而导致touchID被锁不可用
case LAErrorTouchIDLockout:{
NSLog(@"密码封锁");
return TouchOK;
}
// 设备不支持指纹识别
default:{
return AllError;
}
break;
}
}
}

###二.指纹识别如何唤起(其实是安全策略的唤起)
其实整个LocalAuthentication库是一个安全策略库,我们所说的指纹只是安全策略的一种,主要为生物技术的使用。这种策略有非常多的种类,现在常用的指纹,iPhone X的face ID,没准以后还会有虹膜等更多的安全策略出现。

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
52
53

[authenticationContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:@"通过Home键验证已有手机指纹" reply:^(BOOL success, NSError * _Nullable error) {
// 指纹识别错误调用分为以下情况,
// 点击取消按钮 : domain = com.apple.LocalAuthentication code = -2
// 点击输入密码按钮 : domain = com.apple.LocalAuthentication code = -3
// 输入密码重新进入指纹系统 : domain = com.apple.LocalAuthentication code = -8
// 指纹三次错误 : domain = com.apple.LocalAuthentication code = -1
// 指纹验证成功 : error = nil
if (error) {
switch (error.code) {
// 指纹识别3次失败进入这里
case LAErrorAuthenticationFailed:
NSLog(@"验证失败");
break;
// 指纹识别时,点击取消
case LAErrorUserCancel:
NSLog(@"点击取消按钮");
break;
// 指纹识别时,点击输入密码按钮
case LAErrorUserFallback:
NSLog(@"点击输入密码按钮");
break;
// 没有在设备上设置密码(我没试出来这一项,有试出来的兄弟评论告诉我一下)
case LAErrorPasscodeNotSet:
NSLog(@"没有在设备上设置密码");
break;
// 设备上TouchID不可用,例如未打开(我没试出来这一项,有试出来的兄弟评论告诉我一下)
case LAErrorTouchIDNotAvailable:
NSLog(@"设备不支持TouchID");
break;
// 没有设置TouchID
case LAErrorTouchIDNotEnrolled:
NSLog(@"设备没有注册TouchID");
break;
// 设备TouchID被锁,且只会在iOS9以上设备出现
case LAErrorTouchIDLockout:
NSLog(@"TouchID被锁");
break;
// 由于不可抗拒力,应用进入后台(其实很简单,你写两个测试demo,在一个启动指纹时开启另一个项目,你的指纹项目就会因为不可抗力进入后台,这时候就会走到这)
case LAErrorSystemCancel:
NSLog(@"由于系统阻止,转入后台");
break;
default:
// 直接写失败吧,也没别的原因了,进入这里都很难了
break;
}
return ;
}
else{
NSLog(@"识别成功");
}
}];

一般用上面写的这段代码就行了
接下来咱们说说策略

1
2
3
4
5
6
/// @param policy 策略
/// @param localizedReason 提示语
/// @param reply Reply block 回调的代码块
[myContext evaluatePolicy:<#(LAPolicy)#> localizedReason:<#(nonnull NSString *)#> reply:^(BOOL success, NSError * _Nullable error) {

}];

咱们来谈谈policy,这玩意有两个枚举值

阅读全文 »