IOS custom Control Development Carding summary _ios

Source: Internet
Author: User
Tags readable touch notification center uikit

In the day-to-day development of iOS, the control provided by the system often does not meet the business function, this time we need to implement some custom controls. Custom controls allow us to fully control the display of the view and the interaction. This article describes some of the concepts associated with custom controls, and explores the basic processes and techniques of customizing control development.

UIView

Before we start, we'll introduce a class uivew, which is absolutely important in iOS apps because almost all of the controls are inherited from UIView classes.
UIView represents a rectangular area on the screen that is responsible for rendering the content within the area and responding to the touch events that occur within the region.

Inside the UIView there is a calayer that provides the rendering and display of content, including the UIView dimension style. The UIView frame actually returns the frame of the calayer.

UIView inherits from the Uiresponder class, which can receive and process events from the system, Calayer inherits from NSObject, and it cannot respond to events. So the biggest difference between UIView and Calayer is that UIView can respond to events and Calayer cannot.
More detailed information: Https://developer.apple.com/reference/uikit/uiview

Two ways to implement
When you create a custom control, there are two main implementations, pure code and Xib. Next we'll show you the steps to create a custom control in either of these ways.
We implement a simple demo, the effect is as follows, encapsulating a rounded imageview.

To create a custom control by using code
Create a custom control using code, first creating a class that inherits from UIView

Implement initWithFrame: Method. In this method, you set the properties of the custom control and create and add child views:

-(Instancetype) initWithFrame: (CGRect) frame {
 self = [super Initwithframe:frame];
 if (self) {
  _imageview = [[Uiimageview alloc] Initwithframe:cgrectmake (0, 0, Frame.size.width, frame.size.height)];
  _imageview.contentmode = Uiviewcontentmodescaleaspectfill;
  _imageview.layer.maskstobounds = YES;
  _imageview.layer.cornerradius = FRAME.SIZE.WIDTH/2;
  [Self Addsubview:_imageview];

 }
 return self;
}

If you need to rearrange the child view, you need to invoke the Layoutsubviews method:

-(void) layoutsubviews {
 [super layoutsubviews];
 _imageview.frame = Self.frame;
 _imageview.layer.cornerradius = SELF.FRAME.SIZE.WIDTH/2;

}

Layoutsubviews is the way to adjust the layout of a child view, as the official document reads:

You should override this method is only if the autoresizing and constraint-based behaviors of the The Subviews does not offer the B Ehavior you want.

It means rewriting the Layoutsubviews method when you need to resize the subview.

Layoutsubviews are invoked in the following situations:

    • Init initialization does not trigger Layoutsubviews
    • Addsubview will trigger layoutsubviews.
    • Setting the view frame triggers the layoutsubviews, of course, if the value setting of the frame changes before and after
    • Scrolling a uiscrollview will trigger layoutsubviews
    • Rotating screen triggers the Layoutsubviews event on the parent UIView
    • Changing the size of a uiview also triggers the Layoutsubviews event on the parent UIView

This custom control provides an external interface method that assigns values to a custom control

-(void) Configewithimage: (UIImage *) Image {
 _imageview.image = image;
}

Finally, add the custom control to the page

 _circleimageview = [[Circleimageview alloc] Initwithframe:cgrectmake (0, M,)];
 [_circleimageview configewithimage:[uiimage imagenamed:@ "tree"]];
 [Self.view Addsubview:_circleimageview];

To create a custom control by xib
First create a custom control Xibcircleimageview, inherited from UIView
Create Xib file with the same name as the Xibcircleimageview class
Configure the properties of the ImageView in Xib and bind the Xibcircleimageview class to the corresponding Xib file
The code is as follows

-(void) awakefromnib {
 [super awakefromnib];

 _imageview.layer.maskstobounds = YES;
 _imageview.layer.cornerradius = SELF.FRAME.SIZE.WIDTH/2;
 [Self Addsubview:_imageview];
}

-(void) Configewithimage: (UIImage *) Image {
 _imageview.image = image;
}

