这个栏目将持续更新–请iOS的小伙伴关注!

1、iOS 应用导航模式有哪些?2、iOS 中持久化方式有哪些?3、iOS
单元测试框架有哪些?4、iOS 7层协议,tcp四层协议及如何对应的?5、iOS
你在项目中用过 runtime 吗?举个例子6、iOS 什么是ARC?7、iOS
说明并比较关键词:atomatic, nonatomic8、iOS 说明并比较关键词:strong,
weak, assign, copy9、iOS 说明并比较关键词:__weak,__block10、iOS
什么情况下会出现循环引用?11、iOS 类和结构体有什么区别?12、iOS
什么是KVO和KVC?他们的使用场景是什么?13、iOS
通知和协议有哪些不同之处?14、iOS
应用有哪些方式保存本地数据?他们都应用在哪些场景?15、iOS
内存的使用和优化的注意事项?16、iOS
UIViewController的完整生命周期?17、iOS 队列和多线程的使用原理?18、iOS
SQLite中常用的SQL语句?19、iOS frame和bounds有什么不同?20、iOS
view的touch事件有哪些?21、iOS 中的响应者链的工作原理?22、iOS
property属性的修饰符的作用?23、iOS 对于Run Loop的理解?24、iOS
@synthesize、@dynamic的理解?25、iOS 对瀑布流的理解?26、iOS
单例模式理解与使用?27、iOS 对沙盒的理解?28、iOS
三方库SDWebImage原理?29、iOS 网络七层协议?30、iOS
如何进行网络消息推送?31、iOS SVN的使用?32、iOS
简述APP发布的上架流程?33、iOS 如何进行真机调试?34、iOS
XML数据解析方式各有什么不同,JSON解析有哪些框架?35、iOS
ASIHttpRequest、AFNetWorking之间的区别?36、iOS
HTTP协议的特点,关于HTTP请求GET和POST的区别?37、iOS
Scoket连接和HTTP连接的区别?38、iOS TCP连接的三次握手?39、iOS
TCP和UDP的区别于联系?40、iOS Apple设备尺寸和编程尺寸?41、iOS
线程与进程的区别和联系?42、iOS 定时器与线程的区别?43、iOS
使用block有什么好处?使用NSTimer写出一个使用block显示(在UILabel上)秒表的代码?44、iOS
解决cell重用的问题?45、iOS
怎样使用performSelector传入3个以上参数,其中一个为结构体?46、iOS
解释self = [super init]方法?47、iOS 在某个方法中 self.name =
_name,name = _name 它 们有区别吗,为什么?48、iOS Core
Data的6成员对象?49、iOS iOS 开发中数据持久性有哪几种?50、iOS
isMemberOfClass 和 isKindOfClass 联系与区别?51、iOS
@public、@protected、@private 它们的含义与作用?52、iOS
#include与#import的区别、**#import **与@class 的区别?53、iOS
static、self、super关键字的作用?54、iOS
NSNotification、Block、Delegate和KVO的区别?55、iOS 代理的作用?56、iOS
键路径、键值编码、键值观察?57、iOS
循环引用的产生原因,以及解决方法?58、iOS 类别的作用?59、iOS
简述类目category优点和缺点?60、iOS 简述内存管理基本原则?61、iOS
OC的理解与特性?62、63、64、65、66、67、68、69、70、71、72、73、74、75、76、77、78、iOS
你在项目中用过 GCD 吗?举个例子79、iOS Category 的实现原理,以及
Category 为什么只能加方法不能加属性?80、iOS block 的原理,block
的属性修饰词为什么用 copy,使用 block 时有哪些要注意的?81、iOS
的热更新方案有哪些?介绍一下实现原理?82、iOS class A 继承 class B,class
B 继承 NSObject。画出完整的类图?83、iOS 细致地讲一下事件传递流程?84、iOS
main()之前的过程有哪些?85、iOS Category 中有 load 方法吗?load
方法是什么时候调用的?load 方法能继承吗?86、iOS 讲一下你对 iOS
内存管理的理解?87、iOS 你在项目中是怎么优化内存的?88、iOS 讲讲
RunLoop,项目中有用到吗?89、iOS
列表卡顿的原因可能有哪些?你平时是怎么优化的?90、iOS
项目有没有做过组件化?或者你是否调研过?91、iOS 讲一下 OC
的消息机制?92、iOS ARC 都帮我们做了什么?93、iOS 实现 isEqual 和 hash
方法时要注意什么?94、iOS
线程安全的处理手段有哪些?把你想到的都说一下?95、iOS 说一下
OperationQueue 和 GCD 的区别,以及各自的优势?96、iOS Swift 中 struct 和
class 的区别?97、iOS Swift 是如何实现多态的?98、iOS Swift 和
OC,各自的优缺点有哪些?99、iOS 如果让你实现
NSNotificationCenter,讲一下思路?100、iOS 如果让你实现 GCD
的线程池,讲一下思路?101、iOS
为什么是三次握手?为什么是四次挥手?三次挥手不行吗?102、iOS 讲一下
HTTPS 密钥传输流程?103、iOS 讲讲
MVC、MVVM、MVP,以及你在项目里具体是怎么写的?104、iOS
系统框架里使用了哪些设计模式?至少说6个?105、iOS
你自己用过哪些设计模式?106、iOS
哪一个项目技术点最能体现自己的技术实力?具体讲一下107、iOS
你在项目中遇到的最大的问题是什么?你是怎么解决的?108、iOS 用 Alamofire
比直接使用 URLSession,优势是什么?109、你是如何学习 iOS 的?110、iOS
和产品经理、测试产生冲突时,你是怎么解决的?111、iOS
手写一下快排?112、iOS 遍历一个树,要求不能用递归?113、iOS
找出两个字符串的最大公共子字符串?114、115、116、117、118、119、120、121、122、123、124、125、126、127、128、iOS
为什么说Objective-C是一门动态的语言?129、iOS
进程和线程的区别?同步异步的区别?并行和并发的区别?130、iOS
用StoryBoard开发界面有什么弊端?如何避免?131、iOS
GCD的一些常用的函数?(group,barrier,信号量,线程同步)?132、iOS
block的实质是什么?一共有几种block?都是什么情况下生成的?133、iOS
为什么在默认情况下无法修改被block捕获的变量?
__block都做了什么?134、iOS
模拟一下循环引用的一个情况?block实现界面反向传值如何实现?135、iOS
什么时候会报unrecognized
selector错误?iOS有哪些机制来避免走到这一步?136、iOS
objc在向一个对象发送消息时,发生了什么?137、iOS
能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么138、iOS
runtime如何实现weak变量的自动置nil?139、iOS
给类添加一个属性后,在类结构体里哪些元素会发生变化?140、iOS
runloop是来做什么的?runloop和线程有什么关系?主线程默认开启了runloop么?子线程呢?141、iOS
runloop的mode是用来做什么的?有几种mode?142、iOS
苹果是如何实现Autorelease Pool的?143、iOS
为什么把NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主运行循环以后,滑动scrollview的时候NSTimer却不动了?144、iOS
isa指针?(对象的isa,类对象的isa,元类的isa都要说)145、iOS
运行时能增加成员变量么?能增加属性么?如果能,如何增加?如果不能,为什么?146、iOS
objc中向一个nil对象发送消息将会发生什么?(返回值是对象,是标量,结构体)147、iOS
UITableview的优化方法(缓存高度,异步绘制,减少层级,hide,避免离屏渲染)148、iOS
有没有用过运行时,用它都能做什么?(交换方法,创建类,给新创建的类增加方法,改变isa指针)149、iOS
看过哪些第三方框架的源码?都是如何实现的?(如果没有,问一下多图下载的设计)150、iOS
KVC的使用?实现原理?(KVC拿到key以后,是如何赋值的?知不知道集合操作符,能不能访问私有属性,能不能直接访问_ivar)151、152、153、iOS
UITableViewCell上有个UILabel,显示NSTimer实现的秒表时间,手指滚动cell过程中,label是否刷新,为什么?154、iOS
有a、b、c、d
4个异步请求,如何判断a、b、c、d都完成执行?如果需要a、b、c、d顺序执行,该如何实现?155、iOS
一个view已经初始化完毕,view上面添加了n个button,除用view的tag之外,还可以采用什么办法来找到自己想要的button来修改button的值?156、iOS
浅复制和深复制的区别?157、iOS MVC设计模式是什么?
你还熟悉什么设计模式?他们和MVC有什么不同的地方?158、 iOS
内存管理的几条原则时什么?按照默认法则.哪些关键字生成的对象需要手动释放?在和property结合的时候如何有效的避免内存泄露?159、iOS
Objective-C如何对内存管理的,说说你的看法以及你遇到的问题以及解决方法?160、iOS
以scheduledTimerWithTimeInterval的方式触发的timer,在滑动页面上的列表时,timer会暂停,为什么?该如何解决

