Elysia Tools
Navigation
Objective-C
macOS Networking Objective-C Samples
macOS Objective-C networking examples including URLSession, HTTP requests, WebSocket, and network reachability
Samples
Entries inside this sample collection
URLSession Basics
Make HTTP requests using URLSession for data downloads, REST API calls, and file uploads
Difficulty
5/10
Estimated time
25 min
Tags
objectivec, macos, networking, urlsession
Prerequisites
Objective-C basics, Foundation framework
// macOS Objective-C URLSession Basics
// Using Foundation framework
#import <Foundation/Foundation.h>
// MARK: - 1. Simple Data Task
@interface DataTaskDemo : NSObject
+ (void)fetchDataWithURL:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithURL:url
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
if (error) {
NSLog(@"Error: %@", error.localizedDescription);
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"Status code: %ld", (long)httpResponse.statusCode);
if (data) {
NSString *responseString = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"Response: %@", responseString);
}
}];
[task resume];
}
+ (void)synchronousFetchWithURL:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.timeoutIntervalForRequest = 30.0;
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
__block NSData *responseData = nil;
__block NSURLResponse *response = nil;
__block NSError *requestError = nil;
NSURLSessionDataTask *task = [session dataTaskWithURL:url
completionHandler:^(NSData *data,
NSURLResponse *resp,
NSError *error) {
responseData = data;
response = resp;
requestError = error;
dispatch_semaphore_signal(semaphore);
}];
[task resume];
// Wait for completion (blocking)
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
if (requestError) {
NSLog(@"Synchronous request error: %@", requestError.localizedDescription);
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"Synchronous status code: %ld", (long)httpResponse.statusCode);
if (responseData) {
NSString *responseString = [[NSString alloc] initWithData:responseData
encoding:NSUTF8StringEncoding];
NSLog(@"Synchronous response: %@", responseString);
}
}
@end
// MARK: - 2. HTTP POST with JSON
@interface JSONPostDemo : NSObject
+ (void)postJSON:(NSDictionary *)jsonDict
toURL:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
// Set headers
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
// Convert JSON to data
NSError *jsonError = nil;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDict
options:0
error:&jsonError];
if (jsonError) {
NSLog(@"JSON error: %@", jsonError.localizedDescription);
return;
}
request.HTTPBody = jsonData;
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
if (error) {
NSLog(@"Error: %@", error.localizedDescription);
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"Status code: %ld", (long)httpResponse.statusCode);
if (data) {
NSError *parseError = nil;
id jsonResponse = [NSJSONSerialization JSONObjectWithData:data
options:0
error:&parseError];
if (!parseError) {
NSLog(@"JSON response: %@", jsonResponse);
}
}
}];
[task resume];
}
@end
// MARK: - 3. Download Task
@interface DownloadDemo : NSObject
+ (void)downloadFileFromURL:(NSString *)urlString
toPath:(NSString *)destinationPath {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url
completionHandler:^(NSURL *location,
NSURLResponse *response,
NSError *error) {
if (error) {
NSLog(@"Download error: %@", error.localizedDescription);
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"Downloaded status: %ld", (long)httpResponse.statusCode);
NSFileManager *fileManager = [NSFileManager defaultManager];
// Remove existing file
if ([fileManager fileExistsAtPath:destinationPath]) {
[fileManager removeItemAtPath:destinationPath error:nil];
}
// Move file to destination
NSError *moveError = nil;
BOOL success = [fileManager moveItemAtPath:location.path
toPath:destinationPath
error:&moveError];
if (success) {
NSLog(@"File saved to: %@", destinationPath);
} else {
NSLog(@"Move error: %@", moveError.localizedDescription);
}
}];
[task resume];
}
+ (void)downloadWithProgress:(NSString *)urlString
toPath:(NSString *)destinationPath {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config
delegate:nil
delegateQueue:nil];
// Create download task with progress
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];
__block NSURLSessionDownloadTask *weakTask = task;
[task resume];
// Monitor progress (simplified)
NSLog(@"Download started: %@", urlString);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
while (weakTask.state == NSURLSessionTaskStateRunning) {
[NSThread sleepForTimeInterval:0.5];
NSLog(@"Downloading...");
}
NSLog(@"Download completed");
});
}
@end
// MARK: - 4. Upload Task
@interface UploadDemo : NSObject
+ (void)uploadFile:(NSString *)filePath
toURL:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
// Read file data
NSError *readError = nil;
NSData *fileData = [NSData dataWithContentsOfFile:filePath
options:0
error:&readError];
if (readError) {
NSLog(@"File read error: %@", readError.localizedDescription);
return;
}
// Create request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
NSString *fileName = [filePath lastPathComponent];
NSString *boundary = [NSString stringWithFormat:@"Boundary-%@", [[NSUUID UUID] UUIDString]];
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:contentType forHTTPHeaderField:@"Content-Type"];
// Create body
NSMutableData *body = [NSMutableData data];
// Add file data
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"file\"; filename=\"%@\"\r\n", fileName] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Type: application/octet-stream\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:fileData];
[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
request.HTTPBody = body;
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request
fromData:body
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
if (error) {
NSLog(@"Upload error: %@", error.localizedDescription);
return;
}
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"Upload status: %ld", (long)httpResponse.statusCode);
if (data) {
NSString *responseString = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
NSLog(@"Response: %@", responseString);
}
}];
[task resume];
}
@end
// MARK: - 5. Custom Delegate
@interface SessionDelegate : NSObject <NSURLSessionDataDelegate>
@property (nonatomic, strong) NSMutableData *receivedData;
@property (nonatomic, strong) NSURLResponse *urlResponse;
@end
@implementation SessionDelegate
- (instancetype)init {
self = [super init];
if (self) {
_receivedData = [NSMutableData data];
}
return self;
}
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
self.urlResponse = response;
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
NSLog(@"Received response: status %ld", (long)httpResponse.statusCode);
completionHandler(NSURLSessionResponseAllow);
}
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data {
[self.receivedData appendData:data];
NSLog(@"Received %lu bytes", (unsigned long)data.length);
}
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error {
if (error) {
NSLog(@"Error: %@", error.localizedDescription);
} else {
NSLog(@"Task completed. Total bytes: %lu", (unsigned long)self.receivedData.length);
NSString *responseString = [[NSString alloc] initWithData:self.receivedData
encoding:NSUTF8StringEncoding];
NSLog(@"Response: %@", responseString);
}
}
@end
@interface DelegateDemo : NSObject
+ (void)fetchWithDelegate:(NSString *)urlString {
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
SessionDelegate *delegate = [[SessionDelegate alloc] init];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config
delegate:delegate
delegateQueue:nil];
NSURLSessionDataTask *task = [session dataTaskWithURL:url];
[task resume];
// Wait for completion
while (task.state == NSURLSessionTaskStateRunning) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
}
}
@end
// MARK: - 6. Background Session
@interface BackgroundSessionDemo : NSObject
+ (NSURLSession *)createBackgroundSession {
NSString *identifier = @"com.example.background.session";
NSURLSessionConfiguration *config = [NSURLSessionConfiguration
backgroundSessionConfigurationWithIdentifier:identifier];
config.discretionary = NO;
config.sessionSendsLaunchEvents = YES;
return [NSURLSession sessionWithConfiguration:config];
}
+ (void)startBackgroundDownload:(NSString *)urlString {
NSURLSession *session = [self createBackgroundSession];
NSURL *url = [NSURL URLWithString:urlString];
if (!url) {
NSLog(@"Invalid URL: %@", urlString);
return;
}
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url];
[task resume];
NSLog(@"Background download started");
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C URLSession Examples ===\n");
// 1. Simple data task
NSLog(@"--- 1. Simple Data Task ---");
[DataTaskDemo fetchDataWithURL:@"https://httpbin.org/get"];
[NSThread sleepForTimeInterval:2.0];
// 2. JSON POST
NSLog(@"\n--- 2. JSON POST ---");
NSDictionary *jsonDict = @{
@"name": @"John Doe",
@"email": @"[email protected]",
@"age": @30
};
[JSONPostDemo postJSON:jsonDict toURL:@"https://httpbin.org/post"];
[NSThread sleepForTimeInterval:2.0];
// 3. Download task
NSLog(@"\n--- 3. Download Task ---");
NSString *downloadPath = @"/tmp/downloaded_file.json";
[DownloadDemo downloadFileFromURL:@"https://httpbin.org/json"
toPath:downloadPath];
[NSThread sleepForTimeInterval:3.0];
// 4. Upload task
NSLog(@"\n--- 4. Upload Task ---");
NSString *testFile = @"/tmp/test_upload.txt";
[@"Test upload content" writeToFile:testFile
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
[UploadDemo uploadFile:testFile toURL:@"https://httpbin.org/post"];
[NSThread sleepForTimeInterval:2.0];
// 5. Custom delegate
NSLog(@"\n--- 5. Custom Delegate ---");
[DelegateDemo fetchWithDelegate:@"https://httpbin.org/get"];
// 6. Background session
NSLog(@"\n--- 6. Background Session ---");
[BackgroundSessionDemo startBackgroundDownload:@"https://httpbin.org/json"];
[NSThread sleepForTimeInterval:2.0];
NSLog(@"\n=== URLSession Examples Completed ===");
}
return 0;
}WebSocket Communication
Implement real-time bidirectional communication using WebSocket
Difficulty
7/10
Estimated time
30 min
Tags
objectivec, macos, networking, websocket
Prerequisites
Intermediate Objective-C, Network programming
// macOS Objective-C WebSocket Examples
// Using Foundation and Network framework
#import <Foundation/Foundation.h>
// MARK: - 1. Basic WebSocket Client
@interface WebSocketClient : NSObject <NSStreamDelegate>
@property (nonatomic, strong) NSInputStream *inputStream;
@property (nonatomic, strong) NSOutputStream *outputStream;
@property (nonatomic, strong) NSString *urlString;
@property (nonatomic, assign) BOOL connected;
- (instancetype)initWithURL:(NSString *)urlString;
- (void)connect;
- (void)disconnect;
- (void)sendMessage:(NSString *)message;
@end
@implementation WebSocketClient
- (instancetype)initWithURL:(NSString *)urlString {
self = [super init];
if (self) {
_urlString = urlString;
_connected = NO;
}
return self;
}
- (void)connect {
NSURL *url = [NSURL URLWithString:self.urlString];
if (!url) {
NSLog(@"Invalid URL: %@", self.urlString);
return;
}
NSString *host = url.host;
NSNumber *port = url.port;
if (!port) {
NSString *scheme = url.scheme;
if ([scheme isEqualToString:@"wss"]) {
port = @443;
} else {
port = @80;
}
}
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL,
(__bridge CFStringRef)host,
[port unsignedShortValue],
&readStream,
&writeStream);
if (!readStream || !writeStream) {
NSLog(@"Failed to create streams");
return;
}
self.inputStream = (__bridge_transfer NSInputStream *)readStream;
self.outputStream = (__bridge_transfer NSOutputStream *)writeStream;
self.inputStream.delegate = self;
self.outputStream.delegate = self;
[self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[self.inputStream open];
[self.outputStream open];
NSLog(@"Connecting to %@", self.urlString);
}
- (void)disconnect {
[self.inputStream close];
[self.outputStream close];
[self.inputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[self.outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
self.inputStream = nil;
self.outputStream = nil;
self.connected = NO;
NSLog(@"Disconnected");
}
- (void)sendMessage:(NSString *)message {
if (!self.connected || !self.outputStream) {
NSLog(@"Not connected");
return;
}
NSString *frame = [NSString stringWithFormat:@"\x00%@\xff", message];
NSData *data = [frame dataUsingEncoding:NSUTF8StringEncoding];
NSInteger written = [self.outputStream write:data.bytes maxLength:data.length];
if (written < 0) {
NSLog(@"Send error");
} else {
NSLog(@"Sent: %@", message);
}
}
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
switch (eventCode) {
case NSStreamEventOpenCompleted: {
if (stream == self.inputStream) {
self.connected = YES;
// Send WebSocket handshake
NSString *handshake = [NSString stringWithFormat:
@"GET %@ HTTP/1.1\r\n"
@"Host: %@\r\n"
@"Upgrade: websocket\r\n"
@"Connection: Upgrade\r\n"
@"Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
@"Sec-WebSocket-Version: 13\r\n"
@"\r\n",
[[NSURL URLWithString:self.urlString] path],
[NSURL URLWithString:self.urlString].host
];
NSData *handshakeData = [handshake dataUsingEncoding:NSUTF8StringEncoding];
[self.outputStream write:handshakeData.bytes maxLength:handshakeData.length];
}
break;
}
case NSStreamEventHasBytesAvailable: {
if (stream == self.inputStream) {
uint8_t buffer[1024];
NSInteger bytesRead = [self.inputStream read:buffer maxLength:sizeof(buffer)];
if (bytesRead > 0) {
NSData *data = [NSData dataWithBytes:buffer length:bytesRead];
// Parse WebSocket frame (simplified)
if (buffer[0] == 0x00) {
NSString *message = [[NSString alloc] initWithBytes:buffer + 1
length:bytesRead - 2
encoding:NSUTF8StringEncoding];
NSLog(@"Received: %@", message);
} else {
NSString *hex = [data description];
NSLog(@"Received data: %@", hex);
}
}
}
break;
}
case NSStreamEventErrorOccurred: {
NSLog(@"Stream error: %@", stream.streamError);
[self disconnect];
break;
}
case NSStreamEventEndEncountered: {
NSLog(@"Stream ended");
[self disconnect];
break;
}
default:
break;
}
}
@end
// MARK: - 2. WebSocket Chat Client
@interface ChatClient : WebSocketClient
@property (nonatomic, strong) NSString *username;
@property (nonatomic, strong) NSMutableArray *messages;
- (instancetype)initWithURL:(NSString *)urlString username:(NSString *)username;
- (void)joinChat;
- (void)sendChatMessage:(NSString *)message;
- (void)printMessages;
@end
@implementation ChatClient
- (instancetype)initWithURL:(NSString *)urlString username:(NSString *)username {
self = [super initWithURL:urlString];
if (self) {
_username = username;
_messages = [NSMutableArray array];
}
return self;
}
- (void)joinChat {
[self connect];
// Send join message
NSString *joinMsg = [NSString stringWithFormat:@"/join %@", self.username];
[self sendMessage:joinMsg];
}
- (void)sendChatMessage:(NSString *)message {
NSString *chatMsg = [NSString stringWithFormat:@"/msg %@", message];
[self sendMessage:chatMsg];
[self.messages addObject:[NSString stringWithFormat:@"%@: %@", self.username, message]];
}
- (void)printMessages {
NSLog(@"\n=== Chat Messages ===");
for (NSString *msg in self.messages) {
NSLog(@"%@", msg);
}
NSLog(@"==================\n");
}
@end
// MARK: - 3. Reconnection Handler
@interface ResilientWebSocketClient : WebSocketClient
@property (nonatomic, assign) NSInteger maxRetries;
@property (nonatomic, assign) NSInteger currentRetry;
@property (nonatomic, assign) NSTimeInterval retryDelay;
- (void)autoConnectWithRetries:(NSInteger)maxRetries delay:(NSTimeInterval)delay;
@end
@implementation ResilientWebSocketClient
- (void)autoConnectWithRetries:(NSInteger)maxRetries delay:(NSTimeInterval)delay {
self.maxRetries = maxRetries;
self.retryDelay = delay;
self.currentRetry = 0;
[self attemptConnect];
}
- (void)attemptConnect {
[self connect];
// Check connection after delay
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.retryDelay * NSEC_PER_SEC)),
dispatch_get_main_queue(), ^{
if (!self.connected && self.currentRetry < self.maxRetries) {
self.currentRetry++;
NSLog(@"Connection failed. Retrying (%ld/%ld)...",
(long)self.currentRetry, (long)self.maxRetries);
[self attemptConnect];
} else if (!self.connected) {
NSLog(@"Max retries reached. Connection failed.");
}
});
}
@end
// MARK: - 4. Heartbeat Protocol
@interface HeartbeatWebSocketClient : WebSocketClient
@property (nonatomic, strong) NSTimer *heartbeatTimer;
@property (nonatomic, assign) NSTimeInterval heartbeatInterval;
- (void)startHeartbeat:(NSTimeInterval)interval;
- (void)stopHeartbeat;
@end
@implementation HeartbeatWebSocketClient
- (void)startHeartbeat:(NSTimeInterval)interval {
self.heartbeatInterval = interval;
self.heartbeatTimer = [NSTimer scheduledTimerWithTimeInterval:interval
repeats:YES
block:^(NSTimer *timer) {
[self sendMessage:@"/ping"];
NSLog(@"Sent heartbeat");
}];
NSLog(@"Heartbeat started (%.0f seconds)", interval);
}
- (void)stopHeartbeat {
[self.heartbeatTimer invalidate];
self.heartbeatTimer = nil;
NSLog(@"Heartbeat stopped");
}
- (void)disconnect {
[self stopHeartbeat];
[super disconnect];
}
@end
// MARK: - 5. Message Queue
@interface MessageQueueWebSocketClient : WebSocketClient
@property (nonatomic, strong) NSMutableArray *messageQueue;
@property (nonatomic, assign) BOOL shouldQueueMessages;
- (instancetype)initWithURL:(NSString *)urlString;
@end
@implementation MessageQueueWebSocketClient
- (instancetype)initWithURL:(NSString *)urlString {
self = [super initWithURL:urlString];
if (self) {
_messageQueue = [NSMutableArray array];
_shouldQueueMessages = YES;
}
return self;
}
- (void)sendMessage:(NSString *)message {
if (self.connected) {
[super sendMessage:message];
} else if (self.shouldQueueMessages) {
[self.messageQueue addObject:message];
NSLog(@"Queued message: %@ (queue size: %lu)",
message, (unsigned long)self.messageQueue.count);
}
}
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
[super stream:stream handleEvent:eventCode];
if (eventCode == NSStreamEventOpenCompleted && stream == self.inputStream) {
// Send queued messages
if (self.messageQueue.count > 0) {
NSLog(@"Sending %lu queued messages", (unsigned long)self.messageQueue.count);
for (NSString *queuedMessage in [self.messageQueue copy]) {
[super sendMessage:queuedMessage];
[self.messageQueue removeObject:queuedMessage];
}
}
}
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C WebSocket Examples ===\n");
// 1. Basic WebSocket client
NSLog(@"--- 1. Basic WebSocket Client ---");
WebSocketClient *client = [[WebSocketClient alloc]
initWithURL:@"ws://echo.websocket.org"];
[client connect];
[NSThread sleepForTimeInterval:1.0];
[client sendMessage:@"Hello, WebSocket!"];
[client sendMessage:@"How are you?"];
[NSThread sleepForTimeInterval:2.0];
[client disconnect];
// 2. Chat client
NSLog(@"\n--- 2. Chat Client ---");
ChatClient *chatClient = [[ChatClient alloc]
initWithURL:@"ws://echo.websocket.org"
username:@"Alice"];
[chatClient joinChat];
[NSThread sleepForTimeInterval:1.0];
[chatClient sendChatMessage:@"Hi everyone!"];
[chatClient sendChatMessage:@"How's it going?"];
[NSThread sleepForTimeInterval:2.0];
[chatClient printMessages];
[chatClient disconnect];
// 3. Resilient client with retries
NSLog(@"\n--- 3. Resilient Client ---");
ResilientWebSocketClient *resilientClient = [[ResilientWebSocketClient alloc]
initWithURL:@"ws://invalid.websocket.org"];
[resilientClient autoConnectWithRetries:3 delay:1.0];
[NSThread sleepForTimeInterval:5.0);
// 4. Heartbeat
NSLog(@"\n--- 4. Heartbeat Protocol ---");
HeartbeatWebSocketClient *heartbeatClient = [[HeartbeatWebSocketClient alloc]
initWithURL:@"ws://echo.websocket.org"];
[heartbeatClient connect];
[NSThread sleepForTimeInterval:1.0];
[heartbeatClient startHeartbeat:2.0];
[NSThread sleepForTimeInterval:8.0);
[heartbeatClient stopHeartbeat];
[heartbeatClient disconnect];
// 5. Message queue
NSLog(@"\n--- 5. Message Queue ---");
MessageQueueWebSocketClient *queueClient = [[MessageQueueWebSocketClient alloc]
initWithURL:@"ws://echo.websocket.org"];
// Send messages before connected
[queueClient sendMessage:@"Queued 1"];
[queueClient sendMessage:@"Queued 2"];
[queueClient sendMessage:@"Queued 3"];
[queueClient connect];
[NSThread sleepForTimeInterval:2.0);
[queueClient sendMessage:@"After connect"];
[NSThread sleepForTimeInterval:2.0];
[queueClient disconnect];
NSLog(@"\n=== WebSocket Examples Completed ===");
}
return 0;
}Network Reachability
Monitor network connectivity status and detect network changes
Difficulty
6/10
Estimated time
25 min
Tags
objectivec, macos, networking, reachability
Prerequisites
Intermediate Objective-C, SystemConfiguration framework
// macOS Objective-C Network Reachability Examples
// Using SystemConfiguration framework
#import <Foundation/Foundation.h>
#import <SystemConfiguration/SystemConfiguration.h>
// MARK: - 1. Basic Reachability Check
@interface ReachabilityChecker : NSObject
+ (BOOL)isNetworkAvailable {
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr *)&zeroAddress);
if (!reachability) {
return NO;
}
SCNetworkReachabilityFlags flags;
BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags);
CFRelease(reachability);
if (!success) {
return NO;
}
BOOL isReachable = (flags & kSCNetworkReachabilityFlagsReachable) != 0;
BOOL needsConnection = (flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0;
return isReachable && !needsConnection;
}
+ (NSString *)getConnectionType {
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (struct sockaddr *)&zeroAddress);
if (!reachability) {
return @"Unknown";
}
SCNetworkReachabilityFlags flags;
BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags);
CFRelease(reachability);
if (!success) {
return @"Unknown";
}
if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) {
return @"No Connection";
}
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) != 0) {
return @"Cellular";
}
return @"WiFi";
}
@end
// MARK: - 2. Reachability Monitor
@interface ReachabilityMonitor : NSObject
@property (nonatomic, assign) SCNetworkReachabilityRef reachability;
@property (nonatomic, strong) NSTimer *pollingTimer;
@property (nonatomic, copy) void (^onChange)(BOOL isReachable, NSString *connectionType);
- (instancetype)initWithCallback:(void (^)(BOOL, NSString *))callback;
- (void)startMonitoring;
- (void)stopMonitoring;
@end
@implementation ReachabilityMonitor
- (instancetype)initWithCallback:(void (^)(BOOL, NSString *))callback {
self = [super init];
if (self) {
_onChange = callback;
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
_reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault,
(struct sockaddr *)&zeroAddress);
}
return self;
}
- (void)startMonitoring {
if (!_reachability) {
NSLog(@"Reachability not initialized");
return;
}
// Start polling timer
self.pollingTimer = [NSTimer scheduledTimerWithTimeInterval:5.0
repeats:YES
block:^(NSTimer *timer) {
BOOL isReachable = [ReachabilityChecker isNetworkAvailable];
NSString *connectionType = [ReachabilityChecker getConnectionType];
if (self.onChange) {
self.onChange(isReachable, connectionType);
}
}];
NSLog(@"Started monitoring network reachability");
}
- (void)stopMonitoring {
[self.pollingTimer invalidate];
self.pollingTimer = nil;
NSLog(@"Stopped monitoring network reachability");
}
- (void)dealloc {
[self stopMonitoring];
if (_reachability) {
CFRelease(_reachability);
}
}
@end
// MARK: - 3. Host Reachability
@interface HostReachabilityChecker : NSObject
+ (BOOL)isHostReachable:(NSString *)hostName;
+ (BOOL)isHostReachableSync:(NSString *)hostName;
@end
@implementation HostReachabilityChecker
+ (BOOL)isHostReachable:(NSString *)hostName {
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(kCFAllocatorDefault,
[hostName UTF8String]);
if (!reachability) {
return NO;
}
SCNetworkReachabilityFlags flags;
BOOL success = SCNetworkReachabilityGetFlags(reachability, &flags);
CFRelease(reachability);
if (!success) {
return NO;
}
BOOL isReachable = (flags & kSCNetworkReachabilityFlagsReachable) != 0;
BOOL needsConnection = (flags & kSCNetworkReachabilityFlagsConnectionRequired) != 0;
return isReachable && !needsConnection;
}
+ (BOOL)isHostReachableSync:(NSString *)hostName {
// Try to actually connect to the host
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL,
(__bridge CFStringRef)hostName,
80,
&readStream,
&writeStream);
if (!readStream || !writeStream) {
return NO;
}
NSInputStream *inputStream = (__bridge_transfer NSInputStream *)readStream;
NSOutputStream *outputStream = (__bridge_transfer NSOutputStream *)writeStream;
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];
// Wait for connection
NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:3.0];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:timeout];
BOOL reachable = [outputStream streamStatus] == NSStreamStatusOpen;
[inputStream close];
[outputStream close];
return reachable;
}
@end
// MARK: - 4. Connection Quality
@interface ConnectionQuality : NSObject
+ (NSString *)assessConnectionQuality {
// Simple quality assessment based on connection type
NSString *connectionType = [ReachabilityChecker getConnectionType];
if ([connectionType isEqualToString:@"No Connection"]) {
return @"None";
} else if ([connectionType isEqualToString:@"WiFi"]) {
return @"Good";
} else if ([connectionType isEqualToString:@"Cellular"]) {
return @"Moderate";
}
return @"Unknown";
}
+ (void)runSpeedTest:(void (^)(double speedMbps))completion {
// Simulated speed test
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *url = [NSURL URLWithString:@"https://httpbin.org/bytes/1048576"];
NSData *data = [NSData dataWithContentsOfURL:url];
double speedMbps = 0;
if (data) {
// Assume it took 2 seconds for 1 MB
double mb = data.length / (1024.0 * 1024.0);
speedMbps = mb / 2.0;
}
dispatch_async(dispatch_get_main_queue(), ^{
if (completion) {
completion(speedMbps);
}
});
});
}
@end
// MARK: - 5. Network State Manager
@interface NetworkStateManager : NSObject
@property (nonatomic, assign) BOOL isReachable;
@property (nonatomic, strong) NSString *connectionType;
@property (nonatomic, strong) NSMutableArray<void (^)(BOOL, NSString *)> *observers;
+ (instancetype)sharedManager;
- (void)addObserver:(void (^)(BOOL, NSString *))observer;
- (void)removeObserver:(void (^)(BOOL, NSString *))observer;
- (void)startMonitoring;
- (void)stopMonitoring;
@end
@implementation NetworkStateManager {
ReachabilityMonitor *_monitor;
}
+ (instancetype)sharedManager {
static NetworkStateManager *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[NetworkStateManager alloc] init];
});
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
_isReachable = [ReachabilityChecker isNetworkAvailable];
_connectionType = [ReachabilityChecker getConnectionType];
_observers = [NSMutableArray array];
__weak typeof(self) weakSelf = self;
_monitor = [[ReachabilityMonitor alloc] initWithCallback:^(BOOL isReachable, NSString *connectionType) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf.isReachable != isReachable ||
![strongSelf.connectionType isEqualToString:connectionType]) {
strongSelf.isReachable = isReachable;
strongSelf.connectionType = connectionType;
NSLog(@"Network changed: %@ - %@", isReachable ? @"Connected" : @"Disconnected", connectionType);
[strongSelf notifyObservers];
}
}];
}
return self;
}
- (void)addObserver:(void (^)(BOOL, NSString *))observer {
[self.observers addObject:observer];
// Immediately call with current state
observer(self.isReachable, self.connectionType);
}
- (void)removeObserver:(void (^)(BOOL, NSString *))observer {
[self.observers removeObject:observer];
}
- (void)notifyObservers {
for (void (^observer)(BOOL, NSString *) in self.observers) {
observer(self.isReachable, self.connectionType);
}
}
- (void)startMonitoring {
[_monitor startMonitoring];
}
- (void)stopMonitoring {
[_monitor stopMonitoring];
}
@end
// MARK: - Main Demonstration
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"=== macOS Objective-C Network Reachability Examples ===\n");
// 1. Basic reachability check
NSLog(@"--- 1. Basic Reachability Check ---");
BOOL isAvailable = [ReachabilityChecker isNetworkAvailable];
NSString *connType = [ReachabilityChecker getConnectionType];
NSLog(@"Network Available: %@", isAvailable ? @"YES" : @"NO");
NSLog(@"Connection Type: %@", connType);
// 2. Host reachability
NSLog(@"\n--- 2. Host Reachability ---");
NSArray *hosts = @[@"apple.com", @"google.com", @"github.com", @"localhost"];
for (NSString *host in hosts) {
BOOL reachable = [HostReachabilityChecker isHostReachable:host];
NSLog(@"%@: %@", host, reachable ? @"✓ Reachable" : @"✗ Unreachable");
}
// 3. Connection quality
NSLog(@"\n--- 3. Connection Quality ---");
NSString *quality = [ConnectionQuality assessConnectionQuality];
NSLog(@"Connection Quality: %@", quality);
[ConnectionQuality runSpeedTest:^(double speedMbps) {
NSLog(@"Speed: %.2f Mbps", speedMbps);
}];
[NSThread sleepForTimeInterval:5.0];
// 4. Reachability monitor
NSLog(@"\n--- 4. Reachability Monitor ---");
ReachabilityMonitor *monitor = [[ReachabilityMonitor alloc]
initWithCallback:^(BOOL isReachable, NSString *connectionType) {
NSLog(@"Status: %@ - %@", isReachable ? @"Connected" : @"Disconnected", connectionType);
}];
[monitor startMonitoring];
NSLog(@"Monitoring for 15 seconds...");
[NSThread sleepForTimeInterval:15.0];
[monitor stopMonitoring];
// 5. Network state manager
NSLog(@"\n--- 5. Network State Manager ---");
NetworkStateManager *manager = [NetworkStateManager sharedManager];
[manager addObserver:^(BOOL isReachable, NSString *connectionType) {
NSLog(@"Observer 1: %@ - %@", isReachable ? @"Connected" : @"Disconnected", connectionType);
}];
[manager addObserver:^(BOOL isReachable, NSString *connectionType) {
NSLog(@"Observer 2: Quality = %@", [ConnectionQuality assessConnectionQuality]);
}];
[manager startMonitoring];
NSLog(@"State manager monitoring for 10 seconds...");
[NSThread sleepForTimeInterval:10.0];
[manager stopMonitoring];
NSLog(@"\n=== Network Reachability Examples Completed ===");
}
return 0;
}Tools
Tools frequently paired with this sample
Related