iOS10 再谈CAAnimationDelegate相关协议的适配

前言

之前写过这样一篇文章:

iOS10 CAAnimationDelegate的简单适配

文中提到了在iOS10中,关于系统API里CAAnimationDelegate协议的一些变化以及一种较为妥协的的适配写法。此文是基于上文的一个补充和完善,并提出一些相对更为完善的写法。
为了方便和节省大家的时间,先在此直接给出下文中提到的一种最简单的写法,对于探究过程没有兴趣的可以直接忽略下文(但是还是强烈建议看看,一方面这么写一项都不能缺省是有重要原因的,另一方面如果你还有其他想法,欢迎据此给出指正或建议)

#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
@interface ViewController () <CALayerDelegate>
#else
@interface ViewController ()
#endif
@end

1.起因

写这篇文章的起因是前阵子在写一个demo时,用到了CALayerDelegate的相关协议方法,并遇到了和CAAnimationDelegate一样的情况,警告。
查看API,也看到了类似的变化:

iOS10以后的CALayerDelegate(截图自xcode8.1相关API)

再对比下10以前的:

iOS10之前的CALayerDelegate(截图自xcode7.3.1相关API)

同样的变化,由基类的分类这种非正式协议,变成了正式的协议声明。再看下这个代理的前后变化:

iOS10以后
iOS10之前

本来也是直接按照之前的方式来解决这个警告的,但是细想下来,不知道这样的变化还有多少,只是目前遇到的,都只是QuartzCore框架下的。这或许是苹果在规范自己的API?

2.关于这里的适配

这里说的适配,并不是像适配某一个方法是否兼容某一系统版本那样的适配,因为那种版本适配不做的话,影响的是APP的兼容性。而这里的适配,并不会影响APP的兼容性,有试过直接用低版本真机编译这些未经适配的协议代码,执行并不会有什么影响。具体机理我并不能说太清楚,但是毕竟这只是一种针对原有API的修改,而不是新增。(其实我一直是很好奇像NS_AVAILABLE_IOS这类相关的宏标示的方法和其指定的低版本系统不兼容的原因,是系统执行这些代码时会遇到什么问题吗?求解。)

那么做这样的适配意义又何在?
开发兼容。

一个团队协作开发,可能因为各种原因,每个人的xcode版本并不能保持一致(适配iOS7及以下的机器用xcode8调试不了、低版本系统的mac装不了新的xcode……)。
还有就是我们在写一些开源三方时,不做这样的兼容适配,有些使用低版本xcode的开发者,在使用你的代码时,可能会因此报错,从而造成一些不必要的麻烦。

3.更好的适配写法

这里的更好,是相对之前那篇文章来的。
之前那样写,是因为不能确定开发者xcode版本,从而不能直接使用__IPHONE_10_0这类宏。

3.1.尝试的方案一

#if (__IPHONE_OS_VERSION_MAX_ALLOWED == __IPHONE_10_0) || (__IPHONE_OS_VERSION_MAX_ALLOWED == __IPHONE_10_1)
@interface ViewController () <CALayerDelegate>
#else
@interface ViewController ()
#endif
@end

既然不能确定__IPHONE_10_0宏是否存在,从而不能直接写__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0这样的判定语句(因为若__IPHONE_10_0宏不存在,这个逻辑恒成立从而无效),那么改为判等应该就没问题了,可惜因为10.1也出来了,只能增加或逻辑。不过,这样做,同样带来了维护的代价,系统肯定是要持续迭代的,每次迭代都要新增或条件,这样做麻烦不说,风险也是远大于之前的做法的。。。

3.2.改进的方案二

#ifdef __IPHONE_10_0
@interface ViewController () <CALayerDelegate>
#else
@interface ViewController ()
#endif
@end

既然是因为无法判断__IPHONE_10_0宏是否存在,那么就以此为条件岂不是正好?而且这类宏是随版本迭代持续递增的,那么只要__IPHONE_10_0存在,应该就可以确认xcode版本至少是8,毕竟__IPHONE_10_1肯定是之后出现的。
然而,经过实际实验……在xcode7.3.1上依旧报错:CALayerDelegate协议不存在,#ifdef条件分支依旧参与编译了……why???
首先这样的逻辑应该是没问题的,那就查看xcode7.3.1的API吧。果然,在CABase.h文件中发现了这样的一段定义:

xcode7.3.1中CABase.h文件中的一段定义

什么鬼???9.3.1还要涉及10.0了?难怪之前的条件可以成立……
再次翻看xcode8.1中关于CABase.h中的相关部分,好嘛,这些已经全都没有了,整个头文件的宏定义改了一大半,基本“面目全非”了,果然是善变啊……

3.3.完善的方案三

有了之前两次尝试,方案三应运而生,也就是文章开头的那个了:

#if defined(__IPHONE_10_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0)
@interface ViewController () <CALayerDelegate>
#else
@interface ViewController ()
#endif
@end

这就是为什么开头有提到,一项都不能缺省,否则后果见方案二。
这里除了判断__IPHONE_10_0宏是否定义,还判断了当前系统的版本是否是大于10.0的,其实主要是为了判断xcode的版本是否是大于8.0的(第2部分提到的开发适配)。
#if defined(__IPHONE_10_0)这个等效于#if defined __IPHONE_10_0,也就是我们通常写的#ifdef __IPHONE_10_0的简化后的单条件版本,用#if defined更为灵活,可以判断多个条件。
当然这里也可以根据习惯拆开写,即先写#ifdef __IPHONE_10_0,再写#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_10_0,只是多了几步,意思相同。

至此,针对这部分的适配结束了。最终的方案应该是较为完善的了,目前也没有想到更合适的了。实际使用测试,还没有发现什么问题,如果你遇到了,欢迎及时反馈。

参考文章:
1.C语言的条件编译#if, #elif, #else, #endif、#ifdef, #ifndef
2.#if、#ifdef、#if defined之间的区别
3.#if defined和#if !defined(c语言的宏定义)

·转载请声明·

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

推荐阅读更多精彩内容

  • 因为要结局swift3.0中引用snapKit的问题,看到一篇介绍Xcode8,swift3变化的文章,觉得很详细...
    uniapp阅读 4,385评论 0 12
  • 一.iPhone X尺寸问题 1. 高度增加了145pt,变成812pt. 2.屏幕圆角显示,注意至少留10pt边...
    骑行天下阅读 12,769评论 5 36
  • 1.尺寸适配1.原因 iOS7中所有导航栏都为半透明,导航栏(height=44)和状态栏(height=20)不...
    LZM轮回阅读 6,084评论 1 4
  • 曾经有一段时间,我的工作非常忙碌,忙到除了睡觉吃饭的时间,其他时间都在工作。而且为了最高效地处理工作,防止工...
    妙贝阅读 766评论 0 1
  • 正确写法应该是:弗洛伊德 弗洛伊德生平 作为一个治疗精神疾病的医生,弗洛伊德创立了一个涉及人类心理结构和功能的学说...
    昭的私房家伙阅读 514评论 0 0