Summary of four callback methods of iOS

  • 2021-01-22 05:24:27
  • OfStack

Recently, the IOS project was called back, so I took some time to sort out the relevant information. The following is the content:

The callback

A callback is the binding of a piece of executable code to a specific event. This code is executed when a specific event occurs.
In Objective-C, there are four ways to implement callbacks.

Target - action pairs

Before the program begins to wait, it is required that "a specific message be sent to the specified object when the time occurs." Here the object that receives the message is the target, and the selector of the message is the action.

Auxiliary object

Before the program begins to wait, it is required to "send a message to a secondary object that adheres to the corresponding protocol when the time occurs." Delegate objects and data sources are common auxiliary objects.

notice

Apple provides an object called a notification center. Before the program starts waiting, you can tell the notification center that an object is waiting for some particular notification. When one of these notifications occurs, a specific message is sent to the specified object. When an event occurs, the object in question publishes a notification to the notification center, which forwards the notification to the waiting object.

Block object

Block is an executable. Before the program begins to wait, declare an Block object, and when an event occurs, execute this Block object.

NSRunLoop

There is an NSRunLoop class in iOS, and an instance of NSRunLoop waits and sends a message to the corresponding object when a particular event occurs. The ES43en instance triggers a callback when a specific event occurs.

cycle

Before implementing the callback, create a loop:


int main(int argc, const char * argv[]) {
  @autoreleasepool {
    [[NSRunLoop currentRunLoop]run];
  }
  return 0;
}

Target - action pairs

Create an application that has NSRunLoop objects and NSTimer objects. Every two seconds, the NSTimer object sends the specified action message to its target, creating a new class named BNRLogger, which is the target of the NSTimer object.
Declare the action method in BNRLogger. h:


#import <Foundation/Foundation.h>

@interface BNRLogger : NSObject<NSURLSessionDataDelegate>
@property(nonatomic) NSDate *lastTime;

-(NSString *) lastTimeString;
-(void)updateLastTime: (NSTimer *) t;

@end

ES66en.ES67en: ES66en.ES67en


#import "BNRLogger.h"

@implementation BNRLogger

-(NSString *)lastTimeString
{
  static NSDateFormatter *dateFormatter=nil;

  if(!dateFormatter)
  {
    dateFormatter =[[NSDateFormatter alloc]init];
    [dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];

    NSLog(@"created dateFormatter");
  }
  return [dateFormatter stringFromDate:self.lastTime];
}

-(void)updateLastTime:(NSTimer *)t
{
  NSDate *now=[NSDate date];
  [self setLastTime:now];
  NSLog(@"Just set time to %@",self.lastTimeString);
}

@end

main.m create 1 instance of BNRLogger:


#import <Foundation/Foundation.h>
#import "BNRLogger.h"

int main(int argc, const char * argv[]) {
  @autoreleasepool {
    BNRLogger *logger=[[BNRLogger alloc]init];

    __unused NSTimer *timer=[NSTimer scheduledTimerWithTimeInterval:2.0 target:logger selector:@selector(updateLastTime:) userInfo:nil repeats:YES];

    [[NSRunLoop currentRunLoop]run];
  }
  return 0;
}


Auxiliary object

My last article on Blog covered the use of NSURLSession methods, so the use of secondary object callbacks makes BNRLogger objects NSURLSession's delegate objects, which send messages to secondary objects when certain events occur.
ES86en. ES87en creates an ES88en object and an ES89en object. Then create an NSURLSession object and set an instance of BNRLogger as its

Delegate object:


#import <Foundation/Foundation.h>
#import "BNRLogger.h"

int main(int argc, const char * argv[]) {
  @autoreleasepool {
    BNRLogger *logger=[[BNRLogger alloc]init];

    //URL is 1 A link to download the image 
    NSURL *url = [NSURL URLWithString:@"http://image.baidu.com/search/down?tn=download&ipn=dwnl&word=download&ie=utf8&fr=result&url=http%3A%2F%2Fimg.xiazaizhijia.com%2Fuploads%2F2016%2F0914%2F20160914112151862.jpg&thumburl=http%3A%2F%2Fimg4.imgtn.bdimg.com%2Fit%2Fu%3D2349180720%2C2436282788%26fm%3D11%26gp%3D0.jpg"];

    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    __unused NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:logger delegateQueue:[NSOperationQueue mainQueue]];

    __unused NSTimer *timer=[NSTimer scheduledTimerWithTimeInterval:2.0 target:logger selector:@selector(updateLastTime:) userInfo:nil repeats:YES];

    //4. Created from the session object 1 a Task( Send a request) 
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];

    //5. Perform a task 
    [dataTask resume];

    [[NSRunLoop currentRunLoop]run];

  }
  return 0;
}

