Day3

作者: Jean_Lina | 来源:发表于2020-07-28 14:08 被阅读0次

1 runtime运行时机制
1:通过runtime,实现方法交换(交换两个类方法、交换两个实例方法)。
2:通过runtime,在分类中设置属性。
3:通过runtime,获取类的属性列表。
4:通过runtime,获取类的方法列表。
5:通过runtime,获取类的协议列表。
6:通过runtime,获取类的成员变量列表。
7:通过runtime,调用对象方法,让对象发送消息。
8:通过runtime,动态添加方法。
9:通过runtime,实现NSCoding的自动归档和解档。
10:通过runtime,实现字典转模型的自动转换。
11:通过runtime,动态修改变量的值。

运行时机制
(1)在程序中,使用运行时函数,动态获取类的属性列表、方法列表、协议列表、Ivar列表。OC的东西在运行时面前,一切都是裸露的。
(2)获取类的属性列表,可以通过KVC动态设置值。
(3)获取类的方法列表,可以通过sendMessage动态发送消息。
(4)获取Ivar列表,是所有第三方框架字典转模型的基础。
(5)基本数据类型,如果定义成可选的,使用运行时获取不到,使用KVC就会崩溃。
(6)private修改属性,使用运行时获取不到,使用KVC就会崩溃。

func propertyList() {
    //属性的数量
    var count: UInt32 = 0
    let list = class_copyPropertyList(UITextField.self, &count)
    var array = [String]()
    for i in 0..<Int(count) {
        //根据下标获取属性
        guard let pty = list?[i] else { continue }
        //获取属性名称C语言字符串
        let cname = property_getName(pty)
        //将属性名称,转换为String
        guard let name = String(utf8String: cname) else { continue }
        array.append(name)
    }
    //释放C语言对象
    free(list)
    print("array = \(array)")
    //class_copyIvarList(<#T##cls: AnyClass?##AnyClass?#>, <#T##outCount: UnsafeMutablePointer<UInt32>?##UnsafeMutablePointer<UInt32>?#>)
    //class_copyMethodList(<#T##cls: AnyClass?##AnyClass?#>, <#T##outCount: UnsafeMutablePointer<UInt32>?##UnsafeMutablePointer<UInt32>?#>)
    //class_copyIvarList(<#T##cls: AnyClass?##AnyClass?#>, <#T##outCount: UnsafeMutablePointer<UInt32>?##UnsafeMutablePointer<UInt32>?#>)
}

2 栈、堆区别
栈区(stack):由编译器自动分配释放,存放函数的参数值,局部变量等值。
栈是一个用来存储局部和临时变量的存储空间。
堆区(heap):一般由程序员分配释放,若程序员不释放,则可能会引起内存泄漏。
堆、栈、静态区。
栈和静态区是操作系统自己管理的
循环引用会导致堆里的内存无法正常回收。

3 NSThread和GCD相比,各自的优势和劣势
NSThread:轻量级的多线程开发,比较简单。需要自动管理线程生命周期。
GCD:基于C语言,不需要自动管理线程生命周期,自动利用更多的CPU内核,可用于多核的并行计算。

4 多线程
进程:一个运行中的应用程序。
线程: 程序执行流的最小单元,线程是进程中的一个实体。
队列: 装载线程任务的队形结构。

一个进程可有多个线程。
一个进程可有多个队列。
队列可分并发队列和串行队列。

5 iOS多线程对比
(1)NSThread:一个轻量级的多线程开发,但是需要自行管理生命周期。
优点:比较轻量级,可以直观的控制线程对象。
缺点:需要自己来管理线程生命周期,手动管理所有的线程活动,如生命周期、线程同步、睡眠等。线程同步对数据的加锁操作会有一定的系统资源开销。

(2)NSOperation:自带线程管理的抽象类。
优点:自带线程周期管理,操作上可更注重自己逻辑。
缺点:面向对象的抽象类,只能实现它或者使用它定义好的两个子类:NSInvocationOperation 和 NSBlockOperation。
(3)GCD(Grand Central Dispatch):
基于C语言的,负责创建线程和调度任务,由系统直接提供线程管理。GCD能够访问线程池,并且可在应用的整个生命的周期里面使用。提高系统资源利用效率,减轻系统的负载。

