Strange behaviour of command line arguments in iOS/Objective-C

I noticed a strange problem on iOS. Consider this code:
Code Block
#import <Foundation/Foundation.h>
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
int main(int argc, char * argv[]) {
NSArray* args = NSProcessInfo.processInfo.arguments;
for(int i = 0; i < args.count; ++i)
{
std::cout<<"Arg "<<i<<" "<<[args[i] UTF8String] <<std::endl;
}
NSArray<NSURL *> *urls =
[[NSFileManager defaultManager]
URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask];
NSString *filename = [[urls[0] path]
stringByAppendingString: @"/file.txt"];
std::ofstream f1([filename UTF8String], std::ios::trunc);
if(args.count > 3)
{
std::cout<<"More than 3 args"<<std::endl;
f1<<"More than 3 args"<<std::endl;
}
else
{
std::cout<<"Less or equal to 3 args"<<std::endl;
f1<<"Less or equal to 3 args"<<std::endl;
}
}

It checks the number of command line arguments. If it is larger than 3 prints a message to console and to a file. Else outputs a different message. I set the input arguments by editing Xcode scheme. Here is the console output when I pass more than 3 input args:
Code Block
Arg 0 /var/containers/Bundle/Application/6354AF7F-6817-423D-88FD-976813627552/CLIArgTest.app/CLIArgTest
Arg 1 hrhtrnd
Arg 2 ebyrebyes
Arg 3 fvtrvter
Arg 4 jvojeojgreo
More than 3 args

However, when I extract the output file from the on device Document folder of the iOS app, I get:
Code Block
Less or equal to 3 args
  • I don’t get this problem if I run the exact same code on MacOS.

  • I tried building both debug and release and it makes no difference.

  • I tried writing to file using ObjC and C++ API, no difference.

  • I tried using argc/argv directly instead of NSProcessInfo.processInfo.arguments, no difference.

  • I couldn’t find any references to this problem online. Although admittedly very few people do this type of command line based dev on iOS. The reason I need to do this is because I am trying to build a unit testing app around a library I wrote and I would like to control some test parameters using command line arguments.

I added at the end of original code snippet:
Code Block    
std::cout<<"args.count: "<<args.count<<std::endl;
    f1<<"args.count: "<<std::to_string(args.count)<<std::endl;
    for(int i = 0; i < args.count; ++i)
        f1<<"Arg "<<i<<" "<<[args[i] UTF8String]<<std::endl;

Now on console I get the correct count of arguments:
Code Block
Arg 0 /var/containers/Bundle/Application/1AB7C174-22A2-4331-9E3D-062044B98DDE/CLIArgTest.app/CLIArgTest
Arg 1 dqwdaw
Arg 2 ebyrebyes
Arg 3 fvtrvter
Arg 4 jvojeojgreo
More than 3 args
args.count: 5

But in the file I get:
Code Block
Less or equal to 3 args: 1
args.count: 1
Arg 0 /var/containers/Bundle/Application/1AB7C174-22A2-4331-9E3D-062044B98DDE/CLIArgTest.app/CLIArgTest

Why would the app see a different size of the NSArray when a write to file enters the picture?


My colleague had the idea of opening the output file in append mode instead and he observed that the app must have been launched twice. The first time, the app received the correct number of arguments. The second time, the app received none of the arguments. However, the console output of the second app launch seems to have been suppressed. Previously, the second app launch must have simply overwritten the output file and erased the output of the first app launch.

But now my question is: why is the app being automatically launched twice? And only on iOS, not on Mac?
Strange behaviour of command line arguments in iOS/Objective-C
 
 
Q