杜文杰


  • 首页

  • 分类

  • 关于

  • 归档

  • 标签

tabBar中动态插入tabBarItem的trick,并由此引发的进一步深入

发表于 2018-05-25 | 分类于 开发经验

需求:

香蕉球APP的tabBar本来一共有5个,由于战略原因,tabBar中的“活动中心” 需要动态由后台配置决定是否显示。

1

理想情况下的做法:

1,获取当前tabBarVC中的所有子VC,得到一个数组 mutArr。

2,根据后台返回的bool值activityCenterOpen,ture为显示,false为隐藏。

3,(1),若为false,判断mutArr是否包含“活动中心”的VC,包含 则将“活动中心VC”从mutArr中删除。
(2),若为true,判断mutArr是否包含“活动中心”的VC,不包含 则将“活动中心VC”插入到这个mutArr数组,index为2。

4,调用
self.tabBarController.viewControllers = mutArr;
则完成动态配置要求。

遇到问题:

执行前面3,(1)的时候是没有问题的,能成功将“活动中心”从tabBar中删除,
然而在3,(2)的时候要将”活动中心“插入到tabBar的第三个的时候,实际显示确实这样的:
2

没错!活动中心被加在了最后一个item上了。
通过调试 发现mutArr中的各个VC的顺序,并没有改变,“活动中心VC”在数组中位置就是index=2,没有问题。

猜测:

面对这样的结果,只能猜测tabBarVC在重置viewControllers的时候是不管mutArr中的顺序的,而是先判断即将设置的VC是否在当前的VCs 里面,若有之前已经存在过,则不再添加,若是不存在就将新的VC设置在最右边显示。也就是说 self.tabBarController.viewControllers = mutArr; 并不是真正的重置!

尝试:

通过这样的猜测,已经可以想象到解决方案了,那就是在插入VC的时候,先把之前的都去掉,再重新复制,即,

1
2
self.tabBarController.viewControllers = @[];
self.tabBarController.viewControllers = mutArr;

结果只是第一行代码起了作用,也就是tabBarItem全部移除了。

没有道理。莫非是先把VCs设置为空数组之后,就不能更改了? 后来将代码改成

1
2
3
4
[mutVCs insertObject:nav atIndex:2];
NSArray *arr1 = [mutVCs subarrayWithRange:NSMakeRange(0, 1)];
self.tabBarController.viewControllers = arr1;
self.tabBarController.viewControllers = mutVCs;

结果依然是第一行代码起作用,第二行没有设置上,显示为

3

并没有放弃,把arr1改成2个试一下。

1
2
3
4
[mutVCs insertObject:nav atIndex:2];
NSArray *arr1 = [mutVCs subarrayWithRange:NSMakeRange(0, 2)];
self.tabBarController.viewControllers = arr1;
self.tabBarController.viewControllers = mutVCs;

神奇的事情发生了,完美的显示出来想要的效果

4

解决:

得出的结论是,
1,tabBarVC在重置viewControllers的时候是不管mutArr中的顺序的,而是先判断即将设置的VC是否在当前的VCs 里面,若有之前已经存在过,则不再添加和改变顺序,若是不存在就将新的VC设置在最右边显示

2,若是tabBarController之前的viewControllers为小于等于1个,那么再次对viewControllers赋值,是起不到作用的。

Wtf!,虽然1的结论可以证实,但是2的结论这么草率??!怎么会有这么奇怪的用法??

再验证:

只能再次去验证其正确性。调试了很多次发现结果变幻莫测,难以找到其规律,比如把index<=1时,即:

1
2
3
4
[mutVCs insertObject:nav atIndex:1];
NSArray *arr1 = [mutVCs subarrayWithRange:NSMakeRange(0, 2)];
self.tabBarController.viewControllers = arr1;
self.tabBarController.viewControllers = mutVCs;

结果竟然

5

为什么会跟insert的index也有关系!,这么乱的复杂情况下面到底藏着怎样的秘密?

再猜测:

