Some Category to improve the development efficiency

Source: Internet
Author: User

Recently work has been produced a number of convenient development of tools, although ultimately not used by income, but does not hinder personal use, so I would like to open a blog post, but also record some of their own trampled pits.

Uigesturerecognizer+block

In simple terms, you can use uigesturerecognizer like this:

[Self.view addgesturerecognizer:[uitapgesturerecognizer gesturerecognizerwithactionblock:^ (ID  Gesturerecognizer) {  //...}]];

It eliminates the need for tedious use of selector reflection, but also solves the problem of code separation. The implementation code is as follows:

Static Const intTarget_key; @implementationUigesturerecognizer (Block)+(Instancetype) Nvm_gesturerecognizerwithactionblock: (nvmgestureblock) block {return[[Self alloc]initwithactionblock:block];}-(Instancetype) Initwithactionblock: (nvmgestureblock) block { self=[self init];  [Self addactionblock:block];  [Self addtarget:self Action: @selector (Invoke:)]; returnSelf ;}- (void) Addactionblock: (nvmgestureblock) block {if(block) {objc_setassociatedobject (self,&Target_key, block, objc_association_copy_nonatomic); }}- (void) Invoke: (ID) Sender {Nvmgestureblock block= Objc_getassociatedobject (self, &Target_key); if(block) {block (sender); }}@end

Github Gist

The principle is to bind the block dynamically to a variable of Uigesturerecognizer and invoke the block again.

Two pits were encountered during the development process.

    1. I started the dynamic binding in the class method, the error code is as follows:
//The following is the error code:+(Instancetype) Initwithactionblock: (kygestureblock) block {return[Self alloc] Initwithtarget: [self _gesturerecognizerblocktarget:block] selector: @selector (Invoke:)];}+ (_kygesturerecognizerblocktarget *) _gesturerecognizerblocktarget: (kygestureblock) block{_kygesturerecognizerblocktarget*target = Objc_getassociatedobject (self, &Target_key); if(!target) {Target=[[_kygesturerecognizerblocktarget Alloc]initwithblock:block]; Objc_setassociatedobject (Self,&Target_key, Target, objc_association_retain_nonatomic); }  returnTarget;}

The result is that the variable is tied to the class object, because self in the class method refers to the class object, and the class object is resident memory until the program exits, which results in the first target being bound on the class, and then no matter what. If you have an object that is forced to hold a block outside of the block, it will cause these objects to not be released, causing a memory leak. It can be resolved by dynamic binding in the instance method.

    • If you do not use dynamic binding, what is the result of using code like this?
// error code + (instancetype) Initwithactionblock: (kygestureblock) block {  return  [[Self Alloc] Initwithtarget: [[_kygesturerecognizerblocktarget Alloc]initwithblock:block] Selector: @selector (Invoke:)];}

The result is that the target object is released from this scope. By looking at the documentation, I saw in the Target-action section of the OC programming concept that Apple mentions this: Control objects do not (and should not) retain their targets. by convention, if there is a special case, Apple will specifically remind you of it (as described in Nstimer's description target The timer maintains a strong reference to this object until it (the timer) is invalidated. ). So Uigesturerecognizer is not a strong reference to target. Once out of scope, the target object is freed. Therefore, you need to use dynamic binding to force hold.

Uiview+extendtouchrect

A line of code expands the view click Area:

Self.button.touchExtendInset = Uiedgeinsetsmake (-ten,-ten,-ten,-ten)  

The implementation code is as follows:

voidSwizzle (Class C, sel orig, selNew) {Method Origmethod=Class_getinstancemethod (c, orig); Method Newmethod= Class_getinstancemethod (c,New); if(Class_addmethod (c, orig, method_getimplementation (Newmethod), method_gettypeencoding (Newmethod))) {Class_ Replacemethod (c,New, Method_getimplementation (Origmethod), method_gettypeencoding (Origmethod)); } Else{method_exchangeimplementations (Origmethod, Newmethod); }}@implementationUIView (extendtouchrect)+ (void) Load {swizzle (self, @selector (pointinside:withevent:), @selector (mypointinside:withevent:));}-(BOOL) Mypointinside: (cgpoint) point withevent: (Uievent *)Event {  if(Uiedgeinsetsequaltoedgeinsets (Self.touchextendinset, Uiedgeinsetszero) | | self.hidden | |([Self iskindofclass:uicontrol.class] &&! ((Uicontrol *Self )) {return[Self mypointinside:point withevent:Event];//Original Implementation} cgrect hitframe=Uiedgeinsetsinsetrect (Self.bounds, Self.touchextendinset); HitFrame.size.width= MAX (HitFrame.size.width,0);//don ' t allow negative sizesHitFrame.size.height = MAX (HitFrame.size.height,0); returnCgrectcontainspoint (Hitframe, point);}Static CharTouchextendinsetkey; - (void) Settouchextendinset: (uiedgeinsets) Touchextendinset {objc_setassociatedobject (self,&Touchextendinsetkey, [Nsvalue Valuewithuiedgeinsets:touchextendinset], Objc_association_reta in);}-(uiedgeinsets) touchextendinset {return[Objc_getassociatedobject (Self, &Touchextendinsetkey) Uiedgeinsetsvalue];}@end

Github Gist

The idea of implementation is substitution pointInside:withEvent: or hitTest:withEvent: method. By the way, review the response chain delivery mechanism: When the finger touches the screen, UIWindow from the bottom up to distribute the event, each to a view, first call hitTest:withEvent: , in the hitTest:withEvent: call to pointInside:withEvent: determine whether the touch point in the current region, if in, traverse its child view recursive call hitTest:withEvent: . A binary tree graph is a reverse depth-first traversal, and once you find the first deepest, the descendant that contains the touch point stops traversing.

Some Category to improve the development efficiency

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.