Upgrade iOS notification center! -You can set the priority to execute block and iosblock.

Source: Internet
Author: User
Tags sendmsg notification center

Upgrade iOS notification center! -You can set the priority to execute block and iosblock.

In brief, this is the requirement-driven discovery that the iOS icationicationcenter has many functions that cannot be implemented, so it is packaged in a layer. It is equivalent to manually managing the observer stack and events that the listener expects to execute. Therefore, you can add many new features to it and name it MessageTransfer.

I. Core Advantages 1. High decoupling
  • The lifecycle is isolated from the page instance cycle.
  • Cross-component communication
  • Business-independent, internal focus only on block Code Execution
2. Flexible Customization
  • Synchronous or asynchronous execution can be set for each piece of information sent.
  • Supports the internal processing of messages. After the internal processing, the results are returned.
  • When a message has multiple receivers, it can be sorted by priority. (Synchronous)
  • The same message can implement multiple blocks in the same instance, and can be a common block + a block for processing.
3. Easy to use
  • The interface clearly complies with the logic settings, blocks are linked together, and code aggregation Management
  • Internal implementation of some joint operations, use or modify only one place, previously needs to change multiple
  • Strictly control the situations where loop references cannot be released, and the removal of observer delloc is implemented internally.

 

Ii. API design 1. Previous API use
// ******** Common practice // 1. send the notification at the same time (the name of the notification must be unified) [[nsnotifcenter center defacenter center] postNotificationName: @ "XXX" object: XXX userInfo: XXX]; // 2. the other side receives [[NSNotificationCenter defacenter center] addObserver: self selector: @ selector (xxx :) name: @ "XXX" object: XXX] // 3. you also need to manually implement a method XXX: // 4. remember to remove the observer when using your own method of delloc, otherwise it will cause a crash. Delloc: [nsicationicationcenter defacenter center] removeObserver
2. MessageTransfer API design
// ******** MessageTransfer API design // the complexity of the following methods is reduced from complexity to complexity, only comments of the most complex method are pasted:/*** add a block also add observer with priority, when msg received ed, and do some processing when msg received Ed, return the results ** @ param msg origin msg * @ param interaction include observer and priority * @ param block doing onReceived, and return the processing results */-(void) listenMsg :( NSString *) msg withInteraction :( SXMessageInteraction *) interaction blocks :( partial) block;-(void) listenMsg :( NSString *) msg withInteraction :( SXMessageInteraction *) interaction onReceive :( partial) block; -(void) listenMsg :( NSString *) msg observer :( id) observer onReceiveAndProcessing :( handle) block;-(void) listenMsg :( NSString *) msg observer :( id) observer onReceive :( MsgPosterVoidAction) block;/*** send a msg with a object and set this msg's excute type, and do the block when msg on reached, ** @ param msg origin msg * @ param object msg carry object * @ param type (async or sync default is sync) * @ param block doing on reached */-(void) sendMsg :( NSString *) msg withObject :( id) object type :( SXMessageExcuteType) type onReached :( MsgPosterVoidAction) block;-(void) sendMsg :( NSString *) msg withObject :( id) object onReached :( MsgPosterVoidAction) block;-(void) sendMsg :( NSString *) msg onReached :( MsgPosterVoidAction) block;
3. Process Structure

The event interaction principle generated when the instance listens to messages and synchronously sends messages is outlined. It includes the pressure stack storage after messages and observer registration. transfer adopts different execution policies for Synchronous asynchronous judgment, and the observer is sorted by priority, the block to be internally processed is executed using the sender's msgObject as the input parameter and the return value is used as the input parameter of the sender block. When an instance is destroyed, it is removed from the observer stack. (Dong Boran blog Park)

 

Iv. Actual use
// ******** Observer A (Common listener) [MsgTransfer listenMsg: @ "DSXDSX" onReceive: ^ (id msgObject) {MTLog (@ "******** the most common listener callback, parameter content % @", msgObject) ;}]; // ******** observer B (complex listener) [MsgTransfer listenMsg: @ "DSXDSX" withInteraction: [SXMessageInteraction interactionWithObserver: self priority: @ (700)] onreceiveandprocess: ^ id (id dict) {MTLog (@ "******* the priority is 700 block execution-parameter % @", dict ); // assume that a dictionary BOOL loginSuccess = [dic is returned after processing the incoming dict. T [@ "pwd"] isEqualToString: @ "123456"] & [dict [@ "account"] isEqualToString: @ "admin"]; return @ {@ "result" :( loginSuccess? @ "Login successful, coming soon... ": @" incorrect account or password ") };}]; // ********* sender (synchronously executed) [MsgTransfer sendMsg: @ "DSXDSX" withObject: @ {@ "account": @ "admin", @ "pwd": @ "123456"} type: SXMessageExcuteTypeSync onReached: ^ (id obj) {if ([obj isKindOfClass: [NSDictionary class]) {MTLog (@ "a callback after internal processing ***** % @", obj [@ "result"]);} else {MTLog (@ "a common callback *** Message ID % @", obj) ;}}]; // then .. no

A login logic is implemented. The object in the sent message carries the login information. The login class receives the message and then judges the parameter or other processes to return the result, the returned value of this block is used as the input parameter of the sender block. That is to say, the class that sends the login information can get the login result in the block of the message. These are all tasks that the previous message center cannot do.

 

