"Only for technical exchanges, without permission to prohibit the reprint"
Usually app-server uses the HTTP protocol to tell the app what it needs to display the picture, text. This is one of the most common protocols. Another kind of client-side protocol, such as the news app, clicks on a focus story and app jumps to the appropriate channel or topic. It is not difficult to find: the former is Server->app communication, mainly content type, the latter is App<->app communication, mainly command, action type.
How to better handle the intra-app communication, it is necessary to first introduce the iOS platform interprocess communication. inter-process communication
For example, the iOS platform, interprocess communication IPC, can be implemented through a custom URL Schema and then app-(BOOL) Application: (UIApplication *) OpenURL: (Nsurl *) sourceapplication :(NSString *) annotation: (ID) method that can handle some commands and parameters. Where Sourceapplication is the caller's bundleidentifier. The following URL, for example, will tune up the Twitter client and pull up the interface for sending tweets.
URL scheme perfectly solves the problem of invoking the app and transmitting messages and commands in the same operating system. The URL schema mechanism provides a good idea for developers to solve the problem of intra-app communication. Cpmessage was born. What is Cpmessage
Cpmessage (Cross Platform message cross-platform messages) can be used as a server/client (let the client handle some commands), or a bridge for internal communication within the client. The originator of the communication may be the server, Push, user action, HTML5, or other app. The client performs the appropriate action according to the specific command and corresponding parameters. In short, the cpmessage idea originates from the URL schema mechanism of the iOS platform. the mechanism of Cpmessage
In order to ensure the consistency of multi-platform, the protocol name CPM is used as the beginning, but the protocol is delivered in a different way. On iOS, the way to communicate to clients is Scheme+protocol, for example:
cpm://message.cmd?messageid=msgid&urls=encodedurlstrings&uid=uid&ex1=ex1&ex2=ex2&ex3= Ex3.
The following sections are labeled:
In general: command names are message.cmd, often changed by MessageID (described in detail below). In the argument list, MessageID indicates the action, such as opening a webview, opening a new page, or adjusting the login box. The argument list is followed by some auxiliary parameters. Some examples are given in the table below.
Parameters |
Use |
Format |
Example |
MessageID |
Used to specify a response from the client |
String |
1.1 |
Url |
URL to jump |
String |
Www.baidu.com |
Ex1 |
Extra parameters |
String |
"03" |
In addition, if Ex1, EX2 and ex3 are not enough. You can also use the more parameter. For example: more = {"title": "HelloWorld", "Name": "Jack"};more parameter format is in JSON format. Facilitates client resolution of fields.
MessageID
The
messageid can be classified according to Mainid and SubID, such as messageid=2.1. So Mainid is 2,subid is 1. Generally speaking, Mainid is the distinction of operation type, for example:
mainid=1 means open page.
mainid=2 is passed data.
mainid=3 is open to other SDK and so on.
SubID is a breakdown of some of the operations, such as: Open the page and so on.
apps are cross-platform, with at least iphone,android clients, so the URL schema header will be different. Example: Server to the H page, a link is a CPM message, URL scheme with the use of CPM, the following format:
Myapp://cpm://xxxxxx. The operating system level reads "myapp://" to pull up the client, and the client reads "cpm://" cpmessage How to apply cpmessage to its app? You need to do three things:
first , register some Uiviewcontroller and methods in advance, and encapsulate them into cpmessageitem.
second , when Cpmessage comes over, it resolves into cpmessagecommand, where Cpmessagecommand contains the parameters.
third , use a Cpmmanager class to correspond command and item to a uiviewcontroller and use Nsinvocation to invoke a previously registered method.
So, back to the first question, let's assume that MessageID = 1.1 is the jump channel, EX1 is the index of the channel. So, the server encapsulates the following URL message into the Focus news
cpm://message.cmd?messageid=1.1&ex1=03
Client Tabviewcontroller Registers a switch channel method-(void) Switchtochannel: (int) index, performing Cpmmanager,tabviewcontroller Executes the Switchtochannel method. Can be very elegant solution to the news app, switch to any channel problem. UML diagram + flowchart of Cpmmanager
Several key functions of Cpmmanger
prepareprocessor Register some class and class methods in advance.
handleurl: receive URL, with a CPM schema URL
oncpmiscoming: parameter is Cpmcommand
handlecpm: Parameter Cpmcommand. The callback is finally implemented through [Nsinvocation invoke]. the realization of Cpmmanger
Here are just a few of the code, the key code for Cpmmanger:
The callback function registered to the Cpmparse.
-(void) oncpmiscoming: (nsnotification *) Noti {nsdictionary *userinfo = Noti.userinfo; if ([UserInfo Iskindofclass:[nsdictionary class]]) {Cpmcommand *command = [UserInfo objectforkey:kcpmessageparser
notificaitoncommandkey];//if ([command Iskindofclass:[cpmcommand class]]) {[Self handlecpm:command]; }}///Where the cpmessage is really handled.
Associating the message command and Uiviewcontroller with Nsinvocation-(void) HANDLECPM: (Cpmcommand *) message {[Self prepareprocessors];
Cpmitem *item = (Cpmitem *) [self.processors objectforkey:nsstringfromcpmessagecommand (message)];
if (nil = = Item) {return;
[Item getinfofromcpmessagecommand:message];
Uiviewcontroller *visiblectrl = [Self.assit Topviewcontroller];
Class Receiverclass = nsclassfromstring (item.classname); if (Item.classmethod!= nil) {[Self PerformClassSelector:item.classMethod ontarget:receiverclass withArgs:item.cl
Assargs]; [Item CLearinfofromcpmessagecommand]; else if (!item.isopenasnew && [Visiblectrl Ismemberofclass:receiverclass]) {//If Target viewcontroller is top Viewcontroller if (Item.reloadmethod!= nil) {[Self PerformSelector:item.reloadMethod ontarget:visibl
Ectrl WithArgs:item.initialArgs]; else if (Item.optmethod!= nil) {[Self PerformSelector:item.optMethod Ontarget:visiblectrl WithArgs:item.op
Targs];
else {//no Reloadsel and no optsel then does nothing} [item Clearinfofromcpmessagecommand];
else {Uiviewcontroller *basectl = [Item.processor perpareOpeningWithHelpFrom:self.assit];
Must be Dispatch_async, otherwise the viewwilldisappear and Viewdiddisappear Dispatch_async (Dispatch_get_main_queue (), ^{ If Target Viewcontroller is top Viewcontroller if (!item.isopenasnew && [Basectl Ismemberofclas S:receiverclass]) {if (Item.reloadmethod!=Nil) {[self performSelector:item.reloadMethod ontarget:basectl WithArgs:item.initialArgs]; else if (Item.optmethod!= nil) {[Self PerformSelector:item.optMethod ontarget:basectl witha
Rgs:item.optArgs];
else {//no Reloadsel and no optsel then does nothing}} else {
ID receiversuper = [receiverclass alloc];
ID receiver = [self PerformSelector:item.initialMethod ontarget:receiversuper WithArgs:item.initialArgs]; if (nil = = Receiver | |![
Receiver Iskindofclass:[uiviewcontroller Class]] {[Receiversuper release];
else {[Item.processor doopen:receiver on:basectl];
[Receiver release];
} [item Clearinfofromcpmessagecommand];
});
}/* Nsinvocation to display the talent of the place, selector and args call methods. */-(ID) perFormselector: (SEL) Aselector ontarget: (ID) Target Withargs: (Nsarray *) args {id ret = nil; if (Aselector = = Nil | | target = = NIL | |![
Target Respondstoselector:aselector]) {return ret;
} nsmethodsignature *signature = [target methodsignatureforselector:aselector];
if (Args.count + 2!= signature.numberofarguments) {return ret;
} nsinvocation *invocation = [Nsinvocation invocationwithmethodsignature:signature];
[Invocation setselector:aselector];
[Invocation settarget:target];
for (int i = 2, j = 0; j < Args.count; i++, J + +) {id arg = [args objectatindex:j];
[Invocation Setargument:&arg atindex:i];
[Invocation invoke];
Nsuinteger length = [[Invocation methodsignature] methodreturnlength];
void *buffer = (void *) malloc (length);
if (length > 0) {[Invocation getreturnvalue:&ret];
return ret; }-(ID) Performclassselector: (SEL) AselecTor Ontarget: (Class) Target Withargs: (Nsarray *) args {id ret = nil;
if (Aselector = = Nil | | target = = nil) {return ret;
} nsmutablestring *argsinctypes = [nsmutablestring stringwithstring:@ "V"];
for (int i = 0; i < Args.count ++i) {[Argsinctypes appendstring:@ ' @: ']; } nsmethodsignature *signature = [target methodsignatureforselector:aselector];
[Nsmethodsignature signatureWithObjCTypes:argsInCTypes.UTF8String];
if (signature = = Nil | | | Args.count + 2!= signature.numberofarguments) {return ret;
} nsinvocation *invocation = [Nsinvocation invocationwithmethodsignature:signature];
[Invocation setselector:aselector];
[Invocation settarget:target];
for (int i = 2, j = 0; j < Args.count; i++, J + +) {id arg = [args objectatindex:j];
[Invocation Setargument:&arg atindex:i];
[Invocation invoke]; Nsuinteger length = [[Invocation methodsignature] MethodretuRnlength];
void *buffer = (void *) malloc (length);
if (length > 0) {[Invocation getreturnvalue:&ret];
return ret;
Uiviewcontroller the class name, selector, and save it to the processor.
-(void) prepareprocessors {nsmutabledictionary *processors = [Nsmutabledictionary new];
Cpmtype type =-1;
Cpmitem *item = nil;
Type = CPMessageTypeSingleHTML5;
item = [Cpmitem cpmessageitemwithprocessor:[cpmessageprocessors Cpmessageprocessorformessage:type]
classname:@ "Webviewcontroller" Classmethod:nil Initmethod: @selector (initwithsurl:title:) Reloadmethod: @selector (loadwithsurl:
Title:) Optmethod:nil]; if (Is_valid_cpmessagetype (type) && (nil!= item) {[Processors Setobject:item Forkey:cpmessagekeys[type]];
item = NIL;
}//Add other item self.processors = processors;
[Processors release]; }