Context in Objective-C

Here’s the translation of the Go code to Objective-C, formatted in Markdown suitable for Hugo:

Our first example demonstrates how to create a simple HTTP server and handle context cancellation. This is useful for controlling cancellation and managing request-scoped values across API boundaries and threads.

#import <Foundation/Foundation.h>

@interface HelloHandler : NSObject <NSURLSessionDataDelegate>
@end

@implementation HelloHandler

- (void)handleRequest:(NSURLRequest *)request withCompletionHandler:(void (^)(NSURLResponse *, NSData *, NSError *))completionHandler {
    NSLog(@"server: hello handler started");
    
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();
    
    dispatch_group_enter(group);
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), queue, ^{
        NSString *response = @"hello\n";
        NSData *data = [response dataUsingEncoding:NSUTF8StringEncoding];
        NSURLResponse *urlResponse = [[NSHTTPURLResponse alloc] initWithURL:request.URL statusCode:200 HTTPVersion:nil headerFields:nil];
        completionHandler(urlResponse, data, nil);
        dispatch_group_leave(group);
    });
    
    dispatch_group_notify(group, queue, ^{
        NSLog(@"server: hello handler ended");
    });
}

@end

@interface Server : NSObject
@property (nonatomic, strong) NSURLSession *session;
@end

@implementation Server

- (instancetype)init {
    self = [super init];
    if (self) {
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        self.session = [NSURLSession sessionWithConfiguration:config delegate:nil delegateQueue:nil];
    }
    return self;
}

- (void)start {
    NSURL *url = [NSURL URLWithString:@"http://localhost:8090"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"GET"];
    
    HelloHandler *handler = [[HelloHandler alloc] init];
    
    [[self.session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error) {
            NSLog(@"server: %@", error.localizedDescription);
            return;
        }
        
        [handler handleRequest:request withCompletionHandler:^(NSURLResponse * _Nonnull response, NSData * _Nullable data, NSError * _Nullable error) {
            if (error) {
                NSLog(@"server: %@", error.localizedDescription);
            } else {
                NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                NSLog(@"%@", responseString);
            }
        }];
    }] resume];
    
    [[NSRunLoop currentRunLoop] run];
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Server *server = [[Server alloc] init];
        [server start];
    }
    return 0;
}

In this Objective-C version, we’ve created a simple server that listens on localhost:8090. The HelloHandler class simulates a long-running operation that takes 10 seconds to complete.

To run the server:

$ gcc -framework Foundation server.m -o server
$ ./server

To simulate a client request and cancellation:

$ curl localhost:8090
server: hello handler started
^C
server: The operation couldn't be completed. (NSURLErrorDomain error -999.)
server: hello handler ended

Note that Objective-C doesn’t have a direct equivalent to Go’s context.Context. Instead, we’ve used NSURLSession and its cancellation mechanism to achieve similar functionality. The dataTaskWithRequest:completionHandler: method can be cancelled, which will trigger an error with domain NSURLErrorDomain and code -999 (cancelled).

This example demonstrates how to handle long-running operations and cancellation in Objective-C, which is conceptually similar to using contexts in Go for managing request lifecycles and cancellation.