iOS 11 UITableView delete rows animation bug
Set estimatedRowHeight, estimatedSectionHeaderHeight, and estimatedSectionFooterHeight to 0.
iOS 11 UITableView delete rows animation bug
Set estimatedRowHeight, estimatedSectionHeaderHeight, and estimatedSectionFooterHeight to 0.
1 | s.xcconfig = { 'LIBRARY_SEARCH_PATHS' => ' "$(PODS_ROOT)/VendorModule/VendorModule/WeChat" "$(PODS_ROOT)/VendorModule/VendorModule/Weibo"' ,'OTHER_LDFLAGS' => '-all_load' } |
Set ulimit -n / open files Permanently in ubuntu
1 | # available limit |
if you got error “sysctl: permission denied on key ‘fs.file-max’” or not effect , you can skip that step, then you doing steps as below :
1 | # edit the following file |
iOS APP启动速度优化的一些经验
应用启动流程
iOS应用的启动可分为pre-main阶段和main()阶段,其中系统做的事情依次是:
pre-main阶段
1.1. 加载应用的可执行文件
1.2. 加载动态链接库加载器dyld(dynamic loader)
1.3. dyld递归加载应用所有依赖的dylib(dynamic library 动态链接库)
main()阶段
2.1. dyld调用main()
2.2. 调用UIApplicationMain()
2.3. 调用applicationWillFinishLaunching
2.4. 调用didFinishLaunchingWithOptions
pre-main阶段
对于pre-main阶段,Apple提供了一种测量方法,在 Xcode 中 Edit scheme -> Run -> Auguments 将环境变量DYLD_PRINT_STATISTICS 设为1 :
main()阶段
对于main()阶段,主要是测量main()函数开始执行到didFinishLaunchingWithOptions执行结束的耗时,就需要自己插入代码到工程中了。先在main()函数里用变量StartTime记录当前时间:
CFAbsoluteTime StartTime;
int main(int argc, char * argv[]) {
StartTime = CFAbsoluteTimeGetCurrent();
double launchTime = (CFAbsoluteTimeGetCurrent() – StartTime);
pre-main阶段的优化
main阶段的优化
1 不使用xib,直接视用代码加载首页视图
2 NSUserDefaults实际上是在Library文件夹下会生产一个plist文件,如果文件太大的话一次能读取到内存中可能很耗时,这个影响需要评估,如果耗时很大的话需要拆分(需考虑老版本覆盖安装兼容问题)
3 每次用NSLog方式打印会隐式的创建一个Calendar,因此需要删减启动时各业务方打的log,或者仅仅针对内测版输出log
4 梳理应用启动时发送的所有网络请求,是否可以统一在异步线程请求
1 | <br />sudo apt install redsocks |
关于单例滥用导致的crash分析
原理
dispatch_once并不是简单的只执行一次那么简单
dispatch_once本质上可以接受多次请求,会对此维护一个请求链表
如果在block执行期间,多次进入调用同类的dispatch_once函数(即单例函数),会导致整体链表无限增长,造成永久性死锁。
优化
仅仅使用一次的模块,可以不使用单例,可以采用在对应的周期内维护成员实例变量进行替换。
和状态无关的模块,可以采用静态(类)方法直接替换。可以通过页面跳转进行依赖注入的模块,可以采用依赖注入或者变量传递等方式解决。
当然,的确有一些情况我们仍然需要使用单例。那在这种情况,也请将dispatch_once调用的block内减少尽可能多的任务,最好是仅仅负责初始化,剩下的配置、调用等等在后续进行。