Friday, September 20, 2013

Starting an application/process from code in OS X

NSString *strArg = @"arg";  //specifying the variable arg
    
NSWorkspace *workspace = [NSWorkspace sharedWorkspace];
NSURL *url = [NSURL fileURLWithPath:[workspace fullPathForApplication:@"Full-Path-To-The-App-To-Start"]];  //e.g. /Applications/TextEdit.app

NSError *error = nil;
NSArray *arguments = [NSArray arrayWithObjects:@"-d", @"-b", strArg, nil];
[workspace launchApplicationAtURL:url options:0 configuration:[NSDictionary dictionaryWithObject:arguments forKey:NSWorkspaceLaunchConfigurationArguments] error :&error];

//Handle error


Wednesday, September 18, 2013

Combining 2 values into a single Byte

Doing & 0x0F and & 0xF0:

& is the bitwise AND operator. "& 0x0F" is sometimes done to replace the first 4 bits with 0s, or ignore the first(leftmost) 4 bits in a value.

0x0f = 00001111. So a bitwise & operation of 0x0f with any other bit pattern will retain only the rightmost 4 bits, clearing the left 4 bits.

If the input has a value of 01010001, after doing &0x0F, we'll get 00000001 - which is a pattern we get after clearing the left 4 bits.

Just as another example, this is a code I've used in a project:

Byte verflag = (Byte)(bIsAck & 0x0f) | ((version << 4) & 0xf0). Here I'm combining two values into a single Byte value to save space because it's being used in a packet header structure. bIsAck is a BOOL and version is a Byte whose value is very small. So both these values can be contained in a single Byte variable. 

The first nibble in the resultant variable will contain the value of version and the second nibble will contain the value of bIsAck. I can retrieve the values into separate variables at the receiving by doing a 4 bits >> while taking the value of version.

Friday, September 13, 2013

Undefined symbols for architecture ... Build Error

Sometimes we get the below error while building a project in XCode. It's not very troublesome, but sometimes we forget how to fix it:

Undefined symbols for architecture x86_64:

  "_OBJC_CLASS_$_", referenced from:
      _OBJC_CLASS_$_VariableOne in ClassOne.o
      _OBJC_CLASS_$_VariableTwo in ClassTwo.o
          ...
  "_OBJC_METACLASS_$_IpcObject", referenced from:
      _OBJC_METACLASS_$_VariableOne in ClassOne.o
      _OBJC_METACLASS_$_VAriableTwo in ClassTwo.o
      ...

This error shows usually because the compiler build doesn't recognise the mentioned object file( in the above error log. 

Fixing this could be as simple as adding the .m file in the "Compile Sources" list in the Project Settings > Build Phases page

Monday, September 9, 2013

Strange NSThread issue in Objective C

I was trying to start a new thread, with the below code, in an OS X command line tool:

.h
NSThread *srvThread;

.mm
srvThread = [[NSThread alloc] initWithTarget:self selector:@selector(serverThreadFunc:)     object:@"Dummy"];

[srvThread start];
        
Everything was just proper in the selector also, but the new thread never started. I tried different possibilities, verified things over and again ... but the thread didn't start. 

Finally, tired, I was trying to just see the running status of the thread, with the below code:


        if ([srvThread isCancelled]) {
            NSLog(@"New Thread is in Cancelled State");
        } else if ([srvThread isExecuting]) {
            NSLog(@"New Thread is in Executing State");
        } else if ([srvThread isFinished]) {
            NSLog(@"New Thread is in Finished State");

        }

And what a surprise, the thread started working at once. The result I got was :

2013-09-10 10:19:31.896 AvConnectCli[1389:303] New Thread is in Executing State
2013-09-10 10:19:31.896 AvConnectCli[1389:2003] Started Server thread

I'm still checking what was the reason behind it for not starting the thread all these times. Maybe there should've a need for something for the Main thread to continue(there was nothing more in the main thread. It was end of the function). Will update if I can find proper reason for it. 

Again, I commented the thread state checking code and added this:

srvThread = [[NSThread alloc] initWithTarget:self selector:@selector(serverThreadFunc:) object:@"Dummy"];
[srvThread start];
        
for(int i=0;i<1000;i++){
     NSLog(@"%d",i);
}

//        if ([srvThread isCancelled]) {
//            NSLog(@"New Thread is in Cancelled State");
//        } else if ([srvThread isExecuting]) {
//            NSLog(@"New Thread is in Executing State");
//        } else if ([srvThread isFinished]) {
//            NSLog(@"New Thread is in Finished State");

//        }


Now also it's working just fine. The reason was because the main thread was ending soon after it spawned the new thread. The program was ending there. This could not be an issue which will be faced by many, but for starters, who try to just try out multithreading in Objective C, this can cause some confusion.