基础篇
1.分类和扩展有什么区别?可以分别用来做什么?分类有哪些局限性?分类的结构体里面有哪些成员?
①分类中原则上只能增加方法(能添加属性的的原因只是通过runtime能添加属性的的原因只是通过runtime的objc_setAssociatedObject和objc_getAssociatedObject方法解决无setter/getter的问题而已);
②类扩展不仅可以增加方法,还可以增加实例变量(或者属性),只是该实例变量默认是@private类型的(
用范围只能在自身类,而不是子类或其他地方);
③类扩展中声明的方法没被实现,编译器会报警,但是类别中的方法没被实现编译器是不会有任何警告的。这是因为类扩展是在编译阶段被添加到类中,而类别是在运行时添加到类中。
④类扩展不能像类别那样拥有独立的实现部分(@implementation部分),也就是说,类扩展所声明的方法必须依托对应类的实现部分来实现。
⑤定义在 .m 文件中的类扩展方法为私有的,定义在 .h 文件(头文件)中的类扩展方法为公有的。类扩展是在 .m 文件中声明私有方法的非常好的方式。
最重要的还是类扩展是在编译阶段被添加到类中,而类别是在运行时添加到类中。
分类方法未实现,编译器也不会报警告。
分类方法与原类中相同会优先调用分类。
分类的结构体
typedef struct objc_category *Category;
struct objc_category {
char *category_name OBJC2_UNAVAILABLE; // 分类名
char *class_name OBJC2_UNAVAILABLE; // 分类所属的类名
struct objc_method_list *instance_methods OBJC2_UNAVAILABLE; // 实例方法列表
struct objc_method_list *class_methods OBJC2_UNAVAILABLE; // 类方法列表
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 分类所实现的协议列表
}
**2.nonatomic和atomic的区别?atomic是绝对的线程安全吗?为什么?如果不是,那该如何实现? **
答:区别:nonatomic和atomic用来决定编译器生成的getter和setter操作是否为原子操作;
atomic不是绝对的线程安全。atomic的本意是指属性的存取方法是线程安全的,并不保证整个对象是线程安全的。如:
声明一个NSMutableArray的原子属性stuff,此时self.stuff 和 self.stuff = otherstuff都是线程安全的。但是使用[self.stuff objectAtIndex:index]就不是线程安全的。需要用互斥锁来保证线程安全性。
如何实现线程安全:http://www.cocoachina.com/ios/20160707/16957.html
**3.为什么说Objective-C 是一门动态的语言? **
动态类型语言是指在运行期间才去做数据类型检查的语言,静态类型语言与动态类型语言刚好相反,它的数据类型是在编译其间检查的,也就是说在写程序时要声明所有变量的数据类型,C/C++是静态类型语言的典型代表。
Objective-C 是C 的超集,在C 语言的基础上添加了面向对象特性,并且利用Runtime 这个运行时机制,为Objective-C 增添了动态的特性;Objective-C 可以通过Runtime 这个运行时机制,在运行时动态的添加变量、方法、类等,所以说Objective-C 是一门动态的语言;Objective-C 使用的是 “消息结构” 并非 “函数调用”:使用消息结构的的语言,其运行时所应执行的代码由运行期决定;而使用函数调用的语言,则由编译器决定,总结:OC利用Runtime可以在运行的时候创建类,修改类,修改对象调用的方法。
**4.NString为什么要用copy关键字,如果用Strong 会有什么问题? **
答:https://www.jianshu.com/p/fc1408bf4e17
**5.为什么代理要用weak?代理的delegate和dataSource有什么区别?block和代理的区别? **
答:防止循环引用。例如View有一个协议,需要一个代理实现回调。一个Controller添加这个View,并且遵守协议,成为View的代理。如果不用week,用strong,Controller ->View -> delegate -> Controller,就循环引用了。
delegate偏重于与用户交互的回调,有那些方法可以供我使用,例如UITableviewDelegate;dataSource偏重于数据的回调,view里面有什么东西,属性都是什么,例UITableviewDatasource;
block和代理的区别:https://www.jianshu.com/p/6bba9b4a25d
**6.说一下深拷贝和浅拷贝,怎么让一个对象具备copy功能 **
答:深拷贝就是拷贝出和原来仅仅是值一样,但是内存地址完全不一样的新的对象,创建后和原对象没有任何关系。浅拷贝就是拷贝指向原来对象的指针,使原对象的引用计数+1,可以理解为创建了一个指向原对象的新指针而已,并没有创建一个全新的对象
在OC中要想自定义的类具有拷贝功能(也就是能用copy方法)则类必须遵守NSCopying协议,并且实现协议中的(id)copyWithZone:(NSZone *)zone方
链接:https://www.jianshu.com/p/5135953a8230
**7.runloop 的理解和使用? **
答:https://blog.ibireme.com/2015/05/18/runloop/ 这个介绍的也很可以
**8.objc使用什么机制管理对象内存? **
答:采用retainCount引用计数器管理内存
9.KVO、Delegate、Notification、block 的优缺点及使用场景?
10.谈一下你对RunTime的理解,能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?
11.Block是如何实现的?Block对应的数据结构是什么样子的?__block的作用是什么?它对应的数据结构又是什么样子的?
block本质是一个对象,底层用struct实现。
数据结构如下:
struct Block_descriptor {
unsigned long int reserved;
unsigned long int size;
void (*copy)(void *dst, void *src);
void (*dispose)(void *);
};
struct Block_layout {
void *isa;
int flags;
int reserved;
void (*invoke)(void *, ...);
struct Block_descriptor *descriptor;
/* Imported variables. */
};
- isa 指针,所有对象都有该指针,用于实现对象相关的功能。
- flags,用于按 bit 位表示一些 block 的附加信息,本文后面介绍 block copy 的实现代码可以看到对该变量的使用。
- reserved,保留变量。
- invoke,函数指针,指向具体的 block 实现的函数调用地址。
- descriptor, 表示该 block 的附加描述信息,主要是 size 大小,以及 copy 和 dispose 函数的指针。
- variables,capture 过来的变量,block 能够访问它外部的局部变量,就是因为将这些变量(或变量的地址)复制到了结构体中。
__block
的作用是让block可以捕获该变量,捕获之后的变量会进入到block内部,通过反编译的代码我们可以看到该对象是这样的
struct __Block_byref_i_0 {
void *__isa;
__Block_byref_i_0 *__forwarding;
int __flags;
int __size;
int val; //变量名
};
Swift
1、Swift中struct和class有什么区别?
struct是值引用,更轻量,存放于栈区,class是类型引用,存放于堆区。struct无法继承,class可继承。
2、怎么理解面向协议编程?
面向对象是以对象的视角观察整体结构,万物皆为对象。
面向协议则是用协议的方式组织各个类的关系,Swift底层几乎所有类都构建在协议之上。
面向协议能够解决面向对象的菱形继承,横切关注点和动态派发的安全性等问题。
Sdwebimage
1.把一些具体的事物
1.控件是否有正在加载的任务--存放在SDoperationDictionary 中,读写的时候加了一把递归锁,来保证读写安全
2.针对 GIF,多图下载 判断是否开启 dispath_group
3.设置placeholder, diapatch_main_async_safe 宏
4.加载图片
5.查找缓存
-
内存缓存(Memory:NSCache),URL——UIImage
如果URL 不变,图片资源变了,如何处理?-- 设置 If-Modified-Since 和 refreshCache
-
磁盘缓存:二进制(文件)
1.是否需要磁盘缓存查询
2.是否需要对加载的大图做尺寸的处理
3.判断是同步线程查询还是异步查询,异步查询会在串行队列中,保证同时只有一个磁盘查询任务存在
4.@autoreleasepool 添加自动缓存池,对用完的临时变量及时回收
5.拿到缓存的图片,对NSData encod解码成 UIImage,第一个字节拿到图片格式
-
NSURLCache: 系统自带的HTTP 缓存
HTTP缓存
-
不同的缓存策略
Cache-control
last-Modified httpResponse.allHeaderFields[@"Last-Modified"] b
If-Modified-Since- [request setvalue:self.localLastModified forHTTPHeaderField:@"If-Modified-Since"]
6.网络请求 NSURlSession
- 下载:缓存策略设置
7.图片的解码
8.图片获取之后
- 根据option 是否需要自动显示图片
SDWebCache--> NCache
特点:线程安全, 可以设置最大个数
1.缓存的对象自身被释放掉了
2.手动掉用removeApi
3.当我们缓存的对象 > countLimit
4.程序进入后台
5.收到系统的内存警告
为什么要看源码?-- 学习知识点
NSURLCache
NSCache
Header
NSOpration
NSURLSession