Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Extreme343GS

macrumors newbie
Original poster
Jan 26, 2010
10
0
Code:
- (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error

Just why does NSError have two pointers? What does it actually mean?
 
Last edited by a moderator:
It's a pointer to a pointer.

Since all Objective-C objects *must* be referenced through pointers you can really think of "NSError*" as "an NSError". So an "NSError**" is "a pointer to an NSError".

In this case, you're supposed to do something like this:
Code:
NSError *errorToBeFilledIn = nil;
[@"foo" writeToFile:aFile atomically:YES encoding:NSUTF8StringEncoding error:&errorToBeFilledIn];
if (errorToBeFilledIn != nil) {
    //handle the error
}
 
Code:
- (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error

Just why does NSError have two pointers? What does it actually mean?

Get out your old C book and look up what a pointer is.

Now write a void function that is supposed to return the age of some person in years as an int, and the weight in pounds as an int. How do you write this function, and how do you call it?

And now write a function that is supposed to return a BOOL as its return value, and that also can optionally return an NSError*. How do you write this function, and how do you call it?
 
Last edited by a moderator:
This is basically covered in the replies above, but in my mind the rationale for this is that NSError is immutable. You couldn't pass in an instantiated NSError and get anything of value back, because the object could not be changed. Therefore, you need to get a new NSError object. If you just pass the pointer to an NSError by value, then the only way for something good to happen would be for the method to somehow get a brand new NSError at the exact same memory location that you passed in. This isn't really possible, so instead you pass a pointer to your NSError * so a new NSError can be alloc'd/init'd and the pointer to the new Object can be assigned to your NSError **.

The ** is pretty rare, often because the "result" of a call is it's return value.

-Lee
 
Code:
- (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)useAuxiliaryFile encoding:(NSStringEncoding)enc error:(NSError **)error

Just why does NSError have two pointers? What does it actually mean?

I'm not familiar with your code, but here is sample code where a double-pointer is used:

Code:
#include <stdio.h>

void get( char ** msg )
{
	*msg = strdup( "This string will survive beyond this function." );
}

void get_bad( char * msg )
{
	// The memory in msg will be lost after exiting this function.
	msg = strdup( "Not seen outside this function" );
}

int main()
{
	char *msg = NULL;

	get( &msg );

	if( msg )
	{
		printf( "Got this message: '%s'\n", msg );
		free( msg );
		msg = NULL;
	}
	else
	{
		printf( "We'll get here if the memory allocation in 'get' failed.\n" );
	}


 	get_bad( msg );

	if( msg )
	{
		printf( "We'll never get here, but, anyway: '%s'\n", msg );
		free( msg );
	}
	else
	{
		printf( "Didn't get a message, as expected.\n" );
	}	

	return 0;
}

The 'get' function allocates memory for the parameter passed to it, just as the function taking the NSError instance can allocate memory for it.

As Catfish_Man has written in his sample, memory is allocated for NSError only when there is an error. That allows you to detect an error and get details in one object. It sounds reasonable.
 
Last edited by a moderator:
+1 for the code :) It always helps when dealing with pointers and dynamically allocated memory.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.