zoukankan      html  css  js  c++  java
  • iOS 多线程及其他补充 02

    • NSOperation

      • NSOperation是个抽象类,并不具备封装操作的能力,必须使用它的子类
    • NSInvocationOperation

      • 如果直接执行NSInvocationOperation中的操作, 那么默认会在主线程中执行
      •  NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo) object:nil];
         [op1 start];
    • NSBlockOperation
      • 如果只封装了一个操作, 那么默认会在主线程中执行
      • 果封装了多个操作, 那么除了第一个操作以外, 其它的操作会在子线程中执行
      • NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
                NSLog(@"1- %@", [NSThread currentThread]);
            }];
        [op1 start];
    • 自定义Operation
        • @implementation XMGOperation
          
          - (void)main
          {
              NSLog(@"%s, %@", __func__,[NSThread currentThread]);
          }
          @end
    • NSOperationQueue
    • GCD队列和NSOperationQueue对比

      • GCD
        • 串行: 自己创建, 主队列
        • 并发: 自己创建, 全局
        NSOperationQueue
        • 自己创建: alloc/init
        • 主队列 : mainQueue
    • NSOperationQueue特点

      • 任务添加到自己创建队列中会开启新线程
        • 默认是并发: maxConcurrentOperationCount -1
        • 串行 : maxConcurrentOperationCount = 1
      • 任务添加到mainQueue队列中不会开启新线程
    • Invocation

        • // 1.创建队列
              NSOperationQueue *queue = [[NSOperationQueue alloc] init];
              // 2.封装任务
              NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(demo) object:nil];
              // 3.将任务添加到队列中
              [queue addOperation:op1];
    • block
        • // 1.创建队列
              NSOperationQueue *queue = [[NSOperationQueue alloc] init];
              // 2.封装任务
               NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
               NSLog(@"1 = %@", [NSThread currentThread]);
               }];
               // 3.将任务添加到队列中
               [queue addOperation:op1];
              // 1.创建队列
              NSOperationQueue *queue = [[NSOperationQueue alloc] init];
          
              // addOperationWithBlock方法会做两件事情
              // 1.根据传入的block, 创建一个NSBlockOperation对象
              // 2.将内部创建好的NSBlockOperation对象, 添加到队列中
          
              // 2.将任务添加到队列中
              [queue addOperationWithBlock:^{
                  NSLog(@"1 = %@", [NSThread currentThread]);
              }];
              [queue addOperationWithBlock:^{
                  NSLog(@"2 = %@", [NSThread currentThread]);
              }];
    • 自定义
        • // 1.创建队列
              NSOperationQueue *queue = [[NSOperationQueue alloc] init];
              // 2.封装任务
              JXOperation *op1 = [[JXOperation alloc] init];
          
              // 3.将任务添加到队列中
              [queue addOperation:op1];
    • 暂停-恢复
        • 不会暂停当前正在执行的任务
        • 会从第一个未执行的任务恢复执行
        • // 如果是YES, 代表需要暂停
          // 如果是NO ,代表恢复执行
          self.queue.suspended = YES;
    • 取消
        • 不会取消当前正在执行的任务
        • 取消后任务不能恢复
        • 耗时操作应该没执行一段判断一次
        • // 内部会调用所有任务的cancel方法
          [self.queue cancelAllOperations];
    • 线程间通信
        • NSOperationQueue *queue = [[NSOperationQueue alloc] init];
          // 开启子线程
          [queue addOperationWithBlock:^{
                  // 回到主线程
                  [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                  }];
          
          }];
    • 依赖和监听
        • 只有被依赖的任务完成, 才会执行当前任务
        • 可以跨队列依赖
        •  [operationB addDependency:operationA]; // 操作B依赖于操作A
              op1.completionBlock = ^{
                  NSLog(@"第一张图片下载完毕");
              };
              op2.completionBlock = ^{
                  NSLog(@"第二张图片下载完毕");
              };
    • 图片下载
        • 重复下载问题
          • 定义字典保存下载好的图片
        • 磁盘缓存问题
          • 内存没有尝试从磁盘获取
        • 阻塞主线程问题
          • 新建NSOperationQueue下载图片
        • 重复设置问题
          • reloadRowsAtIndexPaths
        逻辑1 - 从来没下载过
         1.查看内存缓存是否有图片
         2.查看磁盘缓存是否有图片
         3.查看时候有任务正在下载当前图片
         4.开启任务下载图片
         5.写入磁盘
         6.缓存到内存
         7.移除下载操作
         8.显示图片
        
         逻辑2 - 已经下载过
         1.查看内存缓存是否有图片
         2.查看磁盘缓存是否有图片
         3.使用磁盘缓存
         4.将图片缓存到内存中
         5.更新UI
        
         逻辑3 - 已经下载过, 并且不是重新启动
          1.查看内存缓存是否有图片
          2.更新UI
    • 目录结构
    • Documents

        • 需要保存由"应用程序本身"产生的文件或者数据,例如:游戏进度、涂鸦软件的绘图
        • 目录中的文件会被自动保存在 iCloud
        • 注意:不要保存从网络上下载的文件,否则会无法上架!
        • Caches

          • 保存临时文件,"后续需要使用",例如:缓存图片,离线数据(地图数据)
          • 系统不会清理 cache 目录中的文件
          • 就要求程序开发时,"必须提供 cache 目录的清理解决方案"
        • Preferences

          • 用户偏好,使用 NSUserDefault 直接读写!
          • 如果要想数据及时写入磁盘,还需要调用一个同步方法
        • tmp

          • 保存临时文件,"后续不需要使用"
          • tmp 目录中的文件,系统会自动清理
          • 重新启动手机,tmp 目录会被清空
          • 系统磁盘空间不足时,系统也会自动清理
        • 封装获取文件路径方法

        • - (NSString *)cacheDir
          {
              // 1.获取cache目录
              NSString *dir = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
              return [dir stringByAppendingPathComponent:[self lastPathComponent]];
          }
          - (NSString *)documentDir {
              NSString *dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
              return [dir stringByAppendingPathComponent:[self lastPathComponent]];
          }
          
          - (NSString *)tmpDir {
              NSString *dir = NSTemporaryDirectory();
              return [dir stringByAppendingPathComponent:[self lastPathComponent]];
          }
      • SDWebImage架构
      • SDWebImageManager

        • SDImageCache
        • SDWebImageDownloader
          • SDWebImageDownloaderOperation
      • SDWebImage常见面试题

      • 默认缓存时间多少

        • 一周
      • 缓存的地址

        • NSString *fullNamespace = [@"com.hackemist.SDWebImageCache." stringByAppendingString:ns];
      • cleanDisk如何清理过期图片

        • 删除早于过期日期的文件
        • 保存文件属性以计算磁盘缓存占用空间
        • 如果剩余磁盘缓存空间超出最大限额,再次执行清理操作,删除最早的文件
      • clearDisk如何清理磁盘

        • 删除缓存目录
        • 新建缓存目录
      • SDWebImage如何播放图片

        • 取出gif中每一帧, 生成一张可动画图片
      • SDWebImage如何判断图片类型

        • 判断图片二进制前8个字节
        • kPNGSignatureBytes[8] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};

      • CocoaPods 是什么?

        • CocoaPods 是开发 OS X 和 iOS 应用程序的一个第三方库的依赖管理工具。利用 CocoaPods,可以定义自己的依赖关系 (称作 pods),并且随着时间的变化,以 及在整个开发环境中对第三方库的版本管理非常方便
      • CocoaPods 背后的理念主要体现在两个方面

        • 在工程中引入第三方代码 会涉及到许多内容。针对 Objective-C 初级开发者来说,工程文件的配置会让 人很沮丧
        • 在配置buildphases和linker flags过程中,会引起许多人为因素的 错误
        • CocoaPods 简化了这一切,它能够自动配置编译选项
      • CocoaPods的原理

        • 它是将所有的依赖库都放到另一个名为Pods项目中,然后 让主项目依赖Pods项目,这样,源码管理工作都从主项目移到了Pods项目中
        • 1、Pods项目最终会编译成一个名为libPods.a的文件,主项目只需要依赖这个.a 文件即可。
        • 2、对于资源文件,CocoaPods提供了一个名为Pods-resources.sh的bash脚本, 该脚本在每次项目编译的时候都会执行,将第三方库的各种资源文件复制到目 标目录中。
        • 3、CocoaPods通过一个名为Pods.xcconfig的文件来在编译时设置所有的依赖和 参数。
      platform :ios
      pod'AFNetworking'
      
      • 注释事项
        • 1.利用CocoPods管理类库后, 以后打开项目就用xxxx.xcworkspace 打开,而不是 之前的.xcodeproj文件
        • 2.每次更改了Podfile文件,你需要重新执行一次pod update命令。
        • 3.CocoaPods在执行pod install和pod update时,会默认先更新一次CocoPods的 spec仓库索引。使用--no-repo-update参数可以禁止其做索引更新操作
      pod install --no-repo-update
      pod update --no-repo-update
  • 相关阅读:
    使用createDocumentFragment的渲染数据(节省性能)
    面向对象写法模板
    面向对象this指向
    js 3D图片叠加旋转切换
    三列布局-中间固定俩边自适应-和两边固定中间自适应布局
    游戏中抽奖的算法
    c++11:lambda表达式
    c++11:模板
    c++11:左值、右值
    游戏服务器语言之争
  • 原文地址:https://www.cnblogs.com/liujiaoxian/p/4822226.html
Copyright © 2011-2022 走看看