Learning about objects you have described may mean many things. If you are after their capabilities then the documentation should be enough. But if you are more after what is under the hood and why we need these objects then I could only suggest you to look into some older language like C.
These objects NSData
, NSMutableData
, NSString
are all data containers, buffers. But NSObject
is just a base class from which all other objects inherit.
So a bit about NSData
and NSMutableData
:
In C when creating a raw buffer you use malloc
which reserves a chunk in memory which you may use as you please. Once done you need to call free
to release that memory or you will have a memory leak.
void *voidPointer = malloc(100); // Reserved 100 bytes of whatever data
int *intPointer = (int *)malloc(sizeof(int)*100); // Reserved enough bytes to fit 100 integers whatever their size may be
intPointer[13] = 1; // You may use these as normal array
free(voidPointer); // Free this memory
free(intPointer); // Free this memory
So NSData
is basically a wrapper for that and does all of it for you. You may even access the raw pointer by calling bytes
on NSData
object.
Then the mutable version NSMutableData
is just a subclass which has some additional functionality. You may actually append data. From what is under the hood appending data is not so simple. You need to allocate a new memory chunk, copy old data to it, copy new data and release the previous memory chunk.
void *currentData = malloc(100); // Assume we have some data
void *dataToAppend = malloc(100); // Another chunk of data we want to append
void *combinedData = malloc(200); // We need a larger buffer now
memcpy(combinedData, currentData, 100); // Copy first 100 bytes to new data
memcpy(combinedData+100, dataToAppend, 100); // Copy next 100 bytes to new data
free(currentData); // Free old data
free(dataToAppend); // Free old data
... use combinedData here ...
free(combinedData); // Remember to free combined data once done
These are all really simple methods but they may already be pain to write and it is easy to produce bugs doing so. So NSData
or NSMutableData
and even Data
in Swift are all just data containers that make your developer life easier. And in Objective-C conversion from data to C buffers is as easy as it gets:
NSData *myData = [NSData dataWithBytes:myDataPointer length:myDataLength];
void *myRawPointer = [myData bytes];
The NSString
is not really that different. In C we again have character pointer which is used as string so we write something like:
char *myText = "Some text";
These are a bit special, a convenience really. We could as well do:
char *myText = (char *)malloc(sizeof(char)*100);
And then fill the data character by character:
myText[0] = 'S';
myText[1] = 'o';
myText[2] = 'm';
...
myText[9] = 't';
myText[10] = '\0'; // We even need to set a null terminator at the end
and then we needed to free the memory again... But never mind the C strings, NSString
is again a wrapper that is responsible to allocate the memory, assign data and do whatever you want with it. It has may methods you can use simply to make your life easier.
As to the code you posted it is a combination of the two. In your case your API accepts images as multipart form data requests which you may understand as a raw image file with a few texts added around it just to explain what the data contains. It is one of a generally used way but not the only one. You might as well just post the raw image data or you might even post a JSON containing a base64 string encoded data. Also as usually these texts are represented as an utf8 encoded data.
In the end it is a set of standards that are generally used so our computers may communicate between each other. Your image is most likely defined by a standard from png or jpg on how to present it with a string of bytes, your strings are defined by utf8 standard and your whole request body is defined by some HTTP standards (not even sure what part of it is that). And the objects you use and want to learn about are just some helpers for achieving your result. Understanding them in most cases is like understanding a screwdriver; you won't need to in most cases, but you do need to know they exist and you need to know when to use them.
The code itself you posted is relatively bad but should do its job. For a beginner it might be a bit confusing even. Probably a more logical pseudocode for this solution would be something like:
let imageData: Data // My image data
let headerString: String // Text I need to put before the image data
let footerString: String // Text I need to put after the image data
var dataToSend: Data = Data() // Generate data object
dataToSend.append(headerString.utf8Data) // Append header
dataToSend.append(imageData) // Append raw data
dataToSend.append(footerString.utf8Data) // Append footer
I hope this clears up a few things.