最近项目上线了Vip订阅功能,包含连续包月和连续包年。上线后市场和运营同事问能不能给一些资深用户送几个月的会员,或者搞活动送会员。因为是海外项目,内购不需要用户系统(我们也没有用户系统)完全依赖Apple购买凭证。所以不能使用国内App那种服务端生成兑换码的做法。
因为完全依赖Apple,所以还是要从Apple这边下手。自然而然想到了Apple的促销代码。
先看看什么是促销代码 官方文档戳这里
可以看到,促销代码是可以兑换内购项目的,并且订购一个自动续期的订阅并不会自动续费。
最近项目上线了Vip订阅功能,包含连续包月和连续包年。上线后市场和运营同事问能不能给一些资深用户送几个月的会员,或者搞活动送会员。因为是海外项目,内购不需要用户系统(我们也没有用户系统)完全依赖Apple购买凭证。所以不能使用国内App那种服务端生成兑换码的做法。
因为完全依赖Apple,所以还是要从Apple这边下手。自然而然想到了Apple的促销代码。
先看看什么是促销代码 官方文档戳这里
可以看到,促销代码是可以兑换内购项目的,并且订购一个自动续期的订阅并不会自动续费。
目前负责的App新增了Widget功能,之后在组内分享中分享了下Widget的开发经验。基于之前的PPT提炼出了这篇文章。本篇文章只讲基于Widget关于iOS10+ 之后的知识点。
Widget是iOS8以后Apple推出的一项功能,并且在iOS10后进行了大幅的优化。
在主屏幕和锁定屏幕上向右滑动来访问Widget,也可以在对应的App图标上面使用3D Touch按压访问相应的Widget。
assert大家都不陌生,在开发阶段用断言函数可以很好的进行调试。
一般OC中,我们使用的是NSAssert
。在Xcode4.2以后,Xcode会在release环境下自动把NSAssert
忽略掉,确保release环境不会出错。
最近遇到一个问题,线上Crash定位在了一个pod库中的assert
方法,在OC里面调用assert是用的C语言的assert。结果在release
环境下也生效了,直接造成了Crash。
查找了一些资料,找到了解决方案。
通过查询源码发现,在C语言中是如何忽略的assert
的
#undef assert |
源码地址详见:https://opensource.apple.com/source/Libc/Libc-583/include/assert.h.auto.html
NDEBUG
是C语言中的一个标准宏,其语义适用于C89,C99,C ++ 98,C ++ 2003,C ++ 2011,C ++ 2014标准。
详见:https://stackoverflow.com/questions/2290509/debug-vs-ndebug
根据源码可知,如果定义了NDEBUG
,那么assert
就返回void
,就不会再生效。
那么我们只需要在主工程中,选择Bulid Settings
选择Preprocessor Marcos
在Release
中添加NDEBUG=1
即可。
但是需要注意的是,只修改主工程并不会对pod库生效,所以还需要对pod库进行处理!
在pod库中一个一个修改太麻烦,并且每次pod install
后就会失效,我们需要从podfile
文件入手。
post_install do |installer| |
判断是否是Release
环境,如果是就在build_settings
中的GCC_PREPROCESSOR_DEFINITIONS
添加$(inherited)
和 NDEBUG=1
。
$(inherited)
是继承Pods
工程的设置
添加完后执行pod install
,就可以发现每个pod库的Preprocessor Marcos
中,在Release
下都添加了NDEBUG=1
说完assert,再来说说我们常用的NSAssert
NSAssert
细分为
NSAssert/NSCAsseet
NSParameterAssert / NSCParameterAssert
他们的区别如下:
NSAssert 和 NSParameterAssert 只适用于OC环境中。NSCAsseet 和 NSCParameterAssert 适用于C语言环境中
当 NSAssert 或 NSParameterAssert 的条件不满足时,断言处理器会调用-handleFailureInMethod:object:file:lineNumber:description:
方法。
当 NSCAssert 或 NSCParameterAssert 的条件不满足时,断言处理器会调用 -handleFailureInFunction:file:lineNumber:description:
方法。
NSAssert和NSAssert都有一些变体,例如NSAssert1
、NSAssert2
、NSCAssert1
、NSCAssert2
等等。他们的区别是会输出不同的参数。
具体信息详见官方文档:https://developer.apple.com/documentation/foundation/nsassert1
从Xcode4.2以后,会自动在release环境下忽略NSAssert
等断言函数。它是通过定义 NS_BLOCK_ASSERTIONS
宏实现的,确保不会对release环境有影响。
我们可以在很多第三方库中看到他们定义的assert,关闭条件也是基于NS_BLOCK_ASSERTIONS
#ifndef _GTMDevAssert |
NSAssert
和NSCAssert
底层都是通过NSAssertionHandler
来实现的,只有2个实现方法
-handleFailureInMethod:object:file:lineNumber:description:
NSAssert/NAParamterAssert调用-handleFailureInFunction:file:lineNumber:description:
NSCAssert/NACParamterAssert调用Xcode的开关在
我们也可以自定义NSAssert
继承NSAssertionHandler,重写handleFailureInFunction:file:lineNumber:description
和handleFailureInMethod:object:file:lineNumber:description:
在AppDelegate中注册
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { |
NSAssert在OC中,会存在循环引用问题
- (IBAction)buttonAction:(UIButton *)sender { |
循环引用的根源在于NSAssert定义中使用了self
#if !defined(_NSAssertBody) |
我们可以试用@weakself 和 @strongself来解决。不过在release环境下,assert并不会调用。所以推荐试用NSCAssert
和 NSParameterAssert
最近在做针对国外用户的App,考虑到国外都是Facebook和Twitter等社交平台,所以考虑使用iOS系统中的原生分享。但是在iOS11上面遇到一些坑,遂记录一下。
在iOS11以下的版本中,系统默认集成了社交账号的功能。但是在iOS11中内置的社交账号被移除了。并且在iOS11中废弃了一些方法。
SOCIAL_EXTERN NSString *const SLServiceTypeTwitter NS_DEPRECATED(10_8, 10_13, 6_0, 11_0); |
代码块是Xcode中很便利的一个功能,你可以自定义不同的代码块,特别是对于一些需要重复写的代码,使用代码块可以大大的提高效率。
代码块介绍
代码块这个功能大家其实都用过,当你在写一些代码时候,代码提示功能就会显示出一些系统定义好的代码块。如图就是系统定义好的if else的代码块。
代码块在右侧边栏的下方,在这里你可以看到系统定义的代码块也可以自定义你自己的代码块。
下图就是系统定义好的dispathc_once_t的代码块。
定义自己的代码块
定义自己的代码块有很多好处,你可以随心所欲的根据自己的项目和喜好定义自己的代码块。
比如一些@property属性,一些三方的统计功能等等。下面我们来定义一个代码块,来快速定 义@property 修饰符为nonatomic和strong
首先在任意一个类下面声明如下的属性 type 和 name 为提示语
@property (nonatomic,strong) type name;
然后把type 和 name 上分别改为<#type#> 和 <#name#>
你会发现 type 和name 都变成了高亮状态,你可以按Tab键来切换。
是不是发现变成和系统的一样了?你可以很方便的在高亮地方写入你需要的代码,然后按Tab键来回切换。
然后全选你刚刚写的那行代码,拖拽到代码块界面所在的区域。
然后会弹出一个界面,在这里填写你的代码块的信息。
Title就是在代码块管理区域显示的名称。重要的下面的Completion Shortcut,这就是你的代码块的快捷键,
然后点击Done。你的代码块就会出现在列表中了。去代码区试一下
输入@ps 就会出现你的代码块提示,按回车后刚刚定义的代码就出现了~
代码块的好处是不言而喻的,绝对是提高效率的利器。比如我们之前的项目要接入好多第三方的统计功能,然而每个界面挨个复制挨个改很浪费时间(当然也可以使用runtime直接在Viewcontroller 的load方法写,但是就不能自定义一些东西了)。使用代码块后就会很方便的完成这些工作啦。
再举个栗子。Xcode8以后禁用了第三方插件,之前使用的多行注释插件(就是喵神写的那个)也被废弃了。虽然Xcode8提供了系统的,但是不太好用,你也可以使用代码块来自定义多行注释。
(快捷键定义为 “///“ 并不会按回车就会出来,而是需要按esc才能提示,所以我用了“ccc”)
代码块的存放路径为 ~/Library/Developer/Xcode/UserData/CodeSnippets
大家可以从网上下载一些大神写好的,也可以自己写完以后备份,防止丢失。
上个地址吧,我自己定义的一些,没怎么管理,有点乱
https://github.com/liweican1992/XcodeCodeSnippets.git
PS:关于统计埋点,我自己根据Runtime写了一些统计功能,回头补上。
随着Apple审核时间的大大加快,确实造福了我们这些苦逼的开发者。今天主要聊一些审核被拒以后如果中间存在误会什么的,如何向苹果申诉。
关于申诉,我之前的博客就提及过,详见: 关于审核被拒申诉那点事
但是考虑到时间这么久了,有一些规则可能发生变化,就再重新开一篇。
苹果的审核总是充满了随机性,之前用的好好的一个功能就会忽然告诉你不符合他们的标准了。这次提交审核总共被拒绝了两次,第一次是因为版本号,第二次因为服务器机房挂了。
简书旧文
推送服务在日常运营中至关重要,就算是大厂也经常发生推送事故。相信很多人都收到过名为“test”的推送信息。本篇将介绍如何在推送事故发生时“撤回”已发送的推送通知。
细心的用户会发现当微信消息被撤回或者视频请求被取消时,相应的推送信息也会消失不见。哪怕是微信没有在后台运行。
本人很是好奇,网上又没有查到有用的资料,今天花了点时间实现了类似的功能。
iOS10已经发了,最近发现App在iOS10上有一些问题,主要是iOS10的字体变了,一些Label要做适配。还有一些相机权限之类的。更加详细的可以参考这篇文章
https://github.com/ChenYilong/iOS10AdaptationTips
之前一直纠结要不要升级Xcode8,毕竟好多插件都不能用了,还有用Xcode7打包的App在iOS10上运行能不能收到推送,经过一天的测试。结果如下:
以下结果是我用极光推送测试的结果(JPush)
答案:可以的,能够收到推送。但是点击推送或者从推送启动App之前的方法不再响应。
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { |
也就是只能收到,但是点击推送以后只会打开App而不会走didReceiveRemoteNotification,所以页面不跳转。
(我是用AD_Hoc证书发了一个测试版。用iOS10的机子装上以后使用推送生产环境推送测试的。AppStore版本没测试)
我是根据最新的Jpush官方文档做的适配
https://docs.jiguang.cn/jpush/client/iOS/ios_guide_new/
需要注意的几点:
刚用Xcoed8时候吓着了,疯狂输出一大堆log信息。建议关闭掉。
关闭办法
进入地方在你选择模拟器的左边有一个你的App图标和名字,点击一下选择Edit Scheme。 然后选择Run->Environment Variables->+号
OS_ACTIVITY_MODE =disable
然后打钩,完事
但是Xcode8的NSLog不打印了 = =!我这边是这个情况
刚在Xcode8上运行时候肯定会报错。需要在Tragets->Capabilites打开Push Notification开关。
点击修复后会自动生成一个xxx.entitlements的文件(xxx是你的工程名字)
你会发现里面会有APS Environment 并且为development
那你需要上线时候改成发布吗?
并不用可以忽略它,它对你发布并无影响。只要你发布时候选择的是发布证书依旧是发布环境。
但是,如果你用Xcode8生成以后再用Xcode7打开,如果不删除这个文件,打包时候就会报错,
所以如果你想用Xcode8做完适配以后还想用Xcode7发包的话请删除掉这个文件。(然后删除掉会报错)把下图选中哪行后面的路径删掉就好了
更新:昨天试了下,删除这个文件再用Xcode7打包以后安装到iOS10可以收到推送但是还是不响应推送处理的方法。
暂时解决办法是使用Xcode7开发最后发版使用Xcode8
Xcode7打包报错应该有解决办法,暂时留个坑
代码适配
因为用的第三方,所以按着文档来就好了,但是也有一些小坑
#ifdef NSFoundationVersionNumber_iOS_9_x_Max |
#ifdef NSFoundationVersionNumber_iOS_9_x_Max |
有趣的是iOS10当App正在运行时候也可以在上方弹出推送框
此文为简书旧文
最近公司开发者账号马上到期了,需要进行续费工作。现在记录一下流程和遇到的一些坑。
首先登陆开发者中心https://developer.apple.com/
选择右上方的Account,然后输入账号和密码。进入后如果过期时间小于30天,在首页会给你一个小弹窗告诉你要续费。
update
补充下图片,当还有一个月过期时候,登录iTunes Connect 或者开发者中心都会有提示信息
做iOS开发已经有几年了,中间也积累下了不少工具
做一个总结吧
一、Mac 菜单栏工具
Barteder是一款优秀的菜单栏管理工具,可以把一些不常用的隐藏起来,将大量的菜单有选择折进 Bartender 的二级菜单,不仅会看起来更整洁,使用起来也不会造成太大的麻烦。配合下面的 iStar Menus 食用更加
官网地址:https://www.macbartender.com/
这个工具可以监测Mac的各种性能,并且可以就改样式颜色等。装逼利器之一~