并没有结束🔚… 正在整理答案 正在搜集面试题中
speed:大概一天5篇的更新速度前进中

另外我附上一份pdf班的面试题大全 ! 要的留言关注联系我

如下图所示:

图片 1iOS
大全图片 2iOS
大全

图片 3

腾讯社交网络相关产品,例如腾讯课堂、增值会员、动漫、直播、游戏商城、音乐、Qzone校园等,主要目标群体定位为年轻一代,属于对新事物接受比较高也更喜欢新鲜个性内容的群体,产品设计上必然使用大量的图片展示;同时核心产品QQ也涉及大量的图片存储及展示,例如QQ群图、群相册等。

在开始之前建议先阅读iOS runtime的基础理解篇:iOS内功篇:runtime

图片在产品中的大量使用拥有诸多好处的同时,也带来以下几点问题:

有筒子在面试的时候,遇到这样一个问题:“你知道成员变量的本质是什么吗?”,筒子立马懵逼了,成员变量的本质?成员变量就是成员变量啊,平时只管用,还有什么更深层的含义?本文着重介绍runtime中成员变量和属性的定义和使用。

服务器端出口流量增加、文件存储磁盘增加,运营成本增高;

用户访问单页面/产品流量消耗增加,尤其当前移动互联网流量按量计费,富图片会明显增加用户访问成本;

