iOS

iOS读书笔记

iOS读书笔记

Posted by 袁平 on February 15, 2019

前言

iOS 各类书籍读书笔记

摘要各本书中重难点


正文


Objective-C 编程之道:iOS 设计模式

  1. 中介者模式是至用一个对象来封装一组对象之间的交互逻辑,中介者通过避免对象间显示的相互引用来增进不同对象间的松耦合

  2. 备忘录模式允许对象按其想要的任何(或者任意复杂的)方式将自己的壮状态保存为一个对象,根据此模式这个对象被称为备忘录对象,然后某个其他对象,比如看管人对象,将备忘录对象保管在某处,通常是文件系统或内存中;看管人对象不知道有关备忘录对象的任何细节的格式,一段时间之后,接收到请求时,看管人对象将备忘录对象传回给原来的对象,让他根据在备忘录对象中保存的信息恢复其状态

  3. 代理模式的一个特点是同归虚拟代理,在接到请求时实现重型资源的懒加载

  4. 软件设计的黄金法则:变动需要抽象

  5. 桥接模式的目的是把抽象层次结构从其实现中分离出来,使其能够独立变更;抽象层定义了供客户端使用的上层抽象接口;可以参见博客

  6. 外观模式为子系统中一组不同的接口提供统一的接口呢,外观模式定义了上层接口,通过降低复杂度和隐藏子系统间的通信及依存关系,让子系统更易于使用(其实就是对一系列复杂操作再次进行封装,隐藏调用或者实现细节)

  7. 中介者模式用于定义一个集中的场所,对象间的交互可以在一个中介者对象中处理;其他对象不必彼此交互,因此减少了它们之间的依存关系

  8. 观察者模式:iOS 中观察者模式可以通过通知和键值观察(KVO)来实现

  9. 迭代器模式:迭代器(Iterator)提供了一种顺序访问聚合对象(集合)中元素的方法,而无需暴露结构的底层表示和细节

  10. 装饰模式:即动态的为一个对象添加额外的指责,是继承的替代方案,属于结构型模式(继承是编译时静态绑定,装饰模式是可以在运行是动态绑定,即定义一个接口,然后动态的注入不同的实现类)

  11. 责任链模式:即如果一个对象不知道如何处理一个请求,则将该请求传递给另一个对象,这样继续传递下去

  12. 策略模式:提取公共接口,不同实现

  13. 命令模式:将请求封装为一个对象,从而可用不同的请求对客户进行参数化,对请求排队或者记录请求日志,以及支持可撤销的操作

  14. 享元模式:实现享元模式需要两个关键组件,通常是可共享的享元对象和保存他们的池

  15. 代理模式:代理是一种替代或占位,它控制对另一些对象的访问,而这些对象可能是远程对象,创建的开销较大的对象,或者是对安全性有要求的对象(NSProxy)


UICollectionView解析

  1. UICollectionViewCell 的层级结构见下图;UICollectionViewCell 有三个子 View ,下图中黑色矩形是 CollectioView Cell 自身,绿色矩形是 contentView,我们应该在contentView上面添加子 View,中间的两层 selectedBackgroundView 和 backgroundView 是可选的,并且可以在任何时候进行设置(当 backgroundView 被设置的时候,将会永远显示;selectedBackgroundView 在 Cell 被选中的时候设置,在 Cell 取消选中的时候移除,并且还可以为其设置动画)


iOS Drawing: Practical UIKit Solution

  1. Context:包含了绘图的上下文环境;主要使用的有两种:
    1. Bitmap Context:使用像素数据来绘制
    2. PDF Contexta:矢量数据,以矢量的形式来绘制
    3. Core Image Context:帮助进行图像处理,如数字图像处理和计算机视觉等,通过GPU加速
  2. iOS绘图程序主要基于UIKit和QuartzCore框架(QuertzCore框架通常被称作Quartz或者Quartz 2D),它由新的Objective-C界面(UIKit提供)和老旧一些的C语言方法和核心基础类(QuartzCore)组成

  3. 在绘制图像的时候,有一个很重要的概念是上下文(Context),其实类似于一个大的状态机,每次改变都会改变其当前状态,可以通过 CGContextSaveGState 来暂存当前状态,之后通过 CGContextRestoreCState 来恢复状态;可以改变 Context 的属性如下图:

  1. 需要注意的是 UIKit 中坐标系原点为屏幕坐上点,在Quartz中,原点位于左下点,如下图;

  1. Quartz 和 UIKit 绘图方法都是线程安全的

  2. 以CG开头Ref结尾的类型是指,指向对象的指针

  3. 坐标系转换,即把一个点从视图坐标系转换到它的父视图的坐标系中:CGPoint convertedPoint = [fahterView convertPoint:samplePoint fromView:childView]; 如果要反向转换,可以使用:转换回来,使用convertRect:toView:;前提是这些视图必须在同一个 UIWindow 中

  4. CGAffineTransform 可以用于进行旋转,缩放,位移变换(其实也是一个变换矩阵,如下图);一般都不使用 CGAffineTransformMake 方法来构建,通常使用 CGAffineTransformMakeScale(),CGAffineTransformMakeRotate()或是CGAffineTransformMakeTranslation()来分别构造缩放,旋转,位移矩阵;可以通过 UIKit 的 NSStringFromCGAffineTransform 方法打印处转换后的矩阵值;

  1. CGPoint,CGRect,CGSize,CGAffineTransform等几何元素并不是对象,如果要存储或者更加直观的打印这些几何元素,OC 也提供了对应的方法,如:
    1. 转换为 strings

  1. 转换为字典

  1. 转换为值类型

  1. 几何测试方法