-(void) layoutsubviews {
 [super layoutsubviews];
 _imageview.layer.cornerradius = SELF.FRAME.SIZE.WIDTH/2;

}

It's a bit different to call in a page, creating a Xib object with the Loadnibnamed method

 Create a custom control using xib
 _xibcircleimageview = [[[NSBundle Mainbundle] loadnibnamed:@ ' Xibcircleimageview ' Owner:nil Options:nil] Lastobject];
 _xibcircleimageview.frame = CGRectMake (0, M, m);
 [_xibcircleimageview Configewithimage:image];
 [Self.view Addsubview:_xibcircleimageview];

When you use Xib to create a custom control, initialization does not call the initWithFrame: method, only the Initwithcoder: method is called, and the Awakefromnib method is invoked before the initialization is completed, noting that the child control is initialized in awakefromnib. Because the Initwithcoder: method means that the object is parsed from a file, it is invoked, and the Awakefromnib method is invoked after loading from xib or storyboard.

Summary

The two ways to create a custom control each have advantages and disadvantages, pure code is more flexible, maintenance and expansion are more convenient, but write more trouble. Xib method is highly efficient, but not easy to expand and maintain, and is suitable for custom control with more stable function style.

Event-Passing mechanism

In a custom control, you may need to respond to events dynamically, such as a button that is too small, not easy to click, and you need to enlarge the button's range of clicks, and then we'll talk about iOS's event-passing mechanism.

Event response Chain

The Uiresponder class can respond to events such as touch, gesture, and remote control. It is the base class for all responsive events, including the very common UIView, Uiviewcontroller, and UIApplication.

The Uiresponder properties and methods are shown in the following illustration, where Nextresponder represents a point to a Uiresponder object.

So what does the incident response chain have to do with Uiresponder? The view within the application is organized in a certain structure, a tree hierarchy, where a view can have multiple child views, and a child view can have only one parent view. When a view is added to the parent view. The Nextresponder attribute of each view points to its parent view, so that the entire application is strung into a chain through the Nextresponder, the response chain. The response chain is a virtual chain, not real, and it is connected by Uiresponder Nextresponder. The following figure

Hit-test View

With the event response chain, the next step is to find the specific response object, we call it: hit-testing view, the process of looking for this view is called Hit-test.
What is Hit-test? We can think of it as a detector, through which we can find and determine whether a finger touches a view.
How does the hit-test work? Hit-test recursively starts through the root node of the view until it finds a clicked view.

First send hittest:withevent from UIWindow: The message begins, determines whether the view responds to a touch event, and if it cannot respond to return nil, the view cannot respond to a touch event. Then call the Pointinside:withevent: method, which is used to determine whether the touch event clicks on the view range, if pointinside:withevent: Returns no, then hittest:withevent: Also return directly to nil.

If the Pointinside:withevent: method returns Yes, the view sends Hittest:withevent to all child views: message, and the order of invocation of all child views is from the topmost view to the bottommost view, That is, traversing forward from the end of the subviews array. Until a child view returns a Non-empty object or all of the traversal is complete. If a child view returns a Non-empty object, the Hittest:withevent: method returns the object, the processing ends, and if all the child views return nil, the Hittest:withevent: method returns the view itself.

Application of event-passing mechanism

Give a few examples of how event-passing mechanisms are used in custom controls.

One, enlarge view of click Area. Suppose a button has a size of 20px 20px and is too small to be clicked. We rewrite this button subclass of Hittest:withevent: method, to determine whether the click Point is within 20px around the button, if it is to return itself, to achieve the function of expanding the scope of the click, the code is as follows:

-(UIView *) HitTest: (cgpoint) point withevent: (Uievent *) Event {
 if (!self.isuserinteractionenabled | | self.hidden | | self.alpha<=0.01) {return
  nil;
 }
 CGRect touchrect = Cgrectinset (Self.bounds, -20, -20);
 if (Cgrectcontainspoint (Touchrect, point)} {for
  (UIView *subview in [self.subviews Reverseobjectenumerator]) {
   cgpoint convertedpoint = [Subview convertpoint:point toview:self];
   UIView *hittestview = [Subview hittest:convertedpoint withevent:event];
   if (Hittestview) {return
    Hittestview
   }}
  return self;
 }
 return nil;
}