客户端加载页面耗时增大,首屏显示时间延迟,影响用户使用体验。

1、定义:Ivar: 实例变量类型,是一个指向objc_ivar结构体的指针

为了进一步降低运营带宽成本,减小用户访问流量及提升页面加载速度,社交网络
CDN运维紧跟行业图片优化趋势,创新引入WebP、SharpP、自适应分辨率、Guetzli等图像压缩技术到现网,经过三年多的多部门联合攻关,已逐渐形成一套覆盖全图片类型(JPEG、JPG、PNG、WebP、GIF)多场景的图片压缩运营体系,适用于各类型终端,每年节约外网带宽几百G。

typedef struct objc_ivar *Ivar;

图片 4QQ空间GIF采用SharpP编码后,单图平均大小降幅90%,高峰期流量降幅30%图片 5示例2:QQ相册GIF采用SharpP编码后,节约流量非常明显,降幅超过80%

2、操作函数:

– 即时通讯开发交流群:320837163[推荐]

– 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》

// 获取所有成员变量class_copyIvarList

// 获取成员变量名ivar_getName

// 获取成员变量类型编码ivar_getTypeEncoding

// 获取指定名称的成员变量class_getInstanceVariable

// 获取某个对象成员变量的值object_getIvar

// 设置某个对象成员变量的值object_setIvar