经过调试发现发现一个现象:
每当我对self.tabBarController.viewControllers = arr1;进行设置时,若arr1中包含自己(也就是Self),那么第二行self.tabBarController.viewControllers = mutVCs; 就会有效!。
通过debug 发现,若arr1中包含self,此时打印self.tabBarController,会打印出self.tabBarController的指针,而arr1中没有包含self时,打印出的是self.tabBarController=nil。
这么说来 第二行代码无效就解释的通了!!

最后结论:

每当调用tabBarController的setVCs的时候 ,会立即生效并生成相应的tabBarItems, 若这些VCs里面有当前self的VC,那么根据self.tabBarController就能找到self的tabBarController,而如果setVCs里面的VC没有self,那么再继续调用self寻找self的tabBarController自然就找不到了,因为tabBarController跟self已经没有半毛钱关系了。


欢迎访问我的微博留言:肚子吃撑的杜

关于APP内购的一点实战经验之谈

发表于 2017-08-02 | 分类于 开发经验

内购上线已经一个多月了,一直没有时间做一个总结,因为之后立马又有两个项目要做,现在闲下来,回忆一下内购路上的一些错误认识,避免其他人进坑。关于iap的文章一搜一大把,这里推荐走在路上的小菜鸟 《iOS Apple内购及掉单问题》的一片文章,算是比较到位的,demo的话推荐YZQ_Nine的IAPDemo,所以下面的内容就是以这个demo和《iOS Apple内购及掉单问题》为出发点慢慢说来,关于文章中没有提到的以及demo中的优缺点我下面会讲,陋识拙见,姑且言之,姑且听之。


为什么要做内购

因为博主做的是直播APP,第一版上架是没打算做充值的,打算先上了再说,然而由于是虚拟货币交易,苹果告知必须走内购路线否则不能上架,你有什么办法呢,默默听话叫爸爸,还得30%过路费。

划重点

注意,看本文之前,先看完开头提的那篇文章,本文所写内容是对《iOS Apple内购及掉单问题》的补充,为避免文字啰嗦 以下以《内购》代之,所以不会对《内购》内已经指明的内容有所重复,也就是说你所看到的都是干货。

协议、税务和银行业务

关于协议的填写按照开头提到的那篇文章里的流程走就是了,基本没有问题,这里需要提到的是填写Bank Account Number的时候这个卡号也支持企业名下账号,同样 Account Holder Name 也要填写企业名。

创建APP内购买项目

参考《内购》,
在“我的APP”中把创建好的APP购买项目添加进来,在这个地方有些文章说,它们说要等到APP审核过了之后才能进行测试,其实不用,在“我的APP”中添加成功之后就可以申请sandBox账户进行测试了。

代码集成

这块是重点,在这里我最初的做法是按照demo的思想,也就是下图的流程,见谅一些细节没有体现,

IAPDemo

下面的这张流程图是我们在项目中的流程

ourIAP

这两者的区别从图中明显可以看出来,我们在做的时候是没有把交易凭证储存在本地沙河的。因为考虑到用户可能存在的一个情况,在一个设备上使用充值苹果那边成功了,而我们服务端验证没有成功,这个时候,若按照第一种方案,app会把验证凭证存在本地沙河中并且告诉苹果结束这一订单,待下次重新启动的时候,app检测到本地沙河中有交易凭证就会把交易凭证发给自己的服务端。但是,若是用户卸载了app或者使用了其他设备,那么保存在本地的交易凭证就会丢失,用户就无法在我们的服务端验证成功,就需要人工服务介入查询,为了避免这个问题,我们采用第二种方案。

第二种方案做法是我们服务端没有验证充值成功的,就不告诉苹果服务器结束这一订单的状态,也就是不去调用
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];

那么在下次启动的时候,苹果会主动告诉你这一单没有结束并且回调给你这一单的状态,我们就可以继续处理这一订单。等于说把有问题的订单交给苹果来帮你保存,这种云端保存省事不少。

《内购》中提到要是想把自己后台这边的交易单号和苹果的交易单号一一对应起来,可以把自己的单号放在交易类SKMutablePayment的applicationUsername属性中,

