iOS开发笔记(七)

正文

这次分享三个有意思的问题:二维码生成、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方法找到字体名。

    字体文件

总结

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容