Archive for the ‘Cocoa Coding’ Category

Xcode 4.4 is Out

Wednesday, July 25th, 2012

xcode.jpg

Today along with OS X 10.8 and Safari 6, Apple released to the Mac App Store Xcode 4.4 and while I can't find any release notes for it, I'm guessing it's an uptick in the version of GCC and the LLVM compiler. With the coding I'm doing these days, it makes a big difference with 10.8 a reality, I need to get things up to date reasonably quickly. Glad to see that Apple is continually improving the tools as well as the end-user products.

Rockin’ the Social Coding on GitHub – ARC Support for XMLRPC

Thursday, June 28th, 2012

GitHub Source Hosting

This morning I decided to check out the Pull Requests on GitHub. Specifically, I've always wondered how they work, and what the interface is, and I've had a nice little example waiting for me in the XMLRPC library that I'm using for SyncKit. So now is as good a time as any.

The core of adding ARC (Automatic Reference Counting) support for a Cocoa project is that ARC support is really compiled into the code. ARC is basically the LLVM correctly identifying when retain, release and autorelease need to be called, and then putting that code into the compiled executable without it having to be in the source.

It's slick, clean, and makes the code a lot less prone to memory issues. But there are things you can't do in ARC code that you can do in retain/release code - like compare-and-swap atomic operations. This is bad for the really low-latency stuff, but when you get into iOS, the ARC stuff is really a much easier way to make sure your app - and not you, has good, clean memory management.

I picked up the following simple fix for ARC support from Gus of FlyingMeat fame, and his FMDB project on GitHub:

  #if ! __has_feature(objc_arc)
    return [NSMakeCollectable(temporaryUUIDString) autorelease];
  #else
    return (__bridge_transfer NSString*)temporaryUUIDString;
  #endif

Because the LLVM compiler knows what the illegal methods are, it's a simple matter of going through all the code and correcting it a line at a time. It took me about two hours to do, and then I had something that worked great for AppKit and UIKit. Sweet.

So this morning, I forked the repo on GitHub, then cloned it to my MacBook Pro, made the changes and cleaned up the whitespace a bit, and then checked it all in and pushed it up to GitHub. Now was the time for the Pull request.

Happily, it's very simple. GitHub knows the commits you have done since the fork, and it's simply a matter of sending those commits to the original project maintainer, and it's up to him to incorporate them or not. You can write a nice set of comments to go along with the pull request, and I did, but I'm not sure that's all that necessary for something this simple. But is was fun.

It's off, and now it's up to Eric to see if he wants to support this. I've got my forked repo now, so it's no big deal to me, but it'd be nice to be able to stay up to date and see the code get better because of my involvement.

Sweet!

UPDATE: It was accepted!

GitHub Pull Accepted

This is why I love public domain coding. I can work to make something better, and the author looks at it and says Sure, why not? This is a great thing we are doing - those of us that can code well… and we need to do more of it. Give more than you take. That's a great motto.

Developing Code in Your Own Style

Tuesday, June 19th, 2012

GeneralDev.jpg

I have been doing a fair bit of coding on a few projects this last week, and yesterday I spent a good bit of time documenting an Xcode project I've spent a couple of weeks on. This was all because I'd moved it to GitHub, and the standard there is to look for a README.md file at the root of the repo and render it in GitHub Flavored Markdown as an introduction or initial documentation on the work in the repo. Since I hadn't had it in GitHub before this, I didn't need to make the documentation. After all, there's only one other guy on the project, and he's not yet done any work with this library, so it wasn't important to do it previously, but it made sense to do it now.

After spending several hours on this documentation - complete with code samples, installation instructions for the server-side required components (PHP, PostgreSQL, Apache), and everything I could think of about the project, my partner in this venture looked at it, deemed it nice, but said "We have to work on de-personalizing the docs".

Immediately, I was taken aback. I worked very hard on the docs, and while they aren't perfect, I was surprised to see exactly how I felt about that comment from him. I wasn't upset - not really. I was just irked.