简单而安全的选择NSOperation实现多线程即可。
处理大量并发数据,又追求性能效率的选择GCD。

6 GCD有哪些好处:
(1)GCD可用于多核的并行运算
(2)GCD会自动利用更多的CPU内核(比如双核、四核)
(3)GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)

7 执行任务有两种方式:同步执行和异步执行
同步执行(sync):不具备开启新线程的能力,只能在当前线程中执行任务
异步执行(async):具备开启新线程的能力,可以在新的线程中执行任务

8 队列:用来存放任务的队列
串行队列(Serial Dispatch Queue):让任务一个接着一个地执行(一个任务执行完毕后,再执行下一个任务)

并发队列(Concurrent Dispatch Queue):可以让多个任务并行(同时)执行(自动开启多个线程同时执行任务)
并发队列只有在异步(dispatch_async)函数下才有效

主队列:GCD自带的一种特殊的串行队列
所有放在主队列中的任务,都会放到主线程中执行

异步执行 + 主队列并不会开启新的线程, 任务都是在主线程中执行的

image.png

9 在控制台输出一个菱形

// MARK: UIBezierPath + CAShapeLayer绘制菱形
    func drawPath() {
        let path = UIBezierPath()
        path.move(to: CGPoint(x: 60, y: 100))
        path.addLine(to: CGPoint(x: 100, y: 200))
        path.addLine(to: CGPoint(x: 240, y: 200))
        path.addLine(to: CGPoint(x: 200, y: 100))
        path.close()
        let layer = CAShapeLayer()
        layer.path = path.cgPath
        layer.strokeColor = UIColor.red.cgColor
        layer.fillColor = UIColor.yellow.cgColor
        view.layer.addSublayer(layer)
    }
// MARK: 设置UIView圆角
    public func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
    }

10 autoreleasepool的工作原理
自动释放池是NSAutorelease类的一个实例,当向一个对象发送autorelease消息时,该对象会自动入池,待池销毁时,将会向池中所有对象发送一条release消息,释放对象。

11 常用的设计模式
block、代理、通知、单例、KVO

Swift代理:

protocol DNPictureBookIntroduceDelegate: NSObjectProtocol {
    /// 代理方法
    func playPictureBook()
    func closePictureBookIntroudce()
}
//定义代理
 weak var delegate: DNPictureBookIntroduceDelegate?

//实现协议方法
extension DNCommonBookDetailController: DNPictureBookIntroduceDelegate {
    func playPictureBook() {

    }

    func closePictureBookIntroudce() {
    }
}

