<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cocoa Is My Girlfriend &#187; Threading</title>
	<atom:link href="http://www.cimgf.com/category/threading/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cimgf.com</link>
	<description>Taglines are for Windows programmers</description>
	<lastBuildDate>Wed, 11 Jan 2012 15:00:37 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Importing and displaying large data sets in Core Data</title>
		<link>http://www.cimgf.com/2011/08/22/importing-and-displaying-large-data-sets-in-core-data/</link>
		<comments>http://www.cimgf.com/2011/08/22/importing-and-displaying-large-data-sets-in-core-data/#comments</comments>
		<pubDate>Mon, 22 Aug 2011 19:48:18 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Core Data]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[NSOperation]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=1525</guid>
		<description><![CDATA[Note: This is a re-print from the Mac Developer Network. I tend to frequent the StackOverflow website and watch for questions about Core Data. Generally if it is a question I can answer I will and if it is a question I can&#8217;t answer then I really dig in for a fun session of exploration [...]]]></description>
			<content:encoded><![CDATA[<p><em>Note: This is a re-print from the Mac Developer Network.</em></p>

<p>I tend to frequent the StackOverflow website and watch for questions about Core Data. Generally if it is a question I can answer I will and if it is a question I can&#8217;t answer then I really dig in for a fun session of exploration and attempt to find the answer.
<span id="more-1525"></span>
One question that I have been seeing with a tremendous amount of regularity is importing and displaying data on CocoaTouch devices.  Generally the question comes from one of a few problems:</p>

<ul>
<li>Trying to import a large amount of data causes the UI to hang.</li>
<li>Trying to save a large block of data causes the UI to hang.</li>
<li>Saving on exit causes the OS to kill the app.</li>
<li>Importing on launch causes the OS to kill the app.</li>
</ul>

<p>All of these &#8220;problems&#8221; are symptoms of the same two issues.</p>

<h2>Issues with large imports</h2>

<p>Importing a large amount of data, either from disk or from a network takes time and memory. If this is done on the main/UI thread then it becomes obvious to the user because the user interface is slow or unresponsive.  This leads to a poor experience for the user.</p>

<p>On the other side of this, once you get the data imported into Core Data then you need to save it.  If you are using a SQLite database then it can take a considerable amount of time.  If you are using a binary store then it will take even longer.  Again a poor user experience.</p>

<p>The answer to this problem involves multi-threading and breaking the job down into smaller pieces.</p>

<h2>Multi-threading</h2>

<p>There is a persistent rumor that you cannot use Core Data in a multi-threaded environment.  This is patently false.  Core Data works very well in a multi-threaded environment but you need to play by the rules:</p>

<ul>
<li>One <code>NSManagedObjectContext</code> per thread.</li>
<li><code>NSManagedObject</code> instances cannot pass between threads.</li>
</ul>

<p>As long as we follow those two rules, we can use Core Data in a multi-threaded environment.</p>

<h2>Breaking It Apart</h2>

<p>The biggest issue with imports is that they are generally huge.  That is going to kill performance even if it is done on a background thread.  This is especially apparent on Cocoa Touch right now because of the single core devices that it runs on.  Therefore, the first thing we <strong>must</strong> do is break that import apart.</p>

<p>I recommend splitting the incoming data (XML/JSON/whatever) into multiple files that you save on disk.  Number these files sequentially.  When the data is fully transferred from the network then start processing them.  In addition, keep track of which file you are currently working on.  When that file is complete and saved, move on to the next file and update the marker.  You can store the marker either in the <code>NSUserDefaults</code> or inside of the metadata of the <code>NSPersistentStore</code> itself.  In either case the idea is that if the user quits in the middle of the import you do not need to start over at zero.  You pick up right where you left off.</p>

<h2>Code Example</h2>

<p>In the attached sample project I have created a very trivial example of an import occurring on a background thread.  If you were actually pulling in data from the net as I described above, you would actually have numerous <code>NSOperation</code> objects that are queued up to run.  However in this example we have a single <code>NSOperation</code> that sleeps periodically.</p>

<p>The heart of this example is the periodic saves.  We want to save frequently enough that each save is very quick.  In addition, when the save occurs, we want to update the main <code>NSManagedObjectContext</code> so that it can refresh which will in turn update the <code>NSFetchedResultsController</code> which will in turn update the UI.  Crazy enough? Let&#8217;s dive in.</p>

<h3>RootViewController <code>-startImport:</code></h3>

<p>If you are familiar with Core Data on Cocoa Touch then most of this class will be very familiar.  Other than code clean up it is straight from the current Xcode template.  Having said that, there are a couple of differences.</p>

<p>The <code>-startImport:</code> method is fired from tapping the start button in the <code>NSNavigationItem</code> shown at the top of the screen.  This method will create the <code>NSOperationQueue</code> if it has not already been created and then it will create our <code>NSOperation</code> which will do the simulated work in the background.</p>

<pre><code>- (void)startImport:(id)sender
{
  [[[self navigationItem] rightBarButtonItem] setEnabled:NO];
  [[[self navigationItem] leftBarButtonItem] setEnabled:NO];

  if (![self operationQueue]) {
    operationQueue = [[NSOperationQueue alloc] init];
  }

  ZSImportOperation *op = [[ZSImportOperation alloc] init];
  [op setPersistentStoreCoordinator:[[self managedObjectContext] persistentStoreCoordinator]];
  [op setRunSpeed:0.25];
  [op setEntriesToCreate:1000];
  [op setSaveFrequency:10];

  [operationQueue addOperation:op];
  [op release], op = nil;
}
</code></pre>

<p>Note that we have several parameters that we are setting on the <code>ZSImportOperation</code> instance.  This dependency injection allows us to pass along the <code>NSPersistentStoreCoordinator</code> to the operation so that it can construct its own <code>NSManagedObjectContext</code> once it starts.  We cannot create the <code>NSManagedObjectContext</code> ourselves and pass it along because that will break the thread barrier and the results are undetermined (<em>i.e.</em> very bad).</p>

<p>We also tell it how many objects to create, how long to pause between each creation and how often to save (<em>i.e.</em> switch files).  Once everything is configured we pass it along to the <code>NSOperationQueue</code> and it starts.</p>

<h3>RootViewController <code>-contextChanged:</code></h3>

<p>This is where the magic happens as they say.  This method is called whenever any <code>NSManagedObjectContext</code> in the entire application saves.  We configured this in the <code>-viewDidLoad</code> method by calling:</p>

<pre><code>[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:nil];
</code></pre>

<p>When this method is fired we know that the data has changed somehow, somewhere.  So we need to narrow it down and confirm it is a data change we care about.</p>

<pre><code>- (void)contextChanged:(NSNotification*)notification
{
  if ([notification object] == [self managedObjectContext]) return;

  if (![NSThread isMainThread]) {
    [self performSelectorOnMainThread:@selector(contextChanged:) withObject:notification waitUntilDone:YES];
    return;
  }

  [[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
}
</code></pre>

<p>Fortunately we are not in a document based application so we really just need to check that the object pointer in the notification is not pointing to our <code>NSManagedObjectContext</code>.  If it is, we bail.</p>

<p>We also need to make sure that all work done is on the main thread.  Now I could just perform the last line of code in the <code>-performSelectorOnMainThread:withObject:waitUntilDone:</code> method and in this case I probably should.  However this is another option in case the code you need to perform on the main thread is complex and you don&#8217;t want to write 12 <code>-performSelectorOnMainThread:withObject:waitUntilDone:</code> calls or write yet another method to be called.  In this example, if we are not on the main thread we recursively call ourselves from the main thread and wait.  This will guarantee that what happens next will always be on the main thread.</p>

<p>The final line is what triggers everything.  This line of code is telling the main <code>NSManagedObjectContext</code> that the underlying data has changed and that it needs to update itself.  This will in turn cause the <code>NSFetchedResultsController</code> to get woken up which finally updates the UI.</p>

<h3>ZSImportOperation <code>-main</code></h3>

<p>This <code>NSOperation</code> subclass is the most trivial example I could come up with.</p>

<pre><code>- (void)main
{
  ZAssert([self persistentStoreCoordinator], @"PSC is nil");
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSRunLoopCommonModes];

  NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
  [moc setPersistentStoreCoordinator:[self persistentStoreCoordinator]];

  NSError *error = nil;

  for (NSInteger index = 0; index &lt; [self entriesToCreate]; ++index) {
    id object = [NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:moc];
    [object setValue:[NSString stringWithFormat:@"User %i", index] forKey:@"name"];
    [object setValue:[NSNumber numberWithInteger:(arc4random() % 99)] forKey:@"age"];

    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:[self runSpeed]]];

    if (index % [self saveFrequency] != 0) continue;

    ZAssert([moc save:&amp;error], @"Error saving context on operation: %@\n%@", [error localizedDescription], [error userInfo]);

    DLog(@"saving background context");
    [moc reset];
    [pool release];
    pool = [[NSAutoreleasePool alloc] init];
  }

  ZAssert([moc save:&amp;error], @"Error saving context on operation: %@\n%@", [error localizedDescription], [error userInfo]);

  [moc release], moc = nil;

  [[NSNotificationCenter defaultCenter] postNotificationName:kImportRoutineComplete object:self];

  [pool release], pool = nil;
}
</code></pre>

<p>It starts with creating a separate <code>NSManagedObjectContext</code> as per the rules.  We then add an empty port so that we can lazily sleep this thread.  From there we start looping based on the set <code>entriesToCreate</code> value.</p>

<p>Inside of the loop we create a new <code>NSManagedObject</code> and give it some random values.  We then sleep based on the <code>runSpeed</code> value.  From there we check to see if it is time to save and if not we move on to the next iteration of the loop.</p>

<p>If it is time to save we then perform a <code>-save:</code> on the <code>NSManagedObjectContext</code> instance wrapped inside of a <code>ZAssert</code>.  The <code>ZAssert</code> allows us to do a conditional check on the results and then spit out either a <code>NSAssert</code> or <code>NSLog</code> depending on whether we are compiling in debug (which would throw an assertion) or production (which will spit out an NSLog).</p>

<p>Once the save is complete we reset the <code>NSManagedObjectContext</code> instance to release the memory it is holding onto and then drain the <code>NSAutoreleasePool</code>.</p>

<p>Once all of the requested objects have been created we perform one final save of the <code>NSManagedObjectContext</code> and drain the <code>NSAutoreleasePool</code> one final time.  We also send out a <code>NSNotification</code> just so that we can update the UI and re-enable the buttons.</p>

<h2>Wrap Up</h2>

<p>If you run the sample application you will notice a few things:</p>

<ul>
<li>The app runs smoothly even while processing data.</li>
<li>The app does not crash on launch due to the OS killing it.</li>
<li>THe app does not crash on exit because the save takes too long.</li>
</ul>

<p>Naturally this is more work for us as the developers but the end result is an application that can handle any amount of data without fear of freezing the UI or having the OS kill our application.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2011/08/PerformantImport.zip'>You can download the sample project here.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2011/08/22/importing-and-displaying-large-data-sets-in-core-data/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Core Data and Threads, Without the Headache</title>
		<link>http://www.cimgf.com/2011/05/04/core-data-and-threads-without-the-headache/</link>
		<comments>http://www.cimgf.com/2011/05/04/core-data-and-threads-without-the-headache/#comments</comments>
		<pubDate>Wed, 04 May 2011 20:12:56 +0000</pubDate>
		<dc:creator>Saul Mora</dc:creator>
				<category><![CDATA[Core Data]]></category>
		<category><![CDATA[GCD & Blocks]]></category>
		<category><![CDATA[NSOperation]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Threading]]></category>
		<category><![CDATA[core-data]]></category>
		<category><![CDATA[gcd]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/?p=1388</guid>
		<description><![CDATA[I know I mentioned we would talk about customizing the fetch requests, however, I have been working on some code related to the Active Record Fetching project, which I am renaming to MagicalRecord, that is also just as useful as fetching&#8211;threading. Whenever most cocoa developers mention threading and Core Data in the same sentence, the [...]]]></description>
			<content:encoded><![CDATA[<p>I know I mentioned we would talk about customizing the fetch requests, however, I have been working on some code related to the Active Record Fetching project, which I am renaming to MagicalRecord, that is also just as useful as fetching&#8211;threading.</p>

<p>Whenever most cocoa developers mention threading and Core Data in the same sentence, the reaction I see most often is that of mysticism and disbelief. For one, multithreaded programming in general is hard&#8211;hard to design correctly, hard to write correctly, and debugging threads is just asking for trouble. Introducing Core Data into that mix can seem like the straw that broke the camel&#8217;s back. However, by following a few simple rules and guidelines, and codifying them into a super simple pattern, one that may be familiar to you, we can achieve safer Core Data threading without the common headaches.</p>

<p><span id="more-1388"></span></p>

<p>Another reminder: the examples in this blog post will refer to the open source project on Github, <a href="http://github.com/magicalpanda/magicalrecord">MagicalRecord</a>, which is basically several helpful categories and classes I&#8217;ve written to extend the standard Core Data APIs.</p>

<h2 style="font-size: 1.5em">What would Apple do?</h2>

<p>Let&#8217;s start by looking up in the docs (see <a href="http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html">Concurrency with Core Data</a>) to see what needs to happen in order to set up Core Data to pass data objects across threads and perform save operations in the background. Summarizing the main points from the recommended approach:</p>

<ul>
    <li>Each thread should have its one NSManagedObjectContext</li>
    <li>NSManagedObjects themselves are <strong>not</strong> thread-safe</li>
    <li>NSManagedObjectIDs <strong>are</strong> thread-safe</li>
    <li>If you save in the background, you need to merge your changes to other contexts using one of the Core Data system notifications, <em>NSManagedObjectContextDidSaveNotification</em>.</li>
</ul>

<p>How do we do this in code? The most common solution is to create a custom NSOperation, and make sure we create and set up our new context in the main method of the operation, like so:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;MGPCoreDataOperation.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> MGPCoreDataOperation <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>nonatomic, retain<span style="color: #002200;">&#41;</span> <span style="color: #400080;">NSManagedObjectContext</span> <span style="color: #002200;">*</span>context;
&nbsp;
<span style="color: #a61390;">@end</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> MGPCoreDataOperation
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>main
<span style="color: #002200;">&#123;</span>
	<span style="color: #002200;">&#91;</span>self setContext<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSManagedObjectContext</span> context<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
	<span style="color: #11740a; font-style: italic;">//perform my core data operations here</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></div></div>


<p>Remember to create the NSManagedObjectContext in the main method of your custom NSOperation, and not the init method. The main is the only one of the two that is guaranteed to be called from another thread. Your secondary NSManagedObjectContext needs to be created inside the thread where it will be used.</p>

<p>This solution is fairly straightforward, however, let&#8217;s think beyond this class. Using this approach, while a valid solution, is somewhat cumbersome to reuse. For every save operation using this technique you will:</p>

<ul>
    <li>need to subclass, or create this class via a template every time</li>
    <li>instantiate this objects on the main thread, and give it to an NSOperationQueue</li>
    <li>have to pass in object ids through a property</li>
</ul>

<p>This solution is for the heavy lifting algorithms such as parsing data in the background and saving it in once the parse is done, and all on a background thread. Let&#8217;s try a solution that is a little lighter weight, a little easier on the eyes, and uses one of the more fun and recent additions to Objective C&#8211;blocks and GCD.</p>

<h2 style="font-size: 1.5em">A small idea</h2>

<p>Before we get started with our threading adventure, we need to first seed our minds with a small idea that will help us for the remainder of this post. In the context of threading and UI, we need to examine the concept of a <em>Main Thread</em>. The <em>main thread</em> is different from other threads in that it is considered the foreground thread, and is the thread which runs the main runloop, which in turn, processes messages sent from outside your app such as taps or clicks, and sends them to your application. From this example, let&#8217;s introduce the concept of a Main Managed Object Context. This context is meant to only be accessed from the same thread as the UI. This context is also always available, as is the <em>Main Thread</em>, and Main Runloop. In the MagicalRecord helpers, I have implemented a defaultContext class method that provides access from anywhere.</p>

<p>The default Xcode Core Data application template promotes this idea by virtue of putting a reused managed object context in the app delegate. Both the app delegate, and the managed object context are implied singletons. MagicalRecord also keeps it&#8217;s default context in a single place for easy reuse in your applications, and is also a singleton-like pattern. But, unlike the application templates, it keeps its reference away from your app delegate. Technically speaking, moving the shared NSManagedObjectContext out of the app delegate is merely a preference, but my preference is to keep the application delegate as free from actual application responsibility as possible.</p>

<p>This main context provides some neat features. First, it let&#8217;s us simplify the find methods described in my <a href="http://www.cimgf.com/2011/03/13/super-happy-easy-fetching-in-core-data/">previous post</a>, while still having the option for a context parameter. Second, this lets us get started with Core Data very quickly since we can do fetching from the main thread on the main context, and not have cross thread issues. And third, and most importantly, we have a single context to which any background changes are merged. And if those benefits weren&#8217;t helpful enough, changes to observed managed object instance can immediately be acted upon by any UI components using KVO.</p>

<h2 style="font-size: 1.5em">Core Data, Blocks and GCD&#8230;oh my!</h2>

<p>Multithreading in Core Data is important when it comes to saving data in the store. While complex fetches can certainly take quite a bit of time to return, most frequently the bottleneck is during a save. As such, the goal in this solution is to make background saving easy and safe.</p>

<p>This block based solution is inspired by one of the newer iOS APIs for animating views. Blocks are incredibly powerful, and for Core Animation code, have greatly simplified animation code. A simple animation now looks like this:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">UIView <span style="color: #002200;">*</span>redView <span style="color: #002200;">=</span> ...;
<span style="color: #002200;">&#91;</span>UIView animateWithDuration<span style="color: #002200;">:</span><span style="color: #2400d9;">5.0</span>
		 animations<span style="color: #002200;">:^</span><span style="color: #002200;">&#123;</span>
			redView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">0.0</span>;
		 <span style="color: #002200;">&#125;</span>
 <span style="color: #002200;">&#93;</span>;</pre></div></div>


<p>Can we use this paradigm to save Core Data objects on a background thread? What if we had a save API resembling this animation API? Let&#8217;s first think about the synchronous (aka. easy) case.  The API would probably look something like this:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> saveDataInContext<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSManagedObjectContext</span> <span style="color: #002200;">*</span>context<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>saveBlock;</pre></div></div>


<p>When using this API our code will resemble this sample:</p>


<div class="wp_syntax"><div class="code"><pre class="obj" style="font-family:monospace;">PersonEntity *person = ...;
NSManagedObjectID *objectID = [person objectID];
[NSManagedObjectHelper saveDataInContext:^(NSManagedObjectContext *localContext){
	PersonEntity *localPerson = (PersonEntity *)[localContext objectWithID:objectID];
&nbsp;
	//make my updates to localPerson here
	localPerson.name = @&quot;IronMan&quot;;
	//...more changes
}];</pre></div></div>


<p>While it&#8217;s not terribly important in this particular example because it&#8217;s all running in the same tread, I must remind you that NSManagedObjects are NOT thread-safe, but NSMangedObjectIDs are, so we need to pass an NSManagedObject&#8217;s object ID across the thread, or in this case, block boundary.</p>

<p>In order for this code sample to work, the implementation of the saveDataInContext method should be:</p>

<ul>
    <li>creating a new NSManagedObjectContext instance, AND</li>
    <li>setting up the both contexts with the proper merge policy, AND</li>
    <li>setting up the main context to listen to the background context to merge on save,</li>
    <li>sending that context as the parameter into the block for use by other code.</li>
</ul>

<p>This would make creating lightweight save or update operations as easy as creating a UIView block-based animation.</p>

<p>So, what would the body of this method look like? Let&#8217;s start the first item on the list.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>saveDataInContext<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSManagedObjectContext</span> <span style="color: #002200;">*</span>context<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>saveBlock
<span style="color: #002200;">&#123;</span>
	<span style="color: #400080;">NSManagedObjectContext</span> <span style="color: #002200;">*</span>context <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSManagedObjectContext</span> context<span style="color: #002200;">&#93;</span>;			<span style="color: #11740a; font-style: italic;">//step 1</span>
	<span style="color: #002200;">&#91;</span>context setMergePolicy<span style="color: #002200;">:</span>NSMergeByPropertyObjectTrumpMergePolicy<span style="color: #002200;">&#93;</span>;				<span style="color: #11740a; font-style: italic;">//step 2</span>
	<span style="color: #002200;">&#91;</span>defaultContext setMergePolicy<span style="color: #002200;">:</span>NSMergeObjectByPropertyStoreTrumpMergePolicy<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#91;</span>defaultContext observeContext<span style="color: #002200;">:</span>context<span style="color: #002200;">&#93;</span>;						<span style="color: #11740a; font-style: italic;">//step 3</span>
&nbsp;
	block<span style="color: #002200;">&#40;</span>context<span style="color: #002200;">&#41;</span>;										<span style="color: #11740a; font-style: italic;">//step 4</span>
	<span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>context hasChanges<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>								<span style="color: #11740a; font-style: italic;">//step 5</span>
	<span style="color: #002200;">&#123;</span>
		<span style="color: #002200;">&#91;</span>context save<span style="color: #002200;">&#93;</span>;  <span style="color: #11740a; font-style: italic;">//MagicalRecord will dump errors to the console with this save method</span>
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>This code uses some <a href="http://github.com/magicalpanda/magicalrecord">MagicalRecord</a> helper methods, but the steps as implemented are:</p>

<ul>
    <li>Step 1: Create the new context</li>
    <li>Step 2: Set the merge policy</li>
    <li>Step 3: Set up the notification</li>
    <li>Step 4: Call back our block with our newly created context that&#8217;s been set up properly.</li>
    <li>Step 5: Save the context if it has any changes</li>
</ul>

<p>Notice also, that in order for a merge to occur automatically, one context has to be set to win during the merge. In this case, we want the background context to win by telling the main context that we want the information in our data store to be the correct answer in the case of a conflict. Also notice that much of the setup of a second context is as simple as calling a single method. We can now build upon this simple foundation and introduce background threading for our saves. Since we&#8217;re using blocks, we can also take advantage of the Grand Central Dispatch APIs.</p>

<p>A background operation using our synchronous method can easily be written using GCD:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>saveDataInBackgroundWithContext<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSManagedObjectContext</span> <span style="color: #002200;">*</span>context<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>saveBlock
<span style="color: #002200;">&#123;</span>
	dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_global_queue<span style="color: #002200;">&#40;</span>DISPATCH_QUEUE_PRIORITY_BACKGROUND, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
		<span style="color: #002200;">&#91;</span>self saveDataInContext<span style="color: #002200;">:</span>saveBlock<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>


<h2>Going the Distance</h2>

<p>But, can we do more? What is one neat feature of the UIView block animation APIs? Their ability to call a block when the animation has completed. How useful would it be to have a block of code called exactly after the changes to your object have been saved and merged? I thought so; let&#8217;s look again at a UIView animation API for inspiration:
<pre>+ (void)animateWithDuration:(NSTimeInterval)<em>duration</em> animations:(void (^)(void))<em>animations</em> completion:(void (^)(BOOL finished))<em>completion</em></pre>
And a usage sample, expanding on our previous UIView animation example:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;">UIView <span style="color: #002200;">*</span>redView <span style="color: #002200;">=</span> ...;
<span style="color: #002200;">&#91;</span>UIView animateWithDuration<span style="color: #002200;">:</span><span style="color: #2400d9;">5.0</span>
		 animations<span style="color: #002200;">:^</span><span style="color: #002200;">&#123;</span>
			redView.alpha <span style="color: #002200;">=</span> <span style="color: #2400d9;">0.0</span>;
		 <span style="color: #002200;">&#125;</span>
		 completion<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span>  completed<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#123;</span>
			<span style="color: #002200;">&#91;</span>redView removeFromSuperview<span style="color: #002200;">&#93;</span>;
			<span style="color: #002200;">&#91;</span>redView release<span style="color: #002200;">&#93;</span>;
			redView <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
		 <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#93;</span>;</pre></div></div>


<p>To be safe, let&#8217;s make sure our completion block is called on the main thread while we&#8217;re at it.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>saveDataInBackgroundWithContext<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSManagedObjectContext</span> <span style="color: #002200;">*</span>context<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>saveBlock completion<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>completion
<span style="color: #002200;">&#123;</span>
	dispatch_async<span style="color: #002200;">&#40;</span>dispatch_get_global_queue<span style="color: #002200;">&#40;</span>DISPATCH_QUEUE_PRIORITY_BACKGROUND, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
		<span style="color: #002200;">&#91;</span>self saveDataInContext<span style="color: #002200;">:</span>saveBlock<span style="color: #002200;">&#93;</span>;
&nbsp;
		dispatch_sync<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
			completion<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
		<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
	<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Now, you can save and reload, or update your data in a single place sort of like this:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"> 
<span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>listOfPeople <span style="color: #002200;">=</span> ...;
<span style="color: #002200;">&#91;</span>NSManagedObjectHelper saveDataInBackgroundWithContext<span style="color: #002200;">:^</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSManagedObjectContext</span> <span style="color: #002200;">*</span>localContext<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#123;</span>
	<span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span>personInfo <span style="color: #a61390;">in</span> listOfPeople<span style="color: #002200;">&#41;</span>
	<span style="color: #002200;">&#123;</span>
		PersonEntity <span style="color: #002200;">*</span>person <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>PersonEntity createInContext<span style="color: #002200;">:</span>localContext<span style="color: #002200;">&#93;</span>;
		<span style="color: #002200;">&#91;</span>person setValuesForKeysWithDictionary<span style="color: #002200;">:</span>personInfo<span style="color: #002200;">&#93;</span>;
	<span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span> completion<span style="color: #002200;">:^</span><span style="color: #002200;">&#123;</span>
	self.people <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>PersonEntity findAll<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#93;</span>;</pre></div></div>


<p>This small block of code does a lot for you. It,</p>

<ul>
    <li>creates and sets up a background Managed Object Context</li>
    <li>creates and sets up a background GCD queue</li>
    <li>saves the background context, which was set up to notify our Managed Object Context in the Main thread</li>
    <li>calls back your completion block on the main thread AFTER the changes have been pushed all the way to the persistent store</li>
</ul>

<p>However, there is one more thing we could add to help keep our saving simple. As it is now, the background operations are performed on a global background queue. I&#8217;ve encountered times where it is necessary to have a single dedicated GCD queue only for Core Data operations. In <a href="http://github.com/magicalpanda/magicalrecord">MagicalRecord</a>, we&#8217;ve defined a simple static function that allows access to a write only GCD queue.</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">static</span> dispatch_queue_t coredata_background_save_queue;
&nbsp;
dispatch_queue_t background_save_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>coredata_background_save_queue <span style="color: #002200;">==</span> <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        coredata_background_save_queue <span style="color: #002200;">=</span> dispatch_queue_create<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">&quot;com.magicalpanda.coredata.backgroundsaves&quot;</span>, <span style="color: #2400d9;">0</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> coredata_background_save_queue;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>And this would only modify our background core data save method like so:</p>


<div class="wp_syntax"><div class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>saveDataInBackgroundWithContext<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSManagedObjectContext</span> <span style="color: #002200;">*</span>context<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>saveBlock completion<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#40;</span><span style="color: #002200;">^</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>completion
<span style="color: #002200;">&#123;</span>
	dispatch_async<span style="color: #002200;">&#40;</span>coredata_background_save_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
		<span style="color: #002200;">&#91;</span>self saveDataInContext<span style="color: #002200;">:</span>saveBlock<span style="color: #002200;">&#93;</span>;
&nbsp;
		dispatch_sync<span style="color: #002200;">&#40;</span>dispatch_get_main_queue<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>, <span style="color: #002200;">^</span><span style="color: #002200;">&#123;</span>
			completion<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
		<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
	<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></div></div>


<p>Using blocks, GCD and a little bit of convention, we&#8217;ve helped to make multithreaded Core Data code much easier to write and stay consistent with Apple&#8217;s recommended methods. Not only that, but this solution consolodates much of the manual boilerplate setup required to properly save data in the background and safely update data throughout your applications.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2011/05/04/core-data-and-threads-without-the-headache/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Core Animation Tutorial: QTMovieLayer and Image Animation</title>
		<link>http://www.cimgf.com/2008/03/05/core-animation-tutorial-qtmovielayer-and-image-animation/</link>
		<comments>http://www.cimgf.com/2008/03/05/core-animation-tutorial-qtmovielayer-and-image-animation/#comments</comments>
		<pubDate>Wed, 05 Mar 2008 19:33:26 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Core Animation]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[NSOperation]]></category>
		<category><![CDATA[QTKit]]></category>
		<category><![CDATA[calayer]]></category>
		<category><![CDATA[convert nsimage to cgimageref]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[qtmovielayer]]></category>
		<category><![CDATA[sample code]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/2008/03/05/core-animation-tutorial-qtmovielayer-and-image-animation/</guid>
		<description><![CDATA[In my first post I wrote about using NSOperation to grab an image of the current frame of a QuickTime movie while it was playing and save it out to the filesystem. Considering the excitement that is surrounding Core Animation these days, I thought it might be interesting to take that project and change it [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://www.cimgf.com/wp-content/uploads/2008/03/qtmovielayer_desktop.jpg' title='QTMovieLayer App Desktop'  rel='lightbox'><img src='http://www.cimgf.com/wp-content/uploads/2008/03/qtmovielayer_desktop.thumbnail.jpg' alt='QTMovieLayer App Desktop' align="left" style="margin:5px;" /></a>In my <a href="http://www.cimgf.com/2008/02/23/nsoperation-example/">first post</a> I wrote about using NSOperation to grab an image of the current frame of a QuickTime movie while it was playing and save it out to the filesystem. Considering the excitement that is surrounding Core Animation these days, I thought it might be interesting to take that project and change it to instead grab the current frame and animate it across the screen using a Core Animation layer (CALayer). I had to employ a few tricks to get it to work, but the end result, while completely useless, is quite excellent.
<br /><br /><br /><br />
&nbsp;
<br /><br /><br /><br />
<span id="more-38"></span></p>

<h2>Getting Ready For The Image</h2>

<p>The focus of this tutorial is Core Animation and specifically how to use a QTMovieLayer as well as animating an image across the screen using a CALayer. I, therefore, will not spend any time addressing NSOperation and I think we&#8217;ve covered this adequately on this site. I would suggest, however, that you familiarize yourself with <a href="http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/">Marcus&#8217; post on NSOperation</a> as he discusses calling back into the main thread once the NSOperation has completed. I employ Marcus&#8217; technique in this project so that I can be notified when the image I&#8217;m wanting to animate is ready.</p>

<blockquote>
You can download the demo project for this post from here: <a href='http://www.cimgf.com/wp-content/uploads/2008/03/movieimageflick.zip' title='Movie Image Flick Demo Project'>Movie Image Flick Demo Project</a>
</blockquote>

<p>Download the project and run it. It will prompt you to select a QuickTime movie to play. Once the movie starts playing, tap your spacebar and watch the images pop off of the movie and animate to random places on the screen. Tap the spacebar quickly to see the effect work in rapid succession.</p>

<p>As in my NSOperation post, I want the video playback to be completely flicker free. I achieve this by obtaining a reference to a copy of the QTMovie object from which I obtain the image at the given time. If you take a look at my <em>main:</em> function in my NSOperation derived class, you&#8217;ll see how I am notifying the main thread that it may now do something with the image I&#8217;ve obtained.</p>

<p><strong>ImageGrabber.m:main</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>main;
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> movie <span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #400080;">NSImage</span><span style="color: #002200;">*</span> image;
        image <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>movie frameImageAtTime<span style="color: #002200;">:</span><span style="color: #a61390;">time</span> 
                      withAttributes<span style="color: #002200;">:</span>imageAttrs error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>image retain<span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>AppDelegate shared<span style="color: #002200;">&#93;</span> performSelectorOnMainThread<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>imageReady<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>
                                               withObject<span style="color: #002200;">:</span>image
                                            waitUntilDone<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>image release<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>In the second last line of the function, notice I am calling back into my main thread and letting the app delegate know that the image is ready. I am also handing the image to the <em>imageReady:</em> function. This is very convenient for what we need to do next. But first, let&#8217;s discuss drawing the layers with no backing view or window.</p>

<h2>Drawing Layers In Thin Air</h2>

<p>This project employs a trick that makes it appear as if the layers are being drawn without a backing view. This is, of course, not really possible, so instead we do a little trick. I achieved this effect by creating a borderless window with a transparent background. As usual, I want to give credit where credit is due. Lucas Newman answered a question <a href="http://theocacao.com/document.page/551">I posted on Scott Stevenson&#8217;s blog</a> to find out how Lucas did this in his demo project a the Silicon Valley CocoaHeads meeting on Core Animation. You simply create your own NSWindow derived class and override the initWithContentRect: method. Here is the resulting initialization code I came up with from his suggestion.</p>

<p><strong>BorderlessWindow.m:initWithContentRect</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span> initWithContentRect<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">NSRect</span><span style="color: #002200;">&#41;</span> contentRect
                 styleMask<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span> aStyle
                   backing<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span>NSBackingStoreType<span style="color: #002200;">&#41;</span> bufferingType
                     defer<span style="color: #002200;">:</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span> flag
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>super initWithContentRect<span style="color: #002200;">:</span> contentRect 
                 styleMask<span style="color: #002200;">:</span> NSBorderlessWindowMask 
                   backing<span style="color: #002200;">:</span> bufferingType 
                   defer<span style="color: #002200;">:</span> flag<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;
    <span style="color: #002200;">&#91;</span>self setBackgroundColor<span style="color: #002200;">:</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSColor</span> clearColor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self setOpaque<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>The only issue with using a transparent backing window/view is that you cannot click through it even though it looks like you ought to be able to. There is probably a way to pass the click on to the next front most window, but I haven&#8217;t yet researched this. I&#8217;ll let you know when I find the answer, or if you know the answer, post it in the comments.</p>

<h2>Rapid Fire Image Animation</h2>

<p>I created a method to initialize my NSOperation derived objects and hand them off to the NSOperationQueue. I hooked it up to the spacebar and can then tap the spacebar as quickly as possible and watch the images just pop off the playing movie. Here is my <em>flickIt:</em> function.</p>

<p><strong>AppDelegate.m:flickIt</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>flickIt<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
    ImageGrabber <span style="color: #002200;">*</span>grabber <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>ImageGrabber alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #002200;">&#91;</span>grabber setTime<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>movie currentTime<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// Hand off the background movie to the NSOperation derived</span>
    <span style="color: #11740a; font-style: italic;">// object</span>
    <span style="color: #002200;">&#91;</span>grabber setMovie<span style="color: #002200;">:</span>movieBak<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Add the oepration to the queue. It will be run immediately.</span>
    <span style="color: #002200;">&#91;</span>queue addOperation<span style="color: #002200;">:</span>grabber<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>This function creates the NSOpeartion derived objects and passes a reference to the current time in the playing movie as well as a reference to the background movie that I use to pull the image data from. Remember that this object is copied from the original QTMovie object and is used to keep from needing to pull the image data from the QTMovie object that is actually playing in the QTMovieLayer. Pulling the image from the QTMovie object that is being used for playback would cause the playback to stutter.</p>

<p>As stated earlier, when my image is ready, the NSOperation derived object, ImageGrabber, calls back into the main thread calling the function called <em>imageReady:</em>. Here is its implementation.</p>

<p><strong>AppDelegate.m:imageReady</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>imageReady<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSImage</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>image;
<span style="color: #002200;">&#123;</span>    
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSAnimationContext</span> currentContext<span style="color: #002200;">&#93;</span> setDuration<span style="color: #002200;">:</span>1.5f<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Save off the rectangle of the ready layer before</span>
    <span style="color: #11740a; font-style: italic;">// it gets animated. We will use this to reset the</span>
    <span style="color: #11740a; font-style: italic;">// ready layer.</span>
    CGRect prevRect <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>readyLayer frame<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Convert the NSImage to a CGImageRef</span>
    CGImageRef imageRef <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self nsImageToCGImageRef<span style="color: #002200;">:</span>image<span style="color: #002200;">&#93;</span>;
    CFRetain<span style="color: #002200;">&#40;</span>imageRef<span style="color: #002200;">&#41;</span>;
    readyLayer.contents <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>imageRef;
    readyLayer.backgroundColor <span style="color: #002200;">=</span> CGColorCreateGenericRGB<span style="color: #002200;">&#40;</span>0.0f,0.0f,0.0f,1.0f<span style="color: #002200;">&#41;</span>;
    readyLayer.borderColor <span style="color: #002200;">=</span> CGColorCreateGenericRGB<span style="color: #002200;">&#40;</span>0.45f,0.45f,0.45f,1.0f<span style="color: #002200;">&#41;</span>;
    readyLayer.borderWidth <span style="color: #002200;">=</span> 4.0f;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Grab a random rectangle on the screen where our image</span>
    <span style="color: #11740a; font-style: italic;">// layer will animate to.</span>
    CGRect randRect <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self getRandomRect<span style="color: #002200;">:</span>prevRect<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>readyLayer setFrame<span style="color: #002200;">:</span>randRect<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>readyLayer setOpacity<span style="color: #002200;">:</span>1.0f<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Reset the ready layer so that it is ready for the next image</span>
    readyLayer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>CALayer alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span> retain<span style="color: #002200;">&#93;</span>;
    readyLayer.frame <span style="color: #002200;">=</span> prevRect;
    readyLayer.opacity <span style="color: #002200;">=</span> 0.01f;
&nbsp;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> layer<span style="color: #002200;">&#93;</span> addSublayer<span style="color: #002200;">:</span>readyLayer<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Notice that we are converting the <em>NSImage</em> that gets passed to this function into a <em>CGImageRef</em> which is what our Core Animation layer requires to set it contents. Here is the code to convert an <em>NSImage</em> to a <em>CGImageRef</em>.</p>

<p><strong>AppDelegate.m:nsImageToCGImageRef</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>CGImageRef<span style="color: #002200;">&#41;</span>nsImageToCGImageRef<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSImage</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>image;
<span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span> imageData <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>image TIFFRepresentation<span style="color: #002200;">&#93;</span>;
    CGImageRef imageRef;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span>imageData<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        CGImageSourceRef imageSource <span style="color: #002200;">=</span> 
                     CGImageSourceCreateWithData<span style="color: #002200;">&#40;</span>
                           <span style="color: #002200;">&#40;</span>CFDataRef<span style="color: #002200;">&#41;</span>imageData,  <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>;
&nbsp;
        imageRef <span style="color: #002200;">=</span> CGImageSourceCreateImageAtIndex<span style="color: #002200;">&#40;</span>
                          imageSource, <span style="color: #2400d9;">0</span>, <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> imageRef;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<h2>Preloading A Layer to Animate</h2>

<p>Instead of creating the layer, setting its contents, and then animating it all at once, I instead set an empty layer with a near zero opacity to overlay the QTMovieLayer when the movie first loads. Then, when the user taps the spacebar, I populate that invisible layer&#8217;s contents with the image data and then animate it. This keeps me from having to create a more complicated animation to get the desired effect.</p>

<p>Once the image layer has it&#8217;s new frame set, I re-initialize the ready layer. You see the ready layer get reset with this code from the <em>imageReady:</em> function.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// Reset the ready layer so that it is ready for the next image</span>
readyLayer <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>CALayer alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span> retain<span style="color: #002200;">&#93;</span>;
readyLayer.frame <span style="color: #002200;">=</span> prevRect;
readyLayer.opacity <span style="color: #002200;">=</span> 0.01f;
&nbsp;
<span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>window contentView<span style="color: #002200;">&#93;</span> layer<span style="color: #002200;">&#93;</span> addSublayer<span style="color: #002200;">:</span>readyLayer<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>


<blockquote>
<br />
<strong>Note:</strong> I set the opacity to near zero as when it is set to zero it won&#8217;t animate the opacity change properly. I&#8217;m looking into why this is and will update this post with what I find when I find it.
<br /><br />

&nbsp;
</blockquote>

<h2>Random Points</h2>

<p>When I animate the layers, I simply grab a random point and the screen and then scale the image down to 35% of the original. When I call <em>setFrame:</em> the magic ensues and my screen gets really cluttered with lots of images. As I said before, not very useful, but excellent. Here is the random rectangle calculation function, <em>getRandomRect:</em>.</p>

<p><strong>AppDelegate.m:getRandomRect</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>CGRect<span style="color: #002200;">&#41;</span>getRandomRect<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGRect<span style="color: #002200;">&#41;</span>startRect;
<span style="color: #002200;">&#123;</span>    
    CGPoint point <span style="color: #002200;">=</span> CGPointMake<span style="color: #002200;">&#40;</span>random<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">%</span> 
                          <span style="color: #002200;">&#40;</span>NSUInteger<span style="color: #002200;">&#41;</span>NSWidth<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>window frame<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span>, 
                          random<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">%</span> 
                           <span style="color: #002200;">&#40;</span>NSUInteger<span style="color: #002200;">&#41;</span>NSHeight<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>window frame<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
    <span style="color: #a61390;">return</span> CGRectMake<span style="color: #002200;">&#40;</span>point.x, point.y, 
                 startRect.size.width <span style="color: #002200;">*</span> 0.35f, startRect.size.height <span style="color: #002200;">*</span> 0.35f<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<h2>Conclusion</h2>

<p>The nuances of Core Animation are quite interesting and provide a fun challenge when trying to solve problems. In other words, the devil is in the details. There is probably a better way to achieve the animation code, but I felt that the solution I came up with here works pretty well. There are details about Core Animation that I am still learning, but this type of effect demonstrates exactly the kinds of interesting things that are possible.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/03/05/core-animation-tutorial-qtmovielayer-and-image-animation/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Does Objective-C Perform Autoboxing on Primitives?</title>
		<link>http://www.cimgf.com/2008/03/01/does-objective-c-perform-autoboxing-on-primitives/</link>
		<comments>http://www.cimgf.com/2008/03/01/does-objective-c-perform-autoboxing-on-primitives/#comments</comments>
		<pubDate>Sat, 01 Mar 2008 05:00:13 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[Coding Practice]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Threading]]></category>
		<category><![CDATA[autoboxing]]></category>
		<category><![CDATA[boxing]]></category>
		<category><![CDATA[unboxing]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/2008/03/01/does-objective-c-perform-autoboxing-on-primitives/</guid>
		<description><![CDATA[This article is inaccurate. The writer was smoking crack or something when he wrote it and has not been able to duplicate his tests since. This article is left here for historical reasons. One of the things about Objective-C that I find extremely useful is the ability to resolve a method call at runtime. In [...]]]></description>
			<content:encoded><![CDATA[<p><center></p>

<h1>This article is inaccurate.</h1>

<p></center>
<i>The writer was smoking crack or something when he wrote it and has not been able to duplicate his tests since.  This article is left here for historical reasons.</i></p>

<p>One of the things about Objective-C that I find extremely useful is the ability to resolve a method call at runtime.  In addition this same functionality allows us to do some fairly creative things with callbacks, passing messages between threads, etc.</p>

<p>However there is a bit of a trick when it comes to passing primitives though some of these methods.  For example, one method that I use quite frequently is performSelectorOnMainThread:withObject:waitUntilDone:.  How exactly does one pass a BOOL or an int to this method?
<span id="more-33"></span></p>

<p>Fortunately, this is actually very simple.  While Objective-C does not have the ability to autobox primitives, it will <em>unbox them</em> in this situation.  For example, if you had the following method:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>updateCounter<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">int</span><span style="color: #002200;">&#41;</span>counter
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">//Do something clever</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>And you needed to call it from a background thread but it needed to be performed on the main thread, all you need to do is:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>aMethodOnABackgroundThread
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">int</span> myInt <span style="color: #002200;">=</span> <span style="color: #2400d9;">12</span>;
    <span style="color: #002200;">&#91;</span>self performSelector<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>updateCounter<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>
               withObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithInt<span style="color: #002200;">:</span>myInt<span style="color: #002200;">&#93;</span>
            waitUntilDone<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>As you can see, we are passing a NSNumber object into the method.  So what is the method actually receiving?  It will receive a primitive int just as it expects to.  No additional work is required in the receiving method.</p>

<p>This same unboxing can be performed with any primitive including BOOL.  Simply wrap them in a NSNumber and pass the NSNumnber through the method call.</p>

<p>As always, there is an exception to the rule.  When you are building your own NSInvocation (the magic Class behind these callbacks) you do not need to pass it an object for a primitive.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>aMethodOnABackgroundThread
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">int</span> myInt <span style="color: #002200;">=</span> <span style="color: #2400d9;">12</span>;
    <span style="color: #a61390;">SEL</span> sel <span style="color: #002200;">=</span> <span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>updateCounter<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>;
    <span style="color: #400080;">NSMethodSignature</span> <span style="color: #002200;">*</span>sig <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self methodSignatureForSelector<span style="color: #002200;">:</span>sel<span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSInvocation</span> <span style="color: #002200;">*</span>invocation <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSInvocation</span> invocationWithMethodSignature<span style="color: #002200;">:</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>invocation setTarget<span style="color: #002200;">:</span>self<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>invocation setSelector<span style="color: #002200;">:</span>sel<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>invocation setArgument<span style="color: #002200;">:&amp;</span>myInt atIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">2</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>invocation invoke<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>In this example, the NSNumber wrapper/boxing is unnecessary as the invocation accepts anything.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/03/01/does-objective-c-perform-autoboxing-on-primitives/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>NSOperation Example</title>
		<link>http://www.cimgf.com/2008/02/23/nsoperation-example/</link>
		<comments>http://www.cimgf.com/2008/02/23/nsoperation-example/#comments</comments>
		<pubDate>Sat, 23 Feb 2008 06:46:05 +0000</pubDate>
		<dc:creator>Matt Long</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[NSOperation]]></category>
		<category><![CDATA[QTKit]]></category>
		<category><![CDATA[Threading]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/2008/02/23/nsoperation-example/</guid>
		<description><![CDATA[Forget Mandelbrot sets (Apple coding headstarts) and Expression Trees. NSOperation is really not that hard. In his post, Marcus introduced how to use NSOperation to greatly simplify multi-threading tasks in your application. I am now going to provide a step-by-step walk-through sample application that uses NSOperation, NSOperationQueue, and QTKit. While looking around the Internet, I [...]]]></description>
			<content:encoded><![CDATA[<p><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-14.thumbnail.png' alt='QT Image Grab' border='0' style='margin:5px' align='left' /><strong>Forget Mandelbrot sets (Apple coding headstarts) and <a href="http://macresearch.org/node/4567" title="Mac Research NSOPeration Tutorial" target="_blank">Expression Trees</a>. NSOperation is really not that hard.</strong></p>

<p>In <a href="http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/">his post</a>, Marcus introduced how to use <em>NSOperation</em> to greatly simplify multi-threading tasks in your application. I am now going to provide a step-by-step walk-through sample application that uses <em>NSOperation</em>, <em>NSOperationQueue</em>, and <em>QTKit</em>.</p>

<p>While looking around the Internet, I noticed that the only examples of using <em>NSOperation</em> available were related to scientific applications. I wanted something that I could relate to a little better and since I&#8217;ve been working with <em>QTKit</em> a lot lately, I figured it would be a good framework to build from. This application simply grabs images of a movie while it is playing back and saves them out to a file. It&#8217;s pretty simple, but it shows how to do something fairly practical.
<span id="more-3"></span></p>

<h2>Grabbing Movie Image Frames</h2>

<p>The application displays a movie and provides a button for the user to click whenever the user wants to save the current frame of the movie to disk while it is playing. Here are some basic requirements I&#8217;ve given the app.</p>

<ul>
    <li>Images are only saved when the movie is playing back</li>
    <li>Clicking the button and the subsequent saving of the current image must not cause the movie to flicker</li>
    <li>Clicking in rapid succession should not cause the application to crash. For each click, a new task (operation) should be generated</li>
</ul>

<p>Here is a screenshot of the final application.</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2008/02/picture-14.png' title='QT Image Grab'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-14.thumbnail.png' alt='QT Image Grab' /></a></p>

<p>Follow along in XCode to create the application called QT Image Grab or <a href='http://www.cimgf.com/wp-content/uploads/2008/02/qtimagegrab.zip' title='Sample Project'>download the sample project here</a>.</p>

<p><strong>Note</strong> If you are already comfortable with setting up an AppDelegate class and making connections in Interface Builder, you can jump down to the section titled <a href="#derivedobject">Derive A Class From NSOperation</a></p>

<h2>Create The Application</h2>

<p>Create a Cocoa Application Using the following steps:</p>

<ol>
<li>Select <strong>File > New Projectâ€¦</strong> and choose <em>Cocoa Application</em> in the ensuing dialog. Click Next</li>
<li>Enter â€˜QTImageGrabâ€™ as the project name. Click Finish</li>
</ul>
</ol>

<p>You should see a project workspace like the following:</p>

<p><a href='http://www.cimgf.com/wp-content/uploads/2008/02/project.png' title='New Project Workspace'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/project.thumbnail.png' alt='New Project Workspace' /></a></p>

<h2>Create A Controller/Delegate Class</h2>

<p>The next thing you need to do is create an application controller, or delegate. To do so, use the following steps:</p>

<ol>
<li><strong>Option-Click</strong> on the <em>Classes</em> folder in your workspace and select &#8216;Add File&#8230;&#8217;

<a href='http://www.cimgf.com/wp-content/uploads/2008/02/picture-2.png' title='Add New Objective-C Class'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-2.thumbnail.png' alt='Add New Objective-C Class' /></a>
</li>
<li>Choose <strong>Object-C Class</strong> in the ensuing dialog and click <strong>Next</strong></li>

<li>Name the file &#8216;AppDelegate.m&#8217; and click <strong>Finish</strong></li>

<li>A new code window will display with your &#8216;AppDelegate&#8217; interface code (.h file). Edit the code so that it looks like this:


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;Cocoa/Cocoa.h&gt;</span>
<span style="color: #6e371a;">#import &lt;QTKit/QTKit.h&gt;</span>
<span style="color: #6e371a;">#import &lt;QuartzCore/CoreAnimation.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> AppDelegate <span style="color: #002200;">:</span> <span style="color: #400080;">NSObject</span> <span style="color: #002200;">&#123;</span>
	IBOutlet QTMovieView <span style="color: #002200;">*</span>movieView;
	IBOutlet <span style="color: #400080;">NSTextField</span> <span style="color: #002200;">*</span>outputPath;
	IBOutlet <span style="color: #400080;">NSWindow</span> <span style="color: #002200;">*</span>window;
&nbsp;
	<span style="color: #400080;">NSOperationQueue</span> <span style="color: #002200;">*</span>operationQueue;
	QTMovie <span style="color: #002200;">*</span>imagesMovie;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>grab<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>openMovie<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>selectOutputDir<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>



</li>

<li>Now we need to add the QTKit framework to your project. Option-Click the Frameworks folder in your project and select <strong>Add > Existing Frameworks&#8230;</strong>

<a href='http://www.cimgf.com/wp-content/uploads/2008/02/picture-3.png' title='Add Existing Frameworks'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-3.thumbnail.png' alt='Add Existing Frameworks' /></a>

In the ensuing dialog, navigate to <strong>/System/Library/Frameworks</strong> and select <strong>QTKit.framework</strong>.

Click <strong>Add</strong>

<li>Now switch over to your implementation file for &#8216;AppDelegate&#8217; (.m file). Add the implementation code so that the file looks like this:<br />


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@implementation</span> AppDelegate
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>awakeFromNib;
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// We're going to add some initialization code here</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>grab<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// This is where will will start the process for grabbing the current image.</span>
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>openMovie<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Here we load our movie using an open panel dialog.</span>
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>selectOutputDir<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Here we will select an output directory where the current frame</span>
    <span style="color: #11740a; font-style: italic;">// image will be saved to.</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>dealloc;
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// We're going to have some cleanup to do.</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>



<br />
We will actually add some code to do something in each of these methods shortly, but first we need to hook it up to the user interface in Interface Builder.
</li><br />
</ol>

<h2>Make The Interface Builder Connections</h2>

<p>Now that we&#8217;ve specified all of our actions and outlets in the <em>AppDelegate</em> code, let&#8217;s make the connections in our NIB file. To do so, use the following steps.</p>

<ol>
<li>In the tree view of your project in XCode, expand the smart folder labeled <em>NIB Files</em> and double click the file called <strong>MainMenu.nib</strong>

<em>Interface Builder</em> will load the NIB file.
</li>
<li>In <em>Interface Builder</em> click and drag an NSObject from the <em>Library</em> palette into your NIB file and rename the object to <strong>AppDelegate</strong> as shown:

<a href='http://www.cimgf.com/wp-content/uploads/2008/02/picture-4.png' title='Add App Delegate Object'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-4.thumbnail.png' alt='Add App Delegate Object' /></a></li>

<li>With the <strong>AppDelegate</strong> selected, select <strong>Tools > Inspector</strong> from the menu bar. In the inspector, select the <em>Object Identity</em> tab (tab 6) and in the <em>Class</em> field, enter <strong>AppDelegate</strong>.

<a href='http://www.cimgf.com/wp-content/uploads/2008/02/picture-5.png' title='Set AppDelegate Object'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-5.thumbnail.png' alt='Set AppDelegate Object' /></a></li>

<li>Now we need to tell our application to use the <em>AppDelegate</em> object as its delegate. <em>Control-Click</em> on the <strong>File&#8217;s Owner</strong> object in the MainMenu.nib window and drag a connection to the <strong>AppDelegate</strong> object and select <strong>delegate</strong> in the ensuing pop-up menu.

<a href='http://www.cimgf.com/wp-content/uploads/2008/02/picture-6.png' title='Set Delegate'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-6.thumbnail.png' alt='Set Delegate' /></a></li>

<li>All we have left now is to drag the controls onto the window and connect the actions and outlets. Edit the main window dragging controls to it so as to make it look like this.

<a href='http://www.cimgf.com/wp-content/uploads/2008/02/picture-7.png' title='Main Window In Interface Builder'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-7.thumbnail.png' alt='Main Window In Interface Builder' /></a>

<strong>Note:</strong> The black area of the window is a <em>QTMovieView</em> which you&#8217;ll be able to find in the object library. It&#8217;s dimensions are set to a standard DV video format of 720 x 480 pixels.</li>

<li>Drag a connection (Control-Click) from the <em>Grab</em> button to the <em>AppDelegate</em> and select <strong>grab:</strong> from the dropdown.

 <a href='http://www.cimgf.com/wp-content/uploads/2008/02/picture-8.png' title='Connect Grab Button'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-8.thumbnail.png' alt='Connect Grab Button' /></a></li>

<li>Drag a connection from the <strong>File | Open&#8230;</strong> menu item to the <em>AppDelegate</em> and select <strong>openMovie:</strong> from the dropdown.

<a href='http://www.cimgf.com/wp-content/uploads/2008/02/picture-9.png' title='Connect Open Movie Menu'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-9.thumbnail.png' alt='Connect Open Movie Menu' /></a></li>

<li>Drag a connection from the <em>Select Output Folder Path</em> button to the <em>AppDelegate</em> and select <strong>selectOutputDir:</strong> from the dropdown.

<a href='http://www.cimgf.com/wp-content/uploads/2008/02/picture-11.png' title='Connect Select Output Folder Path Button'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-11.thumbnail.png' alt='Connect Select Output Folder Path Button' /></a></li>

<li>Drag a connection from the <em>AppDelegate</em> object to the Output Folder Path text field and select the <strong>outputPath</strong> <em>NSTextField</em> from the dropdown.

<a href='http://www.cimgf.com/wp-content/uploads/2008/02/picture-10.png' title='Connect AppDelegate To Output Path Textfield'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-10.thumbnail.png' alt='Connect AppDelegate To Output Path Textfield' /></a></li>

<li>Drag a connection from the <em>AppDelegate</em> object to the QTMovieView and select <strong>movieView</strong> from the dropdown.

<a href='http://www.cimgf.com/wp-content/uploads/2008/02/picture-13.png' title='Connect Movie View'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-13.thumbnail.png' alt='Connect Movie View' /></a></li>
</ol>

<p>Now we are finished in Interface Builder. Let&#8217;s return to XCode and start populating our event handlers with code. Don&#8217;t forget to save your NIB file in Interface Builder.</p>

<h2>Adding Event Handling Code</h2>

<p>For most of our event handlers, you can simply copy and paste the code from this section as their use is simply to set up the application and not directly related to the use of <em>NSOperation</em> or <em>NSOperationQueue</em>.</p>

<p><strong>- (void)awakeFromNib</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>awakeFromNib;
<span style="color: #002200;">&#123;</span>
    <span style="color: #11740a; font-style: italic;">// Initialize the queue</span>
    operationQueue <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSOperationQueue</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p><strong>- (IBAction)selectOutputDir:(id)sender;</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>selectOutputDir<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSOpenPanel</span> <span style="color: #002200;">*</span>openPanel;
&nbsp;
    openPanel <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSOpenPanel</span> openPanel<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>openPanel setCanChooseDirectories<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>openPanel setAllowsMultipleSelection<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>openPanel setResolvesAliases<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>openPanel setCanChooseFiles<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>openPanel runModalForTypes<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> NSOKButton<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>directory <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>openPanel directory<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>outputPath setStringValue<span style="color: #002200;">:</span>directory<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p><strong>- (void)dealloc</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>dealloc;
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>super dealloc<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> imagesMovie <span style="color: #002200;">&#41;</span>
        <span style="color: #002200;">&#91;</span>imagesMovie release<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>There are two other event handlers that we need to fill in, but they will require a little bit of explanation, so first let&#8217;s go and create our NSOpeation derived class that will do all of the work we need.</p>

<p><a name="derivedobject">&nbsp;</a></p>

<h2>Derive A Class From NSOperation</h2>

<p>In our application, we want to get the current image of the movie while it is playing back and save it out to disk. This is the operation that we want our NSOoperation to complete in a separate thread. In order to do this, we need to create a new Objective-C class that derives from NSOperation. To do so, complete the following steps.</p>

<ol>
<li>In the XCode treeview, Option-Click the <em>Classes</em> folder and select <strong>Add | New File&#8230;</strong>.

<a href='http://www.cimgf.com/wp-content/uploads/2008/02/picture-12.png' title='Add New File'><img src='http://www.cimgf.com/wp-content/uploads/2008/02/picture-12.thumbnail.png' alt='Add New File' /></a>

In the ensuing dialog, select <strong>Objective-C Class</strong> and click next. Enter the name &#8216;GragQTImageOperation.m&#8217; making sure that <strong>Also create &#8220;GrabQTImageOperation.h&#8221;</strong> is checked and click <strong>Finish</strong></li>

<li>In the header file for the new Objective-C class you just created, change the interface so that our object inherits from NSOperation.


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@interface</span> GrabQTImageOperation <span style="color: #002200;">:</span> <span style="color: #400080;">NSOperation</span> <span style="color: #002200;">&#123;</span>
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>



</ol>

<h2>Give Our NSOperation Something To Do</h2>

<p>Our new class now needs some objects to work with and a method to do the work. To do work, an NSOperation derived class, must override the method called <strong>main:</strong>. Edit the file <em>GrabQTImageOperation.m</em> and provide the following function declaration.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>main
<span style="color: #002200;">&#123;</span>
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>In order to do the work, we need the following objects:</p>

<ul>
<li><strong>QTMovie*</strong>: a pointer to a QTMovie view from which we will obtain our image to save.</li>
<li><strong>NSDictionary*</strong>: a dictionary to hold our attributes we will use when exporting to an image format</li>
<li><strong>NSLock*</strong>: a lock object to synchronize access to our QTMovie object.</li>
<li><strong>NSString*</strong>: a pointer to the output folder path we will use to save the files to.</li>
<li><strong>QTTime</strong>: a QTTime object representing the point in time as the movie was playing at which the grab button was clicked.</li>
</ul>

<p>Change the <em>GrabQTImageOperation</em> header file to look like this.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;Cocoa/Cocoa.h&gt;</span>
<span style="color: #6e371a;">#import &lt;QTKit/QTKit.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> GrabQTImageOperation <span style="color: #002200;">:</span> <span style="color: #400080;">NSOperation</span> <span style="color: #002200;">&#123;</span>
    QTMovie<span style="color: #002200;">*</span> movie;
    <span style="color: #400080;">NSDictionary</span> <span style="color: #002200;">*</span>imageAttrs;
    <span style="color: #400080;">NSLock</span> <span style="color: #002200;">*</span>lock;
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>outputPath;
    QTTime <span style="color: #a61390;">time</span>;
&nbsp;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>assign<span style="color: #002200;">&#41;</span> QTMovie <span style="color: #002200;">*</span>movie;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>assign<span style="color: #002200;">&#41;</span> <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>outputPath;
<span style="color: #a61390;">@property</span> <span style="color: #002200;">&#40;</span>assign<span style="color: #002200;">&#41;</span> QTTime <span style="color: #a61390;">time</span>;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>main;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>saveImage<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSImage</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>image;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>


<p>The method <strong>saveImage:</strong> actually saves the image to disk. Go ahead and add its declaration in the header as shown above. We&#8217;ll get back to that in a minute.</p>

<h2>Implement main:</h2>

<p>Now we need to switch to our implementation file (<strong>GrabQTImageOperation.m</strong>) and enter the following code into the <strong>main:</strong> function.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>main
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> movie <span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #400080;">NSImage</span><span style="color: #002200;">*</span> image;
        <span style="color: #002200;">&#91;</span>lock lock<span style="color: #002200;">&#93;</span>;
        image <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>movie frameImageAtTime<span style="color: #002200;">:</span><span style="color: #a61390;">time</span> withAttributes<span style="color: #002200;">:</span>imageAttrs error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>lock unlock<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>self saveImage<span style="color: #002200;">:</span>image<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>All we are doing at this point is getting the image at the specified time from our QTMovie reference and passing it on to our <strong>saveImage:</strong> method. Now fill we can populate the rest of the methods with the code we need to finish our NSOperation derived class.</p>

<p><strong>- (id)init</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>init
<span style="color: #002200;">&#123;</span>
    lock <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSLock</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #11740a; font-style: italic;">// Specify that we want to save out a high-quality image.</span>
    imageAttrs <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObjectsAndKeys<span style="color: #002200;">:</span>
                       QTMovieFrameImageTypeNSImage, QTMovieFrameImageType,
                       <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSNumber</span> numberWithBool<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>, QTMovieFrameImageHighQuality, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>imageAttrs retain<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p><strong>- (void)saveImage:(NSImage*)image</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>saveImage<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSImage</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>image;
<span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>representations;
    <span style="color: #400080;">NSData</span> <span style="color: #002200;">*</span>bitmapData;
&nbsp;
    representations <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>image representations<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Specify that we want to save the file as a JPG</span>
    bitmapData <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSBitmapImageRep</span> representationOfImageRepsInArray<span style="color: #002200;">:</span>representations 
                                usingType<span style="color: #002200;">:</span>NSJPEGFileType 
                                properties<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDictionary</span> dictionaryWithObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSDecimalNumber</span> numberWithFloat<span style="color: #002200;">:</span><span style="color: #2400d9;">1.0</span><span style="color: #002200;">&#93;</span> 
                                forKey<span style="color: #002200;">:</span>NSImageCompressionFactor<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Creates a long filename, but at least it's unique.</span>
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>filename <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSProcessInfo</span> processInfo<span style="color: #002200;">&#93;</span> globallyUniqueString<span style="color: #002200;">&#93;</span>;
    filename <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>filename stringByAppendingString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;.jpg&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>imgOut <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>outputPath stringByAppendingString<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;/&quot;</span><span style="color: #002200;">&#93;</span>;
    imgOut <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>imgOut stringByAppendingString<span style="color: #002200;">:</span>filename<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>bitmapData writeToFile<span style="color: #002200;">:</span>imgOut  atomically<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>And finally, don&#8217;t forget to add our synthesize calls at the top of the implementation.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@implementation</span> GrabQTImageOperation
&nbsp;
<span style="color: #a61390;">@synthesize</span> movie;
<span style="color: #a61390;">@synthesize</span> <span style="color: #a61390;">time</span>;
<span style="color: #a61390;">@synthesize</span> images;
<span style="color: #a61390;">@synthesize</span> outputPath;
...</pre></td></tr></table></div>


<h2>Finish Implementing AppDelegate</h2>

<p>Now that we&#8217;ve finished creating our <em>NSOperation</em> derived class, we can finish the implementation of our <em>AppDelegate</em>. First add the following code to the <strong>openMovie:</strong> event handler.</p>

<p><strong>- (IBAction)openMovie:(id)sender</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>openMovie<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSOpenPanel</span> <span style="color: #002200;">*</span>openPanel;
&nbsp;
    openPanel <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSOpenPanel</span> openPanel<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>openPanel setCanChooseDirectories<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>openPanel setAllowsMultipleSelection<span style="color: #002200;">:</span><span style="color: #a61390;">NO</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>openPanel setResolvesAliases<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>openPanel setCanChooseFiles<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">&#91;</span>openPanel runModalForTypes<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span> <span style="color: #002200;">==</span> NSOKButton<span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>filesToOpen <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>openPanel filenames<span style="color: #002200;">&#93;</span>;
        <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>theFilePath <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>filesToOpen objectAtIndex<span style="color: #002200;">:</span><span style="color: #2400d9;">0</span><span style="color: #002200;">&#93;</span>;
        QTMovie <span style="color: #002200;">*</span>movie <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>QTMovie movieWithFile<span style="color: #002200;">:</span>theFilePath error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        imagesMovie <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>QTMovie movieWithFile<span style="color: #002200;">:</span>theFilePath error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>imagesMovie retain<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>movieView setMovie<span style="color: #002200;">:</span>movie<span style="color: #002200;">&#93;</span>;		
    <span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>Take note of these two lines:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;">QTMovie <span style="color: #002200;">*</span>movie <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>QTMovie movieWithFile<span style="color: #002200;">:</span>theFilePath error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;
imagesMovie <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>QTMovie movieWithFile<span style="color: #002200;">:</span>theFilePath error<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span><span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>


<p>Notice that we are loading the same movie into memory twice. The first is for the object called <em>movie</em> which will be used in our <em>QTMovieView</em> for actual movie playback. The other movie is an instance variable called <em>imagesMovie</em> which will <em>act as a background movie</em>. It will be passed to our <em>NSOperation</em> derived class and it is the object from which the images will be obtained for saving to disk.</p>

<p>We use two movie objects representing the same file on disk in order to satisfy one of our requirements which was to ensure that the movie doesn&#8217;t flicker or stutter when the operation is happening. One movie reference is for display, the other for processing.</p>

<p>And finally, we now need to populate our <strong>grab:</strong> method which initializes our <em>NSOperation</em> derived objects and passes them off to the <em>NSOperationQueue</em> which runs them immediately. First, we need to import our header file at the top of <strong>AppDelegate.h</strong> like this:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;GrabQTImageOperation.h&quot;</span></pre></td></tr></table></div>


<p>And now, here is the implementation of <strong>grab:</strong> in <strong>AppDelegate.m</strong>.</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>IBAction<span style="color: #002200;">&#41;</span>grab<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>sender;
<span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>path <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>outputPath stringValue<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> <span style="color: #002200;">!</span>path || <span style="color: #002200;">&#91;</span>path length<span style="color: #002200;">&#93;</span> &lt;<span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span> <span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #400080;">NSAlert</span> <span style="color: #002200;">*</span>alert <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSAlert</span> alertWithMessageText<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Set Output Directory&quot;</span> defaultButton<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;OK&quot;</span> alternateButton<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> otherButton<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span> informativeTextWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;You must first select an output directory before grabbing images.&quot;</span><span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #002200;">&#91;</span>alert beginSheetModalForWindow<span style="color: #002200;">:</span>window
            modalDelegate<span style="color: #002200;">:</span>self
            didEndSelector<span style="color: #002200;">:</span><span style="color: #a61390;">nil</span>
            contextInfo<span style="color: #002200;">:</span><span style="color: #a61390;">NULL</span><span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #a61390;">return</span>;
    <span style="color: #002200;">&#125;</span>
&nbsp;
    <span style="color: #11740a; font-style: italic;">// Check to see if the movie is playing	</span>
    <span style="color: #a61390;">if</span><span style="color: #002200;">&#40;</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>movieView movie<span style="color: #002200;">&#93;</span> rate<span style="color: #002200;">&#93;</span> &gt; 0.0f <span style="color: #002200;">&#41;</span>
    <span style="color: #002200;">&#123;</span>
        <span style="color: #11740a; font-style: italic;">// If so, create our NSOperation derived object and hand it off to the queue</span>
        GrabQTImageOperation <span style="color: #002200;">*</span>op <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>GrabQTImageOperation alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>op setMovie<span style="color: #002200;">:</span>imagesMovie<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>op setTime<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>movieView movie<span style="color: #002200;">&#93;</span> currentTime<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>op setOutputPath<span style="color: #002200;">:</span>path<span style="color: #002200;">&#93;</span>;
&nbsp;
        <span style="color: #11740a; font-style: italic;">// As soon as this method finishes, the operation is set to work</span>
        <span style="color: #002200;">&#91;</span>operationQueue addOperation<span style="color: #002200;">:</span>op<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>The first thing we do is make sure our output path is set. If it is not, we alert the user and return. Otherwise, we check to see if our movie is playing by checking the movie&#8217;s current rate. If it is playing, then we are going to spin off one of our new <em>GrabQTImageOperation</em> objects to grab the image at the <em>currentTime</em>. Once we hand the image operation off to the <em>NSOperationQueue</em> we can watch the specified folder in the Finder and images will start to display.</p>

<p>To see the application run, click <strong>Build and Go</strong></p>

<h2>Conclusion</h2>

<p>Developing with <em>NSOperation</em> and <em>NSOperationQueue</em> is a very pleasant experience to me so far. This was a fun application to build and the results are quite pleasing. I was able to achieve all of my project requirements with very little effort. It&#8217;s a great addition to the toolset now available in OS X 10.5 Leopard.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/02/23/nsoperation-example/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Cocoa Tutorial: NSOperation and NSOperationQueue</title>
		<link>http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/</link>
		<comments>http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/#comments</comments>
		<pubDate>Sat, 16 Feb 2008 07:26:08 +0000</pubDate>
		<dc:creator>Marcus Zarra</dc:creator>
				<category><![CDATA[Cocoa]]></category>
		<category><![CDATA[NSOperation]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Threading]]></category>

		<guid isPermaLink="false">http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/</guid>
		<description><![CDATA[Threading is hard in any language. And what is worse, when it goes wrong, it usually goes wrong in a very bad way. Because of this, programmers either avoid threading completely (and refer to it as the spawn of the devil) or spend a LOT of time making sure that everything is perfect. Fortunately, Apple [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.cimgf.com/wp-content/uploads/2008/02/light_bulb.png" alt="Light Bulb" align="left" style="margin: 5px;" />Threading is hard in any language.  And what is worse, when it goes wrong, it usually goes wrong in a very bad way.  Because of this, programmers either avoid threading completely (and refer to it as the spawn of the devil) or spend a LOT of time making sure that everything is perfect.</p>

<p>Fortunately, Apple has made a lot of progress in OS X 10.5 Leopard.  NSThread itself has received a number of very useful new methods that make threading easier.  In addition, they have introduced two new objects: NSOperation and NSOperationQueue.
<span id="more-4"></span>
In this Tutorial I will walk through a basic example that shows how to use these new Objects and how they make multi-threading your application nearly trivial.</p>

<blockquote>
You can get the example project here: <a href='http://www.cimgf.com/wp-content/uploads/2008/02/asyncdownloader.zip' title='Async Downloader Example Project'>Async Downloader Example Project</a>
</blockquote>

<p>In this tutorial, I will demonstrate one way in which to use NSOperation and NSOperationQueue to handle tasks that are best performed on background threads.  The intent of this tutorial is to demonstrate a basic use of these classes and is not intentioned to be the <em>only</em> way to use them.</p>

<p>If you are familiar with Java, or one of its variants, the NSOperation object is very similar to the java.lang.Runnable interface.  Like, in Java&#8217;s Runnable interface, the NSOperation object is designed to be extended.  Also like Java&#8217;s Runnable, there is a minimum of one method to override.  For NSOperation that method is -(void)main. One of the easiest ways to use an NSOperation is to load it into an NSOperationQueue.  As soon as the operation is loaded into the queue, the queue will kick it off and begin processing.  As soon as the operation is complete the queue will release it.</p>

<h2>NSOperation Example</h2>

<p>In this example, I have written an NSOperation that fetches a webpage as a string, parses it into an NSXMLDocument and then passes that NSXMLDocument back to the main thread in the application before completing.</p>

<p><strong>PageLoadOperation.h</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;Cocoa/Cocoa.h&gt;</span>
&nbsp;
&nbsp;
<span style="color: #a61390;">@interface</span> PageLoadOperation <span style="color: #002200;">:</span> <span style="color: #400080;">NSOperation</span> <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSURL</span> <span style="color: #002200;">*</span>targetURL;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@property</span><span style="color: #002200;">&#40;</span>retain<span style="color: #002200;">&#41;</span> <span style="color: #400080;">NSURL</span> <span style="color: #002200;">*</span>targetURL;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithURL<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSURL</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>url;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>


<p><strong>PageLoadOperation.m</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;PageLoadOperation.h&quot;</span>
<span style="color: #6e371a;">#import &quot;AppDelegate.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> PageLoadOperation
&nbsp;
<span style="color: #a61390;">@synthesize</span> targetURL;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>initWithURL<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSURL</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>url;
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;
    <span style="color: #002200;">&#91;</span>self setTargetURL<span style="color: #002200;">:</span>url<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>dealloc <span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>targetURL release<span style="color: #002200;">&#93;</span>, targetURL <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
    <span style="color: #002200;">&#91;</span>super dealloc<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>main <span style="color: #002200;">&#123;</span>
    <span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>webpageString <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSString</span> alloc<span style="color: #002200;">&#93;</span> initWithContentsOfURL<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span>self targetURL<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span> autorelease<span style="color: #002200;">&#93;</span>;
&nbsp;
    <span style="color: #400080;">NSError</span> <span style="color: #002200;">*</span>error <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
    <span style="color: #400080;">NSXMLDocument</span> <span style="color: #002200;">*</span>document <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSXMLDocument</span> alloc<span style="color: #002200;">&#93;</span> initWithXMLString<span style="color: #002200;">:</span>webpageString 
                                                              options<span style="color: #002200;">:</span>NSXMLDocumentTidyHTML 
                                                                error<span style="color: #002200;">:&amp;</span>error<span style="color: #002200;">&#93;</span>;
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>document<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%s Error loading document (%@): %@&quot;</span>, _cmd, <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>self targetURL<span style="color: #002200;">&#93;</span> absoluteString<span style="color: #002200;">&#93;</span>, error<span style="color: #002200;">&#41;</span>;
        <span style="color: #a61390;">return</span>;
    <span style="color: #002200;">&#125;</span>	
&nbsp;
    <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>AppDelegate shared<span style="color: #002200;">&#93;</span> performSelectorOnMainThread<span style="color: #002200;">:</span><span style="color: #a61390;">@selector</span><span style="color: #002200;">&#40;</span>pageLoaded<span style="color: #002200;">:</span><span style="color: #002200;">&#41;</span>
                                           withObject<span style="color: #002200;">:</span>document
                                        waitUntilDone<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>document release<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>


<p>As you can see, this class is very simple.  It accepts a URL in the init and stores it.  When the main method is called it constructs a string from the URL and then passes that string into the init of an NSXMLDocument. If there is no error with the loading of the xml document, it is then passed back to the AppDelegate, on the main thread, and the task is complete.  When the main method of the NSOperation ends the queue will automatically release the object.</p>

<p><strong>AppDelegate.h</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &lt;Cocoa/Cocoa.h&gt;</span>
&nbsp;
<span style="color: #a61390;">@interface</span> AppDelegate <span style="color: #002200;">:</span> <span style="color: #400080;">NSObject</span> <span style="color: #002200;">&#123;</span>
	<span style="color: #400080;">NSOperationQueue</span> <span style="color: #002200;">*</span>queue;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>shared;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>pageLoaded<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSXMLDocument</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>document;
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>


<p><strong>AppDelegate.m</strong></p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #6e371a;">#import &quot;AppDelegate.h&quot;</span>
<span style="color: #6e371a;">#import &quot;PageLoadOperation.h&quot;</span>
&nbsp;
<span style="color: #a61390;">@implementation</span> AppDelegate
<span style="color: #a61390;">static</span> AppDelegate <span style="color: #002200;">*</span>shared;
<span style="color: #a61390;">static</span> <span style="color: #400080;">NSArray</span> <span style="color: #002200;">*</span>urlArray;
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>init
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>shared<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>self autorelease<span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">return</span> shared;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;
&nbsp;
    <span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>array <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>array addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://www.google.com&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>array addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://www.apple.com&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>array addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://www.yahoo.com&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>array addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://www.zarrastudios.com&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>array addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://www.macosxhints.com&quot;</span><span style="color: #002200;">&#93;</span>;
    urlArray <span style="color: #002200;">=</span> array;
&nbsp;
    queue <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSOperationQueue</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    shared <span style="color: #002200;">=</span> self;
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>applicationDidFinishLaunching<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSNotification</span> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>aNotification
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #400080;">NSString</span> <span style="color: #002200;">*</span>urlString <span style="color: #a61390;">in</span> urlArray<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #400080;">NSURL</span> <span style="color: #002200;">*</span>url <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #400080;">NSURL</span> URLWithString<span style="color: #002200;">:</span>urlString<span style="color: #002200;">&#93;</span>;
        PageLoadOperation <span style="color: #002200;">*</span>plo <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>PageLoadOperation alloc<span style="color: #002200;">&#93;</span> initWithURL<span style="color: #002200;">:</span>url<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>queue addOperation<span style="color: #002200;">:</span>plo<span style="color: #002200;">&#93;</span>;
        <span style="color: #002200;">&#91;</span>plo release<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>dealloc
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>queue release<span style="color: #002200;">&#93;</span>, queue <span style="color: #002200;">=</span> <span style="color: #a61390;">nil</span>;
    <span style="color: #002200;">&#91;</span>super dealloc<span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">+</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>shared;
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span>shared<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>AppDelegate alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">return</span> shared;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>pageLoaded<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #400080;">NSXMLDocument</span><span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>document;
<span style="color: #002200;">&#123;</span>
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%s Do something with the XMLDocument: %@&quot;</span>, _cmd, document<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>


<p>In this example AppDelegate, two things are occurring.  First, in the init method, the NSOperationQueue is being initialized and an array of urls is being loaded.  Then when the application has completed its load, the applicationDidFinishLaunching: method is called by the NSApplication instance and the AppDelegate loops over the urls, creating a task for each one and loading those tasks into the NSOperationQueue.  As soon as each item is loaded into the queue the queue will kick it off by assigning it to a NSThread and the thread will then run the main method of the operation.  Once the operation is complete the thread will report back to the queue and the queue will release the operation.</p>

<h2>NSOperationQueue Concurrency</h2>

<p>In this very simple example, it is quite difficult to load up the queue with enough objects to actually see it running them in parallel.  However, if you run tasks that take more time than these,  you will see that the queue will run all of the tasks at the same time.  Fortunately, if you want to limit how many tasks are running in parallel you can alter the init method in the App Delegate as follows:</p>


<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
</pre></td><td class="code"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>init
<span style="color: #002200;">&#123;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span>shared<span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
        <span style="color: #002200;">&#91;</span>self autorelease<span style="color: #002200;">&#93;</span>;
        <span style="color: #a61390;">return</span> shared;
    <span style="color: #002200;">&#125;</span>
    <span style="color: #a61390;">if</span> <span style="color: #002200;">&#40;</span><span style="color: #002200;">!</span><span style="color: #002200;">&#91;</span>super init<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#41;</span> <span style="color: #a61390;">return</span> <span style="color: #a61390;">nil</span>;
&nbsp;
    <span style="color: #400080;">NSMutableArray</span> <span style="color: #002200;">*</span>array <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSMutableArray</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>array addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://www.google.com&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>array addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://www.apple.com&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>array addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://www.yahoo.com&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>array addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://www.zarrastudios.com&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>array addObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;http://www.macosxhints.com&quot;</span><span style="color: #002200;">&#93;</span>;
    urlArray <span style="color: #002200;">=</span> array;
    queue <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span><span style="color: #400080;">NSOperationQueue</span> alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>queue setMaxConcurrentOperationCount<span style="color: #002200;">:</span><span style="color: #2400d9;">2</span><span style="color: #002200;">&#93;</span>;
    shared <span style="color: #002200;">=</span> self;
    <span style="color: #a61390;">return</span> self;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>


<p>In this updated init method, the queue is throttled down to 2 operations running at the same time.  The rest of the operations will wait until one of the first two is completed and then they will get an opportunity to run until the queue is empty.</p>

<h2>Conclusion</h2>

<p>That is the NSOperation and NSOperationQueue in its most basic form.  You will note that most of the code in this example has nothing to do with the building up or using of the NSOperation or the NSOperationQueue.  The actual code required to use the NSOperation is amazingly small.  Yet with this small amount of code you can easily start using multiple threads in your application and provide a better experience for the user and be able to fine tune those complicated tasks.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.cimgf.com/2008/02/16/cocoa-tutorial-nsoperation-and-nsoperationqueue/feed/</wfw:commentRss>
		<slash:comments>27</slash:comments>
		</item>
	</channel>
</rss>