After 38 yrs of being a professional programmer, and all this is still not making me a dime, I think I was feeling that I deserved the opportunity to write docs the way that I feel they should be written. I'm writing code the way I think it should be written, so why not the docs as well? It's got a wealth of information in there, and while the comment wasn't a serious critique, it was something that I just didn't see coming.

More importantly, it got me to thinking: At what point in your life do you really get to do what you want to do? I suppose the answer to many is obvious: Never. Others will say just as assuredly: Always.

Clearly, neither is right. There are certain times you can do certain things and everything is fine. I'm sure he was thinking that the documentation needed for a 510k medical instrument was more formal than I was writing. Maybe so, and I understand where he was coming from, but it didn't really lesson the question any.

After all, I'm in the middle of my fourth month of forced unemployment, and I'm finding that there are a lot of people out there that are getting jobs after being laid off from the same company a lot faster than I am. I'm not jealous of them, I'm just very surprised at the difficult that I'm having. But I have faith - it'll all come together at the right time with the right company, and things will pick up again.

And my choice to take this time to write code for a project that by all accounts might never see the light of day, let alone generate anything more than lunch-money for me, is all on me. No one forced me into it. No one told me it'd make me rich. OK, I fibbed there, my partner in this said that, but I knew right off he was a little over the top on this.

But I'd still like to think that after 38 yrs of being a professional developer. I know how to document my own code. But maybe for this certain instance, for this certain licensing with the FDA, I don't.

Kinda bites to realize that.

WWDC Sells Out in 2 Hours

Wednesday, April 25th, 2012

It's shocking, but I'm not really surprised. As John Gruber put it:

Three years ago it sold out in a month. Two years ago it took a week. Last year it took 12 hours. So, if you want to go, I wouldn’t fuck around.

And indeed he was right. It sold out in two hours. Amazing.

I'm not sure what they'll be doing a year from now - it's likely to get even worse as time goes on. I'm guessing they are just going to have a shorter and shorter sell-out time and let people stay up all night to try and anticipate when they will go on sale.

After all, what else can they do? Raise the price? They'd have to make it 10x to impact the demand in any really significant way, and then the people you really want coming will probably stay away. You want the indie Mac developers that have made it - at least a little, and the soon-to-be indie Mac developers to intermingle and share ideas. This gets the ecosystem going and makes sure that you have great ideas passed around.

I think it's an interesting note that if you were in a long meeting, or might have been sleeping in, you'd have totally missed it. Amazing.

Working with XML-RPC, Mac OS X 10.7 and Xcode 4.3

Monday, March 26th, 2012

xcode.jpg

For the last week or so I've been working getting something going with an old friend that involves a centralized service, Macs and iOS devices all sharing data. Most of this data is numeric, but that's only a current design consideration, and what we basically needed was something that was similar to iCloud, but not file or key/value based. We needed to have a specific local database (SQLite3 for Mac and iOS), and have that be a local copy of some data in a more centralized database (PostgreSQL) on a centralized server (Apache, PHP).

So the question was How to do it?

My initial thoughts went back to The Broker codec that I worked with back at The Shop, but then I realized that it was a really bad idea to use that as there's no proven need for that level of complexity, and that a far easier solution - and one I've used on the Mac in the past, is to have a simple XML-RPC client and server, and allow the server to be in PHP, and the client in the native frameworks and libraries on Mac OS X (and iOS). So I went that direction instead, and I think I've got something that works really well - and stays away from the entire marshalling/demarshalling issues that The Broker had.

But the XML-RPC route was not without it's trials and tribulations. Neither was using the wonderful FMDB Open Source library for Mac OS X and SQLite3. I had several things to figure out, and while it's all working now, it's not simple to figure all these things out, so I wanted to write this all down in a nice, concise way.

Step 1 - The Changes in Xcode 4.3

One of the firs things I wanted to do was to start a new Xcode project from scratch. Most of the projects I have weren't started with Xcode 4, and I wanted to see what I was going to get if I started clean, and put everything into git right from the start.

