欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

程序员文章站 2022-07-12 23:38:45
...

只是随笔, 若有不知所云处, 敬请忽略.

  1. 关于NSInvocation

        1. 创建一个MethodSignature,签名中保存了方法的名称,参数和返回值
    
        //这个方法属于谁,那么就用谁来进行创建
        //注意:签名一般是用来设置参数和获得返回值的,和方法的调用没有太大的关系
        NSMethodSignature *signature = [ViewController instanceMethodSignatureForSelector:@selector(callWithNumber:andContext:withStatus:)];
    
        2. 通过MethodSignature来创建一个NSInvocation
    
         //NSInvocation中保存了方法所属于的对象|方法名称|参数|返回值等等
         NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
    
    
          > 2.1 设置invocation,来调用方法
    
    
        invocation.target = self;
         //    invocation.selector = @selector(call);
         //    invocation.selector = @selector(callWithNumber:);
          //    invocation.selector = @selector(callWithNumber:andContext:);
          invocation.selector = @selector(callWithNumber:andContext:withStatus:);
    
         NSString *number = @"10086";
         NSString *context = @"下课了";
         NSString *status = @"睡觉的时候";
    
    //注意:
         //1.自定义的参数索引从2开始,0和1已经被self and _cmd占用了
         //2.方法签名中保存的方法名称必须和调用的名称一致
            [invocation setArgument:&number atIndex:2];
            [invocation setArgument:&context atIndex:3];
            [invocation setArgument:&status atIndex:4];
    
         /3.调用invok方法来执行/
         [invocation invoke];
    
    
    
  2. NSJSONReadingMutableContainers 返回一个可变对象.

    
    NSDictionary *pushBody = [NSJSONSerialization JSONObjectWithData:[pushBodyString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableContainers error:nil];
                
    
  3. 系统版本适配宏

    #define SYSTEM_VERSION_EQUAL_TO(v)                  ([[[UIDevice currentDevice] systemVersion]       compare:v options:NSNumericSearch] == NSOrderedSame)
    #define SYSTEM_VERSION_GREATER_THAN(v)              ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
    #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
    #define SYSTEM_VERSION_LESS_THAN(v)                 ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
    #define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v)     ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)
    
  4. 设置图片的UIImageRenderingMode可以将tintColor的颜色覆盖到图片上。

     imageVoice.image = UIImage(named: "icon_voice02.png" )!.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate)
    
  5. 设置后台运行任务

    - (void)applicationDidEnterBackground:(UIApplication *)application {
        
            UIApplication *app = [UIApplication sharedApplication];
        
            __block UIBackgroundTaskIdentifier bgTask;
        
            bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
        
            dispatch_async(dispatch_get_main_queue(),^{
            
                if (bgTask != UIBackgroundTaskInvalid) {
                
                    bgTask = UIBackgroundTaskInvalid;
                }
        
            });
        
        }];
        
        
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        
            dispatch_async(dispatch_get_main_queue(), ^{
        
                if (bgTask != UIBackgroundTaskInvalid){
                
                    bgTask = UIBackgroundTaskInvalid;
                }
            });
        });
    }
    
  6. 关于cocoapods报错

     错误信息:
         /Library/Ruby/Site/2.0.0/rubygems/dependency.rb:308:in `to_specs': Could not find 'cocoapods' (>= 0) among 35 total gem(s) (Gem::MissingSpecError)
     Checked in 'GEM_PATH=/Users/qinengwanwei/.gem/ruby/2.0.0:/Library/Ruby/Gems/2.0.0:/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/gems/2.0.0', execute `gem env` for more information
         from /Library/Ruby/Site/2.0.0/rubygems/dependency.rb:320:in `to_spec'
         from /Library/Ruby/Site/2.0.0/rubygems/core_ext/kernel_gem.rb:65:in `gem'
         from /usr/local/bin/pod:22:in `<main>'
         
     解决方法:
     & sudo gem install -n /usr/local/bin cocoapods
    
  7. 关于app多次审核不通过, 遇见的一个问题

     由于app做了多语言适配, 每个语言中都会自动生成与当前主语言中相同的配图和描述信息等.
     当app版本更新时, 也需要一同将多个语言下的配图信息及描述信息更改掉.
    
  8. 数组遍历报错

    错误信息:
        
        Collection <__NSArrayM> was mutated while being enumerated
    
    
    错误代码:
     for (BBTStationParcelScanOrderInfoModel *model in self.orderInfoModels) {
        
        if (![courierListData.expressInfoModel.expressCode isEqualToString:model.expressCode]) {
            
            [self.orderInfoModels addObject:courierListData.expressInfoModel];
        }
        
    }
    
    正确代码:
    
            NSMutableArray *arrM = [NSMutableArray arrayWithArray:self.orderInfoModels];
    
    for (BBTStationParcelScanOrderInfoModel *model in self.orderInfoModels) {
        
        if (![courierListData.expressInfoModel.expressCode isEqualToString:model.expressCode]) {
            
            [self.orderInfoModels addObject:courierListData.expressInfoModel];
        }
        
    }
    
    原因:
        因为你在你遍历的数组的循环中更改了你遍历的数组的元素的个数,使得系统不知道遍历了几次了,遍历到哪了,所以报错;这时需要一个新的数组来中转一下;
    
    
  9. UITextField相关位置改变的方法

    
    - (CGRect)borderRectForBounds:(CGRect)bounds;
    - (CGRect)textRectForBounds:(CGRect)bounds;
    - (CGRect)placeholderRectForBounds:(CGRect)bounds;
    - (CGRect)editingRectForBounds:(CGRect)bounds;
    - (CGRect)clearButtonRectForBounds:(CGRect)bounds;
    - (CGRect)leftViewRectForBounds:(CGRect)bounds;
    - (CGRect)rightViewRectForBounds:(CGRect)bounds;
    
    
  1. jeckines问题

    1. BundelID 冲突,在packaging中修改 BundelID. 
        
    2. 在此目录中删除杂乱证书: ~/Library/MobileDevice/Provisioning Profiles/
    重新生成
    
    3. 关于ResourceRules.plist can not read问题:
    
        Click on your project > Targets > Select your       target > Build Settings >
    
        Code Signing Resource Rules Path
    
        and add :
    
        ip
    
    
  2. 为ipa添加可以调试的UUID
    https://developer.apple.com/account/ios/device/deviceList.action

  3. 去除警告"ld: warning: directory not found for option"

    1. 选择 Build Settings
    2. 查找 Library Search Paths 和 Framework Search Paths
    3. 删除报错路径.
    
  4. 关于加载自定义字体.

    Xcode自带字体查询:http://iosfonts.com/
    
    1. 下载所需的ttf格式字体.
    2. 导入工程
    3. 在info.plist中添加Fonts provided by application,填写字体文件名称加后缀
    4. 在TARGETS -> Build Phases -> Copy Bundle Resources中添加字体文件
    5. 因文件名与字体名可能不同,所以需要循环打印所有字体名称,找出添加的字体
    
        NSArray *familyNames = [UIFont familyNames];
        for( NSString *familyName in familyNames )
        {
            NSArray *fontNames = [UIFont fontNamesForFamilyName:familyName];
            for( NSString *fontName in fontNames )
            {
                printf( "\tFont: %s \n", [fontName UTF8String] );
            }
        }
    
  5. 新工作配置新环境之Charles - Response中文乱码

    解法1:

    1. 右键Charles.app -> 显示包内容 
    2. 打开`info.plist` -> 找到`字典Java`中Key值为`VMOptions`的元素
    3. 将`value`改为`-Xmx256m -Dfile.encoding=UTF-8`
    
    4. 重启Charles. 完事.
    
    解法2:
    
    1. 打开charles -> help -> SSL Proxying -> Install Charles Root Certificate
    2. 打开钥匙串
    3. 选择Charles 证书
    4. 选择始终信任
    5. 解决问题
    
  6. UIApplication.SharedApplication.ScheduledLocalNotifications 取不到值,因本地通知没有设置循环次数:

    http://*.com/questions/14215214/uiapplication-scheduledlocalnotifications-is-empty-for-past-non-repeating-notifi

  7. NSAttributeString富文本 数字比汉子高一点. 解决方法

    [attributeStr addAttribute:NSBaselineOffsetAttributeName value:@(kStationAssignedNumberLabelAttrebuteMargin) range:rangeUnit];
    
  8. 关于时间格式转换.

    //例如
    NSString *str = @"May 27, 2016 1:37:04 PM";
    
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    //输入格式
    [dateFormatter setDateFormat:@"MMM dd,yyyy K:mm:ss aa"];
    
    
    dateFormatter.locale = [[NSLocale alloc]initWithLocaleIdentifier:@"es_US"];
    
    NSDate *detaildate=[dateFormatter dateFromString:str];
    
    
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    
    NSString *time = [dateFormatter stringFromDate:detaildate];
    
    NSLog(@"%@", time);
    
    
  9. 犯了个低级错误, 错误信息 Tried to pop to a view controller that doesn't exist.

    错误原因是在navpop操作时创建了个新的控制器.....而没有pop到栈中的控制器.

  1. 当更改superView的frame时,在有些情况下subViews的frame也发生了变化。这种情况并不一定都是自己想要的。解决方法如下:

    [superView setAutoresizesSubviews:NO];
    
  2. Xcode编译错误:
    Warning: no rule to process file '' of type ## for architecture arm64

    • Build Phases中的Compile Sources里删除相应文件即可.
  3. Xcode编译错误:
    ld: warning: directory not found for option '-F~

    • 打开Build Setting
    • 查找Library Search Paths
    • 删除报错目录
  4. 彻底解决OBJC_CLASS$_某文件名", referenced from:问题

  5. 打包之后下载dSYMs文件,提示There are no dSYMs available for download.

    • Build Settings -> Build Options -> Debug Information Format中, 置为了 DWARF,如果选为DWARF则不会产生dSYM文件,必须选择DWARF with dSYM File. 但我没成功...
  1. 遇见个证书导不出p12问题.

    • 打开 钥匙串
    • 点击 登录
    • 点击 我的证书
    • 将在app开发官网上下载的证书拖进去
    • 右键导出.
  2. 由于版本调试需要,下载了Xcode6.4来使用iOS8.3系统的模拟器调试.

        但是启用模拟器时报错.说未找到一个liblaunch_sim.dylib的库文件. 解决方法如下:
        一、找到目标文件
    /Applications/Xcode-beta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/lib/system/host/liblaunch_sim.dylib 
    
        二、拷贝到目标地址一和目标地址二。
    
           目标地址一
           /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 8.1.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/host/liblaunch_sim.dylib
    
           目标地址二
           /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 8.2.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/host/liblaunch_sim.dylib
    
    
  3. 子视图的alpha不能高于父视图,但有时遮罩或者其他需求 需要子视图的alpha高于父视图, 解决方法:

    superView.backgroundColor = [[UIColor lightGrayColor] colorWithAlphaComponent:0.5];

  4. 在Instruments中需要真机的调试工具中, 可能出现真机不能点击的问题,解决原因及方法:

    可能由于手机版本过低, 而项目的版本号过高.
    将项目的版本号调低即可.

  5. Xcode 解决自定义类不自动联想的方法?

    1. 点击target
    2. 进入build setting
    3. 搜索Weak References In Manual Retain Release
    4. 改成YES;
  6. forin的一个小封装

    static void [name](NSArray *objects, void (^block)(id object)) {
    
    for (id obj in objects)
        block(obj);
    }
        
    
  1. 设置Button的文字居中等状态

    button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
    
  2. 只有当label的numberLine == 0 并且不使用富文本时, 字符串才可以通过@"\n"来换行.

  1. 获得当前正在显示的navigation中的ViewController

    在appDelegate中记录一下nav.
    
    AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    
    UIViewController* topViewController = appDelegate.navController.topViewController;
    
  2. 一个汉字占14个点 NSKernAttributeName

  3. iPhone系统提示音http://iphonedevwiki.net/index.php/AudioServices

  4. iOS7.0 scrollView不滚动, 解决: 在viewDidLayoutSubviews中设置contentSize.

  5. CLPreviewController,UIDocumentInteractionController -> PPT,Word,PDF等.

  6. iOS新版本发布,若及时使用新功能,苹果官方会推荐应用.

  7. nshipster.com

  8. Xcode8.0 cmd+shfit+0 快速查看版本更新.

  9. cmd+option+/ == vvdocumen ,自动生成文档注释.

  10. Xcode8 可直接写图片名来设置图片, 省略imageNamed.

  11. Xcode8在设置图像为nil后 自动约束可能会变

  12. Swift3.0 GCD : 队列调度任务, 以同步/异步方式执行
    大量类变成结构体, 省略NS.

  13. Xcode8 增加内存图,可分析内存情况, 查看循环引用.

  14. couldn't get the value of variable ****: variable not available Errored out in Execute...
    Product -> Scheme -> Edit Scheme -> Run -> Diagnostics -> Enable Address Sanitizer

  15. 主队列异步可变相调整视图生命周期. 如: 在ViewDidLoad中把相关代码放入dispatch_async(dispatch_get_main_queue(), ^{ code })中, 可实现相关代码执行于viewDidAppear之后.

  16. activator 手势插件 需越狱.

  17. <a>http://www.th7.cn/Program/IOS/201405/211416.shtml</a>

  18. 终端: lipo -inof 静态库名 可查看静态库支持平台.

  19. 企业打包应选择save for Enterprise Deployment,若选择AD hoc 需添加设备UUID.

  20. unable to read from device

    1. Open Devices in Xcode
    2. Select your device. It should have an unexpected error message
    3. Delete "~/Library/Developer/Xcode/iOS DeviceSupport" directory
    4. Unplug your device
    5. Restart your device
    6. Plug back your device
    7. Xcode should start copying the symbol files immediately
    
  21. #include <iostream>引用cpp文件报错, 解决方法:

    需在yourClass.mm中引用
    
  22. 将编译环境改为C99后, typeof()报错, 解决方法:

    将typeof改为 __typeof 即可

  23. Xcode8, iOS10 调用相机,相册,麦克风crash.

    调用相机crash: 在info.plist中添加 NSCameraUsageDescription
    
    调用相册: NSPhotoLibraryUsageDescription
    
    调用麦克风: NSMicrophoneUsageDescription
    
  24. SVN错误: Server sent unexpected return value (405 Method Not Allowed) in response to MKCOL request for ***

    commit时 添加了一个库里已经存在的文件, 可先备份库文件, 将库中文件删除, 再次commit.
    
  25. iOS 7.0 百度地图mapView报错 BMKMapView's implementation of -layoutSubviews needs to call super

    将mapView布局由autolayout改为frame布局可解决问题.
    
  26. APP包瘦身

    1)删除项目中没有使用的图片。

    -----查找XCode工程中没被使用的图片资源

    2)删除项目中没有用到的class 和 xib 及storyboard。分析工程中没有用到class

    安装 fui 工具
    
    sudo gem install fui -n /usr/local/bin
    
    fui usage: https://github.com/dblock/fui
    
    到工程目录下,执行 fui find 命令,可以找出所有的没有用到的class文件。
    

    3)分析ipa包,找出大于500K的文件或内容 使用

    find . -type f -size +500000c | xargs ls -lh
    
  27. 解决百度地图和TableView手势冲突.

    1. tableView.bounces = NO;
    
    2. tableView遵守UIGestureRecognizerDelegate
    
    3. 实现方法UIGestureRecognizerDelegate代理方法
    
     -(BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer shouldReceiveTouch:(UITouch*)touch {
            //判断tableView是否滑动到最底部(或最顶部,此处最底), round函数:四舍五入
          if (round(self.contentOffset.y) == round(self.contentSize.height - self.frame.size.height)) {
             // 判断当前View是否是百度地图的手势处理View.
             if([NSStringFromClass([touch.view class])isEqual:@"TapDetectingView"]){
                  return NO;//百度地图的手势处理View,tableView的手势事件不响应
              }
          }
        return YES;
     }
    
  28. svn -> Git 代码库迁移 相关操作

    1.命令行执行

    ## 地址支持协议 : svn://, http://, https://. 注意这个 URL 应该指向项目的 base repository,例如: http://svn.mycompany.com/myrepo/repository. 不要指到了 /trunk, /tag 或 /branches 里。
    
    1. git svn clone svn://10.68.245.11/tclshop --authors-file=users.txt --no-metadata -s dufy-move 
    
    ##进入clone 的文件夹
    cd dfuy-move 
    
    ##使所有的 SVN commit 都被抓下来了
    git svn fetch
    
    ##在git中查看svn commit记录信息
    git log --pretty=oneline
    
    ##查看分支 -- svn tag的被解析为git分支 ,需转换一下
    git branch -r 
    
    ##转换分支-tag  
    git tag tags_20160329_hg origin/tags/tags_20160329_hg  
    
    ##删除远程的分支(tags)
    git branch -r -d origin/tags/tags_20160329_hg  
     
    ##本地初始化git仓库完成
    git remote add origin [email protected]:move/dufy-tclshop-test-two.git
     
    #推送到远端的git的仓库中
    git push origin master --tags
    
    ##切换到分支
    git checkout 16130_20151125_hg 
    
    ##提交分支到远程的仓库中
    git push origin 16130_20151125_hg
    
  29. 调用本地html后css不加载

        导入html文件时选择错误, 不应只创建组, 应保留文件路径.
        只创建组会导致html中引入路径错误,所以css, js, img, video等文件会找不到.
        
        当然你也可以选择Create Groups后 修改html中link的href路径 script的src, img的src等...
    
  30. git push, clone , pull等 报错 Connection to XXXXX: Broken pipe

    方案1: 找到 ~/.ssh/config
            添加 Host *
                 ServerAliveInterval 120
                 ServerAliveCountMax 5
                 
            若没有config可自行创建, 如下
            命令行: cd ~/.ssh
                    vim config
                    <i> 
                    Host *
                    ServerAliveInterval 120
                    ServerAliveCountMax 5
                    <esc> -> :wq
    方案2: 找到 private/etc/ssh/ssh_config 并打开
            找到 # Host *
            添加 # ServerAliveInterval 120
  1. mac配置node.js及npm环境

    1. 安装brew - 软件包安装管理工具
        终端: ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
    
    2.将brew的位置添加到$PATH环境变量中,并保存bash或者profile文件;
        export PATH="/usr/local/bin:$PATH"
    
    3. 通过brew安装node 
        brew link node
        brew uninstall node
        brew install node
    
    3.
    
    4. 若npm命令符失效
        ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm
    
  2. 搭建本地服务器(node.js) 请求假数据

    1.在routes目录下新建一个xx.js
    
    代码:
        var express = require('express');
        var router = express.Router();
        
        var fs = require('fs');
        var path = require('path');
        
        var DATA_PATH = path.resolve(__dirname, '../public/data') + '/';
        
        var delay = function(req, res, next) {
            <!--if (req.baseUrl.indexOf('details') > -1) {
                setTimeout(function() {
                    next();
                }, 1000);
            } else {
                next();
            }-->
            
            next();
        
        }
        
    
        router.use('/:proj/:intf', delay, function(req, res, next) {
        
            fs.readFile(DATA_PATH + 
                          req.params.proj + 
                          '/' + 
                          req.params.intf,
                           'utf-8',
                            function(err, data){
                
                if (err) {
                    res.status(500).end();
                } else {
                    res.json(JSON.parse(data));
                }
            
            });
        
        });
    
        module.exports = router;
    
    2.在app.js中注册路由    
    
            var xx= require('./routes/xx');
            app.use('/', xx);
                            
            ...
            
            var http = require('http');
            http.createServer(app).listen(4333);
    
        module.exports = app;
    
  3. 解决html在iOS中滑动不流畅

    -webkit-overflow-scrolling: touch;
    
  4. css 层级

    z-index: 6000;
    
  5. 去除html, body滚动

    html: <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
    css: html, body {
                    height: 100%;
                    overflow:hidden;
                    }
    
  6. image not found

    在linked frameworks and libraries中找到相应framework, 将required改为optional;
    此问题是由于设备中找不到此framework镜像导致. iOS10以下系统默认不会加载UserNotification.framework
    
  7. JavaScript调用本地服务器(node.js + express)跨域, 解决:

    var app = express();
    app.all('*', function(req, res, next) {
        res.header("Access-Control-Allow-Origin", "*");
        res.header("Access-Control-Allow-Headers", "X-Requested-With");
        res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
        res.header("X-Powered-By",' 3.2.1')
        res.header("Content-Type", "application/json;charset=utf-8");
        next();
    });
    
  8. RunLoop

        RunLoop在子线程中如果没有调用, 应该是没有创建的, 和懒加载一个原理. 当在子线程中
    第一次获取Runloop时会先创建一个 <全局Dict> 用于储存runloop, 并获取到mainLoop存
    入其中, 然后获取子线程runloop, 如果获取不到会创建并存入Dict中.
    
        引用ibireme RunLoop中所言: 苹果不允许直接创建 RunLoop,它只提供了两个自动获取
    的函数:CFRunLoopGetMain() 和 CFRunLoopGetCurrent()。 这两个函数内部的逻
    辑大概是下面这样:
    
    /// 全局的Dictionary,key 是 pthread_t, value 是 CFRunLoopRef
    static CFMutableDictionaryRef loopsDic;
    /// 访问 loopsDic 时的锁
    static CFSpinLock_t loopsLock;
    
    /// 获取一个 pthread 对应的 RunLoop。
    CFRunLoopRef _CFRunLoopGet(pthread_t thread) {
        OSSpinLockLock(&loopsLock);
        
        if (!loopsDic) {
            // 第一次进入时,初始化全局Dic,并先为主线程创建一个 RunLoop。
            loopsDic = CFDictionaryCreateMutable();
            CFRunLoopRef mainLoop = _CFRunLoopCreate();
            CFDictionarySetValue(loopsDic, pthread_main_thread_np(), mainLoop);
        }
        
        /// 直接从 Dictionary 里获取。
        CFRunLoopRef loop = CFDictionaryGetValue(loopsDic, thread));
        
        if (!loop) {
            /// 取不到时,创建一个
            loop = _CFRunLoopCreate();
            CFDictionarySetValue(loopsDic, thread, loop);
            /// 注册一个回调,当线程销毁时,顺便也销毁其对应的 RunLoop。
            _CFSetTSD(..., thread, loop, __CFFinalizeRunLoop);
        }
        
        OSSpinLockUnLock(&loopsLock);
        return loop;
    }
    
    CFRunLoopRef CFRunLoopGetMain() {
        return _CFRunLoopGet(pthread_main_thread_np());
    }
    
    CFRunLoopRef CFRunLoopGetCurrent() {
        return _CFRunLoopGet(pthread_self());
    }
    
            
        从上面的代码可以看出,线程和 RunLoop 之间是一一对应的,其关系是保存在一个全局的 
    Dictionary 里。线程刚创建时并没有 RunLoop,如果你不主动获取,那它一直都不会有。
    RunLoop 的创建是发生在第一次获取时,RunLoop 的销毁是发生在线程结束时。你只能在一个
    线程的内部获取其 RunLoop(主线程除外)。--
    
    由图片加载引起的滑动卡顿可将图片加载置于runloop的DefaultModel中.
    
  9. YUV数据格式

    1. YUV 数据格式有两大类: planar 和 packed.
    
    planar: 先连续存储所有像素点的 Y分量, 接着所有像素点的 U分量, 然后所有像素点的 V分量 .
    Packed: 每个像素点的Y U V是连续交叉存储的.
    
    2. Y -- 明亮度
       UV -- 色彩及饱和度
    
    
    3. YUV 是一种颜色的编码方式,主流的采样方式有三种: YUV4:4:4,YUV4:2:2, YUV4:2:0
    
    
    4. YUV422 和 YUV420转换
    
       422 -> 420
            Y 不变, 将 U 和 V 信号值在行(垂直方向)再进行一次隔行抽样.
       420 -> 422
           Y不变, 将 U 和 V 信号值得每一行分别拷贝一份形成连续两行数据.
    
    
    
     下面区分一下YUV和YCbCr: 
        YUV色彩模型来源于RGB模型,该模型的特点是将亮度和色度分离开,从而适合于图像处理领域。
    应用:模拟领域
    Y'= 0.299*R' + 0.587*G' + 0.114*B'
    U'= -0.147*R' - 0.289*G' + 0.436*B' = 0.492*(B'- Y')
    V'= 0.615*R' - 0.515*G' - 0.100*B' = 0.877*(R'- Y')
    R' = Y' + 1.140*V'
    G' = Y' - 0.394*U' - 0.581*V'
    B' = Y' + 2.032*U'
    
    
    YCbCr模型来源于YUV模型。YCbCr是 YUV 颜色空间的偏移版本.
    应用:数字视频,ITU-R BT.601建议
    Y’ = 0.257*R' + 0.504*G' + 0.098*B' + 16
    Cb' = -0.148*R' - 0.291*G' + 0.439*B' + 128
    Cr' = 0.439*R' - 0.368*G' - 0.071*B' + 128
    R' = 1.164*(Y’-16) + 1.596*(Cr'-128)
    G' = 1.164*(Y’-16) - 0.813*(Cr'-128) - 0.392*(Cb'-128)
    B' = 1.164*(Y’-16) + 2.017*(Cb'-128)
    
    PS: 上面各个符号都带了一撇,表示该符号在原值基础上进行了伽马校正,伽马校正有助于弥补在抗锯齿的过程中,线性分配伽马值所带来的细节损失,使图像细节更加丰富。在没有采用伽马校正的情况下,暗部细节不容易显现出来,而采用了这一图像增强技术以后,图像的层次更加明晰了。
    
  10. void* rgbData 转 Image

    1. 创建色彩空间
    CGColorSpaceRef colorRef = CGColorSpaceCreateDeviceRGB();
    
    2. 创建BitMapContext
    CGContextRef context = CGBitmapContextCreate(rgbData, width, height, 8, width * 4, colorRef, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst);
    
    3. 获取CGImageRef
    CGImageRef quartsImage = CGBitmapContextCreateImage(context);
    
    4. CGImage转UIImage
    UIImage *image = [UIImage imageWithCGImage:quartzImage];
    
    5. 释放CGImage, 释放context, 释放ColorRef
    CGImageRelease(quartsImage);
    CGContextRelease(context);
    CGColorSpaceRelease(colorRef);
    
  11. void* rgbData 转 CVPixelBuffer

    1. 创建CVPixelBufferRef
    CVPixelBufferRef pixelBuffer = NULL;
    NSDictionary *pixelAtt = [NSDictionary dictionaryWithObject:@{} forKey:(NSString *)kCVPixelBufferIOSurfacePropertiesKey];
    CVReturn result = CVPixelBufferCreate(kCFAllocatorDefault, width, height, kCVPixelFormatType_32ARGB, (__bridge CFDictionaryRef)pixelAttributes, &pixelBuffer);
    
    if (result != kCVReturnSuccess) {
        NSLog(@"创建失败 %d", result);
        return;
    }
            
    2. 锁定baseAddress
    CVPixelBufferLockBaseAddress(pixelBuffer, 0);
    
    3. 获取yBaseAddressOfPlane
    unsigned char* yDestPlane = (unsigned char*)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
    if (yDestPlane == NULL) {
        NSLog(@"获取 Y baseAddressOfPlane失败");
        return;
    }
            
    4. 内存copy
    memcpy(yDestPlane, rgbData, width * height * 4);
    
    5. 解锁baseAddress
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
    
    6. do something
    // 传递pixelBuffer等.
        
    7. 释放pixelBuffr
    CVPixelBufferRelease(pixelBuffer);
    
  12. pixelBuffer 转 image

    1. 获取CVImageBufferRef
    CVImageBufferRef imageBuffer = pixelBuffer;
    
    2. 锁定BaseAddress
    CVPixelBufferBaseAddressLock(imageBuffer, 0);
    
    3. getBaseAddress
    void* baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
    
    4. getWidth, height, bufferSize, bytesPerRow
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CGPixelBufferGetHeight(imageBuffer);
    size_t bufferSize = CVPixelBufferGetDataSize(imageBuffer);
    size_t bytesPerRow = CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, 0);
    
    5. 创建色彩空间
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    
    6. 创建CGDataProviderRef
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, baseAddress, bufferSize, NULL);
    
    7. 创建CGImageRef, 转成UIImage
    CGImageRef cgImage = CGImageCreate(width, height, 8, 32, bytesPerRow, colorSpace, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little, provider, NULL, true, kCGRenderingIntentDefault);
    UIImage *image = [UIImage imageWithCGImage:cgImage];
    
    8. 解锁BaseAddress
    CVPixelBufferUnLockBaseAddress(imageBuffer, 0);
    
    9. 释放CGImage, 释放CGDataProvider
    CGImageRelease(cgImage);
    CGColorSpaceRelease(colorSpace);
    CGDataProviderRelease(provider);
    
  13. Xcode 10 Build Error about Info.plist

    Error:
    
    Multiple commands produce '~/Info.plist':
    
    1) Target 'target' has copy command from '~/Info.plist' to '~/Info.plist'
    2) Target 'target' has process command with input '~/Info.plist'
    
    解决方法:
    1. Target -> Build Phases -> Copy Bundle Resources
    2. Delete Info.plist
    3. Build Again.