iOS开发中非业务类一些坑和技巧记录

罗列下这几年开发iOS的一些坑和个人的一些技巧总结。全是回忆所得,并不完整。

1.属性修饰符误写,例如float写了strong等,容易出现手误。其实这个可以用脚本检查。

2.WP本地js跨域问题。这不是iOS问题,是WP问题,最好是把网页做成远端的,当初采用本地原生请求,传数据到js处理。这个问题我一直记着,当初就有跨域的猜测,直到后来对web开发有了更多的了解之后,才肯定了这点。

3.系统联系人选择器dismiss问题。处理办法:初期作为tabbarVC的一个tab来避免,后期因内置行为不符合我们的需要,直接拨打了,没法自定义点击后的行为,于是采取自定义联系人选择器。

4.七牛短视频切片播放不完全。处理办法:未处理,可以考虑不切片,暂时不清楚是否是切片导致。

5.七牛视频上传方向问题。处理办法:未处理,可以考虑上传cdn前进行校正,或者存储视频方向等办法。

6.block内存泄漏问题。处理办法:MLeakers发现并修正,人肉识别,提升对block的认识之后,可以避免这些问题,例如UIVIew动画一般不会导致循环引用,类似的类方法一般不会导致循环引用。

7.个推UserNotification因为强连接导致低版本iOS系统上崩溃问题。处理办法:使用弱连接。这是我第一次听说这种framework的链接方式,原来要区分强链接和弱链接。

8.推送没有处理前后台判断,导致前台直接跳页面。处理办法:判断了收到通知时的前后台状态。刚做推送,没料到应用在前台也会收到静默的推送消息。

9.json model特性,字段多于实际接收会解析失败。处理办法:线上全部可选,开发限制。刚接触json转model,以前都是XML?。经常遇到缺字段,导致页面变空白了,线下还好,线上就麻烦了。后来为了扩大容错性,BaseModel里根据debug编译标识返回全部可选或不可选,子类可以按需覆盖。

10.配置了过多图片,导致内存暴涨崩溃。处理办法:跳过了SDWebImage的转码功能。

11.手机内存及其紧张时,二维码扫描库Zxing及其封装都会发生崩溃。感觉内存不足会影响自动释放的性能。

12.多个App使用相同的scheme导致冲突。处理办法:后续将scheme配置在info文件里了。这个需要配合我们的URL组件化机制。

13.网络鉴权问题,处理办法:通过版本检测先触发网络鉴权,引导图消失前发个通知让首页重新加载。

14.BlocksKit库多次bk_whenTapped导致卡顿。处理办法:只在cell的init里或者View的懒加载的初始化中调用。

15.某个页面设置了UITextField、UITextView的inputAccessoryView,如果重置会导致inputAccessoryView出现在别的页面,而inputAccessoryView里添加的UIBarButtonItem的target和action是另一个页面的,可能会导致崩溃或者看起来无响应。处理办法:后来使用IQKeyboardManager管理键盘。

16.微信分享预览图分辨率限制问题,图片过大导致无法唤起分享。处理办法:通过重绘限制分辨率和转换成JPEG,不断尝试压缩比例。

17.下拉刷新清空数组,请求完成后数据加到数据在刷新这段时间内,滚动tableview就会发生数组越界问题。处理办法:使用安全的数组方法和将数组清空放到请求完成才进行。

18.某些页面会触发登陆,跳到登录页面,这时候用户不点登陆返回就会陷入循环中。处理办法:触发登陆后pop到根视图控制器,选择不会触发登陆的首页tab,然后push登录页面进去。会打破正常交互流程,但不会陷入循环中。

19.引导图过大长期驻留内存。处理办法:不放在assets里,不使用imageNamed。

20.iOS9以前注册通知中心不移除,对象dealloc后发生崩溃。KVO也有类似问题。

21.NSTimer强引用导致的循环引用问题,自己捕获自己引起的循环引用问题等。

22.注册通知的时机问题。有些通知可以推迟到didLoadView注册,有些init的时候就得注册。例如tabbar item是可配置的,那么请求得到配置后,就得发通知让TabBar VC的所有children自行改变item,这时候由于一些页面并未显示出来,didLoadView就不会被调用,在这里的注册的通知不会被观察到。

23.标记代替调用。我们从一个页面push到另一个页面后,在新的页面进行操作可能会对前面一个页面产生影响,需要刷新前面一个页面。但是每次做修改,就刷新前面一个页面又没有必要,因为页面被遮挡了。此时可以发送通知让前面一个页面标记为再次展示时需要刷新。当pop到那个页面时,那个页面的viewWillAppear才去检查刷新标志位,判断是否需要刷新页面。

24.performSelector系列不能传基本类型数据。如果你想通过performSelector为一个属性设置BOOL型NO是不能实现的。因为@(NO)作为bool参数的实际值时是对象地址,必然为YES。

