Disclosure of Invention
The invention aims to overcome the defects of the prior art and provide a lightweight decoupling embedded point method and device based on iOS application, wherein the class and method of the embedded point are specified by maintaining a JSON file, and then embedded with embedded point codes dynamically in the corresponding class and method by utilizing an AOP mode; providing a parameter entering of a hook method and reading attribute values of the class of the parameter for a scene requiring logic judgment to determine the buried point value, and setting different buried points according to corresponding state values; has the following advantages: supporting dynamic issuing embedded point configuration; physically isolating the embedded point code and the service code; the embedded point function of the plug-in type is realized.
In order to solve the technical problems, the invention provides the following technical scheme:
the invention discloses a lightweight decoupling embedded point method and device based on iOS application, wherein the device comprises an embedded point configuration JSON table and an embedded point SDK, and the specific embedded point method is as follows:
1. configuring buried point information
The embedded point configuration JSON table contains class names class requiring hook and specific event information, and the event comprises a hook method and a corresponding embedded point value; the buried point codes and the service codes are physically isolated in an AOP mode, so that the logic of the buried point is prevented from invading the polluted service logic; the embedded points comprise fixed embedded points and scene embedded points needing logic judgment, and for the scene embedded points, impl classes are needed to be provided for providing corresponding logic judgment;
2. fixed buried point scene:
For a fixed buried point, the buried point is only required to be directly recorded when a corresponding method is executed, and the specific method is to realize AOP by utilizing runtime of an iOS system, and the corresponding class and method are checked by a MethodSwizzling mechanism; in order to facilitate detection of invalid buried points, matching verification is also needed for the class and the method of the hook, and if no corresponding method exists in the class, the assertion is thrown out;
3. Scenerising buried points:
The scene buried points are mainly the same event but are different buried points under various states or logics, the method is realized by buried points impl by providing a protocol, and corresponding buried point values are returned according to different logic judgment; the class name of the embedded point implementation class needs to be consistent with the key in the event in the embedded point configuration JSON;
4. and (3) judging the state:
determining a buried point value according to the state quantity; returning corresponding buried point values according to the order types and the order states, firstly defining impl types with the same name in a JSON table, and conforming to RJEventTracking protocol;
5. and (5) parameter entering judgment:
Determining the situation of the buried point names according to the participation of the hook method set in the JSON, such as clicking all, in-progress, to-be-paid, to-be-evaluated and when menu items are completed in an order list; the method of the hook is tripLabClickWithLabKey, the parameter is UILabel, the tag of the Label in the original code judges which sub item is clicked, the parameter of the Label can be obtained and judged according to the sub item, and the first value of arguments can be directly obtained because the parameter is only one; when the hook method is carried out through the AOP, an example object and an entry corresponding to the current hook method can be obtained, and when the protocol method is called, the example object and the entry are directly transmitted to the protocol implementation class;
6. The method is as follows:
Similar to the reading of the attribute value, the condition of different buried point names of the same event in different scenes is adopted, but the acquired state quantity is not the return value of the current instance object, but the return value of a certain method, and the condition can be realized by calling a function through a method provided by the buried point SDK;
7. Logic judgment:
For a scene requiring additional logic judgment, such as counting the checking behavior of a user entering a page in order detail pages, the type of the detail pages can be acquired after a network request, and the network request is triggered at fixed time, so that the method of embedding the point hook can be carried out for a plurality of times, in the case, an attribute is required to be added for marking whether the embedded point is recorded or not, and the embedded point SDK is required to provide a function of dynamically adding the attribute; adding additional attributes to mark whether the buried point is recorded or not in the buried point implementation impl class; using addExtraProperty defaultValue to dynamically add attributes to the current instance, and extraProperty method to obtain some additional attributes of the instance, if isRecorded returns YES to represent that the buried point has been recorded, return nil to ignore the buried point;
8. Dynamic issuing embedded point configuration:
The embedded point JSON configuration table can be provided with an interface by the server, and the client obtains the latest embedded point configuration table through the interface when starting each time, so that the purpose of dynamic issuing is achieved, and after the client gets the JSON, the client reads embedded point information and takes effect; the logic of reading the embedded point configuration is a method of traversing the class and hook in the embedded point, and detects whether the embedded point is a fixed embedded point or a scene embedded point, and whether the class is realized by the corresponding embedded point impl is inquired for the situation of the scene embedded point, and of course, whether each class is matched with the method in the JSON configuration table is also detected.
Compared with the prior art, the invention has the following beneficial effects:
the invention specifies the class and the method of the buried point by maintaining a JSON file, and then dynamically embeds the buried point code when the corresponding class and method are executed by utilizing an AOP mode; providing a parameter entering of a hook method and reading attribute values of the class of the parameter for a scene requiring logic judgment to determine the buried point value, and setting different buried points according to corresponding state values; has the following advantages: supporting dynamic issuing embedded point configuration; physically isolating the embedded point code and the service code; the embedded point function of the plug-in type is realized.
Detailed Description
The preferred embodiments of the present invention will be described below with reference to the accompanying drawings, it being understood that the preferred embodiments described herein are for illustration and explanation of the present invention only, and are not intended to limit the present invention.
Example 1
As shown in fig. 1-4, the invention provides a lightweight decoupling embedded point method and device based on iOS application, wherein the device comprises an embedded point configuration JSON table and an embedded point SDK, and the specific embedded point method is as follows:
1. configuring buried point information
The embedded point configuration JSON table contains class names class and specific event information requiring the hook, and the event comprises a method of the hook and a corresponding embedded point value, as follows:
in short, the buried point needs to be manually written with the buried point code to record the buried point value, and the buried point code and the service code are physically isolated in an AOP mode at present, so that the logic intrusion of the buried point is avoided to pollute the service logic. The buried points comprise fixed buried points and scene buried points needing logic judgment, wherein the fixed buried points are as follows:
RJTripHistoryViewModel is a class name, tableView: didSelectRowAtIndexPath is a method in a class requiring hook, and user_ mytrip _show is a specific buried point value, namely, the buried point value user_ mytrip _show is recorded when the method tableView: didSelectRowAtIndexPath in RJTripHistoryViewModel is executed;
For a scene buried point, a impl class needs to be provided to provide corresponding logic judgment. Such as:
The rj_trip_tracking in the configuration table is an implementation class of the scene embedded point, and the corresponding embedded point value is returned in the class according to the state quantity, namely, the embedded point impl with the same name of the rj_trip_tracking is found when the CALLSERVICEEVENT method is executed, and the returned embedded point value is taken to record the embedded point. It should be noted that the key value in the event may be used as a buried point value or a class name of impl, where the buried point SDK may first determine whether a corresponding class exists, that is, consider that the class is a impl implementation class, and take a specific buried point value from the class. Otherwise, the value is considered to be a fixed buried point value.
The class names and the method names in the configuration table need to be corresponding, the matching is carried out when the hook is carried out, and if no corresponding method exists in the class, the assertion is automatically triggered;
2. fixed buried point scene:
for fixed buried points, the buried points only need to be directly recorded when the corresponding Method is executed, and the specific Method is to realize AOP by utilizing runtime of an iOS system, and to look corresponding classes and methods through a Method Swizzling mechanism (a third party framework widely used in the industry is commonly used in actual development-Aspects)
In order to facilitate detection of invalid buried points, matching verification is also needed for the class and the method of the hook, and if no corresponding method exists in the class, the assertion is thrown out;
3. Scenerising buried points:
The scenerized burial points are mainly the same event but are different under various states or logics, such as the operation of connecting customer service, and the set burial points are different under various order types and order states. In this case, the present invention is implemented by providing a protocol (protocol) by the buried point impl (implementation class), and returns the corresponding buried point value according to different logic judgments:
@protocol RJEventTracking<NSObject>
-(NSString*)trackingMethod:(NSString*)method instance:(id)instance arguments:(NSArray*)arguments;
@end
The rj_trip_tracking class, such as that above, needs to follow RJEventTracking protocols and return the corresponding buried point values according to the relevant logic decisions.
The class name of the embedded point implementation class needs to be consistent with the key in the event in the embedded point configuration JSON, because the embedded point SDK can implement the plug-in embedded point rule by detecting whether there is a class with the same name. In addition, one impl may correspond to multiple methods.
4. And (3) judging the state:
And determining the buried point value according to the state quantity. In the example of contact customer service buried points, corresponding buried point values are returned according to the order types and the order states, and the impl types with the same names in the JSON table are defined first and the RJEventTracking protocol is followed:
#import"RJEventTracking.h"
@interface rj_trip_tracking:NSObject<RJEventTracking>
@end
protocol method for realizing custom buried point in impl types of buried points
In the protocol method, the current instance (RJTripViewController in this example) and the set of parameters are acquired. The type and status of the order are stored in DATAMANAGER attributes in RJTripViewController, so attribute values can be obtained by the property encapsulated by the buried point SDK method, and corresponding buried point names are returned according to the attribute values.
When the method in the AOP method hook class is used, an instance object of the class where the method is located and the input parameters and the output parameters of the method are obtained at the same time when the method is intercepted and operated, and the state value (variable value) of the instance object can be obtained through a KVC mode. KVC (Key-value coding) Key value coding, that is, in the development of iOS, may allow a developer to directly access an attribute of an object through a Key name or assign a value to the attribute of the object. Without requiring explicit access methods to be invoked. In this way, the properties of the object can be dynamically accessed and modified at runtime. Rather than at compile time.
5. And (5) parameter entering judgment:
The buried roll name needs to be determined according to the entry of the hook method set in JSON. For example, clicking all the menu items in the order list, respectively burying the menu items when the menu items are finished, waiting for payment, waiting for evaluation, and the like. The method of the hook is tripLabClickWithLabKey, the parameter is UILabel, the original code judges which sub item is clicked through the tag of the Label, and the parameters of the Label can be obtained and judged according to the parameters. Since there is only one parameter, the first value can be taken directly arguments.
When the hook method is carried out through the AOP, an instance object and an entry corresponding to the current hook method can be obtained (the functions are also provided by open source library enterprises), and when the protocol method is called, the instance object and the entry are directly transmitted to the protocol implementation class.
6. The method is as follows:
Similar to the reading of the attribute value, the situation of different buried point names of the same event in different scenes is also the situation that the acquired state quantity is not the current instance object, but the return value of a certain method, and in this case, the situation can be realized by calling a function through a method provided by the buried point SDK:
@interface NSObject(RJEventTracking)
-(id)performSelector:(NSString*)selector arguments:(nullable NSArray*)arguments;
@end
for example, a view type of a page is acquired, and this view type is stored in a single object:
[RJViewTypeModel sharedInstance].viewType
In this scenario, the corresponding buried point name is returned according to the type viewType:
The principle of the method call is that the method is adopted by performSelector: arguments of the iOS system, and the appointed method of any instance can be called through a character string of an incoming method name. In addition, iOS supports fetching corresponding class objects from a string.
7. Logic judgment:
the scenario of adding additional logic judgment is needed, for example, when the order detail page needs to count the viewing behavior of the user entering the page, but the detail page type needs to be acquired after the network request, and the network request is triggered at regular time, so that the method of embedding the point hook can be carried out multiple times, and in this case, an attribute needs to be added to mark whether the embedded point is recorded or not. The buried SDK needs to provide a function of dynamically adding attributes.
@interface NSObject(RJEventTracking)
-(id)extraProperty:(NSString*)property;
-(void)addExtraProperty:(NSString*)property defaultValue:(id)value;
@end
Within the buried point implementation impl class, an additional attribute is added to mark whether a buried point has been recorded:
The default value is used addExtraProperty to dynamically add attributes to the current instance, while the method extraProperty is used to obtain some additional attribute of the instance. If isRecorded returns YES to indicate that the buried point has been recorded, the nil value is returned to ignore the buried point.
The isRecorded attribute added in the above example is that because the requirement of the buried point is irrelevant to the business logic, a reasonable way is to add in the plug-in impl class of the buried point, so as to avoid affecting the business code.
The principle of dynamic addition of attributes by the embedded point library is also simple, and the objc _ setAssociatedObject and objc _ getAssociatedObject methods of runtime are used to bind attributes to instance objects.
8. Dynamic issuing embedded point configuration:
the embedded point JSON configuration table can be provided with an interface by the server, and the client obtains the latest embedded point configuration table through the interface when starting each time, so that the purpose of dynamic issuing is achieved, and after the client gets the JSON, the embedded point information is read and validated.
The logic for reading the embedded point configuration is a method for traversing classes and hooks in the embedded points, and detects whether the embedded points are fixed or scene embedded points, and queries whether the corresponding embedded points impl are implemented in the case of scene embedded points. Of course, the validity of the JSON configuration table needs to be checked, and whether each class and the method therein match.
Specifically, the triggering assertion is that in a Development (DEBUG) mode, methods in each class listed in the JSON are checked after the APP is started, if no corresponding method name is found in a certain class (i.e. the method name specified in the JSON is inconsistent with the actual method name in the class, this may happen when a developer modifies the method name in the subsequent development process after completing configuration of the class and the method name of the embedded point in the JSON, but forgets to update the JSON file), the assertion is triggered, and which method in which class in the JSON does not exist is printed out, and the developer checks the method name and updates the JSON file after seeing the assertion prompt. The embedded point test method is a prompt function, and after no problem exists in a development environment (namely, class names and method names in JSON exist and are matched), the embedded point test method is submitted to a tester for embedded point test. In an online (Release) environment, even if an assertion is not triggered (because the assertion is only in effect under DEBUG), the problem of class name and method name errors that theoretically trigger the assertion is not present in an online situation (unless a developer triggers the assertion but does not change it when developing, but the assertion is always triggered without changing it, and the assertion cannot be executed as soon as the trigger program is asserted, so the developer can only change it and cannot override it).
The protocol name is well defined, the implementation of the protocol is self-defined and is used for returning the embedded point value in the scene state, and the implementation method is a parameter of the protocol. Please refer to fig. 3 in detail;
For fig. 3, the protocol name is specified, only one. The implementation of the protocol is self-defined, and is used for returning the embedded point value in the scene state, and the execution (hook) method is one parameter of the protocol;
For example, in the JSON of FIG. 3, RJMainViewController is a class name, tripTypeViewChangedWithIndex:and tripLabClickWithLabKey: tripTypeViewChangedWithIndex: tripLabClickWithLabKey in the class of hook RJMainViewController are needed, and when the two methods are executed, it is judged whether rj_main_tracking is a present class (whether there are two files of rj_main_tracking.h and rj_main_tracking.m in the code), if there is no class, rj_main_tracking is a buried point value, and when the two methods are executed, the string value of [ rj_main_tracking ] is directly recorded as the buried point value; if this class exists, it needs to be determined whether it is a valid buried point impl class, and whether it is valid, i.e. whether it implements (complies with) the RJEventTracking protocol, all buried point impl classes must implement the RJEventTracking protocol, and the method of the protocol is declared as:
@protocol RJEventTracking<NSObject>
-(NSString*)trackingMethod:(NSString*)method instance:(id)instance arguments:(NSArray*)arguments;
@end
The entry of the protocol is a method name, an instance object of the current class, and parameters, and impl classes make corresponding logic scene judgment according to the parameters, and finally the corresponding buried point value (return value) is returned. For example, in the present example, the method would be tripTypeViewChangedWithIndex:or tripLabClickWithLabKey:instance, the instance is an instance object of RJMainViewController, and arguments is a parameter value of tripTypeViewChangedWithIndex:or tripLabClickWithLabKey.
Also the above example, such as creating rj_main_tracking class
#import"RJEventTracking.h"
@interface rj_main_tracking:NSObject<RJEventTracking>
@end
In the h header, the tag follows RJEventTracking protocol, then implemented in m
-(NSString*)trackingMethod:(NSString*)method instance:(id)instance arguments:(NSArray*)arguments;
This method. The specific codes are as follows:
In the protocol method, judging which method is currently according to the method, tripTypeViewChangedWithIndex: tripLabClickWithLabKey, and entering parameters of the methods; the value of RJMainViewController on-the-fly member variables can be taken from instance. And finally, returning to the buried point value by combining the information values with corresponding logic judgment.
One impl may correspond to multiple methods in multiple classes. The purpose is to reduce the number of embedded point code files. Referring specifically to FIG. 4, the strict convention in FIG. 4 is that one impl may correspond to multiple methods in multiple classes. The purpose is to reduce the number of embedded point code files.
For example, tripTypeViewChangedWithIndex and tripLabClickWithLabKey methods, clickConfirmBtn and confirmViewWillAppear methods in two classes of the two types RJMainViewController and RJConfirmViewController can be specified in JSON, and the corresponding embedded point impl class is rj_main_tracking, so that rj_main_tracking needs to determine which method is currently which class when implementing the protocol method, and then make corresponding logic determination
Of course, different impl classes can be designated by different classes, so that the number of implementation classes of impl is relatively large, and it is recommended that impl of a group of classes with related functions are all designated as the same class
Supplementary abnormal situation handling logic:
the method names in the JSON and the method names in the code are not matched;
Such as by writing the wrong method name in JSON due to pen errors. The method names in JSON in practical projects are numerous and can be very energy-intensive if relying solely on manual inspection. The method comprises the steps of sequentially detecting whether the class designated in the JSON contains a corresponding method name before HOOK according to the class and the method in the HOOK JSON when the APP is started, triggering assertion if the class does not have the corresponding method name, and reporting the class name and the method name. The judging method is that the class is generated by the character string name:
Class c=NSClassFromString(classname);
Then detecting whether the class has two conditions of a corresponding class method and an example method, if not, considering that the method specified in the JSON does not exist in the class
BOOL respond=[c respondsToSelector:sel]||[c instancesRespondToSelector:sel];
NSString*err=[NSString stringWithFormat:@"<SCReportTracking>-no specified method:%@found on class:%@,please check",method,class];
NSAssert (respond, err); engineer/trigger assertion
2. Missing or erroneous for a fixed buried point (non-scene)
Directly updating (adding/modifying/deleting) the corresponding class name in the JSON, and then re-issuing the method name or the embedded point value to the client
3. For the scene buried point content causing serious problems
Corresponding disaster tolerance and fault tolerance are achieved by deleting corresponding content in the JSON and then transmitting the content to the client.
Compared with the prior art, the invention has the following beneficial effects:
the invention specifies the class and the method of the buried point by maintaining a JSON file, and then dynamically embeds the buried point code when the corresponding class and method are executed by utilizing an AOP mode; providing a parameter entering of a hook method and reading attribute values of the class of the parameter for a scene requiring logic judgment to determine the buried point value, and setting different buried points according to corresponding state values; has the following advantages: supporting dynamic issuing embedded point configuration; physically isolating the embedded point code and the service code; the embedded point function of the plug-in type is realized.
Finally, it should be noted that: the foregoing description is only a preferred embodiment of the present invention, and the present invention is not limited thereto, but it is to be understood that modifications and equivalents of some of the technical features described in the foregoing embodiments may be made by those skilled in the art, although the present invention has been described in detail with reference to the foregoing embodiments. Any modification, equivalent replacement, improvement, etc. made within the spirit and principle of the present invention should be included in the protection scope of the present invention.