NSImage
NSURLConnection
asynchronous
image loading
Swift development

Populating NSImage with data from an asynchronous NSURLConnection

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

When you load an image with an asynchronous NSURLConnection, the important detail is that the data arrives in chunks, not all at once. The usual pattern is to accumulate those chunks in NSMutableData, create the NSImage only after loading finishes, and then update the interface on the main thread.

Keep a Buffer for the Incoming Data

NSURLConnection delegate callbacks are incremental. That means you need a mutable buffer that survives across didReceiveResponse, didReceiveData, and connectionDidFinishLoading.

Here is a complete Objective-C example for a simple image loader object:

objective-c
1#import <Cocoa/Cocoa.h>
2
3@interface ImageLoader : NSObject <NSURLConnectionDataDelegate>
4@property (nonatomic, strong) NSMutableData *receivedData;
5@property (nonatomic, strong) NSImageView *imageView;
6@property (nonatomic, strong) NSURLConnection *connection;
7- (void)loadImageFromURL:(NSURL *)url;
8@end
9
10@implementation ImageLoader
11
12- (void)loadImageFromURL:(NSURL *)url
13{
14    NSURLRequest *request = [NSURLRequest requestWithURL:url];
15    self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
16}
17
18- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
19{
20    self.receivedData = [NSMutableData data];
21}
22
23- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
24{
25    [self.receivedData appendData:data];
26}
27
28- (void)connectionDidFinishLoading:(NSURLConnection *)connection
29{
30    NSImage *image = [[NSImage alloc] initWithData:self.receivedData];
31
32    dispatch_async(dispatch_get_main_queue(), ^{
33        self.imageView.image = image;
34    });
35}
36
37- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
38{
39    NSLog(@"Image download failed: %@", error);
40    self.receivedData = nil;
41}
42
43@end

This is the core pattern. Reset the buffer when the response starts, append each chunk, and build the image at the end.

Do Not Create the Image Too Early

One common mistake is trying to create the NSImage inside didReceiveData: every time a chunk arrives. That leads to repeated parsing work and can fail if the image data is incomplete.

The safer rule is:

  • buffer in didReceiveData:
  • decode in connectionDidFinishLoading
  • update UI only after decoding succeeds

That keeps the responsibilities of each delegate method clear.

Handle Reuse and Multiple Requests Carefully

If the same object may load several images over time, clear previous state before starting a new connection. Otherwise old data can leak into the next request.

objective-c
1- (void)loadImageFromURL:(NSURL *)url
2{
3    [self.connection cancel];
4    self.connection = nil;
5    self.receivedData = nil;
6
7    NSURLRequest *request = [NSURLRequest requestWithURL:url];
8    self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
9}

This is especially important for reusable UI components such as table or collection view items where one view may start a second image request before the first one finishes.

Validate the Result Before Updating the View

Not every successful HTTP response contains a valid image. If the server returns HTML or corrupt bytes, initWithData: may return nil. Check that before assigning it to the image view.

objective-c
1- (void)connectionDidFinishLoading:(NSURLConnection *)connection
2{
3    NSImage *image = [[NSImage alloc] initWithData:self.receivedData];
4    if (!image) {
5        NSLog(@"Downloaded data was not a valid image");
6        return;
7    }
8
9    dispatch_async(dispatch_get_main_queue(), ^{
10        self.imageView.image = image;
11    });
12}

That small check turns mysterious blank-image bugs into something easier to diagnose.

Remember the Main Thread for UI Updates

NSImage creation itself is one thing. Updating NSImageView is another. AppKit objects should be touched on the main thread, so it is good practice to dispatch the assignment back to the main queue even if the delegate currently arrives there in your setup.

That habit becomes more important if the networking code later changes or if image processing is moved onto a background queue.

Prefer NSURLSession for New Code

NSURLConnection is a legacy API. It still appears in older macOS codebases, so it is useful to understand, but new work should generally use NSURLSession because it has a more modern design and better support for configuration, delegates, and background behavior.

The core idea remains the same, though: collect the bytes, decode the image after completion, and update the UI safely.

Common Pitfalls

The biggest mistake is trying to create an NSImage before the full response body has arrived. Another common issue is forgetting to reset NSMutableData in didReceiveResponse:, which can mix bytes from multiple loads. Developers also sometimes assume that any successful network response contains image data, but initWithData: can fail if the server returns something else. Finally, UI updates should stay on the main thread even when the networking code is asynchronous.

Summary

  • Use a persistent NSMutableData buffer to collect chunks from the asynchronous connection.
  • Reset the buffer when the response begins and append in didReceiveData:.
  • Build the NSImage in connectionDidFinishLoading: after all bytes arrive.
  • Check that image decoding succeeded before assigning it to the view.
  • For new code, prefer NSURLSession, but the same buffering pattern still applies.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.