25.某段时间不知道是服务器抽风还是怎么的,加载页面很慢,导致审核被拒,说页面空白。后来给加载图片的地方都加了灰色的占位图,不是纯色的话,可能会变形。由于用的SDWebImage,只需要在最高层的接口写死默认的占位图就可以了。不同的业务需要被不同占位图时,采用较低一级的接口指定占位图即可。

26.对于请求的设计。

请求除了API要求的业务参数外,应该由框架自动添加全局参数,全局参数包括版本号、客户端类型、sign等。版本号、客户端类型用于版本检测、兼容性处理、统计等目的。sign则是作为登陆用户的唯一标识。这些参数不仅要带入接口,也要带入webview组件中。

响应一般包括状态码,消息短语,响应内容实体组成。参考结构如下:

```
    {
        status:{
            code:1001,
            message:"OK"
        },
        result:{}
    }
```
我们需要对status进行分类,哪些是正常的,那些是异常的。正常我们一般就1001,message可以是正确反映接口行为的,也可以是笼统的OK。前者的话,后端压力较大,需要指定不同的提示。后者前端需要灵活展示,又要考虑各端的一致性问题。对于异常类的code,那么只能后端提供错误提示了,因为前端对此并不知晓。在一般开发中,可以定义若干个固定的异常,例如要触发跳转登陆页面的(这种情况适合必须要登录才能完成余下操作的,例如商品页面到确认订单页面),要提示未登录的(这种情况适合业务上要求页面需要根据登陆与否展示不同的样子),要返回上个页面的(这种情况比较罕见,例如你在商品页面缺乏检查接口,跳到确认订单页面时才发现商品不可购买,这时候最好是提示后返回上个页面)等。固定的code适合所有的业务,属于保留code。每个业务又可以根据自己的特点增加code,属于自定义code。对于保留的code,都是框架内部处理即可,业务层不需要关心它们,只需要展示消息即可。框架内部可以提供一些block来全局处理固定的code。但是我们实践中并未遇到这种需求。

27.cell的高度存储。面对复杂的cell,我们一般为提高性能,会将cell的高度存起来,避免多次计算,这是一种空间换取时间的策略。每个cell的高度我们可以考虑存在VC的mutable dictionary中,以indexPath为键,高度为值。这里有些问题,一每个页面都要提供这个可变字典,并提供读写设施。二不适合列表数据会变动的情况,例如列表中的项目可能会被删除、修改等。使用id代替indexPath可以解决项目被删除的问题。但是项目在本地被修改需要更新高度,在远端被修改需要刷新列表数据同时重建可变字典。还有一种思路是将高度存在模型中,这样就不需要可变字典和读写设施了,但是每次刷新数据,高度都需要重新计算,这种刷新是符合一般需求的。唯一的缺陷是不适合单个模型多个视图的情况,但是这种情况很罕见,例如左侧有一个联系人列表,右侧有个选中的联系人列表,它们的模型相同,但是cell是两种cell,这时候模型想存储多种高度就不可行了。这种模型很容易实现,只需要在基类增加__height或xxHeight等不会被业务使用到的字段就行,并不会增加太多负担和侵入,但是要为模型中的字段增加高度支持就会污染模型,因为它们需要在业务模型中分别增加,还会和业务字段混在一起。顺便说道,这种为业务模型增加本地字段,提供额外的功能支持,还被用在列表的选择(本地增加xxSelected字段)等场景。

28.请求基类的利用。我们的请求按功能是可以划分为基础请求和业务请求的。基础请求往往是那些上传图片、文件、获取省市区信息等的接口,它们往往可以分成多个请求,分别归属到FileRequest和LocationRequest下,也可以一股脑儿放到UtilsRequest下。但是归属到BaseRequest下的话,可以在任意请求中使用它们,而无需导入业务请求之外的头文件,也就给编码带来一些便利。

29.Xcode9.2打包App在iOS8.1-iOS8.3上图片花屏(https://www.jianshu.com/p/5f0f2004bd64)当时是回退到Xcode9.1打的包。没办法,不可能不用assets。

30.这个跟业务有点关系,以前项目中用到了趣拍SDK,通过method swizzling改变了一些功能,例如拍摄分辨率,授权验证等。发现它没有实现imagepicker的一个代理,导致不能dismiss,就用class_add给它加了个imagePickerControllerDidCancel的实现。发现会在iOS7上崩溃,最后定位到原因是使用了iOS8上才引入的NSURLQueryItem,就替换了它的实现。这里主要是说,掌握runtime的一些技巧,有助于解决一些本来要央求他人的问题,显然我们不能等待人家修复这个问题才上线。

31.用手写一堆视图的属性是很繁琐的事情,因此根据我们的框架和我的编码习惯,我开发了根据属性一键生成属性代码的Xcode插件,生成完之后,只需要根据设计稿去设置字体、颜色、frame就行,大大减轻了敲代码的负担,也统一了编码风格。这个插件的github地址:
https://github.com/Mamong/XMCodeGenerator。稍作修改应该就可以适应不同的项目中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值