(本文同步发布于:

3、使用实例:Model的头文件声明如下:

《QQ音乐团队分享:Android中的图片压缩技术详解》

 @interface Model : NSObject { NSString * _str1; } @property NSString * str2; @property (nonatomic, copy) NSDictionary * dict1; @end

《QQ音乐团队分享:Android中的图片压缩技术详解》

获取其成员变量:

《腾讯原创分享:如何大幅提升移动网络下手机QQ的图片传输速度和成功率》

 unsigned int outCount = 0; Ivar * ivars = class_copyIvarList([Model class], &outCount); for (unsigned int i = 0; i < outCount; i ++) { Ivar ivar = ivars[i]; const char * name = ivar_getName; const char * type = ivar_getTypeEncoding; NSLog(@"类型为 %s 的 %s ",type, name); } free;

《腾讯原创分享:如何大幅压缩移动网络下APP的流量消耗》

打印结果:

《腾讯原创分享:如何大幅压缩移动网络下APP的流量消耗》

runtimeIvar[602:16885] 类型为 @"NSString" 的 _str1 runtimeIvar[602:16885] 类型为 @"NSString" 的 _str2 runtimeIvar[602:16885] 类型为 @"NSDictionary" 的 _dict1 

《基于社交网络的Yelp是如何实现海量用户图片的无损压缩的?》

1、定义:objc_property_t:声明的属性的类型,是一个指向objc_property结构体的指针

《腾讯团队分享 :一次手Q聊天界面中图片显示bug的追踪过程分享》

typedef struct objc_property *objc_property_t;

《微信团队分享:视频图像的超分辨率技术原理和应用场景》

2、操作函数:

图片 6

// 获取所有属性class_copyPropertyList

WebP是Google在2010年推出的新一代web图片压缩格式,它的优势体现在:

说明:使用class_copyPropertyList并不会获取无@property声明的成员变量

具有更优的图像数据压缩算法,能带来更小的图片体积(原图基础上节约30%左右大小);

// 获取属性名property_getName

// 获取属性特性描述字符串property_getAttributes

// 获取所有属性特性property_copyAttributeList

拥有肉眼识别无差异的图像质量;

说明:property_getAttributes函数返回objc_property_attribute_t结构体列表,objc_property_attribute_t结构体包含name和value,常用的属性如下:

具备了无损和有损的压缩模式、Alpha 透明以及动画的特性;

属性类型 name值:T value:变化编码类型 name值:C & W 空 等 value:无非/原子性 name值:空 N(Nonatomic) value:无变量名称 name值:V value:变化

在 JPEG 和 PNG 上的转化效果都相当优秀、稳定和统一;

使用property_getAttributes获得的描述是property_copyAttributeList能获取到的所有的name和value的总体描述,如
T@"NSDictionary",C,N,V_dict1

支持GIF,对GIF的压缩效果尤其显著,可以节约企业大量的带宽资源以及数据空间。

3、使用实例:

运维同事及时跟进研究WebP并推动应用现网,并基于该技术建立了最初的CDN图片压缩访问方案。

 unsigned int outCount = 0; objc_property_t * properties = class_copyPropertyList([Model class], &outCount); for (unsigned int i = 0; i < outCount; i ++) { objc_property_t property = properties[i]; //属性名 const char * name = property_getName; //属性描述 const char * propertyAttr = property_getAttributes; NSLog(@"属性描述为 %s 的 %s ", propertyAttr, name); //属性的特性 unsigned int attrCount = 0; objc_property_attribute_t * attrs = property_copyAttributeList(property, &attrCount); for (unsigned int j = 0; j < attrCount; j ++) { objc_property_attribute_t attr = attrs[j]; const char * name = attr.name; const char * value = attr.value; NSLog(@"属性的描述:%s 值:%s", name, value); } free; NSLog; } free(properties);

压缩参数设置:

打印结果:

图片 7

runtimeIvar[661:27041] 属性描述为 T@"NSString",&,V_str2 的 str2 runtimeIvar[661:27041] 属性的描述:T 值:@"NSString"runtimeIvar[661:27041] 属性的描述:& 值:runtimeIvar[661:27041] 属性的描述:V 值:_str2runtimeIvar[661:27041] runtimeIvar[661:27041] 属性描述为 T@"NSDictionary",C,N,V_dict1 的 dict1 runtimeIvar[661:27041] 属性的描述:T 值:@"NSDictionary"runtimeIvar[661:27041] 属性的描述:C 值:runtimeIvar[661:27041] 属性的描述:N 值:runtimeIvar[661:27041] 属性的描述:V 值:_dict1runtimeIvar[661:27041] 

通过验证发现,压缩质量参数在编码后图片质量及大小间形成正相关关系,质量参数越高,编码后图片质量越好体积也就越大。质量参数设置70%~90%间,可以达到最优平衡。现网默认设置80%。

在开发中相信最常用的就是接口数据需要转化成Model了(当然如果你是直接从Dict取值的话。。。),很多开发者也都使用著名的第三方库如JsonModel、Mantle或MJExtension等,如果只用而不知其所以然,那真和“搬砖”没啥区别了,下面我们使用runtime去解析json来给Model赋值。

编/解码性能优化:

原理描述:用runtime提供的函数遍历Model自身所有属性,如果属性在json中有对应的值,则将其赋值。核心方法:在NSObject的分类中添加方法:

终端WebP解码性能,在当前网络环境下不存在问题,平均解码耗时在100ms以内。并且,通过有限制的使用WebP图片,例如限制图片尺寸、使用的CPU核心及最大频率等方式,可以进一步优化编解码能力。

- (instancetype)initWithDict:(NSDictionary *)dict { if (self = [self init]) { //获取类的属性及属性对应的类型 NSMutableArray * keys = [NSMutableArray array]; NSMutableArray * attributes = [NSMutableArray array]; /* * 例子 * name = value3 attribute = T@"NSString",C,N,V_value3 * name = value4 attribute = T^i,N,V_value4 */ unsigned int outCount; objc_property_t * properties = class_copyPropertyList([self class], &outCount); for (int i = 0; i < outCount; i ++) { objc_property_t property = properties[i]; //通过property_getName函数获得属性的名字 NSString * propertyName = [NSString stringWithCString:property_getName encoding:NSUTF8StringEncoding]; [keys addObject:propertyName]; //通过property_getAttributes函数可以获得属性的名字和@encode编码 NSString * propertyAttribute = [NSString stringWithCString:property_getAttributes encoding:NSUTF8StringEncoding]; [attributes addObject:propertyAttribute]; } //立即释放properties指向的内存 free(properties); //根据类型给属性赋值 for (NSString * key in keys) { if ([dict valueForKey:key] == nil) continue; [self setValue:[dict valueForKey:key] forKey:key]; } } return self;}

终端兼容性:

读者可以进一步思考:1、如何识别基本数据类型的属性并处理2、空值的处理3、json中嵌套json(Dict或Array)的处理尝试解决以上问题,你也能写出属于自己的功能完备的Json转Model库。

图片 8

有时候我们要对一些信息进行归档,如用户信息类UserInfo,这将需要重写initWithCoder和encodeWithCoder方法,并对每个属性进行encode和decode操作。那么问题来了:当属性只有几个的时候可以轻松写完,如果有几十个属性呢?那不得写到天荒地老?。。。

嵌入WebP解码库的自有APP以及已知支持WebP的公共浏览器,例如Chrome、Opera等,其他场景下无法解码WebP数据(关于主流浏览器对WebP的支持情况点此查看)。

原理描述:用runtime提供的函数遍历Model自身所有属性,并对属性进行encode和decode操作。核心方法:在Model的基类中重写方法:

一期主要联合ISUX开发实现现网CDN的WebP能力引入,并建立了相应压缩访问方案,如下图所示:

- initWithCoder:(NSCoder *)aDecoder { if (self = [super init]) { unsigned int outCount; Ivar * ivars = class_copyIvarList([self class], &outCount); for (int i = 0; i < outCount; i ++) { Ivar ivar = ivars[i]; NSString * key = [NSString stringWithUTF8String:ivar_getName]; [self setValue:[aDecoder decodeObjectForKey:key] forKey:key]; } } return self;}- encodeWithCoder:(NSCoder *)aCoder { unsigned int outCount; Ivar * ivars = class_copyIvarList([self class], &outCount); for (int i = 0; i < outCount; i ++) { Ivar ivar = ivars[i]; NSString * key = [NSString stringWithUTF8String:ivar_getName]; [aCoder encodeObject:[self valueForKey:key] forKey:key]; }}

图片 9

我们知道,OC中没有真正意义上的私有变量和方法,要让成员变量私有,要放在m文件中声明,不对外暴露。如果我们知道这个成员变量的名称,可以通过runtime获取成员变量,再通过getIvar来获取它的值。方法:

服务器端部署异步压缩工具,对特定规则的图片应用压缩,并生成对应的副本文件;

 Ivar ivar = class_getInstanceVariable([Model class], "_str1"); NSString * str1 = object_getIvar(model, ivar);

客户端(Browser+APP)和后台管理端联动,客户端识别载体是否支持WebP解码,并将结果返回后台管理端,后台管理端再根据客户端能力,确定最终的资源访问URL。

欢迎大家交流探讨。

大致的原理是:

哪里涉及到runtime

CDN源站部署WebP编码工具,对符合规则的资源进行WebP编码及写DB操作;

1.1 OC的方法调用流程

下面以实例对象调用方法[blackDog walk]为例描述方法调用的流程:

1、编译器会把`[blackDog walk]`转化为`objc_msgSend(blackDog,SEL)`,SEL为@selector。2、Runtime会在blackDog对象所对应的Dog类的方法缓存列表里查找方法的SEL3、如果没有找到,则在Dog类的方法分发表查找方法的SEL。(类由对象isa指针指向,方法分发表即methodList)4、如果没有找到,则在其父类(设Dog类的父类为Animal类)的方法分发表里查找方法的SEL(父类由类的superClass指向)5、如果没有找到,则沿继承体系继续下去,最终到达NSObject类。6、如果在234的其中一步中找到,则定位了方法实现的入口,执行具体实现7、如果最后还是没有找到,会面临两种情况:`` 如果是使用`[blackDog walk]`的方式调用方法```` 使用`[blackDog performSelector:@selector]`的方式调用方法`

WebP编码采用异步模式,且编码成功后才写DB知会后台管理,因此即使编码失败或耗时长也不影响客户端实际访问;

1.2 消息转发流程

1、动态方法解析接收到未知消息时(假设blackDog的walk方法尚未实现),runtime会调用+resolveInstanceMethod:或者+resolveClassMethod:2、备用接收者如果以上方法没有做处理,runtime会调用- forwardingTargetForSelector:aSelector方法。如果该方法返回了一个非nil的对象,而且该对象实现了这个方法,那么这个对象就成了消息的接收者,消息就被分发到该对象。适用情况:通常在对象内部使用,让内部的另外一个对象处理消息,在外面看起来就像是该对象处理了消息。比如:blackDog让女朋友whiteDog来接收这个消息3、完整消息转发在- forwardInvocation:(NSInvocation *)anInvocation方法中选择转发消息的对象,其中anInvocation对象封装了未知消息的所有细节,并保留调用结果发送到原始调用者。比如:blackDog将消息完整转发給主人dogOwner来处理

图片 10

”你知道成员变量的本质是什么吗?”答案在这里:OS
runtime实战应用:成员变量和属性

客户端需先向后台管理获取资源路径,然后才能对资源发起实际请求,向管理端请求资源访问路径时,会带上自身WebP兼容性标签数据;

2.1 json->model

原理描述:用runtime提供的函数遍历Model自身所有属性,如果属性在json中有对应的值,则将其赋值。核心方法:在NSObject的分类中添加方法

- (instancetype)initWithDict:(NSDictionary *)dict { if (self = [self init]) { //获取类的属性及属性对应的类型 NSMutableArray * keys = [NSMutableArray array]; NSMutableArray * attributes = [NSMutableArray array]; /* * 例子 * name = value3 attribute = T@"NSString",C,N,V_value3 * name = value4 attribute = T^i,N,V_value4 */ unsigned int outCount; objc_property_t * properties = class_copyPropertyList([self class], &outCount); for (int i = 0; i < outCount; i ++) { objc_property_t property = properties[i]; //通过property_getName函数获得属性的名字 NSString * propertyName = [NSString stringWithCString:property_getName encoding:NSUTF8StringEncoding]; [keys addObject:propertyName]; //通过property_getAttributes函数可以获得属性的名字和@encode编码 NSString * propertyAttribute = [NSString stringWithCString:property_getAttributes encoding:NSUTF8StringEncoding]; [attributes addObject:propertyAttribute]; } //立即释放properties指向的内存 free(properties); //根据类型给属性赋值 for (NSString * key in keys) { if ([dict valueForKey:key] == nil) continue; [self setValue:[dict valueForKey:key] forKey:key]; } } return self;}

CDN缓存是基于访问URL为key的,而原图及WebP副本访问URL不一样(副本为.webp后缀),因此实际会在CDN节点缓存两份不同数据。

2.2 一键序列化

原理描述:用runtime提供的函数遍历Model自身所有属性,并对属性进行encode和decode操作。核心方法:在Model的基类中重写方法:

- initWithCoder:(NSCoder *)aDecoder { if (self = [super init]) { unsigned int outCount; Ivar * ivars = class_copyIvarList([self class], &outCount); for (int i = 0; i < outCount; i ++) { Ivar ivar = ivars[i]; NSString * key = [NSString stringWithUTF8String:ivar_getName]; [self setValue:[aDecoder decodeObjectForKey:key] forKey:key]; } } return self;}- encodeWithCoder:(NSCoder *)aCoder { unsigned int outCount; Ivar * ivars = class_copyIvarList([self class], &outCount); for (int i = 0; i < outCount; i ++) { Ivar ivar = ivars[i]; NSString * key = [NSString stringWithUTF8String:ivar_getName]; [aCoder encodeObject:[self valueForKey:key] forKey:key]; }}

以上方案在接入CDN的ISUX上使用稳定,并且达到了预期效果,后续也逐步推广应用到了少量Qzone图片上。不过由于该方案对接入业务侵入性较强,要求业务客户端必须具备WebP兼容性检测能力,以及访问URL后台下发能力,最终接入业务除相册外,寥寥无几。

2.3 访问私有变量

我们知道,OC中没有真正意义上的私有变量和方法,要让成员变量私有,要放在m文件中声明,不对外暴露。如果我们知道这个成员变量的名称,可以通过runtime获取成员变量,再通过getIvar来获取它的值。方法:

Ivar ivar = class_getInstanceVariable([Model class], "_str1");NSString * str1 = object_getIvar(model, ivar);

如何給NSArray添加一个属性答案在这里:iOS
runtime实战应用:关联对象polen:OC的分类允许给分类添加属性,但不会自动生成getter、setter方法所以常规的仅仅添加之后,调用的话会crash

runtime如何关联对象

//关联对象void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)//获取关联的对象id objc_getAssociatedObject(id object, const void *key)//移除关联的对象void objc_removeAssociatedObjects(id object)

应用,如何关联:

- setCustomTabbar:customTabbar { //这里使用方法的指针地址作为唯一的key objc_setAssociatedObject(self, @selector(customTabbar), customTabbar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);}- customTabbar { return objc_getAssociatedObject(self, @selector(customTabbar));}

method
Swizzling原理每个类都维护一个方法列表,Method则包含SEL和其对应IMP的信息,方法交换做的事情就是把SEL和IMP的对应关系断开,并和新的IMP生成对应关系

+ load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ Class selfClass = object_getClass([self class]); SEL oriSEL = @selector(imageNamed:); Method oriMethod = class_getInstanceMethod(selfClass, oriSEL); SEL cusSEL = @selector(myImageNamed:); Method cusMethod = class_getInstanceMethod(selfClass, cusSEL); BOOL addSucc = class_addMethod(selfClass, oriSEL, method_getImplementation(cusMethod), method_getTypeEncoding(cusMethod)); if  { class_replaceMethod(selfClass, cusSEL, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod)); }else { method_exchangeImplementations(oriMethod, cusMethod); } });}

自己使用过例子:使用场景,在iOS7中如果viewdidappear还没有完成,就立刻执行push或者pop操作会crash,见我之前写过的一篇文章iOS7中的pop导致的crash

解决方案就是利用method swizzing,
将系统的viewdidappear替换为自己重写的sofaViewDidAppear

@implementation UIViewController (APSafeTransition)+ load{ Method m1; Method m2; m1 = class_getInstanceMethod(self, @selector(sofaViewDidAppear:)); m2 = class_getInstanceMethod(self, @selector(viewDidAppear:)); method_exchangeImplementations;}

runtime这种消息机制,并非iOS特有,其他系统下也有类似的东西,比如windows下的MFC等等.
这里是cocoachina下所有和runtime相关的文章,请点击查看

参考1参考2

老架构的图片压缩在CDN现网能正常服务部分业务,减小服务器端带宽消耗和数据存储的同时,提升了客户端的加载速度。

RunTime基础

基础路径图:

图片 111

在学习RunTime的基础时, 我们要搞清楚一些重要的东西, 一些专业术语:

  • SEL
  • id
  • Class
  • Method
  • Ivar
  • IMP
  • Cache
  • Property

我们可以从这些东西里获取到指定类的所有信息, 无论是公开的, 还是私有的,
全部都可以拿到, 并且操作.

PS: 但操作私有方法的时候, 注意不要用来上架,
除非你有方法让苹果审核的时候通过.

但该架构的固有缺陷也十分明显:

RunTime进阶

进阶路径图:

<figure>图片 122

<figcaption></figcaption>

</figure>

在学习RunTime进阶的时候, 我们就要了解更加的深入.

  • objc_msgSend
  • objc_msgSend_fpret
  • objc_msgSend_stret
  • objc_msgSendSuper
  • objc_msgSendSuper_stret

  • objc_setAssociatedObject()
  • objc_getAssociatedObject()
  • objc_removeAssociatedObjects()

  • OBJC_ASSOCIATION_ASSIGN
  • OBJC_ASSOCIATION_RETAIN_NONATOMIC
  • OBJC_ASSOCIATION_COPY_NONATOMIC
  • OBJC_ASSOCIATION_RETAIN
  • OBJC_ASSOCIATION_COPY

  • resolveInstanceMethod:
    • YES, 通过class_addMethod消息得到处理, 结束
    • NO, 进入forwardingTargetForSelector
      • 指定响应selector, 消息得到处理, 结束
      • 不指定响应selector
        • 进入methodSignatureForSelector, 指定方法签名,
          调用forwardInvovation, 通过anInvocation做处理,
          消息得到处理, 结束
        • 不指定方法签名, 该消息没有得到处理, 系统报错

压缩能力有限,只支持WebP一种方式,跟不上行业压缩技术趋势;

RunTime应用

应用路径图:

图片 133

在学习完RunTime之后, 我们就可以应用到我们的实际开发中.

  • 关联对象
  • 控制对象

  • 动态添加方法
  • 动态交换方法
  • 动态拦截并替换方法
  • 动态给方法添加额外功能

  • 自动归档和解档
  • 自动字典转模型
    • 字典转模型(模型属性数量大于字典key数量)
    • 字典转模型
    • 字典转模型

压缩场景有限,只支持兼容WebP格式的部分客户端访问;

RunTime实例开发场景

在实际开发中, 我们有一些实例场景会用到RunTime:

  • 替换ViewController的声明周期
  • 解决集合类因索引的问题崩溃的问题
  • 防止按钮重复高强度点击
  • 全局更换控件初始效果
  • App热修复
  • App异常加载的展位图
  • 全局修改UINavigationBarbackButtonItem

Runtime Method Swizzling开发实例汇总

对业务侵入严重,导致实际推广效果不佳。

发表评论

电子邮件地址不会被公开。 必填项已用*标注