Generated iOS Code Throws NSInvalidArgumentException

When using generated iOS code for consuming a Hosted API Service, the following error is thrown:









*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]'

*** First throw call stack:

(

	0   CoreFoundation                      0x0000000110805c65 __exceptionPreprocess + 165

	1   libobjc.A.dylib                     0x0000000110085bb7 objc_exception_throw + 45

	2   CoreFoundation                      0x00000001106ca478 -[__NSPlaceholderArray initWithObjects:count:] + 360

	3   CoreFoundation                      0x0000000110729384 +[NSArray arrayWithObjects:count:] + 52

	4   Digitz                              0x000000010d24f2c8 -[CustomService invoke:serviceVersion:method:args:responder:] + 225

	5   Digitz                              0x000000010d24f3d6 -[CustomService invoke:serviceVersion:method:args:response:error:] + 95

I can confirm that none of the parameters that I supply are nil.

Hi!

Do you use default example of hosted service or your own?
Regards,
Kate.

I dropped the MyCustomService.m and MyCustomService.h files into my app, the default example wasn’t useful as there is no easy way to get good test data in it.

UPDATE: I fixed the above issue, it was an order of operations error. However, I now get the following (from the generated code):

FAULT = '14002' [Service method not found] <Service method not found> 

I found the error. The generated code adds “Async” to the service name string in the async versions of the method calls, which is not correct. Below, I’ve included a snippet from Android (which is correct) and a snippet from iOS to illustrate the difference.

Android

public static HashMap<String, String> upsertUser(String service, String authToken, String authSecret, String userId)
{
    Object[] args = new Object[]{service, authToken, authSecret, userId};
    return Backendless.CustomService.invoke( SERVICE_NAME, SERVICE_VERSION_NAME, "upsertUser", args, HashMap.class );
}

public static void upsertUserAsync(String service, String authToken, String authSecret, String userId, AsyncCallback<HashMap<String, String>> callback)
{
    Object[] args = new Object[]{service, authToken, authSecret, userId};
    Backendless.CustomService.invoke( SERVICE_NAME, SERVICE_VERSION_NAME, "upsertUser", args, HashMap.class, callback);
}

iOS









-(NSArray *)upsertUser:(NSString *)service authToken:(NSString *)authToken authSecret:(NSString *)authSecret userId:(NSString *)userId error:(Fault **)fault {

    return [backendless.customService invoke:SERVICE_NAME serviceVersion:SERVICE_VERSION_NAME method:@"upsertUser" args:@[service,authToken,authSecret,userId] fault:fault];

}




-(void)upsertUser:(NSString *)service authToken:(NSString *)authToken authSecret:(NSString *)authSecret userId:(NSString *)userId response:(void(^)(NSArray *))responseBlock error:(void(^)(Fault *))errorBlock {

    [backendless.customService invoke:SERVICE_NAME serviceVersion:SERVICE_VERSION_NAME method:@"upsertUserAsync" args:@[service,authToken,authSecret,userId] response:responseBlock error:errorBlock];

}

Notice that the string representing the service name doesn’t change in the Android code. You should update the code generation so others don’t face this issue in the future.

In addition, the iOS generated code provided the wrong return type, which caused further crashes after I changed the service name. It picked NSArray as the return type, but the service instead returns a JSON object (so in this case, an NSDictionary). After changing both the service name and the return type, I have the service working now.

Hi Tim,

Can you give me your project (without “lib” folder) for investigating this problem?
My email: slavav@themidnightcoders.com

Slava