分身不乏术,Objective-C的多线程
我们在现实生活中,往往会在统一调时间线上同时做好几件事情, 比如刷牙的时候看手机,为了不浪费时间,我们总是同时进行两件三件甚至更多的事情;而在编程的世界中, 我们可以通过软件或者硬件上实现多个线程并发执行的技术来做到类似现实世界中的行为, 这就叫做多线程;能够大大提升整体处理性能;
很多编程语言都实现了这种功能,java, .net,C++, php的pthreads和swoole,oc当然也不例外, 下面我们就来了解一下我们在oc中会经常用到的多线程技术GCD和NSOperation,NSOperationQueue;
GCDGCD的好处能够充分利用iOS或者macOS多核心的特性,大大提高整体的处理性能和计算能力;
GCD的队列和任务任务即一个操作行为,或者是要执行的代码块; 类似买票的行为,即一个任务;
队列执行任务的调度池, 用来存放任务,一个一个的任务被创建好之后放入队列中等待执行; 采用先进先出的原则,类似排队买票的行为;
同步队列(sync)添加任务同步队列,任务会一个接着一个去执行,后一个任务等待前一个任务的完毕状态; 同步队列不会开启新的线程; 类似一个窗口买票的而 ...
拥抱一下沉默的 NSString 吧~
NSString 作为作为OC的一种数据类型, 他帮我们做了很多事情, 而且也是我们在项目中运用频率很高的一个数据类型.我们经常会对它进行各式各样的操作,生成新的字符串,修改,查找,比较等等. 但是有人可能会问, 既然我已经有C的字符串了,为撒子还要在定义一个字符串对象呢? 嘿嘿,首先,我们使用NSString对象来处理字符串操作, 一方面是可以统一很多方面的东西,比如api, 例如NSArray,NSDictionary中都是存放的对象, 而且使用NSString还可以使用isKindofCLass的很多常用查询. 假如我们真的去使用了C的字符串去替代NSString的话, 那我们光是桥接代码就会让人写到吐,因为字符串在使用中的频率还是比较高的. 在和其他数据对象进行联合使用的时候,那种怪异的语法肯定也会让使用者大呼痛苦的. 向来注重用户体验的苹果肯定不会这样子干的,所以,定义一个NSString 对象还是很必要的. NSString 主要的方法都在 Foundation/NSString.h 中定义, 提供了很多的方法接口
常量字符串12NSString *name = @&qu ...
iOS block详解
什么是Blockblock又叫块对象, 是MacOS X 10.6 以及 iOS4.0 平台下都可以使用的功能,block不是oc的实现, 而是c语言的实现; 与其他编程语言中的闭包
如何定义一个块对象1^(返回值类型)(参数列) {表达式主体}
无参数无返回值1234void(^testBlock)(void) = ^(void){ NSLog(@"无参数无返回值");}testBlock();
无参数有返回值1234int(^testRetunValueBlock)(void) = ^(int){ return 100;}int value = testRetunValueBlock();
有参数无返回值1234void(^ testParamsBlcok) (NSString *) = ^(NSString *string){ NSLog(@"%@",string);};testParamsBlcok(@"hhh& ...
从 NSObject 占用的内存说起
之前iOS的一个 git 仓库看到一个面试问题, 一个 NSObject 对象占用多少内存, 看到这个面试题以后我想不是4个就是8个嘛, 因为之前我打印过 64位设备下 NSString 对象的内存大小就是8; 可是答案却有一点出乎意料, 是16, 于是我就找了些资料进行了一下深入的研究, 果然…..
我们都知道, Objective-C 底层是使用 C和C++ , oc 的对象基本就是 C/C++的结构体;我们将 oc 的 m 文件使用 clang 编译后输出 cpp, 代码会告诉你对象的数据结构是类似如下所示的一个结构体:使用命令行将 .m 转成 cpp文件:
1234567命令行xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的CPP文件eg:xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main.cppstruct NSObject_IMPL { Class isa;} ...
iOS中for 和 for-in 循环数组的小区别
在 OC 开发中, 数组是我们经常会用到的数据结构;而对数据进行遍历是很常见的操作, OC也为我们提供一下几种常用的操作:
for 循环,普通遍历
for-in,快速 遍历
Block
枚举器NSEnumerator
之前大部分情况下都是用for循环进行普通遍历, 但前几天我使用 for-in 去遍历一个数据的时候却报了异常;
代码如下:
123456789NSMutableArray *testArray = [NSMutableArray arrayWithObjects:@"耐克",@"阿迪达斯",@"李宁",@"匡威",nil];for(NSString *temp in testArray){if{[temp isEqualToString:@"阿迪达斯"]){NSLog(@"我不喜欢");[testArray removeObjective:temp];}}
报错信息如下:
1Collection & ...
iOS中KVO使用和底层原理
iOS 中 KVO, 是key-value-observing 的缩写, 是Objective-C 对观察者设计模式的一种实现,类似观察者设计模式的还有NSNotificationCenter,不过一个是一对一(KVO),一个是一对多(NSNotificationCenter) ; 一般继承自NSObject 的对象都支持KVO. 日常开发中我们常常会监听数据模型的变化, 从而达到根据数据模型的修改对视图进行更新的要求;
KVO 常用方法1234567891011121314151617181920212223242526/*注册监听器监听器对象为observer,被监听对象为消息的发送者即方法的调用者在回调函数中会被回传监听的属性路径为keyPath支持点语法的嵌套监听类型为options支持按位或来监听多个事件类型监听上下文context主要用于在多个监听器对象监听相同keyPath时进行区分添加监听器只会保留监听器对象的地址,不会增加引用,也不会在对象释放后置空,因此需要自己持有监听对象的强引用,该参数也会在回调函数中回传*/- (void)addObserver:(NSObje ...
iOS 扩展&代理&通知
扩展用途
声明私有属性
声明私有成员变量
声明私有方法
特点注意与 category 的区别 * 编译时决议 * 只以声明的形式存在,多数情况下寄生在宿主类的. m中 * 不能为系统类添加扩展
代理
准确的来说是一种软件设计模式, 代理模式
iOS 中, 系统为我们提供了@ protocol 形式
代理是一对一的
协议有必须要实现的(@require), 不惜要实现的(option)
一般用 weak 来规避循环引用
通知
使用观察者模式来实现用于跨层传递消息的机制
传递方式 一对多
iOS 分类源码解读
分类的好处用分类声明一些私有方法;分类一些体积庞大的类文件,eg: AppDelegate, 组织代码更灵活把 framework 的私有方法公开
分类的特点
运行时决议, 在 runtime 添加到类中, 在编辑的时候分类会将分类方法作为一个数组,动态的添加到宿主类中, 如果存在同名的扩展方法, 那么最后一个参与编译的方法生效并覆盖之前的同名方法(但是还是实际存在的,不过优先级没有分类中的高), 但是可以通过一些代码决定调用最后一个参与编译的方法还是调用其他同名方法memcopy(array->lists, addedLists,addedCount *sizeof*array()->lists[0])) 覆盖宿主 方法的原因,;
为系统类添加分类
名字相同的分类会引起编译报错
分类中可以添加哪些内容
可以添加实例方法
类方法
协议
属性 只声明了 set get , 并没有在分类中添加实例变量
添加分类的实例变量, 需要通过关联对象进行设置
分类的结构体构成1234567891011121314151617181920212223//分类文件struct categ ...
UI事件传递以及事件响应原理
CALayer -> content显示内容, 实际是合成了一个个位图; 用来展示 我们平常所说的掉帧也是因为位图合成后未来得及显示绘制造成的 view 提供内容, 负责处理触摸事件,参与视图响应链 layer, 负责内容上的显示, contents; 之所以这样设计是因为单一元件负责单元任务, 即单一原则;
事件传递:1234//返回响应事件的视图-(UIView *)hitTest:(CGPoint)point WithEvent:(UIEvent *)event;//判断是否在响应区域内-(BOOL)pointInside(CGPoint)point WithEvent:(UIEvent *)event;
事件传递流程:如何寻找合适的响应者来处理事件: 1. 判断主窗口是否可以接受触摸事件 2. 判断触摸点是否在自己的区域内( pointInside: withEvent:) 3. 子控件数组中从后往前遍历子控件,重复前面的两个步骤(所谓从后往前遍历子控件,就是首先查找子控件数组中最后一个元素,然后执行1、2步骤) 事件传递给一个控件就会调用hitTest: withEv ...
模仿 tableViewCell 实现一个简易的重用视图
之前面试的时候会有很多人问道 UITableviewCellde 重用机制, 大部分回答都是
在缓存池初中通过 dequeueReusableCellWithIdentifier:CellIdentifier 方法取出可重用的 cell, 在一个 cell 离开屏幕显示的范围内, 会自动被加入到缓存池中,然后在缓存池中取出一个 cell, 放到当前屏幕上;用重用机制会节省性能,避免出现一些因为网络因素而造成的卡顿现象。
复用机制避免了大量的初始化过程, 我们可以节约很大一部分资源; 下面我们来试着模仿 tableview 创建一个复用视图吧~
实例化一个重用池;新建一个继承自NSObject 的类, reusePool; 在reusePool 中定义三个方法,
获取重用 view -(UIView *)getReuseTableView;
添加 view 到重用池中 -(void)addViewForReusePool:(UIView *)view;
重置重用池 -(void)reset;
在类的.m文件中, 实现刚才定义的几个方法, 并定义两个属性, wattingQu ...