The first thing was that the new Xcode projects allow for a simple unit test framework that's very similar to the JUnit framework. You have a nice pair of set-up and tear-down methods, and then anything you define in the implementation file (.m), that starts with test is going to get run in the alphabetical order in which it was defined.

This is very nice and clean, and it means that you really don't have to mess around with the interface (header) file for the tests. Sure, you have to put in the ivars that you might need, but there than that, it's pretty bare. It's all in the implementation file.

There are also a set of methods for assertions like true and not nil, and all kinds of tests that you can sprinkle in the test code to make sure it's running the way you think it should. Very simple to use.

Running the tests is equally easy as it's just a simple, single key-stroke in Xcode to build the project, and the tests, and run the tests. I was very impressed as it made it very easy to run the tests until I got everything working just the way I wanted it.

Step 2 - FMDB as a Framework (well… almost)

I knew I wanted to use Flying Meat's FMDB library on GitHub for access to the SQLite3 database. I've read a lot about this library, and it looks to be set up exactly as I might have done it - but I didn't have to do it. Excellent.

But it wasn't without a little bit of grief. First off, it's not a Framework. Or a Library. It's a group of files. More than that, it's a group of files with a test app that's put together in a way that makes it a little unclear how to actually use it. I had to do a little googling to see that what you needed to do was to extract the files you needed from the project, place them into your project, and then start using them. In short, it's a library that's really a bunch of files.

This isn't bad, but a few sentences in the README would have made it very clear what I needed to do, and based on the things I've seen in Xcode 4.3 - converting it to Xcode 4.3 and using the unit test framework would make this all unnecessary. It could be a library, and it could have unit tests, and it would be the same code, it just would be a lot easier to use. But so it goes.

I added the files to my project, placed them in a 'group' (a folder in Xcode 4, but not on the disk itself), and then I was ready to go. Not horrible, but again, a few sentences, or a migration to Xcode 4 and this would all have been unnecessary.

Step 3 - XML-RPC Service in PHP

I had some code from a while back when I used a different XML-RPC implementation than what now is standard in PHP 5. So I was a little careful about how much to expect to be the same, and how much was implementation-dependent. Turns out, the built-in XML-RPC in PHP 5 is far nicer than the previous version I was using, and far faster as well. Win-win.

I have had no problems writing simple XML-RPC code in PHP 5, and it's nicely compact as well:

  <?php
  /**
   * This is the simple 'ping' service that let's the client know that we
   * are here and answering requests.
   */
  function doPing($method, $args) {
    return "PONG";
  }
 
  /**
   * At this point, we need to set up the XML-RPC server, bind the method
   * calls to the individual functions in this file, and then let the
   * user's call get processed and return the results. It's all pretty
   * simple, and handles all the ugly parts of the marshalling/
   * de-marshalling and method invocation.
   */
  // first off, make an XML-RPC server
  $server = xmlrpc_server_create() or die("Can't create rpc server!");
  // next, let's register the PHP functions as methods
  xmlrpc_server_register_method($server, 'ping', 'doPing') or
      die("Can't register the 'ping' method!");
 
  // now let's get the request and options...
  $request = $GLOBALS['HTTP_RAW_POST_DATA'];
  $options = array('output_type' => 'xml', 'version' => 'xmlrpc');
  // ...and make the call, returning the data to the client.
  print xmlrpc_server_call_method($server, $request, NULL, $options) or
      die("Can't call the method!");
 
  // finally, we can shut down the XML-RPC server.
  xmlrpc_server_destroy($server);
  ?>

This is a simple ping service that was the first thing I built to make sure that I could communicate with the PHP service and the Obj-C client. It's not bad at all in PHP, and since it's implemented in C, it's as fast as we're going to get.

So far, looking very good

Step 4 - XML-RPC Client in Objective-C

