block

一 block delegate优势 block 注意事项:

1)共同的作用: Block 和 Delegate中的方法都可以理解成回调函数,当某件事情发生的时候取执行一段代码片段

2)Block(代码块) 优点:是一种轻量级的回调,能够直接访问上下文,使用块的地方和块的实现地方在同一个地方,使得代码组织更加连贯

3.Delegate(代理) 相对来说是重量级的回调, 缺点: 因方法的声明和实现分离开来,代码的连贯性不是很好 代理很多时候需要存储一些临时数据 优点: 代理的回调函数可以是一组多个函数,在不同的时机调用不同的回调函数

注意事项: 1,block 在实现时就会对它引用到的它所在方法中定义的栈变量进行一次只读拷贝,然后在 block 块内使用该只读拷贝。

2,非内联(inline) block 不能直接访问 self,只能通过将 self 当作参数传递到 block 中才能使用,并且此时的 self 只能通过 setter 或 getter 方法访问其属性,不能使用句点式方法。但内联 block 不受此限制。

3,使用 weak–strong dance 技术来避免循环引用 函数体执行结束后 函数体有个自动释放池

三.内存循环引用场景

• 定时器(NSTimer): NSTimer经常会被作为某个类的成员变量,而NSTimer初始化时要指定self为target,容易造成循环引用(self->timer->self)。 另外,若timer一直处于validate的状态,则其引用计数将始终大于0,因此在不再使用定时器以后,应该先调用invalidate方法, 说白了就是一定要移除定时器.

• block的使用: block在copy时都会对block内部用到的对象进行强引用(ARC)或者retainCount增1(非ARC)。在ARC与非ARC环境下对block使用不当都会引起循环引用问题, 一般表现为,某个类将block作为自己的属性变量,然后该类在block的方法体里面又使用了该类本身,简单说就是self.someBlock = Type var{[self dosomething];或者self.otherVar = XXX;或者_otherVar = …};出现循环的原因是:self->block->self或者self->block->_ivar(成员变量)

代理(delegate): 在委托问题上出现循环引用问题已经是老生常谈了,规避该问题的杀手锏也是简单到哭,简单的来说:声明delegate时请用assign(MRC)或者weak(ARC)

四.ios中如何让uibutton内的非矩形区域响应uitouch

