iOS开发一些常用库的理解

1.iOS开发常用的库有哪些?

    这里不在叙述,超全iOS开发三方库

 

2.说说你熟悉的第三方框架,解释一下它的原理

例子1:SDWebImage

知识点一:

SDWebImage 加载图片的流程:

1.


入口 setImageWithURL:placeholderImage:options: 
会先把 placeholderImage 显示,然后 SDWebImageManager 根据 URL 开始处理图片。

2.


进入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:
交给 SDImageCache 从缓存查找图片是否已经下载 queryDiskCacheForKey:delegate:userInfo:

3.


先从内存图片缓存查找是否有图片
如果内存中已经有图片缓存,SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。

4.


SDWebImageManagerDelegate 回调 webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示图片。

5.


如果内存缓存中没有,生成 NSInvocationOperation 添加到队列开始从硬盘查找图片是否已经缓存。

6.


根据 URLKey 在硬盘缓存目录下尝试读取图片文件。
这一步是在 NSOperation 进行的操作,所以回主线程进行结果回调 notifyDelegate:。

7.


如果上一操作从硬盘读取到了图片,将图片添加到内存缓存中(如果空闲内存过小,会先清空内存缓存)。
SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo:。进而回调展示图片。

8.


如果从硬盘缓存目录读取不到图片,说明所有缓存都不存在该图片,需要下载图片,回调 imageCache:didNotFindImageForKey:userInfo:。

9.


共享或重新生成一个下载器 SDWebImageDownloader 开始下载图片。

10.


图片下载由 NSURLConnection 来做,实现相关 delegate 来判断图片下载中、下载完成和下载失败。

11.


connection:didReceiveData: 中利用 ImageIO 做了按图片下载进度加载效果。

12.


 connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 做图片解码处理。

13.


图片解码处理在一个 NSOperationQueue 完成,不会拖慢主线程 UI。如果有需要对下载的图片进行二次处理,最好也在这里完成,效率会好很多。

14.


在主线程 notifyDelegateOnMainThreadWithInfo: 宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo: 回调给 SDWebImageDownloader。

15.


mageDownloader:didFinishWithImage: 回调给 SDWebImageManager 告知图片下载完成。

16.


通知所有的 downloadDelegates 下载完成,回调给需要的地方展示图片。

17.


将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存。写文件到硬盘也在以单独 NSInvocationOperation 完成,避免拖慢主线程。

18.


SDImageCache 在初始化的时候会注册一些消息通知,在内存警告或退到后台的时候清理内存图片缓存,应用结束的时候清理过期图片。

19.


 SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,方便使用。

20.


SDWebImagePrefetcher 可以预先下载图片,方便后续使用。

 

 

 

 

知识点

清除缓存

 

cleanMemary

1、遍历缓存目录,删除所有过期图片(一周)

2、统计没有过期图片大小总和

3、判断没有过期的图片总大小是否超过缓存大小(getSize获得内存缓存大小)

4、如果超过就会删除没有过期的图片,从大到小删除

 

知识点三:

1.SDImageCache是怎么做数据管理的?

 

SDImageCache分两个部分,一个是内存层面的,一个是硬盘层面的。
内存层面的相当是个缓存器,以Key-Value的形式存储图片。当内存不够的时候会清除所有缓存图片。
用搜索文件系统的方式做管理,文件替换方式是以时间为单位,剔除时间大于一周的图片文件。
当SDWebImageManager向SDImageCache要资源时,先搜索内存层面的数据,如果有直接返回,没有的话去访问磁盘,将图片从磁盘读取出来,然后做Decoder,将图片对象放到内存层面做备份,再返回调用层。
2.为啥必须做Decoder?
  (1)显示下载进度 