The client side was a little more code, but logically, it was very simple as well. I wanted to encapsulate the XML-RPC call into a simple method that would take Foundation objects and return Foundation objects so that I wouldn't have to worry about data type conversions, or any marshaling or demarshalling issues. What I came up with was a general 'call' method:

  - (NSObject*) call:(NSURL*)aURL method:(NSString*)aMethod
     with:(NSDictionary*)aParams orderedBy:(NSArray*)aKeyOrder
  {
    BOOL      error = NO;
    NSObject* retval = nil;
 
    // first, make sure that we have something to do
    if (!error) {
      if (aURL == nil) {
        error = YES;
        NSLog(@"[SKPipe(Protected) -call:method:with:orderedBy:] - the
               provided URL is nil and that means that there's nothing
               I can do!");
      }
    }
    if (!error) {
      if (aMethod == nil) {
        error = YES;
        NSLog(@"[SKPipe(Protected) -call:method:with:orderedBy:] - the
               provided method name is nil and that means that there's
               nothing I can do!");
      }
    }
 
    // make the XML-RPC method invocation as it's the basis of the call
    WSMethodInvocationRef    rpcCall;
    if (!error) {
      rpcCall = WSMethodInvocationCreate((__bridge CFURLRef)aURL,
                  (__bridge CFStringRef)aMethod, kWSXMLRPCProtocol);
      if (rpcCall == NULL) {
        error = YES;
        NSLog(@"[SKPipe(Protected) -call:method:with:orderedBy:] - the
               XML-RPC method invocation to '%@' with method '%@' could
               not be created and this is a real problem. Please check
               on it.", aURL, aMethod);
      } else {
        // set the parameters for the invocation - if we have any
        if (aParams != nil) {
          // see if the user has given us the key order to use
          if (aKeyOrder != nil) {
            WSMethodInvocationSetParameters(rpcCall,
                               (__bridge CFDictionaryRef)aParams,
                               (__bridge CFArrayRef)aKeyOrder);
          } else {
            WSMethodInvocationSetParameters(rpcCall,
                               (__bridge CFDictionaryRef)aParams, NULL);
          }
        }
      }
    }
 
    // do the actual XML-RPC call and get the results
    if (!error) {
      NSDictionary* pkg = (__bridge NSDictionary *)
                                 (WSMethodInvocationInvoke(rpcCall));
      if (pkg == nil) {
        error = YES;
        NSLog(@"[SKPipe(Protected) -call:method:with:orderedBy:] - the
               XML-RPC call returned nothing at all and that's a serious
               problem. Check on it.");
      } else if (WSMethodResultIsFault((__bridge CFDictionaryRef)pkg)) {
        error = YES;
        NSLog(@"[SKPipe(Protected) -call:method:with:orderedBy:] - the
               XML-RPC invocation of '%@' to '%@' returned a fault: %@",
               aMethod, aURL,
               [pkg objectForKey:(__bridge NSString *)kWSFaultString]);
      } else {
        // looks OK... get the results
        retval = [pkg objectForKey:(__bridge NSString *)
                                         kWSMethodInvocationResult];
      }
    }
 
    return (error ? nil : retval);
  }

The code is pretty simple - we first check to see if we have the necessary arguments to the method, and then we construct the method invocation. If there are parameters to pass to the call, then we add them, and if there is an array defining the order of the arguments in the dictionary, then we supply that as well.

We then first off the method invocation and get the return value. Pretty clean, but you have to know all the little tricks to get it to work. Thankfully, once we have this one method, we don't have to mess with XMl-RPC any more and can just stay in Objective-C and Foundation objects.

Calling the ping method isn't too bad… in fact, one of my tests does exactly that:

  - (void) test_1_Ping
  {
    if (![_pipe ping]) {
      STFail(@"The server ping failed!");
    }
  }

where:

  - (BOOL) ping:(NSURL*)aURL
  {
    BOOL      error = NO;
 
    NSObject* ans = [self call:aURL method:@"ping"];
    if (![ans isEqual:@"PONG"]) {
      error = YES;
      NSLog(@"[SKPipe(Protected) -pingServiceAt:] - the XML-RPC response
             was not good: %@", ans);
    }
 
    return !error;
  }

It's really pretty simple to use for strings, integers, arrays, dictionaries, and most data types and values. But there are two things that XML-RPC doesn't do really well, and I needed them both: NULL and Date/Time values.

Step 5 - Dealing with NULLs

XML-RPC just can't send a NULL. No way to tag it. I found a reasonable solution in the idea of sending a special value and then interpreting that special value as a NULL in the different parts of the code. For instance, if we sent a string: "__NULL__", then we could test for the data being a string, and it's value being '__NULL__'. It's possible that a call would have that as an argument, but not very likely.

If we decode this as the true NULL, then we're OK. Not easy given all the places that I'd like to have an argument or return value be NULL, but it's possible.

Step 6 - Dealing with Dates

NSDate values can be passed through - but they are passed through as string values where the NSDate is expanded out to it's human-readable value. This is OK, but it means that we need to have quite a bit of standardization on the format across different machines and platforms, and it means that we have to take the time to decode it and encode it on every call. Non-ideal.

Far nicer would be to send milliseconds since epoch as the date and then reconstruct the dates on the other side. This is easily done in Obj-C using the NSDate class:

  // build up the parameters to pass into the call - the local 'as of'
  NSMutableDictionary*	params = [NSMutableDictionary
                                     dictionaryWithCapacity:3];
  [params setObject:[NSNumber numberWithInt:aPID] forKey:@"pid"];
  [params setObject:[NSNumber numberWithDouble:
                        [aDate timeIntervalSince1970]]
             forKey:@"asof"];

I essentially turn it into a simple 'number' and then pass it through without any problems. On the other end, we have to worry about how to interpret this data properly. After all, it's not a date, it's a number of milliseconds since epoch, and that means that in PHP and PostgreSQL we need to account for this. What I found was that it was fairly simple to do something like:

  function removeData($method, $args) {
    // first, get the SQL that we need based on the method name invoked
    if ('removeIt' == $method) {
      $sql = "delete from meas where pid=" . (int)$args[0]
             . " and mid=" . (int)$args[1]
             . " and extract(epoch from taken)=" . (double)$args[2];
    }
    // now we need to open up the database, make the call, get the response
    $conn = pg_connect('host=localhost port=5432 dbname=primary');
    if (!$conn) {
      $retval = "no db";
    } else {
      $result = pg_exec($conn, $sql);
      if (!$result) {
        $retval = "no result for: " . $sql;
      } else {
        $result = pg_exec($conn, $sql);
        if (!$result) {
          $retval = "BAD";
        } else {
          $retval = "OK";
          // make sure to free up the result
          pg_free_result($result);
        }
        // make sure to close up the database connection
        pg_close($conn);
      }
      // make sure to close up the database connection
      pg_close($conn);
    }
    return $retval;
  }

Finishing Up

This has a lot of partial code, but it's all in the git repos for the project, and if you really need it, let me know. However, I think this is a great start for what you need, and a little experimentation should get you where you need to be. It's not perfect, but it's pretty close.

Relocating FileMerge with Xcode 4.3

Tuesday, February 28th, 2012

FileMerge.jpg

Today I was thinking about FileMerge because I was talking to someone about diffing files, and FileMerge is the best tool I've seen for that. But I remembered that with Xcode 4.3, the entire /Developer directory was removed. So where did it go? Seems I had to go on a hunt.

The obvious places were out - /Applications, and that's about it these days with the App Store. So I got serious:

  $ find /Applications -name FileMerge.app
  /Applications/Xcode.app/Contents/Applications/FileMerge.app
  $

What? they put an entire Applications directory under the Xcode.app bundle? Why do that? Well… at least I can get at it and run it. It'd be nice if LaunchBar was able to see inside the app bundles, but I can force that on a custom scan. The next question was the command-line opendiff command.

Turns out, there's a command to "refocus" the location of the Developer Tools:

  $ sudo /usr/bin/xcode-select -switch /Applications/Xcode.app/Contents/Developer

After this, the opendiff command works exactly as you'd expect. Good enough. They were lost (for a bit), but now they are found.

Xcode 4.3 is Out!

Friday, February 17th, 2012

xcode.jpg

This morning I found out that Xcode 4.3 was released, and this time, it was a regular app on the Mac App Store! No more "installer app" that you download and then install from - this places all the files and directories right where you need them. I was a little surprised to see everything fall right into place, but the apps weren't in /Developer any longer. Maybe this is part of the plan to clean things up, but it's OK with me. I've moved all the docs I had out of that directory with my new laptop, so it's simple for me to use the new Xcode location.

Plus, it's just getting nicer and nicer. The tools and the OS for this Mac are the most amazing things I can imagine. Had I had tools like this in grad school, I'd have made my simulator run on distributed Macs and the graphics would be so nice, it'd make your eyes tear up.

Not to mention the thesis would not have been vtroff and tape for figures.

Everything gets better, and this update is no exception. I'm really glad they are pushing forward.

Finally Found Colloquy Developers on FreeNode

Thursday, October 20th, 2011

Colloquy.jpg

Today I finally found the Colloquy developers on FreeNode (IRC) because I wanted to start working on getting the latest Growl 1.3 working with Colloquy. I've spent a little of the last several days looking at the other Mac OS X IRC clients, and while there are a few that look OK, there's nothing that's as well-targeted for my needs as Colloquy. I looked at Textual IRC Client, and while it was reasonably minimal, it didn't have the configurability in the themes to make it really what I wanted. Basically, I want a small but readable IRC window that I can have up all the time to monitor all the development group chats that I monitor as part of what I consider to be "important to my life in the trenches". So if I can't change the font, or vertical spacing, it's possible that the client isn't going to be something I'm really interested in.

Thankfully, Textual IRC Client is available as a trial download, so I was able to try it without having to buy it on the Mac App Store. The same goes for the other one I seriously looked at - Linkinus. I have to say that this was a little closer to my liking, but again, there's no way for me to make a theme for it, and if that were the case, I'd have bought it.

It's got all I need - and to be fair, Textual IRC Client had most of what I needed, but in both, it's the visual representation that fell short. Neither seemed to have the ability to configure the theme to the level I wanted to get a view that would fit into what I had with Colloquy.

Growl 1.3

After all, the only real problem with Colloquy is the Growl 1.3 integration. Also, it seems that the updates for Colloquy have been few and far between, and with Lion, there are a lot of new features that probably need to be addressed. But on the whole, it's not a lot of changes.

So I set out to find the developers of Colloquy and see if I could get the code and work in the Growl 1.3 support. What I found was that Colloquy (#colloquy) and Growl (#growl) are on FreeNode, and that one of the Colloquy developers has already integrated the Growl 1.3 beta Framework, and he's just waiting for the Framework to be released. Wow. Sweet deal! This really help, as all I have to do is watch the chats for the release of the Growl 1.3 Framework and then the Colloquy guys will drop a new version, and I'll have everything I need.

Great news. Can't wait for the new releases.

Joined the Apple Mac Developer Program

Friday, March 18th, 2011

xcode.jpg

This morning I decided that $99/yr is only $8.25/month, and I pay more than that for my NNTP feed, so I decided that getting Xcode 4 was best achieved through joining the program as opposed to paying $4.99 at the Mac App Store. Plus, I get a lot more stuff in the Mac Developer Program - like access to radar bugs, pre-release software (if I want it), and I think it's even a decent discount on buying machines.

So I plopped down the PayPal card, and away we go! I'll be able to get Xcode 4, and while I may not love the single-editor pane interface, I'll see if I can't get used to it as it seems to be a big win for a lot of things.

Just kicked it up a notch... Nice.

Xcode 3.2.5 is Out on Software Updates

Thursday, December 16th, 2010

I probably missed this by a week, but today I noticed that Apple has updated Xcode to 3.2.5 with the final release of iOS 4.2 development tools. I'm not doing any iOS development (yet), but it's part of the update, and that's a good thing to have. I'm still very anxious about the release of Xcode 4 with the new features like better built-in SCM and history, and the toolset... it's going to be very nice.