BNRLogger.h, states NSURLSessionDataDelegate protocol:


#import <Foundation/Foundation.h>

@interface BNRLogger : NSObject<NSURLSessionDataDelegate>
@property (nonatomic, strong) NSMutableData *responseData;
@property(nonatomic) NSDate *lastTime;

-(NSString *) lastTimeString;
-(void)updateLastTime: (NSTimer *) t;

@end

BNRLogger.m has a proxy method for NSURLSession. For details, see NSURLSession:


#import "BNRLogger.h"

@implementation BNRLogger

-(NSMutableData *)responseData
{
  if (_responseData == nil) {
    _responseData = [NSMutableData data];
  }
  return _responseData;
}

-(NSString *)lastTimeString
{
  static NSDateFormatter *dateFormatter=nil;

  if(!dateFormatter)
  {
    dateFormatter =[[NSDateFormatter alloc]init];
    [dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];

    NSLog(@"created dateFormatter");
  }
  return [dateFormatter stringFromDate:self.lastTime];
}

-(void)updateLastTime:(NSTimer *)t
{
  NSDate *now=[NSDate date];
  [self setLastTime:now];
  NSLog(@"Just set time to %@",self.lastTimeString);
}

//1. This method is called when a response is received from the server 
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
  // In this method, the response header information can be obtained, i.e response
  NSLog(@"didReceiveResponse--%@",[NSThread currentThread]);
  NSLog(@" The response ");
  // Note: Need to use completionHandler The callback tells the system what to do with the data returned by the server 
  // The default is cancelled 
  /*
   NSURLSessionResponseCancel = 0,     Default handling, cancel 
   NSURLSessionResponseAllow = 1,      Receive the data returned by the server 
   NSURLSessionResponseBecomeDownload = 2, become 1 Download request 
   NSURLSessionResponseBecomeStream     become 1 A flow 
   */

  completionHandler(NSURLSessionResponseAllow);
}

//2. This method is called when data is returned from the server, and may be called multiple times if the data is large 
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
  NSLog(@"didReceiveData--%@",[NSThread currentThread]);
  NSLog(@" return ");
  // Stitching the data returned by the server 
  [self.responseData appendData:data];
}

//3. When the request is complete ( successful | failure ) If the request fails, then error Have a value 
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
  NSLog(@"didCompleteWithError--%@",[NSThread currentThread]);
  NSLog(@" complete ");
  if(error == nil)
  {
    // Analytical data 
    NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:self.responseData options:kNilOptions error:nil];
    NSLog(@"%@",dict);
  }
}

@end

notice

When the system time zone changes, an NSSystemTimeZoneDidChangeNotification notification is issued to the Notification Center, which forwards the notification to the appropriate observer.

main.m registers an instance of BNRLogger as an observer and notifies the system of any change in the time zone:


 // In the auxiliary object method application main.m Add this line of code to 
 [[NSNotificationCenter defaultCenter]addObserver:logger selector:@selector(zoneChange:) name:NSSystemTimeZoneDidChangeNotification object:nil];

Implement this method in ES123en.m:


 // In the auxiliary object method application BNRLogger.m Add this line of code to 
 -(void)zoneChange:(NSNotification *)note
{
  NSLog(@"The system time zone has changed!");
}

Block callback

Use the "notification" method application main.m as follows:


[[NSNotificationCenter defaultCenter]addObserver:logger selector:@selector(zoneChange:) name:NSSystemTimeZoneDidChangeNotification object:nil];

To:


#import <Foundation/Foundation.h>

@interface BNRLogger : NSObject<NSURLSessionDataDelegate>
@property(nonatomic) NSDate *lastTime;

-(NSString *) lastTimeString;
-(void)updateLastTime: (NSTimer *) t;

@end

0

The "Notification" method application BNRLogger.m removes this method:


#import <Foundation/Foundation.h>

@interface BNRLogger : NSObject<NSURLSessionDataDelegate>
@property(nonatomic) NSDate *lastTime;

-(NSString *) lastTimeString;
-(void)updateLastTime: (NSTimer *) t;

@end

1

conclusion

For objects that only do one thing (for example), use target-action pairs. For more complex objects (such as NSURLSession), use auxiliary objects. The most common secondary object type is the delegate object. For objects (such as NSTimeZone) that are to trigger multiple callbacks (among other objects), the advice is used. Block implements callbacks to make the code easy to read.

Thanks for reading, hope to help you, thank you for your support on this site!


Related articles: