首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS开发笔记(七)

iOS开发笔记(七)

作者头像
落影
发布2018-04-27 18:07:50
1.3K0
发布2018-04-27 18:07:50
举报
文章被收录于专栏:落影的专栏落影的专栏

正文

这次分享三个有意思的问题:二维码生成、Xcode8单元测试的问题、添加新字体

二维码生成

iOS平台上的二维码生成有很多第三方库,也可以使用原生的方法,这里选用的是QREncoder。 二维码的生成非常简单,仅需几行代码,如下:

    DataMatrix* qrMatrix = [QREncoder encodeWithECLevel:QR_ECLEVEL_H version:QR_VERSION_AUTO string:urlStr];
    int qrcodeImageDimension = 256;
    UIImage* qrcodeImage = [QREncoder renderDataMatrix:qrMatrix imageDimension:qrcodeImageDimension];

但是,在开发的时候,还是会遇到很多的问题:

1、编译失败的问题

编译的时候,会报无法识别class CQR_Encode{...}的错误。 从编译的错误来看,是编译器无法识别C++类CQR_Encode,通过头文件的索引定位到问题: QREncoder 的头文件用到了QR_LEVEL_H 这些属性需要引入QR_Encode.h,QR_Encode.h里面是c++的类; 解决方案有两个,一个是把代码的文件名后缀改成.mm,第二个是修改文件的Type类型为Objective-C++,如下:

这里如果把QR_ECLEVEL_H这几个define改成常量,用extern声明,也是一种解决方案;

2、图片的颜色值异常

QREncoder生成的图片是黑白的,我需要把图片改成下面这样:

设计的同学给出的颜色值是0xFFF04F43,格式是ARGB。 我尝试的解决方案是:遍历像素,把黑色的颜色值改成红色。 在看代码前,介绍几个基本知识点:

  • kCGBitmapByteOrderDefault 是小端模式; RGBA的模式,内存中的布局是0xAABBGGRR ARGB的模式,内存中的布局是0xBBGGRRAA
  • kCGImageAlphaPremultipliedLast 是先把alpha值乘到RGB值,再放到对应的内存;
- (UIImage *)lyRenderBlackToRedColor
{
    // 分配内存
    const int imageWidth = self.size.width;
    const int imageHeight = self.size.height;
    size_t      bytesPerRow = imageWidth * 4;
    uint32_t* rgbImageBuf = (uint32_t*)malloc(bytesPerRow * imageHeight);
    
    // 创建context
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(rgbImageBuf, imageWidth, imageHeight, 8, bytesPerRow, colorSpace,
                                                 kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast);
    CGContextDrawImage(context, CGRectMake(0, 0, imageWidth, imageHeight), self.CGImage);
    
    // 遍历像素
    int pixelNum = imageWidth * imageHeight;
    uint32_t* pCurPtr = rgbImageBuf;
    for (int i = 0; i < pixelNum; i++, pCurPtr++)
    {
        // RGBA的模式,内存中的布局是0xAABBGGRR
        // ARGB的模式,内存中的布局是0xBBGGRRAA
        if ((*pCurPtr & 0x00FFFFFF) == 0x00000000 && (*pCurPtr & 0xFF000000) == 0xFF000000)    // 将黑色变成红色
        {
            //            *pCurPtr = 0xFFF04F43;
            uint8_t* ptr = (uint8_t*)pCurPtr;
            ptr[3] = 0xff;
            ptr[2] = 0x43;
            ptr[1] = 0x4f;
            ptr[0] = 0xf0;
        }
        
        
    }
    // 将内存转成image
    CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, rgbImageBuf, bytesPerRow * imageHeight, lyProviderReleaseData);
    CGImageRef imageRef = CGImageCreate(imageWidth, imageHeight, 8, 32, bytesPerRow, colorSpace,
                                        kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast, dataProvider,
                                        NULL, true, kCGRenderingIntentDefault);
    CGDataProviderRelease(dataProvider);
    
    UIImage* resultUIImage = [UIImage imageWithCGImage:imageRef];
    
    // 释放
    CGImageRelease(imageRef);
    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);
    
    return resultUIImage;
}

