iOS builds its own user behavior statistics system

Source: Internet
Author: User
Tags instance method uicontrol

?? To build a user behavior in line with their needs of the statistical system, I believe that many operators dream, but also the development of the technology of the persistent pursuit. Below, I share the user's behavior statistics system that we have built for the company.
?? User behavior statistics (users Behavior Statistics, UBS) has always been an essential part of mobile Internet products, also known as buried point. For the product manager, the operator, of course, the more buried, the more coverage the better. The nonsense is not much, here I mainly use AOP oriented to the idea of slicing programming to solve this problem. Reference Blog: Refer to the blog address? First of all, I do not have a full copy of the blog, here is the main way to follow others blog ideas to go, into the dead end, and then back to basics, with their own ideas to achieve. The reason to write down other people's thoughts is to explain that the process of thinking is sometimes important.

User behavior Statistics what?

?? We often say that the user behavior statistics, then the user behavior statistics is the main system, in my opinion, mainly divided into two categories:1, page statistics: PV ;2, Event statistics: Events.

Page Statistics: PV

?? Page statistics is just when the user enters a page, the record is saved, and the user leaves a page to save records. Send the saved data to the backend server when appropriate. The implementation code is as follows:

[UiviewcontrollerAspect_hookselector: @selector (viewdidappear:) Withoptions:Aspectpositionafterusingblock:^ (ID Data)        {[ self jkhandlepv:data status:jkubspv_enter]; } Error:nil];[UiviewcontrollerAspect_hookselector: @selector (viewdiddisappear:) Withoptions:Aspectpositionafterusingblock:^ (ID Data)        {[ self jkhandlepv:data status:jkubspv_leave]; } Error:nil];

A lot of blog post such code to solve the problem, in fact, ignoring a big problem, so simple rough single-storm to deal with, will find the item in the Uiviewcnotroller of the two methods viewDidAppear: , viewDidDisappear: are will hook, made into an additional performance overhead, very bad. That's why I'm working on it. Hook operation only for the meter page to be integrated. The present body is as follows:

+ (void) configpv{for (NSString*vcnameinch[jkubsshareinstance].configuredata[Jkubspvkey]) {Classtarget =nsclassfromstring(Vcname); [Target aspect_hookselector: @selector (viewdidappear:) Withoptions:Aspectpositionafterusingblock:^ (ID Data)        {[ self jkhandlepv:data status:jkubspv_enter]; } Error:nil];[Target aspect_hookselector: @selector (viewdiddisappear:) Withoptions:Aspectpositionafterusingblock:^ (ID Data)        {[ self jkhandlepv:data status:jkubspv_leave]; } Error:nil];}}
Incident Statistics: Event

?? Event statistics is mainly to save the record when the user triggers the event, and then send the recorded data to the background server for processing at the appropriate time. By referring to the blog at the beginning of the article, it is simple to divide the matter into Uibutotn,uicontrol,uigesturerecognizer and click on the event triggered by cell cell UITableView. Click the Uicollectionview cell cell to trigger the event.
?? According to this idea, I first deal with the events triggered by Uibutton,uicontrol:

+ (void)configUIControlEvent{    [UIControl aspect_hookSelector:@selector(sendAction:to:forEvent:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> data){        [self JKHandleEvent:data];    } error:nil];}

This is relatively easy to implement, I believe we have achieved.

?? To UIGestureRecognizer deal with the triggered event, the trouble is first UIGestureRecognizer a class cluster, we trigger the event when the Tap,longpress,swipe,pan and other gesture send event is not the real class to send the event, my side through the form of break point to find the real class to send the event is: UIGestureRecognizerTargetthe private method of sending the event is: _sendActionWithGestureRecognizer: then I handle the event triggered by the gesture via the hook operation:

+ (void)configGestureRecognizerEvent{    Class UIGestureRecognizerTarget =NSClassFromString(@"UIGestureRecognizerTarget");    [UIGestureRecognizerTarget aspect_hookSelector:@selector(_sendActionWithGestureRecognizer:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> data){        [self JKHandleEvent:data];    } error:nil];}

It is difficult to count the events triggered by gestures, but it has been achieved.
?? For an event triggered by clicking UITableView Cell Cell, click Uicollectionview cell to trigger the event. On my side, for example, click the UITableView cell cell-triggered event. Assuming JKBViewController the implementation UITableView of the proxy method tableView:didSelectRowAtIndexPath: then my implementation is as follows:

