Clang Error on "Potential null dereference." - cocoa

I keep getting Clang errors on the following type of code and I can't figure out why they're erroneous or how to resolve them to Clang's satisfaction:
+ (NSString *)checkForLength: (NSString *)theString error: (NSError **)error {
BOOL hasLength = ([theString length] > 0);
if (hasLength) return theString;
else {
*error = [NSError errorWithDomain:#"ErrorDomain" code:hasLength userInfo:nil];
return nil;
}
}
Leaving aside the utterly-contrived nature of the example (which Clang did object to so it's illustrative enough), Clang balks at the error assignment line with the following objection:
Potential null dereference. According to coding standards in 'Creating and Returning NSError Objects' the parameter 'error' may be null.
I like having a pristine Clang report. I've read the cited document and I can't see a way to do what's expected; I checked some open-source Cocoa libraries and this seems to be a common idiom. Any ideas?

The way to do what's expected is shown in listing 3-5 in that document. With your example code:
+ (NSString *)checkForLength: (NSString *)theString error: (NSError **)error {
BOOL hasLength = ([theString length] > 0);
if (hasLength) return theString;
else {
if (error != NULL) *error = [NSError errorWithDomain:#"ErrorDomain" code:hasLength userInfo:nil];
return nil;
}
}

The Cocoa convention is that the return value should indicate success or failure (in this case, you return nil for failure) and the error is filled in with additional information, but only when the caller requests it.
In other words
NSError *error = nil;
NSString *result = [self checkForLength: aString error: &error];
and
NSString *result = [self checkForLength: aString error: NULL];
are both valid ways to invoke the method. So the method body should always check for a NULL error param:
if (error != NULL)
*error = ...;

Related

Twilio iOS unrecognized selector sent to Class

I'm new to using Twilio and I'm hoping someone can help me debug my app.
I am making a call to get a capability token and it is returned just fine. I print it in the console to check then it appears when I make the call to initWithCapabilityToken that's where something is breaking and I cant figure it out.
Here is my code...
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:
^(NSURLResponse *response, NSData *data, NSError *error){
// Log Any Reply
if ([data length] >0 && error == nil) {
NSData *jsonData = data;
// Deserialize JSON into Dictionary
error = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingAllowFragments
error:&error ];
if (jsonObject != nil && error == nil) {
NSLog(#"Successfully deserialized JSON response...");
if ([jsonObject isKindOfClass:[NSDictionary class]]) {
NSDictionary *deserializedDictionary = (NSDictionary *)jsonObject;
NSLog(#"Deserialized JSON Dictionary = %#", deserializedDictionary);
NSString *token = [deserializedDictionary objectForKey:#"token"];
if (token == nil) {
NSLog(#"Error retrieving token");
} else {
NSLog(#"Token: %#", token);
// Setup TCDevice
_phone = [[TCDevice alloc] initWithCapabilityToken:token delegate:self];
}
}
} else if (error != nil){
NSLog(#"An error happened while de-serializing the JSON data.");
}
}else if ([data length] == 0 && error == nil){
NSLog(#"Nothing was downloaded.");
}else if (error != nil){
NSLog(#"Error happened = %#", error);
}
}];
Here is what I get right after my token is logged...
2015-01-29 16:32:14.637 AppName[4649:701822] +[NSString stringWithPJStr:]: unrecognized selector sent to class 0x3377da98
2015-01-29 16:32:14.639 AppName[4649:701822] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSString stringWithPJStr:]: unrecognized selector sent to class 0x3377da98'
*** First throw call stack:
(0x254da49f 0x32c90c8b 0x254df7d5 0x254dd7d7 0x2540f058 0x10ee7d 0x10e32b 0x10e2b7 0x105959 0x10568d 0x7b3ab 0x24fa228d 0x261d52b1 0x2614034d 0x26132b07 0x261d7c1b 0x487e29 0x4822c9 0x489567 0x48a891 0x33351e31 0x33351b84)
libc++abi.dylib: terminating with uncaught exception of type NSException
Thanks
After reading all of Twilios documentation I discovered I was missing one thing. I had to add -ObjC to Other Linker Flags and that solved my problem.
add this lines to the other linker flags:
-ObjC
-lTwilioClient
-lcrypto
-lssl
it worked for me only with a upper C add the end (-ObjC)
Somewhere you are calling a stringWithPJStr function(selector) that doesn't exist.

`PFFile getDataInBackgroundWithBlock` block not getting called Obj-C

I have the following code, to retrieve an image from Parse. This code block is in a recursive loop that gets called for a list of images in an array.
PFFile *remoteImageFile = object[#"Image"]
[remoteImageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
DDLogInfo(#"%s:%d %#", __PRETTY_FUNCTION__, __LINE__, [error debugDescription]);
// other logics
}];
The code fetches most of the images successfully, the sizes of the images being 2MB to 3MB. But randomly it fails for certain files and the block is not getting fired and my whole fetching operation freezes. Couldn't find the reason.
Any help please
I doubt that there is a bug in the Parse framework here. The most probable cause is that your remoteImageFile is nil which means that getDataInBackgroundWithBlock: is not even called.
Can you check by using the following code :
PFFile *remoteImageFile = object[#"Image"];
if (remoteImageFile == nil || ![remoteImageFile isKindOfClass:[PFFile class]]) {
NSLog(#"Error : remoteImageFile = %#", remoteImageFile);
} else {
[remoteImageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
DDLogInfo(#"%s:%d %#", __PRETTY_FUNCTION__, __LINE__, [error debugDescription]);
// other logics
}];
}

sqlite error parsing query

I'm receiving a strange error querying a database with sqlite:
SQLlite error: near "SE": syntax error
I don't really get why he doesn't like the query string I'm sending to it. Here's my code:
-(Wallet*)loadDataFromSQL{
sqlite3 *database;
NSLog(#"opening..");
if (sqlite3_open([[NSString stringWithFormat:#"mywallet.sqlite3"] UTF8String], &database) == SQLITE_OK) {
NSLog(#"opened..");
const char *query = [[NSString stringWithFormat:#"SELECT * FROM 'Transaction';"] UTF8String]; // "insert into \"Transaction\" values (\"2013-01-01\",\"tipo\",\"cat\",1)";
sqlite3_stmt *selectstmt;
NSLog(#"preparing stmnt..");
if(sqlite3_prepare_v2(database, query, SQLITE_OPEN_READWRITE, &selectstmt, nil) == SQLITE_OK) {
NSLog(#"Prepared..");
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
NSLog(#"row..");
NSString *data = [NSString stringWithUTF8String: (char*)sqlite3_column_text(selectstmt, 0)];
NSString *type = [NSString stringWithUTF8String: (char*)sqlite3_column_text(selectstmt, 1)];
NSString *category = [NSString stringWithUTF8String: (char*)sqlite3_column_text(selectstmt, 2)];
float amount = (float)sqlite3_column_double(selectstmt, 0);
Transaction *t = [[Transaction alloc]init:data transactionType:type transactionCategory:category transactionAmount:[NSString stringWithFormat:#"%f",amount]];
NSLog(#"%#",t);
}
}else{
NSLog([NSString stringWithFormat:#"SQLlite error: %s\n", sqlite3_errmsg(database)]);
}
}
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
return nil;
}
Nothing too fancy.. what's wrong with it?
Thanks!
The third parameter of sqlite3_prepare_v2 must be the length of the query string, or just -1.
sqlite3_prepare_v2(database, query, SQLITE_OPEN_READWRITE, &selectstmt, nil)
With SQLite complaining about "SE", I'd guess that the value of SQLITE_OPEN_READWRITE is 2. :-)

Getting an AppleScript property of an NSAppleEventDescriptor

I'm trying to use some Apple Events in my Cocoa project to get access to the Terminal application. I did not want to use embedded AppleScripts or any compiled scripts, so I started looking into the NSAppleEventDescriptor.
I have succeeded in creating a new window using the do script command, and I have succeeded to get the window from the return value. The only thing I want to do right now is get a property of that window.
I had now idea how to get such a property, so I started googling. Unfortunately, there aren't a lot of good examples how to use Apple Events, and I failed to find what I was looking for.
So I started digging deeper. And the first thing I did was looking for the code for the get command in the Terminal .sdef file. I failed to find it, so I did a grep on my /System/ directory and I found /System/Library/Frameworks/AppleScriptKit.framework/Versions/A/Resources/AppleScriptKit.sdef. I apparently found the core of the AppleScript syntax. That file did indeed have the getd four character code.
So now I know I have to use the getd event from the Core Suite. However, the argument to that get-command was an objectSpecifier. I have searched high and low for an example that uses kAEGetData. But I have failed to find any code from which I could learn anything.
So I am asking here: how do I build such an objectSpecifier descriptor?
This is what I've already got:
Code to create and get the tab descriptor
NSAppleEventDescriptor *createEvent;
NSAppleEventDescriptor *scriptParam;
AppleEvent aeReply;
OSErr err;
/* Make the do script event */
createEvent = [NSAppleEventDescriptor
appleEventWithEventClass:kAECoreSuite
eventID:kAEDoScript
targetDescriptor:_applicationDescriptor
returnID:kAutoGenerateReturnID
transactionID:kAnyTransactionID];
if(createEvent == nil) {
NSLog(#"%s Failed to create a do script event",
__PRETTY_FUNCTION__);
return nil;
}
/* Make script parameter */
scriptParam = [NSAppleEventDescriptor descriptorWithString:#"echo Hello World"];
if(scriptParam == nil) {
NSLog(#"%s Failed to create the script parameter",
__PRETTY_FUNCTION__);
return nil;
}
/* Set parameter */
[createEvent setParamDescriptor:scriptParam forKeyword:keyDirectObject];
/* Send event */
err = AESendMessage([createEvent aeDesc], &aeReply,
kAEWaitReply | kAENeverInteract, kAEDefaultTimeout);
if(err != noErr) {
NSLog(#"%s Failed to send the create command",
__PRETTY_FUNCTION__);
return nil;
}
/* Retrieve information */
{
/* SEE BELOW TO SEE HOW I GET THE WINDOW DESCRIPTOR */
}
Now I try and succeed in getting the window of that tab
// NSAppleEventDescriptor *ansr is set to the result of the code above
NSAppleEventDescriptor *mainObj;
NSAppleEventDescriptor *desiredClass;
NSAppleEventDescriptor *window;
mainObj = [ansr paramDescriptorForKeyword:keyDirectObject];
if([mainObj descriptorType] != typeObjectSpecifier) {
NSLog(#"%s Main object was not an object specifier",
__PRETTY_FUNCTION__);
return nil;
}
desiredClass = [mainObj paramDescriptorForKeyword:keyAEDesiredClass];
if([desiredClass typeCodeValue] != kAETerminalTab) {
NSLog(#"%s Main object's desired class was not a Terminal tab",
__PRETTY_FUNCTION__);
return nil;
}
window = [mainObj paramDescriptorForKeyword:keyAEContainer];
if(window == nil) {
NSLog(#"%s Couldn't get container of the tab",
__PRETTY_FUNCTION__);
return nil;
}
desiredClass = [window paramDescriptorForKeyword:keyAEDesiredClass];
if([desiredClass typeCodeValue] != cWindow) {
NSLog(#"%s The container of the tab was not a window",
__PRETTY_FUNCTION__);
return nil;
}
return window;
And now I fail in getting, let's say, the bounds property
// _windowDescriptor is the result of the code above
NSAppleEventDescriptor *getEvent;
NSAppleEventDescriptor *prop;
AppleEvent aeReply;
NSAppleEventDescriptor *reply;
FourCharCode propName;
OSErr err;
propName = keyAEBounds;
/* Create get event */
getEvent = [NSAppleEventDescriptor
appleEventWithEventClass:kAECoreSuite
eventID:kAEGetData
targetDescriptor:_windowDescriptor
returnID:kAutoGenerateReturnID
transactionID:kAnyTransactionID];
if(getEvent == nil) {
NSLog(#"%s Failed to create a get event",
__PRETTY_FUNCTION__);
return NSZeroRect;
}
/* Get property */
prop = [NSAppleEventDescriptor
descriptorWithDescriptorType:typeProperty
bytes:&propName length:sizeof(propName)];
if(prop == nil) {
NSLog(#"%s Failed to create the bounds property",
__PRETTY_FUNCTION__);
return;
}
/* Set parameter */
[getEvent setParamDescriptor:prop forKeyword:keyDirectObject];
/* Exectue */
err = AESendMessage([getEvent aeDesc], &aeReply,
kAEWaitReply | kAENeverInteract, kAEDefaultTimeout);
if(err != noErr) {
NSLog(#"%s Failed to send the get message",
__PRETTY_FUNCTION__);
return;
}
reply = [[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&aeReply];
[reply autorelease];
NSLog(#"Bounds: %#", reply);
As explained, the above code works, just until the last block.
Thank you in advance for the help.
Thanks to Rob Keniger I've succeeded in what I wanted.
Apparently I had to create a record descriptor, set my wanted properties and, then coerce it to a typeObjectSpecifier.
Also, I was wrong in setting the window descriptor as a the receiver of my Apple Event. You always have to address the application itself, and set the from (keyAEContainer) property of the direct object to the window you want.
Here is the working code, with a little bit of NSLog-statements:
- (NSRect)bounds {
// ! ! !
// _windowDescriptor is an instance variable which points to a valid
// window NSAppleEventDescriptor
// ! ! !
NSAppleEventDescriptor *getEvent;
NSAppleEventDescriptor *objSpec;
NSAppleEventDescriptor *propEnum, *propType, *propSeld;
AppleEvent aeReply;
NSAppleEventDescriptor *reply;
FourCharCode propName;
OSErr err;
propName = keyAEBounds;
/* Create get event */
getEvent = [NSAppleEventDescriptor
appleEventWithEventClass:kAECoreSuite
eventID:kAEGetData
targetDescriptor:[[FTMTerminalApp sharedApp] AEDescriptor]
returnID:kAutoGenerateReturnID
transactionID:kAnyTransactionID];
if(getEvent == nil) {
NSLog(#"%s Failed to create a get event",
__PRETTY_FUNCTION__);
return NSZeroRect;
}
/* Get property */
/* create object specifier main ojcect */
objSpec = [[[NSAppleEventDescriptor alloc] initRecordDescriptor]
autorelease];
if(objSpec == nil) {
NSLog(#"%s Failed to create the object specifier",
__PRETTY_FUNCTION__);
return NSZeroRect;
}
NSLog(#"%s Created object specifier %#",
__PRETTY_FUNCTION__, objSpec);
/* create property enum, we want a property */
propEnum = [NSAppleEventDescriptor
descriptorWithEnumCode:formPropertyID];
if(propEnum == nil) {
NSLog(#"%s Failed to create the property enum",
__PRETTY_FUNCTION__);
return NSZeroRect;
}
NSLog(#"%s Created property enum %#",
__PRETTY_FUNCTION__, propEnum);
[objSpec setDescriptor:propEnum forKeyword:keyAEKeyForm];
/* create prop type */
propType = [NSAppleEventDescriptor
descriptorWithTypeCode:typeProperty];
if(propType == nil) {
NSLog(#"%s Failed to create the property type",
__PRETTY_FUNCTION__);
return NSZeroRect;
}
NSLog(#"%s Created property type %#",
__PRETTY_FUNCTION__, propType);
[objSpec setDescriptor:propType forKeyword:keyAEDesiredClass];
/* create property key data */
propSeld = [NSAppleEventDescriptor
descriptorWithTypeCode:keyAEBounds];
if(propSeld == nil) {
NSLog(#"%s Failed to create the bounds property type",
__PRETTY_FUNCTION__);
return NSZeroRect;
}
NSLog(#"%s Created property key data %#",
__PRETTY_FUNCTION__, propSeld);
[objSpec setDescriptor:propSeld forKeyword:keyAEKeyData];
/* Set destination */
NSLog(#"%s Setting from key %#",
__PRETTY_FUNCTION__, _windowDescriptor);
[objSpec setDescriptor:_windowDescriptor forKeyword:keyAEContainer];
/* Send message */
objSpec = [objSpec coerceToDescriptorType:typeObjectSpecifier];
NSLog(#"Coerced: %#", objSpec);
[getEvent setParamDescriptor:objSpec forKeyword:keyDirectObject];
err = AESendMessage([getEvent aeDesc], &aeReply,
kAEWaitReply | kAENeverInteract, kAEDefaultTimeout);
if(err != noErr) {
NSLog(#"%s Failed to send the message (event = %#)",
__PRETTY_FUNCTION__, getEvent);
return NSZeroRect;
}
reply = [[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&aeReply];
NSLog(#"BOUNDS = %#", reply);
[reply autorelease];
return NSZeroRect;
}
I hope this will help someone.
Apple Events are complicated to use. Unless you really want to spend the time working through the convoluted and generally nasty API, I recommend that you save yourself a lot of time and heartache by using Mike Ash's excellent AEVTBuilder class.
It's a nice Cocoa wrapper for all the nasty Carbon Apple Event code.

What could cause NSMigrationManager to return a nil error?

I have this code:
NSError *error; // NSMigrationManager hates it if you don't provide an error pointer
BOOL result = [manager migrateStoreFromURL:sStoreURL
type:NSSQLiteStoreType
options:nil
withMappingModel:mappingModel
toDestinationURL:dStoreURL
destinationType:NSBinaryStoreType
destinationOptions:nil
error:&error];
To my surprise, it's sometimes returning NO and leaving/setting the error pointer to nil. What can cause this?
This is caused if you have a custom migration policy that returns NO without setting the error pointer. e.g.
- (BOOL)createDestinationInstancesForSourceInstance:(NSManagedObject *)sInstance entityMapping:(NSEntityMapping *)mapping manager:(SVMigrationManager *)manager error:(NSError **)error;
{
return NO;
}
Check the code carefully to find any situations where this could occur.

Resources