<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
 
 <title>Pat Collins</title>
 <link href="http://www.patcoll.com/atom.xml" rel="self"/>
 <link href="http://www.patcoll.com/"/>
 <updated>2011-04-19T12:00:42-07:00</updated>
 <id>http://www.patcoll.com/</id>
 <author>
   <name>Pat Collins</name>
   <email>pat@burned.com</email>
 </author>

 
 <entry>
   <title>Love and Hate Relationships: Core Data</title>
   <link href="http://www.patcoll.com/2011/04/15/love-hate-relationships-core-data.html"/>
   <updated>2011-04-15T00:00:00-07:00</updated>
   <id>http://www.patcoll.com/2011/04/15/love-hate-relationships-core-data</id>
   <content type="html">&lt;h1&gt;Love and Hate Relationships: Core Data&lt;/h1&gt;

&lt;p class=&quot;meta&quot;&gt;15 April 2011 - Pittsburgh&lt;/p&gt;


&lt;p&gt;I have been working with a lot of Objective-C and Cocoa for iOS lately.&lt;/p&gt;

&lt;p&gt;The joys and sorrows of Cocoa have evened themselves out, mostly.&lt;/p&gt;

&lt;p&gt;Developing for a popular mobile platform like iOS has its advantages. A lot of attention is paid to the entire infrastructure and ecosystem, which makes developing for it an easier task. Xcode is a great tool. There are data structures that &lt;a href=&quot;http://ridiculousfish.com/blog/archives/2005/12/23/array/&quot;&gt;optimize themselves&lt;/a&gt;. There are well-designed components for handling a lot of common tasks. StackOverflow has an endless supply of answered newbie questions that help enormously&lt;sup class=&quot;reference&quot;&gt;1&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;There is one unique set of sorrow and joy I'd like to share today, and it has to do with the data storage layer in Cocoa known as Core Data.&lt;/p&gt;

&lt;h2&gt;What happened&lt;/h2&gt;

&lt;p&gt;As I came to find out, managed objects (objects that inherit from &lt;code&gt;NSManagedObject&lt;/code&gt;) are always contained within a managed object context (&lt;code&gt;NSManagedObjectContext&lt;/code&gt;) in an application that uses Core Data. Managed object contexts (MOCs) are like scratchpads, in that you can create, modify or deleted managed objects in a context, but those changes do not actually get persisted to the data store unless the context is explicitly saved.&lt;/p&gt;