NSString *URLString = @"http://ww1.sinaimg.cn/bmiddle/bfc243a3gw1ezautzt7guj20ku0v978r.jpg"; [self.iconView sd_setImageWithURL:[NSURL URLWithString:URLString] placeholderImage:nil options:SDWebImageProgressiveDownload progress:^(NSInteger receivedSize, NSInteger expectedSize) { /** receivedSize 前面总共接收了多少字节数 expectedSize 服务器上面文件的总大小 */ CGFloat progress = (CGFloat)receivedSize / expectedSize; //0 NSLog(@"下载进度---%f",progress); } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { }];

(2)使用SDManager来显示下载进度

//1.创建一个Manager SDWebImageManager *manager =[SDWebImageManager sharedManager]; //根据URLString去下载图片 NSString *URLString = @"http://imgsrc.baidu.com/forum/w%3D580/sign=1c9daa96dbb44aed594ebeec831d876a/9661edf81a4c510f437c4bc66159252dd52aa553.jpg"; __weak typeof(self) weakSelf = self; [manager downloadImageWithURL:[NSURL URLWithString:URLString] options:SDWebImageProgressiveDownload progress:^(NSInteger receivedSize, NSInteger expectedSize) { /** receivedSize 前面总共接收了多少字节数 expectedSize 服务器上面文件的总大小 */ CGFloat progress = (CGFloat)receivedSize / expectedSize; //0 NSLog(@"下载进度---%f",progress); } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { //NSLog(@"%@",image); weakSelf.iconView.image = image; }];

例子2:AFNetworking

AFNetworking由五个模块组成:

1.NSURLSession:网络通信模块(核心模块) 对应 AFNetworking中的 AFURLSessionManager和对HTTP协议进行特化处理的AFHTTPSessionManager,AFHTTPSessionManager是继承于AFURLSessionmanager的

2.Security:网络通讯安全策略模块  对应 AFSecurityPolicy

3.Reachability:网络状态监听模块 对应AFNetworkReachabilityManager

4.Seriaalization:网络通信信息序列化、反序列化模块 对应 AFURLResponseSerialization

5.UIKit:对于IOSUIKit的扩展库

1.AFNetworkReachabilityManager

    这个是用来监控网络环境变化的类。

2.AFSecurityPolicy 

    网络连接安全方面

    1). AFSSLPinningModeNone    代表无条件信任服务器的证书

    2). AFSSLPinningModePublicKey 代表会对服务器返回的证书中的PublicKey进行验证,通过则通过,否则不通过

    3). AFSSLPinningModeCertificate 代表会对服务器返回的证书同本地证书全部进行校验,通过则通过,否则不通过

3.AFURLRequestSerialization

4.AFURLResponseSerialization

5.AFURLSessionManager  

    AFURLSessionManager 创建并管理着NSURLSession这个对象。而NSURLSession又基于NSURLSessionConfiguration

6.AFHTTPSessionManager是AFURLSessionManager的子类,是专门为HTTP请求设计的。里面涉及到GET,POST,PUT,DELETE等等HTTPMehtod。
7.AFAutoPurgingImageCache

    我们要写一个通用的网络框架,除了必备的请求数据的方法外,必须提供一个下载器来管理应用内的所有的下载事件。

8.AFImageDownloader

    专门管理一组图片的下载任务 

9.AFNetworkActivityIndicatorManager

    对状态栏中网络激活那个小控件的管理

10.UIActivityIndicatorView/UIRefreshControl/UIImageView +AFNetworking

    尝试让一个控件的layer也能够加载网络图片。

11.UIButton/UIProgressView/UIWebView +AFNetworking

 

 

 

例子3:MJRefresh

    默认情况下,如果下拉一个UIScrollView,在松手之后,会弹回初始的位置,而大部分的下拉刷新控件都是将自己放在scrollView的上方,起始y设置成负数,所以平时不会显示出来,只有下拉的时候才会出现,放开又回弹回去,然后在loading的时候,临时把contentInset增大,相当于把UIScrollView往下挤,于是下拉刷新的控件就会显示出来,然后刷新完成之后,再把contentInset改回原来的值,实现回弹的效果。

 

3.BLOCK

 

知识点1:   block分类,iOS中有三种block

  • NSConcreteGlobalBlock; //没有用到外界变量或只用到全局变量、静态变量的block为_NSConcreteGlobalBlock,生命周期从创建到应用程序结束。
  • NSConcreteStackBlock; //只用到外部局部变量、成员属性变量,且没有强指针引用的block都是StackBlock。
    StackBlock的生命周期由系统控制的,一旦返回之后,就被系统销毁了。
  • NSConcreteMallocBlock;//有强指针引用或copy修饰的成员属性引用的block会被复制一份到堆中成为MallocBlock,没有强指针引用即销毁,生命周期由程序员控制