Swift文档

http://www.swift51.com/swift4.0/chapter2/10_Properties.html

  1. 结构体和枚举是值类型,这意味着它们的实例,以及实例中所包含的任何值类型属性,在代码中传递的时候都会被复制;值类型被赋予给一个变量、常量或者被传递给一个函数的时候,其值会被拷贝;在 Swift 中,所有的基本类型:整数(Integer)、浮点数(floating-point)、布尔值(Boolean)、字符串(string)、数组(array)和字典(dictionary),都是值类型,并且在底层都是以结构体的形式所实现

  2. 类是引用类型;可以使用恒等运算符(===!==)来判断两个常量或变量是否引用同一个类实例;Objective-C 中NSString,NSArray和NSDictionary类型均以类的形式实现,而并非结构体

  3. 存储属性存储常量或变量作为实例的一部分(varlet),而计算属性计算(不是存储)一个值。计算属性可以用于类、结构体和枚举,存储属性只能用于类和结构体;一个存储属性就是存储在特定类或结构体实例里的一个常量或变量;计算属性不直接存储值,而是提供一个 getter 和一个可选的 setter,来间接获取和设置其他属性或变量的值

  4. 延迟存储属性(lazy),即第一次使用的时候才会计算其值;必须将延迟存储属性声明成变量(使用 var 关键字),因为属性的初始值可能在实例构造完成之后才会得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性(如果一个被标记为 lazy 的属性在没有初始化时就同时被多个线程访问,则无法保证该属性只会被初始化一次);全局的常量或变量都是延迟计算的,跟延迟存储属性相似,不同的地方在于,全局的常量或变量不需要标记lazy修饰符(全局变量是在函数、方法、闭包或任何类型之外定义的变量)

  5. 属性观察器:willSet 在新的值被设置之前调用;didSet 在新的值被设置之后立即调用;父类的属性在子类的构造器中被赋值时,它在父类中的 willSet 和 didSet 观察器会被调用,随后才会调用子类的观察器。在父类初始化方法调用之前,子类给属性赋值时,观察器不会被调用

  6. 类型属性:即与类相关的属性(而非与特定实例相关);使用关键字 static 来定义类型属性;在方法的func关键字之前加上关键字static,来指定类型方法(类还可以用关键字class来允许子类重写父类的方法实现)

  7. 结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一(在 Objective-C 中,类是唯一能定义方法的类型)

  8. 下标:下标可以定义在类、结构体和枚举中;一个类型可以定义多个下标,通过不同索引类型进行重载。下标不限于一维,你可以定义具有多个入参的下标满足自定义类型的需求;定义下标使用subscript关键字

  9. 可以通过把方法,属性或下标标记为final来防止它们被重写,只需要在声明关键字前加上final修饰符即可;也可以将类标记为final的,那么此时该类不可被继承

  10. 指定构造器:指定构造器是类中最主要的构造器;每一个类都必须拥有至少一个指定构造器,在某些情况下,许多类通过继承了父类中的指定构造器而满足了这个条件

  11. 便利构造器:类中比较次要的、辅助型的构造器(在init关键字之前放置convenience关键字)。你可以定义便利构造器来调用同一个类中的指定构造器,并为其参数提供默认值。你也可以定义便利构造器来创建一个特殊用途或特定输入值的实例(应当只在必要的时候为类提供便利构造器)

  12. 在类的定义中,每个类最多只能有一个析构器,而且析构器不带任何参数

  13. Swift通过引用计数来实现内存管理,引用计数仅仅应用于类的实例。结构体和枚举类型是值类型,不是引用类型,也不是通过引用的方式存储和传递;Swift 提供了两种办法用来解决你在使用类的属性时所遇到的循环强引用问题:弱引用(weak reference)和无主引用(unowned reference)(弱引用和无主引用允许循环引用中的一个实例引用而另外一个实例不保持强引用。这样实例能够互相引用而不产生循环强引用)
    1. 弱引用(weak):当其他的实例有更短的生命周期时,使用弱引用;当实例被销毁后置为nil
    2. 无主引用(unowned):当其他实例有相同的或者更长生命周期时,使用无主引用;当实例被销毁后不会被置nil(无主引用通常都被期望拥有值,使用无主引用,你必须确保引用始终指向一个未销毁的实例,如果你试图在实例被销毁后,访问该实例的无主引用,会触发运行时错误)
    3. 隐式解析可选属性
  14. 闭包也是引用类型,当闭包和类混用时需要注意不要引起引用循环,可以使用如下功能解决:
lazy var someClosure: (Int, String) -> String = {
    [unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in
    // 这里是闭包的函数体
}

lazy var someClosure: Void -> String = {
    [unowned self, weak delegate = self.delegate!] in
    // 这里是闭包的函数体
}
  1. Swift会自动调用父类的初始化方法(在子类初始化方法的末尾(而不是开始))

AutoLayout文档

  1. https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/AutolayoutPG/AnatomyofaConstraint.html
  1. AutoLayout实际上是解一个线性方程组;可以设置每一个约束的优先级