Swift通知:
//注册监听者
NotificationCenter.default.addObserver(self, selector: #selector(receiveUpdateProgressNotification(_:)), name: NSNotification.Name(rawValue:kUpdateProgressNotification), object: nil)

//移除监听者
deinit {
        NotificationCenter.default.removeObserver(self)
    }
//发送通知
NotificationCenter.default.post(name: NSNotification.Name(kUpdateProgressNotification), object: progress)

12 pod install、pod update、pod outdated 、Pofile.lock区别
pod install:第一次用CocoaPods建立工程、添加或移除库,不会更新那些已经安装了的库。
pod update: CocoaPods更新Podfile里面的库到尽可能的最新版本,不需要考虑Podfile.lock里面的版本限制。
pod outdated:CocoaPods会列出那些所有较Podfile.lock里面有新版本的库。
Podfile.lock:记录每个安装库的版本号、锁定这些版本。
保证项目的每个开发者都使用相同版本的库,就是每个电脑中都使用同样的Podfile.lock,并且合理使用pod install 和 pod update。
CocoaPods:只上传Podfile,Podfile.lock文件, 可以保证多人开发使用的第三方库版本一致,checkout下来, 一定要pod install,不要pod update。

13 钥匙串存储数据特点
keychain(钥匙串)存储数据更为安全。
keychain里保存的信息不会因App被删除而丢失。
iOS系统存储的数据都是在sandBox里面,一旦删除App,sandBox也不复存在。

14 rumtime、runloop原理和实用场景
runloop运行循环、跑圈。其实也就是一个循环跑圈,用来处理线程里面的事件和消息。

runloop和线程的关系:每条线程都有唯一的一个与之对应的runloop对象。每个线程如果想继续运行,不被释放,就必须有一个runloop来不停的跑圈,以来处理线程里面的各个事件和消息。

线程 =====》 runloop对象(处理线程里面的各个事件和消息)
主线程默认是开启一个runloop。也就是这个runloop才能保证我们程序正常的运行。
子线程是默认没有开启runloop的。

runloop基本作用:保持程序的持续运行,处理App中的各种事件,节省CPU资源,提高程序性能。
runloop的生命周期:Runloop在第一次获取时创建,在线程结束时销毁。
如何让子线程不死:给这条子线程开启一个runloop

15 Swift语言中的struct替代class有什么好处
struct使用的时候是copy的, class使用的时候是引用的。
struct为值类型,struct 不可以继承。

16 排序算法:冒泡排序、选择排序


image.png image.png

17 互斥锁的优缺点
优点:能有效防止因多线程抢夺资源造成的数据安全问题
缺点:需要消耗大量的CPU资源
互斥锁的使用前提:多条线程抢夺同一块资源

OC定义属性:
atomic:原子属性,为setter方法加锁(默认就是atomic)
nonatomic:非原子属性,不会为setter方法加锁
atomic:线程安全,需要消耗大量的CPU资源
nonatomic:非线程安全,适合内存小的移动设备

18 SDWebImage的底层原理:
1.显示placeholderImage
2.SDImageCache从缓存中查找图片是否已经下载
3.先从内存查找是否有图片缓存(用图片的url查找)
4.如果内存中有图片缓存,显示图片
5.如果内存中没有,开始从硬盘查找图片缓存,根据图片url经过MD5加密,生成的32位字符串进行查找。
6.如果硬盘中有,将图片添加到内存缓存中(如果空闲内存过小,会先清空内存缓存),显示图片
7.如果硬盘中没有,说明该图片没有缓存,需要下载图片,共享或重新生成一个下载器SDWebImageDownLoader开始下载图片
8.开始图片网络请求,下载数据
9.数据下载完成后交给SDWebImageDecoder做图片解码
10.回调展示图片
11.图片保存到硬盘缓存和内存缓存
12.SDImageCache初始化会注册一些通知,在内存警告或退到后台的时候清理内存图片缓存,应用结束的时候清理过期图片。
SDImageCacheType:SDImageCacheTypeNone、SDImageCacheTypeDisk(从本地沙盒缓存图像)、SDImageCacheTypeMemory(从内存中获取图像)
1:图片文件缓存的时间:1 周
static const NSInteger kDefaultMaxCacheAge = 60 * 60 * 24 * 7;
2:SDWebImage 的内存缓存是用NSCache实现的
3:SDWebImage 的最大并发数:6
可以通过属性进行调整!
_downloadQueue.maxConcurrentOperationCount = 6;
4:网络访问超时时长:15 秒
iOS 开发中,默认的访问时长是 1 分钟,SDWebImage 中是 15 秒
_downloadTimeout = 15.0;
5:SDWebImage 支持动图:支持GIF动图

import "UIImage+GIF.h"

6:SDWebImage 是如何区分不同格式的图像的
根据图像数据第一个字节来判断的!
PNG:0x89 image/png ,压缩比没有 JPG 高、无损压缩、解压缩性能高,苹果推荐的图像格式。
JPG:0xFF image/jpeg,压缩比最高、有损压缩、解压缩的性能不好。
GIF:0x47 image/gif ,序列桢动图
7:SDWebImage 缓存图片的名称是怎么确定的!
使用 MD5 的散列函数!对完整的 URL 进行 md5加密,结果是一个 32 个字符长度的字符串!
8:SDWebImage 的内存警告是如何处理的!
利用通知中心观察
UIApplicationDidReceiveMemoryWarningNotification 接收到内存警告的通知
执行 clearMemory 方法,清理内存缓存!
bug:
SDWebImage 中,一旦内存警告,清理了内存之后,之后所有的图片都是从沙盒加载的。
SDImageCache的缓存机制
两种:内存缓存、沙盒缓存
沙盒目录:Documents、Library(Caches、Preferences)、SystemData、tmp
SDWebImage缓存的网络图片路径:Library/Caches/目录下
首页数据缓存路径:Documents目录下,缓存文件名是请求url经过MD5加密之后的32位字符串
清除本地缓存:清除Library/Caches/目录下的所有文件

网友评论

      本文标题:Day3

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