默认情况下,block是存档在栈中,栈中的Block的生命周期是和栈绑定的,可能被随时回收,通过copy操作后Block才会在堆中,可以使其在堆中保留一份, 相当于一直强引用着, 因此如果block中用到self时, 需要将其弱化, 通过__weak或者__unsafe_unretained。由于_NSConcreteStackBlock所属的变量域一旦结束,那么该Block就会被销毁。在ARC环境下,编译器会自动的判断,把Block自动的从栈copy到堆。比如当Block作为函数返回值的时候,肯定会copy到堆上。

1.手动调用copy
2.Block是函数的返回值
3.Block被强引用,Block被赋值给__strong或者id类型
4.调用系统API入参中含有usingBlcok的方法

以上4种情况,系统都会默认调用copy方法把Block赋复制

知识点2:

    自动变量是以值传递方式传递到Block的构造函数里面去的。Block只捕获Block中会用到的变量。由于只捕获了自动变量的值,并非内存地址,所以Block内部不能改变自动变量的值。需要对自动变量添加__bloclk;

知识点3:

    Block中可以修改全局变量,全局静态变量,局部静态变量吗?答案:可以 底部原理

 

 4.iOS事件响应链

  第一个感知触摸事件的是操作系统,是他最先检测到屏幕上的压力,而不是你看上去触摸到的那个视图

1.形成响应链,首先调用 hitTest:withEvent: 方法。   该方法接受位置参数CGPoint,并从底层开始按照subview的顺序,测试该CGPoint在哪个View上,如果在该View上,则继续测试是否在View的subview上。需要注意的是,所有的响应链都是父子视图的关系。

2.响应链已经形成后,开始找事件的处理者,按照响应链往上回溯即可,一直回溯到application,也无人处理此事件,则将事件丢弃。

5.介绍下内存的几大区域

由地址排序(由低到高)

程序代码区----->常量区(数据区)----->全局区(静态区)----->堆区----->栈区

1.栈区(stack)

是个线程独有的,保存其运行状态和局部自动变量的,每个函数都有自己的栈,栈被用来在函数之间传递参数,栈在线程开始的时候初始化,每个线程的栈互相独立。栈区由编译器自动分配并释放,不会产生内存碎片,存放函数的参数值,局部变量等。栈是系统数据结构,对应线程/进程是唯一的。

优点是快速高效,缺点时有限制,数据不灵活。[先进后出]

栈空间分静态分配 和动态分配两种

1)静态分配是被编译器完成的,比如自动变量的分配。

2)动态是有alloca函数完成,栈的动态分配是没有释放函数的(自动释放),为程序的可移植性和内存泄漏方面不被鼓励使用。

2.堆区(heap)

堆区是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。 由程序员分配和释放,容易产生内存碎片,如果程序员不释放,程序结束时,可能会由操作系统回收 ,比如在ios 中 alloc 都是存放在堆中。

优点是灵活方便,数据适应面广泛,但是效率有一定降低。

堆是函数库内部数据结构的一种,不一定唯一,不同堆分配的内存无法相互操作,堆的分配总是动态的。

3.全局区(静态区)(static)

全局变量和静态变量的存储是放在一起的,初始化的全局变量和静态变量存放在一块区域,未初始化的全局变量和静态变量在相邻的另一块区域(BSS),程序结束后有系统释放。

4.常量区(数据区)

存放常量字符串,程序结束后由系统释放。

5.程序代码区

存放函数体的二进制代码 , 程序结束后由系统释放。

注意的问题:

1.比如申请后的系统是如何响应的?

 

栈:存储每一个函数在执行的时候都会向操作系统索要资源,栈区就是函数运行时的内存,栈区中的变量由编译器负责分配和释放,内存随着函数的运行分配,随着函数的结束而释放,由系统自动完成。

注意:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

堆:

1.首先应该知道操作系统有一个记录空闲内存地址的链表。

2.当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。

3 .由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

2.申请大小的限制是怎样的?

 

栈:栈是向低地址扩展的数据结构,是一块连续的内存的区域。是栈顶的地址和栈的最大容量是系统预先规定好的,栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数 ) ,如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。

堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值