前言
在平时的日常工作、学习、开发、写博客能巩固自身!
正好,这次就借着这个机会分享一波,不出意外又是一篇托家底的分享,大家记得点赞、收藏。好东西记得分享哦。
首先如何解决35岁程序员误解?
古人云:“活到老,学到老。”互联网算是最辛苦的行业之一,“加班”对程序员来说已是“家常便饭”,同时互联网技术又日新月异,很多程序员都疲于应付,叫苦不堪。
以至于长期以来流传一个很广的误解:35岁是程序员工作的终点。
如何在繁忙的工作中做好技术积累,构建个人核心竞争力,相信是很多程序员都在思考的问题。
对于当下的生存,个人的意见仍然是去依附,尤其是依附于单一公司,个人发展要适配市场需求,同时在资本回报率远大于劳动回报率的大背景下,能够早日攒下资本实现资产增值和收入多样化是我们的最终目标。
- 对于一穷二白的年轻人,无非四条路:
年轻时应该选择当下高回报的技术路径,早日攒下可观的财富,去买楼买铺,为自己获取资产保障,靠资本投资或者被动收入保底。
打通技术栈,不再专纠结于细节,将自己摆在供应商的位置,将公司摆在客户的位置,将自己的技术团队和开发成果打造成为公司业务链中的一环,而不是一颗精密的螺丝钉,然后慢慢从技术思维过渡到客户服务思维,争取将团队的开发成果产品化打造成同类市场产业链中的一环,可以为行业内其他公司提供整套技术咨询和开发服务,填补一定的市场空白,总体而言就是:功能->模块->框架->产品的进化。
尽管仍然是行业依附,但至少了对公司的依附,有机会获取超越工资收入的财富,进行更多的资本投资保障未来生活。进入师医公等类体制内工作, 尽管收入不高,但目前看来至少能保底,还有一定社会地位。
不做有明确成长路径的技术类工作,从事创意类工作,并且要善于利用互联网早日攒下名声和流量,可以靠流量和名声生活,同样美滋滋,优点是替代性小,大流量可以攒下巨大财富,可以尽早进行资本增值,保障后半辈子生活。缺点是太吃天赋和运气,上限下限差距过大,有点赌博性质,而且要能做拉得下脸割粉丝韭菜的心理建设。
技术本身不是最重要的,重要的是持续地学习。
文章进阶路线图,需要的可以自行保存下载
进阶总纲
iOS开发
视频分析iOS架构模式
观看地址:https://www.bilibili.com/video/BV1wA411H7jB
视频解析手把手教iOS音视频开发
观看地址:https://space.bilibili.com/107521719/channel/detail?cid=157340&ctype=0
函数响应式编程
一: 函数式
函数式编程简称FP(FunctionalProgramming),函数式编程就是一种抽象程度很高的编程范式,它将计算机运算看做是数学中函数的计算,而纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。
而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。
常规需求例子,感受函数式的舒服!
let array = [1,2,3,4,5,6,7,8,9,10] for num in array{ if num > 2{ let number = num + 1 if (number % 2 == 0) { print(number) } } }
let array = [1,2,3,4,5,6,7,8,9,10] array.filter{ $0 > 2} .filter{ ($0+1) % 2 == 0 } .forEach { print($0) }
二: 响应式
对象对某一数据流变化做出响应的这种编码方式称为响应式。
例如我们在爱奇艺平台观看视频,我们只需要在某一个时刻订阅了这个视频,后面平台自媒体运营者不断更新视频,我们随着时间也能自定接受推送,这就是响应在iOS开发中我们经常会响应一些事件button、tap、textField、textView、notifaction、KVO、NSTimer等等这些,都需要做响应监听,响应后都需要在对应的响应事件中去做处理,而原生开发中,触发对象与响应方法是分离的,如button的初始化和点击响应方法是分离的。功能代码与逻辑代码分析,导致很多比较恶心的感觉!
blingbling, blingbling, blingbling!
RxSwift 闪亮登场
ReactiveX不仅仅是一个编程接口,它是一种编程思想的突破,它影响了许多其它的程序库和框架以及编程语言。它拓展了观察者模式,使你能够自由组合多个异步事件,而不需要去关心线程,同步,线程安全,并发数据以及I/O阻塞。
RxSwift 是 Rx 为 Swift 语言开发的一门函数响应式编程语言, 它可以代替iOS系统的 Target Action / 代理 / 闭包 / 通知 / KVO,同时还提供网络、数据绑定、UI事件处理、UI的展示和更新、多线程……
鉴于Swift日渐增长的影响力,ios开发者不可避免的要学习和使用Swift这门语言进行编程开发。
RxSwift对使用Swift的帮助有如下几点:
Swift为值类型,在传值与方法回调上有影响,RxSwift一定程度上弥补Swift的灵活性
一: button点击事件
//MARK: - RxSwift应用-button响应 func setupButton() { // 传统UI事件 self.button.addTarget(self, action: #selector(didClickButton), for: .touchUpInside) // 这样的操作 - 不行啊!代码逻辑与事件逻辑分层 self.button.rx.tap .subscribe(onNext: { [weak self] in print("点了,小鸡炖蘑菇") self?.view.backgroundColor = UIColor.orange }) .disposed(by: disposeBag) }
二: textfiled文本响应
//MARK: - RxSwift应用-textfiled func setupTextFiled() { // 我们如果要对输入的文本进行操作 - 比如输入的的内容 然后我们获取里面的偶数 // self.textFiled.delegate = self // 感觉是不是特别恶心 // 下面我们来看看Rx self.textFiled.rx.text.orEmpty.changed.subscribe(onNext: { (text) in print("监听到了 - \(text)") }).disposed(by: disposeBag) self.textFiled.rx.text.bind(to: self.button.rx.title()).disposed(by: disposeBag) }
三: scrollView效果
//MARK: - RxSwift应用-scrollView func setupScrollerView() { scrollView.rx.contentOffset.subscribe(onNext: { [weak self] (content) in self?.view.backgroundColor = UIColor.init(red: content.y/255.0*0.8, green: content.y/255.0*0.3, blue: content.y/255.0*0.6, alpha: 1); print(content.y) }).disposed(by: disposeBag) }
四: KVO
//MARK: - RxSwift应用-KVO func setupKVO() { // 系统KVO 还是比较麻烦的 // person.addobserver(self, forKeyPath: "name", options: .new, context: nil) person.rx.observeWeakly(String.self, "name").subscribe(onNext: { (change) in print(change ?? "helloword") }).disposed(by: disposeBag) }
原生KVO就需要三部曲,非常恶心,其实对于我们开发来说根本没必要! RxSwift还是温柔的一句代码搞定
五: 通知
//MARK: - 通知 func setupNotification(){ NotificationCenter.default.rx .notification(UIResponder.keyboardWillShowNotification) .subscribe { (event) in print(event) }.disposed(by: disposeBag) }
六: 手势
//MARK: - 手势 func setupGestureRecognizer(){ let tap = UITapGestureRecognizer() self.label.addGestureRecognizer(tap) self.label.isUserInteractionEnabled = true tap.rx.event.subscribe { (event) in print("点了label") }.disposed(by: disposeBag) }
很多小伙伴可能会吐槽手势怎么不那么爽!其实你误解,RxSwift是实现的响应关系,本身手势也是需要添加事件对象的!
- 当然这里我个人建议:
降低代码量 感觉RxSwift会把开发者变傻,哈哈哈…
- 可以更多拓展一层!
七: 网络请求
//MARK: - RxSwift应用-网络请求 func setupNextwork() { let url = URL(string: "https://www.baidu.com") URLSession.shared.rx.response(request: URLRequest(url: url!)) .subscribe(onNext: { (response, data) in print("response ==== \(response)") print("data ===== \(data)") }, onError: { (error) in print("error ===== \(error)") }).disposed(by: disposeBag) }
针对URLSession也是封装处理。
提供了response,data,json不同的便于开发者选择的合适函数,说白就是方便
但是针对网络这一层,我们一般开发肯定是要处理,不可能这么简单(毕竟不符合开发需求)
其实RxSwift在网络这一层也是有很多响应式处理:比如典型的RxMoya
八: timer定时器
//MARK: - RxSwift应用-timer定时器 func setupTimer() { timer = Observable.interval(1, scheduler: MainScheduler.instance) timer.subscribe(onNext: { (num) in print("hello word \(num)") }).disposed(by: disposeBag) }
- RxSwift实现的timer免去了我们计时器的一些不必要的麻烦
- runloop影响
- 销毁问题
- 线程问题
RxSwift这个框架非常牛逼,把函数响应式玩到了高潮!无论从代码量,还是从代码的可读性,抑或代码的复用性…都是大大优化!让开发者抛弃更多的胶水代码,直面开发需求。如果你还在为你开发效率而烦恼,那么RxSwift是你不二的选择!
性能优化探索
一、入门级
1、 用 ARC 管理内存
2、 在正确的地方使用reuseIdentifier
3、 尽量把 views 设置为透明
4、 避免过于庞大的 XIB
5、 不要阻塞主线程
6、 在 ImageViews 中调整图片大小。
如果要在 UIImageView 中显示一个来自 bundle 的图片,你应保证图片的大小和 UIImageView 的大小相同。
在运行中缩放图片是很耗费资源的,特别是 UIImageView 嵌套在
UIScrollView中的情况下。如果图片是从远端服务加载的你不能控制图片大小,比如在下载前调整到合适大小的话,你可以在下载完成后,最好是用
backgroundthread,缩放一次,然后在 UIImageView 中使用缩放后的图片。
7、 选择正确的 Collection。
8、 打开 gzip 压缩。
app 可能大量依赖于服务器资源,问题是我们的目标是移动设备,因此你就不能指望网络状况有多好。减小文档的一个方式就是在服务端和你的 app
中打开 gzip。 这对于文字这种能有更高压缩率的数据来说会有更显著的效用。 iOS 已经在 NSURLConnection 中默认支持了
gzip 压缩,当然 AFNetworking 这些基于它的框架亦然。
二、中级
1、 重用和延迟加载(lazy load) Views
2、 Cache, Cache, 还是 Cache!
3、 权衡渲染方法.性能能还是要 bundle 保持合适的大小。
4、 处理内存警告.移除对缓存,图片 object 和其他一些可以重创建的 objects 的 strongreferences.
5、 重用大开销对象
6、 一些 objects 的初始化很慢,比如 NSDateFormatter 和 NSCalendar。
然而,你又不可避免地需要使用它们,比如从 JSON 或者 XML 中解析数据。
想要避免使用这个对象的瓶颈你就需要重用他们,可以通过添加属性到你的 class 里或者创建静态变量来实现。
7、 避免反复处理数据.在服务器端和客户端使用相同的数据结构很重要。
8、 选择正确的数据格式.
解析 JSON 会比 XML 更快一些,JSON 也通常更小更便于传输。 从 iOS5 起有了官方内建的 JSON
deserialization 就更加方便使用了。 但是 XML 也有 XML 的好处,比如使用 SAX 来解析 XML
就像解析本地文件一样,你不需像解析 json 一样等到整个文档下载完成才开始解析。
当你处理很大的数据的时候就会极大地减低内存消耗和增加性能。
9、 正确设定背景图片
10、 减少使用 Web 特性。
想要更高的性能你就要调整下你的 HTML 了。
第一件要做的事就是尽可能移除不必要的 javascript,避免使用过大的框架。
能只用原生js 就更好了。
尽可能异步加载例如用户行为统计 script这种不影响页面表达的 javascript。
注意你使用的图片,保证图片的符合你使用的大小。
11、 Shadow Path 。
CoreAnimation 不得不先在后台得出你的图形并加好阴影然后才渲染,这开销是很大的。
使用 shadowPath的话就避免了这个问题。
使用 shadow path 的话 iOS 就不必每次都计算如何渲染,它使用一个预先计算好的路径。
但问题是自己计算path 的话可能在某些 View 中比较困难,且每当view 的 frame 变化的时候你都需要去 update shadow path.
12、 优化 Table View
13、 选择正确的数据存储选项
- NSUserDefaults 的问题是什么?
- 虽然它很 nice 也很便捷,但是它只适用于小数据,比如一些简单的布尔型的设置选项,再大点你就要考虑其它方式了
- XML 这种结构化档案呢?
- NSCoding?
- 在性能层面来讲,sqlite 和 Core Data 是很相似的。他们的不同在于具体使用方法。
- Core Data 代表一个对象的 graph model,但 sqlite 就是一个 DBMS。
- Apple 在一般情况下建议使用 Core Data,但是如果你有理由不使用它,那么就去使用更加底层的 sqlite吧。
- 如果你使用 sqlite,你可以用 FMDB 这个库来简化 sqlite 的操作,这样你就不用花很多经历了解 sqlite的CAPI了。
三、高级
1、 加速启动时间。
快速打开 app 是很重要的,特别是用户第一次打开它时,对 app 来讲,第一印象太 太太重要了。
你能做的就是使它尽可能做更多的异步任务,比如加载远端或者数据库数据,解析数据。 避免过于庞大的 XIB,因为他们是在主线程上加载的。
所以尽量使用没有这个问题的 Storyboards 吧! 一定要把设备从 Xcode 断开来测试启动速度
2、 使用 Autorelease Pool。
NSAutoreleasePool`负责释放 block 中的 autoreleased objects。 一般情况下它会自动被 UIKit
调用。
但是有些状况下你也需要手动去创建它。 假如你创建很多临时对象,你会发现内存一直在减少直到这些对象被 release 的时候。
这是因为只有当 UIKit 用光了 autorelease pool 的时候memory 才会被释放。
消息是你可以在你自己的@autoreleasepool 里创建临时的对象来避免这个行为。
3、 选择是否缓存图片。
常见的从 bundle 中加载图片的方式有两种,一个是用
imageNamed,二是imageWithContentsOfFile,第一种比较常见一点。
4、 避免日期格式转换。
如果你要用 NSDateFormatter 来处理很多日期格式,应该小心以待。
就像先前提到的,任何时候重用NSDateFormatters 都是一个好的实践。
如果你可以控制你所处理的日期格式,尽量选择 Unix 时间戳。
你可以方便地从时间戳转换到 NSDate:这样会比用 C 来解析日期字符串还快!
需要注意的是,许多 web API会以微秒的形式返回时间戳,因为这种格式在 javascript 中更方便使用。
记住用dateFromUnixTimestamp 之前除以1000 就好了。
- 利用性能分析工具检测,包括静态 Analyze 工具,以及运行时 Profile 工具,通过 Xcode 工具栏中
Product->Profile 可以启动 - 比如测试程序启动运行时间,当点击 Time Profiler 应用程序开始运行后.就能获取到整个应用程序
运行消耗时间分布和百分比.为了保证数据分析在统一使用场景真实需要注意一定要使用真机,因 为此时模拟器是运行在 Mac 上,而 Mac 上的cpu 往往比 iOS 设备要快。 - 为了防止一个应用占用过多的系统资源,开发 iOS的苹果工程师门设计了一个“看门狗”的机制。在不同的场景下,“看门狗”会监测应用的性能。如果超出了该场景所规定的运行时间,“看门狗”就会强制终结这个应用的进程。开发者们在crashlog 里面,会看到诸如 0x8badf00d 这样的错误代码。
优化 Table View
正确使用 reuseIdentifier 来重用 cells
尽量使所有的 view opaque,包括 cell 自身
尽量不适用 cellForRowAtIndexPath:,如果你需要用到它,只用一次然后缓存结果
使用 rowHeight, sectionFooterHeight 和 sectionHeaderHeight 来设定固定的高,不要请求 delegateUIImage 加载图片性能问题 • imagednamed 初始化
imageWithContentsOfFile 初始化
imageNamed默认加载图片成功后会内存中缓存图片,这个方法用一个指定的名字在系统缓存中查找并返回一个图片对象.如果缓存中没有找到相应的图片对象,则从指定地方加载图片然后缓存对象,并返回这个图片对象.
imageWithContentsOfFile 则仅只加载图片,不缓存.
加载一张大图并且使用一次,用 imageWithContentsOfFile 是最好,这样 cpu 不需要做缓存节约时间.
使用场景需要编程时,应该根据实际应用场景加以区分,UIimage 虽小,但使用元素较多问题会 有所凸显.
不要在 viewWillAppear 中做费时的操作:
viewWillAppear:
在正确的地方使用 reuseIdentifier:
table view 用tableView:cellForRowAtIndexPath:
- 为 rows 分配 cells 的时候,它的数据应该重用自UITableViewCell。
尽量把 views 设置为透明:
避免过于庞大的 XIB:
不要阻塞主线程:
facebook 启动时间优化
瘦身请求依赖
UDP 启动请求先行缓存
队列串行化处理启动响应
Alamofire全部实现共有17个文件组成,如下:
--------接口---------- Alamofire.swift // api 声明 --------请求---------- Request.swift // 请求类,用于构建请求 ParameterEncoding.swift // 参数编码 MultipartFormData.swift // 自定义表单类 ServerTrustPolicy.swift // 服务器验证 --------响应----------- Response.swift // 相应类,用于构建响应 ResponseSerialization.swift // 响应数据序列化 Validation.swift // 响应数据验证 Result.swift // 请求结果表示 AFError.swift // 错误类型 --------底层----------- SessionManager.swift // 请求session的管理类,底层使用NSURLSession实现 SessionDelegate.swift // 请求Session的代理对象,主要实现NSURLSession的代理方法以及回调闭包 TaskDelegate.swift // 请求Task任务的代理对象,主要实现NSURLDataTask的代理方法 dispatchQueue+Alamofire.swift //GCD扩展,定义多个不同功能的队列 ---------其他----------- NetworkReachabilityManager.swift // 网络状态监听类 Notifications.swift // 定义通知 Timeline.swift //描述请求有关的时间 结构体
Alamofire有五模块组成,即接口、请求、响应、底层和其他。分析各模块的实现,功能和联系就可以理解Alamofire。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。