Second, through the transmission of events.

Assuming that there are two View,viewa and viewb,viewb completely covering Viewa, we want to respond to Viewa events when we click on the VIEWB. We rewrite this Viewa's hittest:withevent: method to return directly to itself without continuing to traverse its child view. The code is as follows:

-(UIView *) HitTest: (cgpoint) point withevent: (Uievent *) Event {
 if (!self.isuserinteractionenabled | | self.hidden | | self.alpha<=0.01) {return
  nil;
 }
 if ([self pointinside:point withevent:event]) {
  NSLog (@ "In view A");
  return self;
 }
 return nil;
}

Callback mechanism

In custom control development, you need to return a value to its parent class. For example, a custom control that holds a button needs to receive button-click events at the top. We can use multiple ways to recall messages, such as target action mode, proxy, block, notification, and so on.

Target-action

Target-action is a design pattern that causes an object to send messages to another object when the event is triggered. This mode we have more contact with, such as the button to bind point to the event, for view add gesture events. Uicontrol and its subclasses support this mechanism. Target-action establishes a loose relationship between the sender and receiver of the message. The recipient of the message does not know the sender, and even the sender of the message does not know what the recipient of the message will be.

One limitation of the target-action delivery mechanism is that messages sent cannot carry custom information. In IOS, you can optionally take the sender and the event that triggers the action as arguments. There is no other way to control the content of the action message.

For example, we use Target-action to add a click gesture to the control.

  UITapGestureRecognizer *TAPGR = [[UITapGestureRecognizer alloc] initwithtarget:self action: @selector (refresh)];
  [_imageview ADDGESTURERECOGNIZER:TAPGR];

-(void) refresh{
 NSLog (@ "Touch ImageView");
}

Agent

The proxy is one of our commonly used callback methods, which is also recommended by Apple, which is used extensively in the system framework Uikit, such as UITableView, Uitextfield.

Advantages: 1, the agent syntax is clear, readable, easy to maintain; 2, it reduces the code coupling, so that event monitoring and event processing separation, 3, a controller can implement multiple agents to meet the needs of customized development, flexibility is high;

Disadvantages: 1, the process of implementing the agent is cumbersome; 2, the cross-layer transfer value to increase the coupling of code, and the program hierarchy has become chaotic; 3, when multiple objects are not easy to distinguish between the value of the same, resulting in a significant reduction in proxy usability;

Block

Block encapsulates a piece of code and passes it as a variable, which makes it very easy to organize code in different places and is very readable.

Advantages: 1, simple syntax, code readability and high maintainability. 2, with GCD excellent solution to multithreading problems.

Disadvantage: 1,block code will automatically do a retain operation, easily resulting in memory leaks. The default reference within 2.Block is a strong reference, which can easily cause circular references.

Notice

The agent is a one-to-one relationship, the notice is a one-to-many relationship, the notification compared to the agent can achieve a larger span of communication mechanism. But there are more objects to receive, it is difficult to control, sometimes do not want the object also received processing messages.

Advantages: 1, simple to use, concise code. 2, to support a one-to-many, to solve the problem of listening to multiple objects at the same time. 3, the transfer value is convenient and quick, the context itself carries the corresponding content.

Disadvantage: 1, the notification needs to log off after use, or it will cause accidental collapse. The 2,key is not secure enough and the compiler does not detect whether the notification center is properly handled. 3, difficult to track when debugging. 4, when users send notifications to the notification center, no feedback can be obtained. 5. A third party object is required to act as an intermediary between the listener and the listener.

Summarize

So far, the knowledge of developing custom controls has been combed out, hoping to help you better understand the development of custom controls.

Related Article

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.