+ (void)configureDelegateEvent{    [JKBViewController aspect_hookSelector:@selector(tableView:didSelectRowAtIndexPath:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> data){        [self JKHandleEvent:data];    } error:nil];}

Through this implementation we can do to click on UITableView cell cell triggered by the event statistics, but along the way of the author of the survey of the idea of this step by step, so that I have a good feeling inside.

Into a dead end

The following is a reference to the problem that the blogger encountered during the development process

1,并不是所有的事件都是有继承自UIControl的空间来发出的,比如:手势,点击Cell。2,并不是所有的按钮点击了之后就立马需要埋点上传?可能在按钮的响应方法中经过了层层的if(){ }else{ }最后才需要埋点。4,对于代理方法该怎样处理?5,如果很多个按钮对应着一个事件该怎样处理?

The needle in the 1th, I side this although comb a lot of types of events, but still have a lot of not be counted, such as shaking a shake triggered events, pedometer triggered events, Tabbar Click Triggered events, but also very much I may not think of the event, I now send if according to the author's intention, By the type of event trigger to do a hook operation, the work is two pretty big, and there will be missing. Especially when it comes to a lot of laws. Apple is not open to developers, we have to deal with it more troublesome. It's exhausting to be counted by the sender.
For the 2nd, according to the intention of the person will be the click after the inside there are layers of judgment, how to bypass the layer of judgment? I'll elaborate on that in the next step.
For the 4th, I've already achieved it.
For the 5th, in reality the situation does exist in different pages, and even different buttons in the same page correspond to the same event as the problem. If you follow the idea of a blog author, it's really a hassle to deal with them.

Basics

?? In view of the above difficulties, I am wondering if there is a better way to solve it. First of all think of our statistics user to do the event, and is not to count the user clicked on a button, or a gesture operation, tuned to use an agent method. The purpose of this is to count what the user is doing in order to do the shopping, or to share. So I broke the idea of referring to the blog author, no longer the button, gesture, unit Gueyang and other events to hook, but the user's purpose of the event triggered by the method of hook, events are events, no source points. That is, hook on the tip of the event, the middle layer of logical judgment, I do not need to consider, I only consider the purpose of the hook event. For example, the user to travel to share - (void)goShare; , I do not care to use the button is clicked, or tap gesture triggered the method, or the cell is selected, I only care about the method of sharing - (void)goShare; is not called, I can be called when the record operation. The only other way to determine a method, in addition to the selector, is to have the relevant target (the method's creator, or the message recipient). Needle above the 5th, the different buttons correspond to the same event, under normal circumstances the same target is different, we can distinguish the out. When it is clear that there are different buttons on the same page to trigger the same event, in this case is not too common, the function outside the package layer, change the name of the individual to distinguish a bit better, but Envetid still want the same.
?? In order to better facilitate everyone, my side according to their own ideas to write a pod library, the following first to say their own plist file file:

You can see the PV field, each page can be set to the name of the page, but also some other information.
There are EventID under the event field, and also allow different triggering events under the same EventID.
Event 1 This level of the field to write the specific event content, mainly to facilitate the development of human reader reading.
JKVC1 Click, JKVC2 Tap, tap click, check TableView cell These are all for the purpose of marking the source of things, so that developers can read. In addition, if the event requires additional parameters to be configured, you can add new content under the EventID sibling field.
Let's take a look at the code:
JKUBS.h

#Import<foundation/foundation.h>#Import "Aspects.h"extern NSStringConst*jkubspvkey;extern NSStringConst*jkubseventkey;extern NSStringConst*jkubseventidkey;extern NSStringConst*jkubseventconfigkey;extern NSStringConst*jkubsselectorstrkey;extern NSStringConst*jkubstargetkey;typedef Ns_enum (Nsinteger, jkubspvstatus) {jkubspv_enter =0,//Enter the pageJkubspv_leave//Leave page};@interfaceJkubs:nsobject@property(nonatomic,strong,readonly) Nsdictionary *configuredata;/** Single-instance method @return Singleton Object * /+ (instancetype) shareinstance;/** Importing configuration information through a JSON configuration file JSON configuration file or Plist profile import only one just fine @param jsonfilepath json file sandbox path * /+ (void) Configuredatawithjsonfile: (NSString *) Jsonfilepath;/** Importing configuration information via plist configuration file JSON configuration file or Plist profile import only one good @param plistfilename plist file name (without suffix) */+ (void) Configuredatawithplistfile: (NSString *) plistfilename;/** Processing PV This method requires developer overloading for specific operations @param data page information @param status Enter or leave the state of the page */+ (void) Jkhandlepv: (id<aspectinfo>) Data status: (Jkubspvstatus) status;/** Handling Events This method requires the developer to overload the specific operation @param data event information @param eventId Event ID * /+ (void) Jkhandleevent: (id<aspectinfo>) Data EventID: (Nsinteger) EventID;@end