1
2
SK_EXTERN_CLASS_AVAILABLE(3_0) @interface SKMutablePayment : SKPayment
@property(nonatomic, copy, readwrite) NSString *applicationUsername NS_AVAILABLE_IOS(7_0);

这样做是没有问题的,但是后来的使用过程中出现过一个问题,那就是,我虽然在请求交易的时候把applicationUsername传了进去,但是会出现某些时候苹果返回给我的交易没有了这个属性,这就比较尴尬了,是个坑,后来我们就不去管这个对应关系了,发起购买的时候我会向服务端请求一个订单,购买结束的时候把交易凭证传到后台,而后台无需去对应,只要这个人有待付款的订单而且productId对的上的话那么当苹果后台验证成功的时候我们就给他充值成功。

添加测试账号

参考《内购》,
有些文章说这些测试账号千万不要在正式环境登录,否则会被注销,bullshit,你根本就登不上好吗。测试之前只需在AppStore中将你的正式账号退出就行,然后在你的app点击充值按钮,会有弹框提示你登录。

另外,使用development证书打包的app都是无法使用正式App Store账号的,也就是说你想测试一下线上的内购就必须审核通过,从App Store下载下来才能测。

测试遇到的问题及解决

  • 前两天测试环境突然验证不了了,苹果付款成功,但是自己的服务端却无法验证成功,原来是苹果默默把字段改掉,之前测试环境返回的类型是“SandBox”,突然变成了“ProductionSandBox”…,所以验证是失败的,无语,不过相信线上不会这么做的。

  • 当有未结束订单的时候,重启APP会走订单监听回调,在这里千万不要APP有问题,比如崩溃😖。。一旦崩溃那么这个用户就再也进不来了,陷入崩溃的死循环中。


欢迎访问我的微博留言:肚子吃撑的杜

iOS工程中使用自定义文字

发表于 2017-06-16 | 分类于 随笔bug

1,把.ttf字体文件拖拽进工程
2,在info.plist中添加 Fonts provided by application:ziti.ttf
3,在build Phase 中 Copy Bundle Resources

如何使用hexo新建一篇博客

发表于 2017-06-16 | 分类于 随笔bug

1,

1
$ cd 进入HEXO文件夹

2,

1
$ hexo new "如何使用hexo新建一片博客"

3, 编辑文档

tags: [hexo,部署hexo]  
category: "随笔bug

4, 将Markdown生成静态网页文件

1
$ hexo generate

5, 部署到Github

$ hexo deploy

6,GitHub desktop pull and push


注意点: 顶部信息”:”后面要跟空格,不然会报错

我的第一篇博客

发表于 2017-05-23 | 分类于 随笔记录

    看到一些大牛都有了自己的个人网站博客,心里十分的痒痒,从在大学的时候就想搞了,无奈一直到现在。趁着工作之余,又有了闲情雅致,就忍不住搞了一波。

  •     首先去万网购买了一个域名,查询www.duwenjie.com一看,被甜到了,秀恩爱的程序员。阔怕。。。

    问题是这并不是我…,然后我就买了du-wenjie.com]这个域名。

  • 接下来是买虚拟主机,然后在网上找了模板,又上传资源,试了一下挺好,然后是备案,很麻烦的说,索性干脆开一个GitHub个人主页,

  • 新建一个个人主页的仓库,然后把万网的域名解析到我的GitHub个人主页下

  • 发现别人都是使用hexo来管理自己的博客,第一次听说,然后查资料、看文档,下载git、 node.js。。。 下载博客主题,格外喜欢next的theme,首先它是我的偶像小鱼周凌宇使用的主题,是一位美女iOS开发,格外佩服,学习

  • 原来hexo是要使用Markdown写blog的,看别人推荐使用MacDown客户端,verygood;


nice ending!
感觉这几天学习了很多,

欢迎访问我的微博:肚子吃撑的杜

杜文杰

杜文杰

do something for you

5 日志
3 分类
10 标签
© 2018 杜文杰
由 Hexo 强力驱动
主题 - NexT.Muse