&lt;p&gt;(Design patterns FTW on this one: I had worked with this pattern before in well-designed ORMs like &lt;a href=&quot;http://www.doctrine-project.org/docs/orm/2.0/en/tutorials/getting-started-xml-edition.html#obtaining-the-entitymanager&quot;&gt;Doctrine 2&lt;/a&gt; and &lt;a href=&quot;http://www.sqlalchemy.org/docs/orm/tutorial.html#creating-a-session&quot;&gt;SQLAlchemy&lt;/a&gt; so it was easy to adapt to. I prefer to call it a &quot;context&quot; now. The name really drives home the meaning.)&lt;/p&gt;

&lt;p&gt;So my main user interface (UI) was constantly saving changes to objects in the foreground then persisting these changes to Core Data and ultimately to a web service. Every so often, a &lt;code&gt;sync&lt;/code&gt; action would download new information from the web service and change the data accordingly in Core Data. This all worked fine.&lt;/p&gt;

&lt;h2&gt;Sorrow&lt;/h2&gt;

&lt;p&gt;When a new requirement came down the pike I had to change the design to handle more objects in bulk. No biggie, right? Wrong. The more objects that the app had to handle at once, the more the &lt;code&gt;sync&lt;/code&gt; froze the UI by saving its changes. To make matters worse -- I was getting unexplained data conflicts and crashes because these data changes were seemingly pulling the rug from underneath what was happening in both the background and foreground. What was happening?&lt;/p&gt;

&lt;p&gt;When I dug deeper, I discovered that even though the &lt;code&gt;sync&lt;/code&gt; appeared like it was performing in the background, it was really performing its work on the main thread, which froze the UI. This wasn't really noticeable when I was dealing with one object at a time, but bulk processing these objects was a different story. I needed to change my approach.&lt;/p&gt;

&lt;p&gt;Also, because both the &quot;background&quot; and the &quot;foreground&quot; processes were happening on the main thread, and overlapping a little, they both were trying to change the same objects, causing conflicts and crashes that were almost impossible to reproduce in a consistent manner.&lt;/p&gt;

&lt;h2&gt;Joy&lt;/h2&gt;

&lt;p&gt;I realized I needed a real solution for processing the same data set in multiple places. Enter threads.&lt;/p&gt;

&lt;p&gt;You know those well-designed components I mentioned? They helped save my sanity. Through reading some really well-written articles&lt;sup class=&quot;reference&quot;&gt;2&lt;/sup&gt; I discovered that the key was to maintain separate managed object contexts for each set of data manipulation you do. Syncing in the background? A new MOC. Editing in the foreground? A new MOC.&lt;/p&gt;

&lt;p&gt;I ended up implementing the approach that describes how to &lt;a href=&quot;http://www.cocoabuilder.com/archive/cocoa/293250-nsmanagedobjectcontextdidsavenotification-across-mocs-on-two-threads.html#293295&quot;&gt;maintain and synchronize data among thread-specific MOCs&lt;/a&gt;. That, combined with running the &lt;code&gt;sync&lt;/code&gt; process in a true background thread, helped alleviate my Core Data woes. I'll include some obfuscated code here for completeness, and hopefully clarity.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/922466.js&quot;&gt; &lt;/script&gt;


&lt;p&gt;&lt;small&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;As an aside, being told to RTFM as a beginner in a particular language or framework is really frustrating. As a programmer I have a good base of knowledge I can use to carefully craft my Google searches. I am eternally grateful for non-RTFM folks who have an ounce of patience to craft their kind answers (or debates) just as carefully, if not more so. The programming community, especially the new guns who learn everything through self-discovery and Google, would be nowhere without these people. Myself included.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Highly-recommended Core Data articles&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html&quot;&gt;Concurrency with Core Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.duckrowing.com/2010/03/11/using-core-data-on-multiple-threads/&quot;&gt;Using Core Data on Multiple Threads&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.timisted.net/blog/archive/multiple-managed-object-contexts-with-core-data/&quot;&gt;Multiple Managed Object Contexts with Core Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.cocoabuilder.com/archive/cocoa/293250-nsmanagedobjectcontextdidsavenotification-across-mocs-on-two-threads.html#293295&quot;&gt;NSManagedObjectContextDidSaveNotification across MOCs on two threads&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;&lt;/small&gt;&lt;/p&gt;

&lt;div id=&quot;disqus_thread&quot;&gt;&lt;/div&gt;


&lt;script type=&quot;text/javascript&quot;&gt;
    /* * * CONFIGURATION VARIABLES: EDIT BEFORE PASTING INTO YOUR WEBPAGE * * */
    var disqus_shortname = 'patcoll'; // required: replace example with your forum shortname

    // The following are highly recommended additional parameters. Remove the slashes in front to use.
    var disqus_identifier = '2011-04-15-love-hate-relationships-core-data';
    var disqus_url = 'http://www.patcoll.com/2011/04/15/love-hate-relationships-core-data.html';

    /* * * DON'T EDIT BELOW THIS LINE * * */
    (function() {
        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
        dsq.src = 'http://' + disqus_shortname + '.disqus.com/embed.js';
        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
    })();
&lt;/script&gt;


&lt;p&gt;&lt;noscript&gt;Please enable JavaScript to view the &lt;a href=&quot;http://disqus.com/?ref_noscript&quot;&gt;comments powered by Disqus.&lt;/a&gt;&lt;/noscript&gt;
&lt;a href=&quot;http://disqus.com&quot; class=&quot;dsq-brlink&quot;&gt;blog comments powered by &lt;span class=&quot;logo-disqus&quot;&gt;Disqus&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Hello World, Again</title>
   <link href="http://www.patcoll.com/2011/04/13/hello-world-again.html"/>
   <updated>2011-04-13T00:00:00-07:00</updated>
   <id>http://www.patcoll.com/2011/04/13/hello-world-again</id>
   <content type="html">&lt;h1&gt;Hello World, Again&lt;/h1&gt;

&lt;p class=&quot;meta&quot;&gt;13 April 2011 - Pittsburgh&lt;/p&gt;


&lt;p&gt;This is my first experiment in blogging in over three years. Previous archives have been ruthlessly purged. Future blog posts be warned.&lt;/p&gt;

&lt;p&gt;There will be more here once I gather my thoughts a bit more.&lt;/p&gt;
</content>
 </entry>
 
 
</feed>