Jkubs.m

#import "JKUBS.h" NSString Const*jkubspvkey = @"PV";NSString Const*jkubseventkey = @"Event";NSString Const*jkubseventidkey = @"EventID";NSString Const*jkubseventconfigkey = @"EventConfig";NSString Const*jkubsselectorstrkey = @"Selectorstr";NSString Const*jkubstargetkey = @"Target"; @interface jkubs()@property(nonatomic,Strong, ReadWrite)nsdictionary*configuredata;@end @implementation jkubs StaticJkubs *_ubs =Nil; + (Instancetype) shareinstance{Static dispatch_once_tOncetoken;dispatch_once(&oncetoken, ^{_ubs = [jkubs new]; });return_ubs;} + (void) Configuredatawithjsonfile: (NSString*) jsonfilepath{NSData *data = [NSData Datawithcontentsoffile:jsonfilepath];nsdictionary*dic = [nsjsonserialization jsonobjectwithdata:data options:nsjsonreadingmutableleaves Error:Nil]; [Jkubs Shareinstance]. Configuredata= dic;if([Jkubs Shareinstance]. Configuredata) {        [ SelfSETUP]; }}+ (void) Configuredatawithplistfile: (NSString*) plistfilename{nsdictionary*dic = [nsdictionarydictionarywithcontentsoffile:[[NSBundleMainbundle] Pathforresource:plistfilename oftype:@"Plist"]]; [Jkubs Shareinstance]. Configuredata= dic;if([Jkubs Shareinstance]. Configuredata) {        [ SelfSETUP]; }}+ (void) setup{[ SelfCONFIGPV]; [ SelfConfigevents];}#pragma mark Pvconfig ----+ (void) configpv{ for(NSString*vcname in [Jkubs shareinstance]. Configuredata[Jkubspvkey])        {Class target = nsclassfromstring (vcname); [Target Aspect_hookselector:@selector(viewdidappear:) Withoptions:aspectpositionafter usingblock:^ (IDData) {[ SelfJkhandlepv:data Status:jkubspv_enter]; } Error:Nil]; [Target Aspect_hookselector:@selector(viewdiddisappear:) Withoptions:aspectpositionafter usingblock:^ (IDData) {[ SelfJkhandlepv:data Status:jkubspv_leave]; } Error:Nil]; }}+ (void) Jkhandlepv: (ID<AspectInfo>) Data status: (Jkubspvstatus) status{}#pragma mark EventConfig ----+ (void) configevents{nsdictionary*eventsdic = [Jkubs shareinstance]. Configuredata[Jkubseventkey];Nsarray*events =[eventsdic allvalues]; for(nsdictionary*dic in events) {NsintegerEventID = [Dic[jkubseventidkey] integervalue];Nsarray*eventconfigs = [Dic[jkubseventconfigkey] allvalues]; for(nsdictionary*eventconfig in Eventconfigs) {NSString*selectorstr = Eventconfig[jkubsselectorstrkey];NSString*targetclass = Eventconfig[jkubstargetkey];            Class Target =nsclassfromstring (targetclass);                SEL selector = nsselectorfromstring (SELECTORSTR); [Target Aspect_hookselector:selector Withoptions:aspectpositionbefore usingblock:^ (ID<AspectInfo> data) {[ SelfJkhandleevent:data Eventid:eventid]; } Error:Nil]; }    }}+ (void) Jkhandleevent: (ID<AspectInfo>) Data EventID: (Nsinteger) eventid{}

There are two ways to focus on that.

+ (void)JKhandlePV:(id<AspectInfo>)data status:(JKUBSPVSTATUS)status;+ (void)JKHandleEvent:(id<AspectInfo>)data EventID:(NSInteger)eventId;

Both of these methods need to be overloaded in the Jkubs category to do a specific implementation. For example, a record of a page activity, an event record. Build user behavior Statistics System, my side has completed the AOP thought of the event collection, how to record, save, sent to the background, here is not detailed description.

Code
Use the pod as follows:

"JKUBS"

iOS builds its own user behavior statistics system

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.