举个例子,纯用button是肯定不行的了。比如说一个正方形边长为D,内中心有一个直径也为D的圆,我要求圆内科响应,圆外正方形部分不响应。圆的直径r = D/2.f; 给正方形_view添加UITapGestrureRecongnizer *tap tap.delegate = self; [_view addGestru...er:tap]; - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch { CGPoint point = [touch locationInView:_view]; //圆原点坐标为 CGFloat x1 = r; CGFloat y2 = r; // CGFloat x2 = point.x; CGFloat y2 = point.y; if((y2-y1)²+(x2-x1)² < r²) { //圆内,响应点击 return YES; }else { return NO; } } 两点间的距离 d,则 d² = (y2-y1)²+(x2-x1)²;

五、详解 CALayer 和 UIView 的区别和联系

1.首先UIView可以响应事件,Layer不可以.

2.View和CALayer的Frame映射及View如何创建CALayer. 一个 Layer 的 frame 是由它的 anchorPoint,position,bounds,和 transform 共同决定的,而一个 View 的 frame 只是简单的返回 Layer的 frame,同样 View 的 center和 bounds 也是返回 Layer 的一些属性。(PS:center有些特列)

3.UIView主要是对显示内容的管理而 CALayer 主要侧重显示内容的绘制。 4.在做 iOS 动画的时候,修改非 RootLayer的属性(譬如位置、背景色等)会默认产生隐式动画,而修改UIView则不会。

总接来说就是如下几点: 每个 UIView 内部都有一个 CALayer 在背后提供内容的绘制和显示,并且 UIView 的尺寸样式都由内部的 Layer 所提供。两者都有树状层级结构,layer 内部有 SubLayers,View 内部有 SubViews.但是 Layer 比 View 多了个AnchorPoint 在 View显示的时候,UIView 做为 Layer 的 CALayerDelegate,View 的显示内容由内部的 CALayer 的 display CALayer 是默认修改属性支持隐式动画的,在给 UIView 的 Layer 做动画的时候,View 作为 Layer 的代理,Layer 通过 actionForLayer:forKey:向 View请求相应的 action(动画行为) layer 内部维护着三分 layer tree,分别是 presentLayer Tree(动画树),modeLayer Tree(模型树), Render Tree (渲染树),在做 iOS动画的时候,我们修改动画的属性,在动画的其实是 Layer 的 presentLayer的属性值,而最终展示在界面上的其实是提供 View的modelLayer 两者最明显的区别是 View可以接受并处理事件,而 Layer 不可以

六、GCD队列

1.串行队列:Dispatch Queues或者Serial Queues

2.并发队列 :Concurrent Queues

3.主队列:main dispatch Queue

针对以上3种队列:concurrent queues和main queue都是由系统生成而且 dispatch_suspend, dispatch_resume, dispatch_set_context这些函数对他们无效。 但是我们的应用不是简单的同步也异步的运行,应用经常是混合的。 比如我们要task1 task2 task3都运行完成后才能异步运行task4 task5 task6我们该怎么做呢?这里我们可以引入group的概念。

七.strong,weak, unsafe_unretained往往都是用来声明属性的,如果想声明临时变量就得用__strong, __weak, __unsafe_unretained, __autoreleasing, 其用法与上面介绍的类似。

_bridge作用是类型转换 

1.__bridge:CF和OC对象转化时只涉及对象类型不涉及对象所有权的转化;

2.__bridge_transfer:常用在讲CF对象转换成OC对象时,将CF对象的所有权交给OC对象,此时ARC就能自动管理该内存;(作用同CFBridgingRelease())

3.__bridge_retained:(与__bridge_transfer相反)常用在将OC对象转换成CF对象时,将OC对象的所有权交给CF对象来管理;(作用同CFBridgingRetain())

八.Runloop的寄生于线程:一个线程只能有唯一对应的runloop;但这个根runloop里可以嵌套子runloops; 自动释放池寄生于Runloop:程序启动后,主线程注册了两个Observer监听runloop的进出与睡觉。一个最高优先级OB监测Entry状态;一个最低优先级OB监听BeforeWaiting状态和Exit状态。 线程(创建)-->runloop将进入-->最高优先级OB创建释放池-->runloop将睡-->最低优先级OB销毁旧池创建新池-->runloop将退出-->最低优先级OB销毁新池-->线程(销毁)

九.copy strong 区别

如果一般情况下,我们都不希望字串的值跟着mStr变化,所以我们一般用copy来设置string的属性。

如果希望字串的值跟着赋值的字串的值变化,可以使用strong,retain。

注意:上面的情况是针对于当把NSMutableString赋值给NSString的时候,才会有不同,如果是赋值是NSString对象,那么使用copy还是strong,结果都是一样的,因为NSString对象根本就不能改变自身的值,他是不可变的。

把一个对象赋值给一个属性变量,当这个对象变化了,如果希望属性变量变化就使用strong属性,如果希望属性变量不跟着变化,就是用copy属性。

由此可以看出:

对源头是NSMutableString的字符串,retain仅仅是指针引用,增加了引用计数器,这样源头改变的时候,用这种retain方式声明的变量(无论被赋值的变量是可变的还是不可变的),它也会跟着改变;而copy声明的变量,它不会跟着源头改变,它实际上是深拷贝。

对源头是NSString的字符串,无论是retain声明的变量还是copy声明的变量,当第二次源头的字符串重新指向其它的地方的时候,它还是指向原来的最初的那个位置,也就是说其实二者都是指针引用,也就是浅拷贝。

另外说明一下,这两者对内存计数的影响都是一样的,都会增加内存引用计数,都需要在最后的时候做处理。

其实说白了,对字符串为啥要用这两种方式?我觉得还是一个安全问题,比如声明的一个NSString *str变量,然后把一个NSMutableString *mStr变量的赋值给它了,如果要求str跟着mStr变化,那么就用retain;如果str不能跟着mStr一起变化,那就用copy。而对于要把NSString类型的字符串赋值给str,那两都没啥区别。不会影响安全性,内存管理也一样。

原文地址:https://www.cnblogs.com/liudongyan/p/6487130.html