5. source code snippets
#pragma mark -#pragma mark listen recieved- (void)workingOnReceived:(NSNotification *)object{    NSString *name = object.name;        SXMessageExcuteType excuteType = [[self.msgExcuteType objectForKey:name]integerValue];        NSArray *observerArray = [self.msgObserversStack valueForKey:name];    if (excuteType == SXMessageExcuteTypeSync) {        NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"_priority" ascending:NO];        observerArray = [observerArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];    }        for (SXMessageObserver *obs in observerArray) {        NSArray *voidBlocks = [self.blockReceivedVoidStack valueForKey:obs.msgName];        NSArray *returnBlocks = [self.blockReceivedReturnStack valueForKey:obs.msgName];                if(voidBlocks && (voidBlocks.count > 0)){            for (id voidBlock in voidBlocks) {                if (excuteType == SXMessageExcuteTypeSync){                    [self excuteWithVoidBlockDict:@{@"obs":obs,@"object":object,@"block":voidBlock}];                }else if (excuteType == SXMessageExcuteTypeAsync){                    NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(excuteWithVoidBlockDict:) object:@{@"obs":obs,@"object":object,@"block":voidBlock}];                    [self.msgQueue addOperation:operation];                }            }        }                if (returnBlocks && (returnBlocks.count >0)){            for (id returnBlock in returnBlocks) {                if (excuteType == SXMessageExcuteTypeSync){                    [self excuteWithReturnBlockDict:@{@"obs":obs,@"object":object,@"block":returnBlock}];                }else if (excuteType == SXMessageExcuteTypeAsync){                    NSInvocationOperation *operation = [[NSInvocationOperation alloc]initWithTarget:self selector:@selector(excuteWithReturnBlockDict:) object:@{@"obs":obs,@"object":object,@"block":returnBlock}];                    [self.msgQueue addOperation:operation];                }            }        }        if(returnBlocks.count + voidBlocks.count < 1){#if TEST || DEBUG            NSString *errormsg = [NSString stringWithFormat:@"dsxWARNING! this msg <%@> not binding Recieved block",obs.msgName];            NSLog(@"%@",errormsg);#endif        }    }}

The above is the method that the observer's block is about to execute. In fact, the principle is that the library has set a lot of stacks to store blocks and observers that cannot be classified. In addition, the former observer may be A, B, or C. The current observer is summarized to MessageTransfer. This transfer station controls the observer to execute the block. The following method is used as an input parameter for the listener to block the processing result returned to the sender.

- (void)excuteWithReturnBlockDict:(NSDictionary *)dict{        SXMessageObserver *obs = dict[@"obs"];    NSNotification *object = dict[@"object"];    id block = dict[@"block"];        MsgPosterReturnAction returnBlockRecieved = (MsgPosterReturnAction)block;    id processingObject = returnBlockRecieved(object.object)?:returnBlockRecieved([NSObject new]);    MsgPosterVoidAction blockReached = [self.blockReachedStack valueForKey:object.name];    if (blockReached) {        // if processingObject is nil .        blockReached((processingObject?:@"processing result is nil"));    }else{#if TEST || DEBUG        NSString *errormsg = [NSString stringWithFormat:@"dsxWARNING! this msg <%@> not binding Reached block",obs.msgName];        NSLog(@"%@",errormsg);#endif    }}

 

Vi. Limitations

Of course, the use of messageTransfer also has some limitations: if an instance has multiple blocks, the priority of these blocks will be subject to the last setting, A single instance can have only one priority. blocks with different priorities are executed in order for the observer who cannot be an instance. What I originally wanted to set was that the order priority could also be set in the instance, but it was found that this would make the data structure too complex and the notification center was not so fine-grained, they all bind only one method to the same message. Therefore, this limitation has not yet been met with unfeasible requirements. Another limitation is the observer's removal process. Although the internal observer's removal method does not need to be removed by every observer in its own delloc, a trigger method is also required, you can send a message to the delloc of the parent class of all classes. If you say that we have a parent class, and my parent class is UIViewController, you can only use delloc In the subclass to send messages.

// Delloc-(void) dealloc {[nsicationcenter center defacenter center] postNotificationName: @ "SXMsgRemoveObserver" object: self];} of the parent class
# Pragma mark-# pragma mark remove observer-(void) removeObserverInObserverStack :( NSNotification *) no {id observer = no. object; if (! [Self. obsIndex containsObject: @ ([observer hash]) return; NSLog (@ "Remove observer -- % ld", [observer hash]); [self. msgObserversStack metadata: ^ (id _ Nonnull key, id _ Nonnull obj, BOOL * _ Nonnull stop) {NSMutableArray * marray = (NSMutableArray *) obj; id temobj = nil; for (SXMessageObserver * obs in marray) {if ([@ (obs. objectID) isEqual: @ ([observer hash]) {temobj = obs;} [marray removeObject: temobj]; [self. msgObserversStack setObject: marray forKey: key] ;}] ;}

 

Figure:

The following two logs are used for debugging. We can see that both the sender and listener blocks can be executed, while normal bock and processable blocks with returned values can be executed; multiple blocks can be bound to the same instance. blocks of instances with different class names do not conflict with each other. log printing is not missing when synchronous and asynchronous execution is good.

Synchronous execution

 

Asynchronous execution

 

This database is still being improved, and will be optimized, empty, prompt, and asserted in the future.

If you are interested can see the source https://github.com/dsxNiubility/SXMessageTransfer

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.