Monday, January 9, 2012

Using NSRunLoop and NSURLConnection


For my book Core Objective-C in 24 Hours I provided example code that demonstrates the use of NSURLConnection objects for downloading URL resources.  Now I believe that it’s a good time to review the NSRunLoop API and how it is used to manage input sources.
As noted in the Foundation Framework Reference, an NSRunLoop object process input for sources such as mouse and keyboard events from the window system, NSPort objects, and NSConnection objects.  Now NSURLConnection objects are commonly used to perform asynchronous loading of data via its delegate methods.  By default, for the connection to work correctly, the calling thread’s run loop must be operating in the default run loop mode.  So, how do you use an NSURLConnection instance and an NSRunLoop object to asynchronously download URL resources?
A run loop can be thought of as an event-processing loop running on a single thread, with input sources (and code [i.e. callback methods] to be executed if the input is received) registered on the loop.  Hence if an NSURLConnection object is registered on a run loop, input from this object (i.e. data loaded from the connection) will cause the corresponding (NSURLConnection delegate) callback methods to be executed.  Therefore, we can use these APIs to asynchronously download a URL resource with the following code fragment:
  // Setup and start connection to resource (urlString)
  NSURL *url = [NSURL URLWithString:urlString];
  NSMutableData *resourceData = [[NSMutableData alloc] init];
  NSURLRequest *request = [[NSURLRequest alloc]
                initWithURL:url
                cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
                timeoutInterval:10];
  NSURLConnection *urlConnection = [[NSURLConnection alloc]
                   initWithRequest:request
                   delegate:self];

  // Attach connection to run loop to receive callbacks for async download
  NSRunLoop *loop = [NSRunLoop currentRunLoop];
  [loop run];
Note that this code may loop forever, even if the NSURLConnection input source is removed.  If you want to guarantee that you exit the run loop after you have finished downloading the resource you can update the code with a conditional statement as follows (the boolean value isLoaded, set to true by the NSURLConnectionDelegate callback method when the URL has finished loading) :
  // Attach connection to run loop to receive callbacks for async download
  NSRunLoop *loop = [NSRunLoop currentRunLoop];
  while ((!isLoaded) &&
         ([loop runMode:NSDefaultRunLoopMode beforeDate:[NSDate
           distantFuture]]))
  {
  }
The same approach can be used for other NSRunLoop input sources.  In summary the steps to connecting an input source to a run loop are:
1.     Create the input source.
2.     Connect the callback methods to the input source.
3.     Start the input source.
4.     Connect the input source to the run loop. 
References:

Friday, January 6, 2012

Compiling and Running Objective-C Code on Windows

My book, Core Objective-C in 24 Hours, includes numerous source code examples that are free to use.  I developed the software using Xcode 4 on my Mac Pro, but thought that it would be a good idea to provide instructions on compiling and running this code (and Objective-C code in general) on Windows machines.  Here are the steps:
  1. Download and install GNUstep for Windows.  The GNUstep MSYS System and GNUstep Core packages are required to run GNUstep and use the core libraries.  An installer is provided for each of these packages; simply launch each installer and follow the step-by-step instructions. GNUstep is a free (GNU LGPL), open-source version of the Cocoa framework.  It includes an implementation of the AppKit and Foundation libraries as well as development tools used with Cocoa, such as Gorm and ProjectCenter (Xcode).  More information on GNUstep can be found here.
  2. Start the GNUstep shell from the Windows start menu.  The shell prompt will appear as follows:

    <username>@hostname ~
    $

  3. Map the home directory for the GNUstep environment to the corresponding location on the Windows file system.  Depending on the installation location you chose, this directory may map to something like C:\GNUstep\home\<username> or C:\GNUstep\msys\1.0\home\<username>.
  4. Create your Objective-C program source code under the GNUstep home directory using your editor of choice.

  5. Compile your Objective-C code using the gcc compiler.  In the following example, the code consists of 3 files:  main.m, hello.h, hello.m, and the program is named hello:

    <username>@hostname ~
    $ gcc `gnustep-config –-objc-flags` -o hello main.m hello.m –L /GNUstep/System/Library/Libraries –lobjc –lgnustep-base


    The `gnustep-config --objc-flags` selection instructs gcc to run the gnustep-config script to configure the GNUstep environment, printing out all the flags required to compile an Objective-C file (the --objc-flags option).  The –L /GNUstep/System/Library/Libraries option adds this directory to the list of directories searched when using the –l option.  The –lobjc and –lgnustep-base options link the objc and gnustep-base libraries (both located in the /GNUstep/System/Library/Libraries directory) to create the executable program.
     
  6. After the program has been compiled with no errors, run it!

    <username>@hostname ~
    $ ./hello.exe

    That’s all there is to it, you can now compile and run Objective-C programs on Windows!