void lyProviderReleaseData (void *info, const void *data, size_t size)
{
    free((void*)data);
}

问题1:CGBitmapContextCreate 创建失败,bitmap的data信息,我发现在上面的代码中仅支持AlphaPremultiplied的类型; 问题2:QREncoder生成的二维码,会有0x00101010 (ARGB)这样的数据,因为alpha=0,0x101010的颜色值会被忽略; 同样的,有部分透明的边会出现0x00ffffff,如果仅仅以RGB的值=0xffffff进行判断,会导致额外的黑边;

Xcode8单元测试的相关问题

1、单元测试的断点失效

stackoverflow上有关于breakpoints in unit test not getting hit的解决方案,但没有解决我的问题,原因可能并不一样。 先尝试非单元测试的raget,可以正常断点; 再尝试其他工程的单元测试,也可以正常断点; 猜测是,单元测试的工程设置存在问题; 仔细查找build setting,找到出问题的设置项:

新建Unit Test的时候,这里的属性值变成了DWARF,没有附带dSYM的符号文件,所以无法断点。

还有其他可能,比如test.m的文件没有加入工程中;(在Build PhasesCompile Soucres可以看到是否添加,也可以通过打Log看是否执行)

2、头文件查找失败

通常是在单元测试中调用了某些第三方库的代码,报.h file not found的错误; 如果单元测试引入文件A,文件A引入了第三方库C,那么需要在build setting添加对应的search framework

如果基础工程的项比较多,可以在选中之后(如上图)按cmd+c 再到新的target的cmd+v

3、embedded错误

错误描述是:ld: embedded dylibs/frameworks are only supported on iOS 8.0 and later (@rpath/XCTest.framework/XCTest) for architecture x86_64 以前加载动态库的时候,记得iOS8.0以上的版本才支持embedded frameworks,新的工程的设置deployment target是7.0。 检查Xcode工程,发现embedded frameworks这一项为空!

Xcode的版本是** Version 8.3.1 (8E1000a)** 猜测是Xcode生成的XCTest Framework是动态库,被Xcodeembedded到项目中。这个版本Xcode能选择最低iOS版本是8.0,所以Xcode可能没有考虑XCTest.framework兼容iOS8以下的情况。 解决方案就是把deployment target暂时设置成8.0。

4、Undefined symbols for architecture x86_64

注意这里的描述是Undefined symbols,表示编译器找到变量的声明,但是没有找到变量的实现,于是在linking的阶段就会报错; 还有一种情况是Use of undeclared identifier,这种是找不到变量的声明,一般是没有引入头文件,或者没有正确设置头文件的search路径。

i386是32位模拟器(5和5s以下的机型) x86_64是64位模拟器(5s后面的机型) armv7/armv7s是32位真机 arm64是64位真机 coocachina上有更详细的介绍。

添加新字体

  • 1、把.ttf字体文件导入Xcode工程;
  • 2、在plist添加对应的字体文件,如下:

plist

  • 3、在代码中通过[UIFont fontWithName:@“newFontName” size:18]加载新字体; newFontName 是字体的名字,通过在Finder双击字体文件,红色圈起来的部分就是字体的family Name,再通过UIFont的-fontNamesForFamilyName方法找到字体名。

字体文件

总结

学而不思则罔,思而不学则殆。 遇到问题,尝试去解决它,并从中得到知识; 思考问题的前因后果,避免再次遇到同样的问题。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.08.17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 正文
    • 二维码生成
      • 1、编译失败的问题
        • 2、图片的颜色值异常
        • Xcode8单元测试的相关问题
          • 1、单元测试的断点失效
            • 2、头文件查找失败
              • 3、embedded错误
                • 4、Undefined symbols for architecture x86_64
                • 添加新字体
                • 总结
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档