Day1

作者: Jean_Lina | 来源:发表于2020-07-25 18:15 被阅读0次

1 KVO方法 注册监听者:

1:所有的KVO会统一调用此方法

2:在程序中,通常只监听某一个对象的多个属性,如果属性太多,方法会很乱。

3:观察者模式,在不需要的时候,都需要释放。

4:通知中心:如果不释放,什么也不发生,但是会有内存泄露,会有多次注册的可能。

5:KVO如果不释放,会崩溃。

所有的下拉刷新框架都是监听父视图contentOffset。

2 关于表格的性能优化

(1)不要动态的创建控件,所有需要的控件,都需要提前创建好,在显示的时候,根据数据隐藏或显示

(2)cell中的控件层次越少越好,数量越少越好

(3)控件上不要设置圆角半径,所有图像的渲染属性,都要注意

(4)尽量的少计算,所有需要的素材提前计算好

(5)如果每次在setter方法中做计算,会影响执行性能。

(6)行高一定要缓存(如果不需要缓存行高,刷新帧率就很高,可以不缓存。)
缓存行高是解决性能的最佳途径

(7)高级优化:离屏渲染、栅格化(如果检测到cell的性能已经很好,就不需要渲染)

(8) 离屏渲染需要在CPU和GPU之间快速切换,并且耗电比较厉害。

(9)要测量,不要猜测

加深版:UITableView性能优化

UITableView的回调顺序是先多次调用tableView:heightForRowAtIndexPath:以确定contentSize及cell的位置,然后才会调用tableView:cellForRowAtIndexPath:,从而来显示在当前屏幕的Cell。

(1)cell复用,极大减少内存的开销

(2)定义尽量少类型的cell,善用hidden隐藏、显示子视图

(3)提前计算并缓存cell的高度

(4)异步绘制,自定义cell绘制

(5)滑动时,按需加载

(6)缓存View
当cell中的部分View是非常独立的,并且不便于重用的,而且“体积”非常小,在内存可控的前提下,我们完全可以将这些view缓存起来。当然也是缓存在模型中。

(7) 图片处理
避免大量的图片缩放、颜色渐变等,尽量显示“大小刚好合适的图片资源”

(8) 数据处理
避免同步的从网络、文件获取数据,cell内实现的内容来自web,使用异步加载,缓存请求结果

(9)渲染处理
(1)减少subviews的个数和层级
子控件的层级越深,渲染到屏幕上所需要的计算量就越大;如多用drawRect绘制元素,替代用view显示

(2)少用subviews的透明图层
对于不透明的View,设置不透明opaque为YES,这样在绘制该View时,就不需要考虑被View覆盖的其他内容(尽量设置cell的view为opaque,避免GPU对Cell下面的内容也进行绘制)

(3)避免CALayer特效(shadowPath)
给cell中View加阴影会引起性能问题,会导致滚动时有明显的卡顿

3 计算型属性
1:不分配独立的存储空间保存计算结果。
2:每次调用时都会被执行。
3:更像一个函数,不过不能接收参数,同时必须有返回值。

var invitateFriendUrl: String {
        guard let userId = DNUserCenter.center.userId else { return "" }
        return DNEnglishInfo.currentEnvironment.webpageBaseURLString + "/#/earnCoins?koo_id=\(userId)"
    }

4 懒加载属性
1:在第一次调用时,执行闭包并且分配空间存储闭包返回的数值。
2:会分配独立的存储空间。

private lazy var backButton: UIButton = {
        let button = UIButton()
        button.setBackgroundImage(UIImage(named: "navigationbar_gray_back"), for: .normal)
        button.setBackgroundImage(UIImage(named: "navigationbar_gray_back"), for: .highlighted)
        button.addTarget(self, action: #selector(backButtonAction(_:)), for: .touchUpInside)
        return button
    }()

5 GCD

//全局队列,模拟耗时操作
DispatchQueue.global().async {
            FileManager.default.createFile(atPath: path, contents: data, attributes: nil)
 }
//主队列,回到主线程刷新UI
DispatchQueue.main.async {
            
 }

//线程停留
Thread.sleep(forTimeInterval: 3)

//打印当前线程
Thread.current

6 图片的性能优化:图片上下文+ UIBezierPath曲线

func avatarRoundedCornersImage(size: CGSize, cornerRadius: CGFloat, fillColor: UIColor = UIColor.white, completion: ((_ image: UIImage?)->())?) {
        DispatchQueue.global().async {
            UIGraphicsBeginImageContextWithOptions(size, true, UIScreen.main.scale)
            //设置背景填充颜色
            fillColor.setFill()
            let rect = CGRect(origin: CGPoint(), size: size)
            //矩形区域填充
            UIRectFill(rect)
            //利用贝塞尔路径裁切(实例化一条圆形路径)
            let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius)
            //对路径进行裁剪
            path.addClip()
            //绘制(在指定区域拉伸屏幕)
            self.draw(in: rect)
            UIColor(RGB: 0xF9C951).setStroke()
            path.lineWidth = adjustValue(2, 3.5)
            path.stroke()
            //获取结果
            let resultImage = UIGraphicsGetImageFromCurrentImageContext()
            //关闭上下文
            UIGraphicsEndImageContext()
            DispatchQueue.main.async {
                completion?(resultImage)
            }
        }
    }

7 闭包的使用场景:
(1)异步执行完成的回调。
(2)控制器间的回调。
(3)自定义视图的回调。
闭包的三种定义形式

 func closure() {
        //最简单的闭包,没有参数,没有返回值,in也可以省略
        let closure1 = {
            print("hello")
        }
        
        //有参数的闭包,所有的定义和实现都在{}内,定义和实现用in分割
        //{ (形参数) -> (返回值) in }
        let closure2 = { (x: Int) -> () in
            print("\(x + 20)")
        }
        
        //有参数和返回值的闭包
        let closure3 = { (x: Int) -> Int in
            return x + 10
        }
        
        closure1()
        closure2(20)
        let value = closure3(30)
    }

8 构造函数作用:为成员变量分配空间,并设置初始化值。

9 移动端开发,延迟加载,减少内存开销。

10 数据存储方式
(1)UserDefaults偏好设置,存储小数据
(2)沙盒
(3)数据库
(4)钥匙串访问(自动加密),存储小数据

11 Swift中的错误处理:
try?弱try 如果解析成功就有值,否则为nil

try!强try 如果解析成功就有值,否则崩溃有风险。

do{} catch{} 处理异常,能够接收错误并且输出错误。

12 OC开发,为什么不用try catch
ARC开发,编译器自动添加retain、release、autorelease

如果使用try catch 一旦不平衡,就会出现内存泄漏。

网友评论

      本文标题:Day1

      本文链接:https://www.haomeiwen.com/subject/mceplktx.html