<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;Ck8FQXk4fip7ImA9WhRaGU4.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471</id><updated>2012-02-22T10:13:30.736-07:00</updated><category term="KVC" /><category term="cstring" /><category term="UIStoryboard" /><category term="Grand Central Dispatch" /><category term="Book Review" /><category term="User Interface" /><category term="Twitter" /><category term="Storyboard" /><category term="GCD" /><category term="Delegate" /><category term="Template" /><category term="Computer Science" /><category term="Dynamic Runtime" /><category term="UITabBarController" /><category term="Pragmatic Bookshelf" /><category term="XIB" /><category term="C" /><category term="Key-Value Validation" /><category term="UX" /><category term="Facebook Connect" /><category term="Quartz Composer" /><category term="Map Kit" /><category term="Core Data" /><category term="Design" /><category term="UIAlertView" /><category term="Quick Look" /><category term="GDAL" /><category term="Management" /><category term="Memory Management" /><category term="Thread Safety" /><category term="Best Practices" /><category term="KVO" /><category term="Key-Value Coding" /><category term="C++" /><category term="Makefile" /><category term="Category" /><category term="iPhone" /><category term="KVV" /><category term="Singleton" /><category term="Blocks" /><category term="Objective-C" /><category term="Design Pattern" /><category term="UITableView" /><category term="iOS" /><category term="UIActionSheet" /><category term="UITableViewCell" /><category term="UITextField" /><title>Programming Knowledge Base</title><subtitle type="html">A collection of obscure errors and elegant solutions.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://robsprogramknowledge.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>32</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/ProgrammingKnowledgeBase" /><feedburner:info uri="programmingknowledgebase" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CEEAQXc-fyp7ImA9WhRVFU0.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-2043201370339821980</id><published>2012-01-13T15:40:00.000-07:00</published><updated>2012-01-13T17:57:20.957-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-13T17:57:20.957-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="XIB" /><category scheme="http://www.blogger.com/atom/ns#" term="Best Practices" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="iOS" /><category scheme="http://www.blogger.com/atom/ns#" term="UIStoryboard" /><category scheme="http://www.blogger.com/atom/ns#" term="User Interface" /><title>UIStoryboard Best Practices</title><content type="html">&lt;div style="text-align: left;"&gt;
UIStoryboard is a hot topic right now in iOS. However, there have been many misconceptions on the topic. The first reaction to storyboards (what I have seen anyway) is that they are a panacea for all situations. Following that reaction I saw many people claim that storyboards are awful and broken. The truth is, both these ideas are wrong. During WWDC 2011 Apple may have over-promoted storyboards, thus giving the wrong impression and leading to unmet expectations. Let me correct this now: UIStoryboard is not an all-purpose solution, it is another tool for your toolbox.&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
My intent here is to provide the best practices for UIStoryboard. I will list my lessons learned, but there are probably more yet to learn. I expect over time that this list will expand to include other best practices for UIStoryboard.&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;strong&gt;Break your storyboard into modules&lt;/strong&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
The first mistake developers have been making with storyboarding is producing large, monolithic storyboards. A single storyboard may be suitable for small apps but certainly not for large apps. Don't forget one of the key principles of programming and abstraction: &lt;em&gt;decomposition&lt;/em&gt;. We decompose our code into modules to make them more reusable and reduce maintenance costs. The same is true for user interfaces, and it applies whether you are using UIStoryboards, XIBs, or anything else. There is an even deeper principle wanting to emerge: when code and user interfaces are decomposed &lt;em&gt;together&lt;/em&gt;, then you have truly useful and reusable code, user interfaces, and products (you can quote me on this). &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
The first question to ask is "how do I identify the natural modules of my app?" Let's start with something easy. Many apps are based on a tab bar controller. Each tab is a natural module and you hence you can put them in their own storyboard. Next, if you have two tabs (or any two views for that matter) with a segue to a common view, then that common view (and its following hierarchy) is almost certainly another natural module. Once you have pruned your view hierarchy, you will probably find that each module can be given a name. For example, you may have your login storyboard, settings storyboard, about storyboard, main storyboard, etc. If you can give a fitting name to each module, then you have decomposed your hierarchy well. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
Keep in mind that having a single view in a storyboard is not a bad thing. This is particularly true with table views. The power of static and prototype table view cells is very useful. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
You should also note that breaking storyboards into modules makes them more friendly to version control and sharing among a team. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;strong&gt;You don't need to convert everything at once&lt;/strong&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
When you first saw storyboards, you may have had an urge to convert everything over to UIStoryboard. I know I did. Be aware that this does take time and you may not gain any immediate benefits from switching everything. Fortunately, you don't need to do it all at once. You can switch over the parts of your app that will benefit the most now. Then over time you can slowly switch out others. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;strong&gt;Make custom UITableViewCell subclasses for prototype cells&lt;/strong&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
Probably the best feature of UIStoryboard is prototype cells. They make custom table view cells easy. Prototype cells can be easily customized; however, the UITableViewCell class may not specify the IBOutlets you need. A custom subclass also gives you another advantage. You can create a -setupWith&amp;lt;#Object#&amp;gt;: method. This takes your setup code out of your table view controller and into the cell itself. This is where you can gain some great reuse. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
Not only can you create custom UITableViewCell subclasses, but you can have one subclass service many prototype cells. For example, you may have a cell that takes a Person object. In one table view your cell may have main label on the left and a detail label on the right. A different table view may use the same cell but have a main label above and a detail label below. Your cell subclass handles the content, but the prototype cell handles the look and feel. Again we gain great reuse and flexibility by decomposing code and views together.&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;strong&gt;Don't forget about IBAction, IBOutlet, and IBOutletCollection&lt;/strong&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
Segues are nice and can do a lot, but don't forget about the other IB fundamentals. Segues can't cross storyboards, but IBActions can. IBActions can also clean up an unnecessary spaghetti segue mess and reduce the need for custom segues. Everything has their place and their use; they are all tools at your disposal. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
While on the topic of IBActions and family, I should cover encapsulation. Most, if not all, your actions and outlets do not need to be public. So, rather than put them in your public headers, put them in a class extension. See &lt;a href="http://robsprogramknowledge.blogspot.com/2011/08/objective-c-property.html"&gt;here&lt;/a&gt; for more details. Xcode/Interface Builder didn't handle this well in the past but now there are no problems. This keeps your interfaces much cleaner and easier for others to understand. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;strong&gt;Don't forget about XIBs&lt;/strong&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
Even though storyboards are very similar to XIBs, they still have a place. Simple, one-view modules may be better represented as XIBs. Also, XIBs can hold custom views without an associated view controller. UIStoryboard requires that view controllers be the basic unit. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;strong&gt;You don't need to have a main storyboard&lt;/strong&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
You may have noticed your app settings now has a "Main Storyboard" setting. To use UIStoryboard you are not required to use this. In fact, my latest project has neither a main storyboard nor a main XIB. It uses a programmatic UITabBarController. From there I load all my tab storyboards. The beauty of it all is that it doesn't matter whether I use UIStoryboards, XIBs, or code. All three options are flexible enough to work with each other in any combination.&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;strong&gt;Specify the name of your app delegate in main.m&lt;/strong&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
As I mentioned &lt;a href="http://robsprogramknowledge.blogspot.com/2011/12/migrating-to-uistoryboard.html"&gt;the other day&lt;/a&gt;, you may need to change your main.m file if it doesn't specify your app delegate's name. It should look something like this:&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: #2b839f; font-size: 11pt;"&gt;UIApplicationMain&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(argc, argv, &lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;nil&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;, &lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;NSStringFromClass&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;([&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;MyAppDelegate&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;class&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;]))&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;strong&gt;Put your storyboards in a category&lt;/strong&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
To get one of your storyboards, you need to call +storyboardWithName:bundle:. Be wary any time you need to hard code a string for a key, especially one that can change frequently. Should you ever need to rename your storyboard, you will have to change all references to that storyboard. My favorite way to handle this is with a category. It looks something like this:&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: 11pt;"&gt;@implementation&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;UIStoryboard (MyApp)&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;+ (&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;UIStoryboard&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;*)mainStoryboard {&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; return&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;[&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;UIStoryboard&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;storyboardWithName&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;:&lt;/span&gt;&lt;span style="color: #a31515; font-size: 11pt;"&gt;@"MainStoryboard"&amp;nbsp;&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;bundle&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;:&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;nil&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;];&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: 11pt;"&gt;@end&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
The benefit of the category approach is that if you ever rename a storyboard, you only need to change the hard coded string in one place. It also makes your code more readable.&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;strong&gt;Summary&lt;/strong&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
If you take anything from this post you should remember these:&lt;/div&gt;
&lt;ol style="list-style-type: decimal;"&gt;
&lt;li style="text-align: left;"&gt;Decompose your code and your views.&lt;/li&gt;
&lt;li style="text-align: left;"&gt;UIStoryboard is a great tool, but it's not the only tool.&lt;/li&gt;
&lt;/ol&gt;
I hope these tips and best practices help promote proper use of UIStoryboard. I invite all my readers to let me know of other best practices they encounter. &lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-2043201370339821980?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=vdGQEl2f6ZM:toalIhLB2BE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=vdGQEl2f6ZM:toalIhLB2BE:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=vdGQEl2f6ZM:toalIhLB2BE:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=vdGQEl2f6ZM:toalIhLB2BE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=vdGQEl2f6ZM:toalIhLB2BE:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=vdGQEl2f6ZM:toalIhLB2BE:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/vdGQEl2f6ZM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/2043201370339821980/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2012/01/uistoryboard-best-practices.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/2043201370339821980?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/2043201370339821980?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/vdGQEl2f6ZM/uistoryboard-best-practices.html" title="UIStoryboard Best Practices" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2012/01/uistoryboard-best-practices.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEIBQHY5cSp7ImA9WhRVFU0.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-6577677230484924316</id><published>2011-12-15T19:21:00.000-07:00</published><updated>2012-01-13T17:55:51.829-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-01-13T17:55:51.829-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Storyboard" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="iOS" /><title>Migrating to UIStoryboard</title><content type="html">&lt;div style="text-align: left;"&gt;
I’ve just recently started using UIStoryboard and so far I’ve been very pleased with it. Building the UI is faster, easier, and requires less code. It’s also immensely helpful to get a bird’s eye view of your full workflow. However, when migrating an old app from using regular XIBs to UIStoryboard I did encounter some troubles. When launching the app, I would get the following error messages:&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;strong&gt;“The app delegate must implement the window property if it wants to use a main storyboard file.”&lt;/strong&gt;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
and&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;strong&gt;“Applications are expected to have a root view controller at the end of application launch.”&lt;/strong&gt;&lt;/span&gt; &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
I could clearly see that my app delegate was implementing the window property as expected. Fortunately, &lt;a href="http://stackoverflow.com/a/7730798/371357"&gt;StackOverflow&lt;/a&gt; came to the rescue. It turns out that main.m needs to be modified when switching to UIStoryboard from XIBs (in older projects). The change looks like this:&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: #007400; font-size: 11pt;"&gt;// Old main.m&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: #2e0d6e; font-size: 11pt;"&gt;UIApplicationMain&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(argc, argv, &lt;/span&gt;&lt;span style="color: #aa0d91; font-size: 11pt;"&gt;nil&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;, &lt;/span&gt;&lt;span style="color: #aa0d91; font-size: 11pt;"&gt;nil&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: #007400; font-size: 11pt;"&gt;// New main.m&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: #2e0d6e; font-size: 11pt;"&gt;UIApplicationMain&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(argc, argv, &lt;/span&gt;&lt;span style="color: #aa0d91; font-size: 11pt;"&gt;nil&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;, &lt;/span&gt;&lt;span style="color: #2e0d6e; font-size: 11pt;"&gt;NSStringFromClass&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;([&lt;/span&gt;&lt;span style="color: #3f6e74; font-size: 11pt;"&gt;MyAppDelegate&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2e0d6e; font-size: 11pt;"&gt;class&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;]));&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
The documentation for this parameter reads:&lt;/div&gt;
&lt;br /&gt;
&lt;span style="font-size: 13pt;"&gt;The name of the class from which the application delegate is instantiated. If principalClassName designates a subclass of &lt;/span&gt;&lt;span style="color: #535353; font-size: 13pt;"&gt;UIApplication&lt;/span&gt;&lt;span style="font-size: 13pt;"&gt;, you may designate the subclass as the delegate; the subclass instance receives the application-delegate messages. Specify &lt;/span&gt;&lt;span style="color: #535353; font-size: 13pt;"&gt;nil&lt;/span&gt; &lt;span style="font-size: 13pt;"&gt;if you load the delegate object from your application’s main nib file.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
Basically, if you aren’t using XIBs, you must let UIApplication know what your app delegate’s name is. You will also notice that any new projects created with the latest version of Xcode will specify the app delegate, even if you are using XIBs. This prevents any problems should you migrate to UIStoryboard later. &lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-6577677230484924316?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=l1P0AUUmKRI:orIPyKsNbEU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=l1P0AUUmKRI:orIPyKsNbEU:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=l1P0AUUmKRI:orIPyKsNbEU:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=l1P0AUUmKRI:orIPyKsNbEU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=l1P0AUUmKRI:orIPyKsNbEU:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=l1P0AUUmKRI:orIPyKsNbEU:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/l1P0AUUmKRI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/6577677230484924316/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/12/migrating-to-uistoryboard.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/6577677230484924316?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/6577677230484924316?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/l1P0AUUmKRI/migrating-to-uistoryboard.html" title="Migrating to UIStoryboard" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/12/migrating-to-uistoryboard.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UNSH06eyp7ImA9WhRQGUQ.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-5800577462295539860</id><published>2011-12-15T17:00:00.000-07:00</published><updated>2011-12-15T17:28:19.313-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-15T17:28:19.313-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Category" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="iOS" /><title>UIColor Category</title><content type="html">&lt;div style="text-align: left;"&gt;
For a long time I’ve wanted more convenience methods for UIColor. The set Apple provides is a nice starting point but I often find myself wanting more. In particular, the Mac color picker has a crayon box color picker with common colors. Sadly, there are no convenience methods for these colors. Since I use them so frequently, I decided to put them all in a category. This was tedious work since I had to do them one-by-one by hand. &lt;/div&gt;
&lt;br /&gt;
After getting these 48 convenience methods I figured why stop there. I moved on to the HTML colors. At the time I didn’t realize how many standard HTML colors exist (147). After seeing that number I almost threw out the idea, but I remembered that &lt;a href="https://twitter.com/#!/alesplin"&gt;@alesplin&lt;/a&gt; taught how to use Vim macros in the November BYU CocoaHeads meeting. Using a list of HTML colors and their associated hex values, I had all 147 HTML color convenience methods finished within minutes. Vim may be an old, crusty text editor, but its macro editing power is unmatched by modern IDEs.&lt;br /&gt;
&lt;br /&gt;
If you want a copy of my UIColor category, you can find it in my &lt;a href="https://github.com/rob-brown/RBCategories/blob/master/UIColor+RBExtras.m"&gt;RBCategories repo&lt;/a&gt; on Github.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-5800577462295539860?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=CPapZJf9i1E:jHmJ1LT8hIc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=CPapZJf9i1E:jHmJ1LT8hIc:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=CPapZJf9i1E:jHmJ1LT8hIc:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=CPapZJf9i1E:jHmJ1LT8hIc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=CPapZJf9i1E:jHmJ1LT8hIc:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=CPapZJf9i1E:jHmJ1LT8hIc:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/CPapZJf9i1E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/5800577462295539860/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/12/uicolor-category.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/5800577462295539860?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/5800577462295539860?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/CPapZJf9i1E/uicolor-category.html" title="UIColor Category" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/12/uicolor-category.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08MQXwyeSp7ImA9WhRRF0w.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-8353228265032237844</id><published>2011-11-30T19:18:00.000-07:00</published><updated>2011-11-30T20:58:00.291-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-30T20:58:00.291-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Grand Central Dispatch" /><category scheme="http://www.blogger.com/atom/ns#" term="Thread Safety" /><category scheme="http://www.blogger.com/atom/ns#" term="GCD" /><title>Read/Write Lockless Exclusion</title><content type="html">&lt;div style="text-align: left;"&gt;
With the recent release of iOS 5, GCD now has a simple and elegant solution to the &lt;a href="http://en.wikipedia.org/wiki/Readers-writers_problem"&gt;reader writer problem&lt;/a&gt; that utilizes lockless exclusion. In summary, this involves using dispatch_async (or dispatch_sync) to enqueue "reader" blocks onto a user concurrent queue. These blocks may be used to read some kind of data but not write to it. If we need write access, then we can use the new dispatch_barrier_async (or dispatch_barrier_sync) function. This will put a special barrier block on the queue. The blocks are still dequeued in FIFO order. However, when there are one or more reader blocks running, then a writer block may not be dequeued. While a single writer block is running, no other blocks may be dequeued, including other writer blocks. This guarantees that writer blocks have exclusive access and reader blocks may share access.&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
The new barrier blocks and user concurrent queues are immensely valuable. Lately, I've been considering how they relate to my recently developed Lockless Exclusion Accessor (LEA) design pattern. If you are not already familiar with my LEA pattern, you should first read &lt;a href="http://robsprogramknowledge.blogspot.com/2011/09/lockless-exclusion-accessor-pattern.html"&gt;my LEA article&lt;/a&gt;. The intent of a LEA is to make mutual exclusion easy and efficient. Since we want to be efficient, let's push efficiency further by allowing shared read access. Here is some generic code that does just that: &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: green; font-size: 11pt;"&gt;/// Block type to use when accessing the shared memory.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: green; font-size: 11pt;"&gt;/// The type is 'id' just to be generic. With a real&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: green; font-size: 11pt;"&gt;/// LEA, you should use the exact type.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: 11pt;"&gt;typedef&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;void&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(^LEABlock)(&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;id&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;sharedMemory);&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: green; font-size: 11pt;"&gt;/// Class extension for holding the private, shared memory&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: green; font-size: 11pt;"&gt;/// and its associated queue.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: 11pt;"&gt;@interface&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;MyObject&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;()&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: 11pt;"&gt;@property&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;(&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;nonatomic&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;, &lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;strong&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;) &lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;id&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;sharedMemory;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: 11pt;"&gt;@property&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;(&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;nonatomic&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;, &lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;assign&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;) &lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;dispatch_queue_t&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;leaQueue;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: 11pt;"&gt;@end&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: 11pt;"&gt;@implementation&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;MyObject&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: 11pt;"&gt;@synthesize&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;sharedMemory = &lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;_sharedMemory&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: 11pt;"&gt;@synthesize&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;leaQueue     = &lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;_leaQueue&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;- (&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;id&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;)init {&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; if&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;((&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;self&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;= [&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;super&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;init&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;])) {&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: green; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // The queue MUST be concurrent to gain shared readership.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: #2b839f; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; dispatch_queue_t&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;queue = &lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;NULL&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;;&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; queue = &lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;dispatch_queue_create&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: #a31515; font-size: 11pt;"&gt;"com.RobBrown.LEAQueue"&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;,&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;DISPATCH_QUEUE_CONCURRENT&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;);&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;self&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;setLeaQueue&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;:queue];&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: green; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Initialize shared memory here.&lt;/span&gt;&lt;/div&gt;
&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;return&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;self&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;;&lt;/span&gt;&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;- (&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;void&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;)accessSharedMemoryReadWriteAsync:(&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;LEABlock&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;)block {&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: green; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; // Block must not be nil.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; NSParameterAssert&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(block);&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: green; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; // Executes the block asynchronously with exclusive access.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; dispatch_barrier_async&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;([&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;self&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;leaQueue&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;], ^{&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; block([&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;self&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;sharedMemory&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;]);&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; });&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;- (&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;void&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;)accessSharedMemoryReadOnlyAsync:(&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;LEABlock&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;)block {&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: green; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; // Block must not be nil.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; NSParameterAssert&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(block);&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: green; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; // Executes the block asynchronously with shared access.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; dispatch_async&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;([&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;self&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;leaQueue&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;], ^{&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; block([&lt;/span&gt;&lt;span style="color: blue; font-size: 11pt;"&gt;self&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2b839f; font-size: 11pt;"&gt;sharedMemory&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;]);&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; });&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: blue; font-size: 11pt;"&gt;@end&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
The first thing to note is that the dispatch queue is now concurrent instead of serial. If you use a serial queue then you will have no added benefits. The next thing to note is that every previous LEA in your object splits in two: a readonly version and a read write version. It's only four extra lines for a potentially great increase in efficiency. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
As always, you should favor dispatch_async over dispatch_sync. If you must have synchronous access, then you can add synchronous variants too. You must, however, never use my &lt;a href="http://robsprogramknowledge.blogspot.com/2011/11/dispatchsyncsafe-deprecated.html"&gt;dispatch_sync_checked function&lt;/a&gt;. It is not and never will be compatible with barrier blocks. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
By introducing the readonly LEA, we now introduce a potential point of failure. What if we write some code that uses a readonly LEA, then we later change the code to modify the shared memory without switching to a read write LEA? This could introduce race conditions. If needed, you can add a sanity check to your readonly LEA. Here are a few options:&lt;/div&gt;
&lt;ol style="list-style-type: decimal;"&gt;
&lt;li style="text-align: left;"&gt;If the object you are passing back has mutable and immutable variants, create two block types. The read write LEA will use the mutable variant and the readonly LEA will use the immutable variant. This is the best solution. &lt;/li&gt;
&lt;li style="text-align: left;"&gt;If you don't have mutable and immutable variants, then you can simply pass a copy of the shared memory to the readonly block. This can potentially mask errors since you won't know if you accidentally use a readonly LEA when you meant to use a read write LEA. &lt;/li&gt;
&lt;li style="text-align: left;"&gt;Before calling the block, you copy the shared memory. Then after calling the block, you check that the shared memory was not changed by comparing it to the earlier copy. If it was changed, then throw an exception. Although Objective-C rarely throws exceptions, this is an appropriate place to do so. Overall, this solution can be tedious work. You should also use a pre-processor macro to remove this check from release builds for efficiency. &lt;/li&gt;
&lt;li style="text-align: left;"&gt;You can create a subclass of NSProxy. Instead of passing back the shared memory you can pass it the proxy. This proxy should throw an exception if any setters are called. This too can be tedious work. You may want to use a pre-processor macro here as well to remove the proxy in release builds. &lt;/li&gt;
&lt;/ol&gt;
Don't forget that user concurrent queues and barrier blocks are iOS 5 (and Mac OS X Lion) only. If you are using iOS 5 and you need mutual exclusion, I highly recommend using Read/Write LEAs (or at least regular LEAs). They make mutual exclusion fast and easy. &lt;br /&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-8353228265032237844?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=Y2uoewMUobo:DG3YVvvyqaw:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=Y2uoewMUobo:DG3YVvvyqaw:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=Y2uoewMUobo:DG3YVvvyqaw:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=Y2uoewMUobo:DG3YVvvyqaw:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=Y2uoewMUobo:DG3YVvvyqaw:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=Y2uoewMUobo:DG3YVvvyqaw:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/Y2uoewMUobo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/8353228265032237844/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/11/readwrite-lockless-exclusion.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/8353228265032237844?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/8353228265032237844?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/Y2uoewMUobo/readwrite-lockless-exclusion.html" title="Read/Write Lockless Exclusion" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/11/readwrite-lockless-exclusion.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEARXc-cSp7ImA9WhRRFU4.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-4669976152880351491</id><published>2011-11-28T18:33:00.000-07:00</published><updated>2011-11-28T19:27:24.959-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-28T19:27:24.959-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Grand Central Dispatch" /><category scheme="http://www.blogger.com/atom/ns#" term="Thread Safety" /><category scheme="http://www.blogger.com/atom/ns#" term="GCD" /><title>dispatch_sync_safe Deprecated</title><content type="html">&lt;div style="text-align: left;"&gt;
A while back I wrote a &lt;a href="https://github.com/rob-brown/RBCategories/blob/master/GCD+RBExtras.c"&gt;pseudo-category for GCD&lt;/a&gt; and posted it to Github. It contains several convenience functions. One of them was a method that makes synchronous calls “safe,” or so I thought. The code looked like this:&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: #aa0d91; font-size: 11pt;"&gt;void&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;dispatch_sync_safe(&lt;/span&gt;&lt;span style="color: #5c2699; font-size: 11pt;"&gt;dispatch_queue_t&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;queue, &lt;/span&gt;&lt;span style="color: #5c2699; font-size: 11pt;"&gt;dispatch_block_t&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;block) {&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #007400; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; // If we're already on the given queue, just run the block.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #aa0d91; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; if&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;(&lt;/span&gt;&lt;span style="color: #2e0d6e; font-size: 11pt;"&gt;dispatch_get_current_queue&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;() == queue)&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; block();&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #007400; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; // Otherwise, dispatch to the given queue.&lt;/span&gt;&lt;/div&gt;
&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;span class="Apple-style-span" style="color: #aa0d91; font-size: 15px;"&gt;else&lt;/span&gt;&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2e0d6e; font-size: 11pt;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; dispatch_sync&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(queue, block);&lt;/span&gt;&lt;/div&gt;
&lt;span class="Apple-style-span" style="font-size: 15px;"&gt;}&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
The idea is that when doing a synchronous dispatch to a queue, I check if the program was already running on that queue. If it is, then the block is immediately executed. Otherwise, the block is run with a regular dispatch_sync. In my naïve implementation I thought this would prevent deadlock. The idea is nice but not correct. Consider the case when we dispatch_sync_safe to queue A. Next, we dispatch_sync_safe to queue B. Finally, we dispatch_sync_safe back to queue A. This is guaranteed deadlock. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
As a result of this case, I immediately marked dispatch_sync_safe as deprecated in my Github repo. Anyone using this function thinking it is perfectly safe should think again. I did, however, add another function called dispatch_sync_checked. It is actually the same implementation as dispatch_sync_safe just under a different name. I recognize that this simple function has great value, but the old name was misleading. The moral of the story is, use dispatch_async (or one of my dispatch_async convenience methods) whenever possible. If you must run code synchronously, use dispatch_sync_checked and be very cautious of deadlock. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
As I mentioned previously, dispatch_sync_checked still has great value. There is at least one case where you can guarantee you won’t deadlock. Consider the case when you have an object with a private serial dispatch queue. This queue is used to serialize access to some shared memory within the object. Using dispatch_sync_checked on the private queue allows you to keep your object’s methods synchronous and thread safe. This requires following two conditions in your critical code:&lt;/div&gt;
&lt;ol style="list-style-type: decimal;"&gt;
&lt;li style="text-align: left;"&gt;Do not make synchronous calls to external objects (which could synchronously call the calling object again).&lt;/li&gt;
&lt;li style="text-align: left;"&gt;Do not call dispatch_sync on any queue (or dispatch_sync_checked on any queue except the private queue).&lt;/li&gt;
&lt;/ol&gt;
Also, since these methods check for running on the private queue, they can call each other without worrying about deadlock. This gives similar behavior to a recursive lock without the overhead. If @synchronized(self) { … } just isn’t fast enough, consider switching to dispatch_sync_checked(_queue, ^{ … }).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-4669976152880351491?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=nupUoQXp_L8:fYs2k5Wciz0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=nupUoQXp_L8:fYs2k5Wciz0:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=nupUoQXp_L8:fYs2k5Wciz0:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=nupUoQXp_L8:fYs2k5Wciz0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=nupUoQXp_L8:fYs2k5Wciz0:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=nupUoQXp_L8:fYs2k5Wciz0:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/nupUoQXp_L8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/4669976152880351491/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/11/dispatchsyncsafe-deprecated.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/4669976152880351491?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/4669976152880351491?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/nupUoQXp_L8/dispatchsyncsafe-deprecated.html" title="dispatch_sync_safe Deprecated" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/11/dispatchsyncsafe-deprecated.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4NQn8_cCp7ImA9WhdbGEU.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-6222324203273434016</id><published>2011-10-17T12:24:00.000-06:00</published><updated>2011-10-17T13:49:53.148-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-17T13:49:53.148-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Computer Science" /><title>My Philosophy on Language</title><content type="html">&lt;div style="text-align: left;"&gt;
When I was called to serve a mission in Canada for The Church of Jesus Christ of Latter-day Saints, I was called to English-speaking assignment. During my mission, I spent six months in a French-speaking assignment since I had taken three years of French in high school. After serving in that assignment for quite some time, I found that my thoughts had become detached from all language. This skill was useful (and probably resulted) because I spent all day switching between French and English. When I thought of something, I would mentally envision the object or idea rather than thinking of the English or French equivalent. This way I could mentally transition between languages without any loss of context.&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
I think language can limit our mental capacities. If we all view the world in the context of our native language, then we can only express ideas that already exist in that language. Language, however, is necessary so we can communicate our thoughts to others. Ironically, I must write this short article in a language, which makes it somewhat difficult to express such an abstract idea.&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
So, how does this relate to computer science? Programming languages are just as much languages as the natural languages, such as English or French. The difference is that programming languages can express different ideas from natural languages. Like natural languages, not all programming languages can express the same ideas. This may limit what you as a developer can mentally design and express. For example, if your language doesn’t support blocks, then you probably don’t know what continuations are. One reason that I like Objective-C so much is that it allows me to express many ideas freely, especially when playing with the dynamic runtime.&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
Likewise, if we only think in the context of our favorite programming language(s), then we can only develop ideas that already exist in that/those languages(s). By becoming detached from all languages (both natural and programmatic) we open ourselves to think of ideas that don’t exist yet. Once we create a new idea, we are then obligated to express that idea in a language or change our language to allow us to express that idea to other people. Again, the language we express our idea in can be natural or programmatic.&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
By the way, my ideas on language have a direct connection to &lt;a href="http://dl.acm.org/citation.cfm?id=352194"&gt;The Five Orders of Ignorance by Philip Armour&lt;/a&gt;. Briefly, Armour argues that in order to ask questions and find answers about some idea, we must first develop a framework for thinking about that idea. I think that language is indirectly, and often directly, related to developing mental frameworks for thinking.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-6222324203273434016?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=BocMy9oHHy0:ssfg93-IaNc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=BocMy9oHHy0:ssfg93-IaNc:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=BocMy9oHHy0:ssfg93-IaNc:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=BocMy9oHHy0:ssfg93-IaNc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=BocMy9oHHy0:ssfg93-IaNc:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=BocMy9oHHy0:ssfg93-IaNc:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/BocMy9oHHy0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/6222324203273434016/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/10/my-philosophy-on-language.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/6222324203273434016?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/6222324203273434016?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/BocMy9oHHy0/my-philosophy-on-language.html" title="My Philosophy on Language" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/10/my-philosophy-on-language.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4GSX44fCp7ImA9WhdUGUw.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-5293253756218565196</id><published>2011-10-06T07:57:00.000-06:00</published><updated>2011-10-06T08:22:08.034-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-10-06T08:22:08.034-06:00</app:edited><title>A Tribute to Steve Jobs</title><content type="html">The world is mourning the loss of a great man. I just hope that his great vision has not been lost as well. Steve lived his dreams. He was never content and continually pushed the boundaries of technology. His quest for perfection led to unparalleled products and user experiences. Perhaps it is best said of him what was said back in 1997:&lt;br /&gt;&lt;br /&gt;Here’s to the crazy one. The misfit. The rebel. The trouble-maker. The Square peg in the round holes. The one who saw things differently. He wasn’t fond of rules, and he had no respect for the status quo. You can quote him, disagree with him, glorify, or vilify him. About the only thing you can’t do is ignore him. Because he changed things. He pushed the human race forward. And while some may see him as the crazy one, we see genius. Because he was crazy enough to think he could change the world, and he did! &lt;br /&gt;&lt;br /&gt;Thank you for everything Steve Jobs. Because of you I have a job I love. The technology you developed has made life better and the world more connected. Through your example, others have strived to push their limits, including me. Rest in peace Steve and may God watch over your family. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-5293253756218565196?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=YJeukmDTA6s:3doX8OwM-jY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=YJeukmDTA6s:3doX8OwM-jY:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=YJeukmDTA6s:3doX8OwM-jY:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=YJeukmDTA6s:3doX8OwM-jY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=YJeukmDTA6s:3doX8OwM-jY:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=YJeukmDTA6s:3doX8OwM-jY:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/YJeukmDTA6s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/5293253756218565196/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/10/tribute-to-steve-jobs.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/5293253756218565196?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/5293253756218565196?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/YJeukmDTA6s/tribute-to-steve-jobs.html" title="A Tribute to Steve Jobs" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/10/tribute-to-steve-jobs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ADRX0_cCp7ImA9WhRRF0w.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-3321222835044084569</id><published>2011-09-17T21:46:00.000-06:00</published><updated>2011-11-30T20:56:14.348-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-30T20:56:14.348-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Grand Central Dispatch" /><category scheme="http://www.blogger.com/atom/ns#" term="Design Pattern" /><category scheme="http://www.blogger.com/atom/ns#" term="Thread Safety" /><category scheme="http://www.blogger.com/atom/ns#" term="Blocks" /><category scheme="http://www.blogger.com/atom/ns#" term="GCD" /><title>Lockless Exclusion Accessor Pattern</title><content type="html">&lt;div style="text-align: left;"&gt;
With all the work I have been doing with blocks and Grand Central Dispatch (GCD), I have developed a useful design pattern for handling mutual exclusion. I haven’t seen any patterns quite like this one, so I’ll claim it as my own. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
Mutual exclusion is always a challenge when multithreading any application. GCD makes mutual exclusion substantially easier by using queues instead of locks. Nevertheless, there are still some challenges. When creating shared data I often include a warning in my documentation that it must only be accessed within a certain serial GCD queue. However, other developers that use my code may not read my documentation. Even I forget occasionally that some particular data isn’t thread safe. So, how do we make this easier? This is a situation for what I call the Lockless Exclusion Accessor pattern. I’ll call it LEA for short. (I also thought of calling it a “letter” since it’s closely related to a getter, but that seemed too silly and generic.)&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
Before going into the details of LEAs, we need to first understand why encapsulation is important. Most object-oriented languages have the ability to make variables private so they can only be directly accessed internal to the class. Limited access is given to the outside through getters and setters. This prevents classes on the outside making arbitrary changes to another classes internal data. To see how to encapsulate @propertys in Objective-C check out my &lt;a href="http://robsprogramknowledge.blogspot.com/2011/08/objective-c-property.html"&gt;@property article&lt;/a&gt;. We will apply the same principles to our shared data. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
First, move your shared data into a class extension so it will not be externally visible. Second, you will want to typdef your block type. This keeps your code cleaner and easier to read. For this example, I’m going to use an NSManagedObjectContext as my shared data. So, my block typedef looks like this:&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="color: #aa0d91; font-size: 11pt;"&gt;typedef&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #aa0d91; font-size: 11pt;"&gt;void&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(^RBMOCBlock)(NSManagedObjectContext * moc);&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
Next, you need to create an accessor method. Outside classes will only be able to access your shared data through this method. It will look something like this:&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;- (&lt;/span&gt;&lt;span style="color: #aa0d91; font-size: 11pt;"&gt;void&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;)accessMOCAsync:(&lt;/span&gt;&lt;span style="color: #3f6e74; font-size: 11pt;"&gt;RBMOCBlock&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;)block {&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2e0d6e; font-size: 11pt;"&gt;dispatch_async&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(&lt;/span&gt;&lt;span style="color: #643820; font-size: 11pt;"&gt;dispatch_get_main_queue&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(), ^{&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 11pt;"&gt;block([&lt;/span&gt;&lt;span style="color: #aa0d91; font-size: 11pt;"&gt;self&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;managedObjectContext]);&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 11pt;"&gt;});&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
The dispatch_async takes the passed in block and runs it on the main queue. We could (and really should) modify this code to run on a private serial queue instead. We also pass the shared data to the block. This grants the block exclusive access to that data (as long as the dispatch queue is a serial queue). You’ll also notice that this is an asynchronous call. If needed, we can also make a synchronous LEA. It looks nearly identical:&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;- (&lt;/span&gt;&lt;span style="color: #aa0d91; font-size: 11pt;"&gt;void&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;)accessMOCSync:(&lt;/span&gt;&lt;span style="color: #3f6e74; font-size: 11pt;"&gt;RBMOCBlock&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;)block {&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #2e0d6e; font-size: 11pt;"&gt;dispatch_sync&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(&lt;/span&gt;&lt;span style="color: #643820; font-size: 11pt;"&gt;dispatch_get_main_queue&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(), ^{&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 11pt;"&gt;block([&lt;/span&gt;&lt;span style="color: #aa0d91; font-size: 11pt;"&gt;self&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #26474b; font-size: 11pt;"&gt;managedObjectContext&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;]);&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 11pt;"&gt;});&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;}&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
Now that we’ve built our asynchronous and synchronous LEAs, let’s use one. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;[&lt;/span&gt;&lt;span style="color: #3f6e74; font-size: 11pt;"&gt;object&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #26474b; font-size: 11pt;"&gt;accessMOCAsync&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;:^(&lt;/span&gt;&lt;span style="color: #5c2699; font-size: 11pt;"&gt;NSManagedObjectContext&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;* context) {&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #007400; font-size: 11pt;"&gt;// Critical code goes here.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;}];&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
That’s all there is to it. Just wrap your critical code in a block and you get exclusive, local access to the NSManagedObjectContext. LEAs are perfect for Core Data MOCs since they are not thread safe and are often the cause of much grief. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
LEAs are also quite flexible. For example, you can merge multiple LEAs into one like this:&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;[&lt;/span&gt;&lt;span style="color: #3f6e74; font-size: 11pt;"&gt;object&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #26474b; font-size: 11pt;"&gt;accessMOCAsync&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;:^(&lt;/span&gt;&lt;span style="color: #5c2699; font-size: 11pt;"&gt;NSManagedObjectContext&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;* context, &lt;/span&gt;&lt;span style="color: #5c2699; font-size: 11pt;"&gt;NSDictionary&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;* userInfo) {&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="color: #007400; font-size: 11pt;"&gt;// Critical code goes here.&lt;/span&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;span style="font-size: 11pt;"&gt;}];&lt;/span&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
The above LEA gives the block exclusive access to two shared variables at once. You can extend this as far as you want. This way to don’t need to write multiple LEAs per class and you don’t need to nest LEAs. However, this comes with a tradeoff. You gain convenience at the cost of more contention for shared data. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
Now, LEAs don’t perfectly protect shared data. It’s as good as Objective-C can get though. Rogue developers could pass the pointer to the MOC out of the block. They could also use the dynamic runtime to call the internal getters and setters. However, any developer doing either of these things is asking for a lot of trouble and should not be permitted to write Objective-C code. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
For more GCD and block design patterns, check out these sources. &lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;a href="http://public.iwork.com/document/?a=p1060057446&amp;amp;d=GCD_Presentation_Sep2011.key"&gt;GCD Design Patterns Presentation&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;a href="http://www.mikeash.com/pyblog/friday-qa-2009-08-14-practical-blocks.html"&gt;Mike Ash&lt;/a&gt;&lt;/div&gt;
&lt;div style="text-align: left;"&gt;
&lt;a href="http://cocoasamurai.blogspot.com/2011/02/practical-design-patterns-with-blocks.html"&gt;Cocoa Samurai&lt;/a&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
&lt;strong&gt;UPDATE:&lt;/strong&gt;&lt;/div&gt;
&lt;br /&gt;
&lt;div style="text-align: left;"&gt;
I've removed all references to SyncSafe due to &lt;a href="http://robsprogramknowledge.blogspot.com/2011/11/dispatchsyncsafe-deprecated.html"&gt;problems&lt;/a&gt; I've discovered. &lt;/div&gt;
&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-3321222835044084569?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=YP2BucI40HM:dEHnhisylMY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=YP2BucI40HM:dEHnhisylMY:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=YP2BucI40HM:dEHnhisylMY:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=YP2BucI40HM:dEHnhisylMY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=YP2BucI40HM:dEHnhisylMY:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=YP2BucI40HM:dEHnhisylMY:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/YP2BucI40HM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/3321222835044084569/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/09/lockless-exclusion-accessor-pattern.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/3321222835044084569?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/3321222835044084569?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/YP2BucI40HM/lockless-exclusion-accessor-pattern.html" title="Lockless Exclusion Accessor Pattern" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/09/lockless-exclusion-accessor-pattern.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0YARHk_cCp7ImA9WhdXEU4.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-1936796955790815940</id><published>2011-08-23T15:58:00.000-06:00</published><updated>2011-08-23T16:39:05.748-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-23T16:39:05.748-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Pragmatic Bookshelf" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="iOS" /><category scheme="http://www.blogger.com/atom/ns#" term="Book Review" /><title>iOS Recipes Review</title><content type="html">Here’s a book I couldn’t recommend more. &lt;em&gt;&lt;a href="http://pragprog.com/book/cdirec/ios-recipes"&gt;iOS Recipes&lt;/a&gt;&lt;/em&gt; by Paul Warren and Matt Drance has done more to improve my code than any other book. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;iOS Recipes&lt;/em&gt; gives 40 code samples to improve common or useful iOS code. The recipes are grouped into five categories: UI, Table/Scroll Views, Graphics, Networking, and Runtime. The book is organized so you can read it in whatever order suits your needs. The wide range of recipes guarantees there is something that will benefit you. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;iOS Recipes&lt;/em&gt; includes many code samples that can be dropped into any project and will just work without any extra modification. Any project could benefit from using at least one of the included recipes. For example, the common table view cell production/customization process typically takes 20+ lines of code. I now write the same code in 3 lines of code and it is fully Interface Builder customizable.  &lt;br /&gt;&lt;br /&gt;The greatest value of this book, however, is the explanation of how these recipes were designed. Warren and Drance explain exactly why they, for example, chose blocks over delegation or vice versa. By applying their same reasoning to other code, you can create your own quality recipes. This is further encouraged by not giving recipes that do everything. Some extensions are left as an exercise to the reader. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;There’s nothing I can say against this book. It really is a great book.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Recommendation&lt;br /&gt;&lt;br /&gt;&lt;/strong&gt;Every experienced iOS developer should own this book. By following the principles taught in &lt;em&gt;iOS Recipes&lt;/em&gt;, your code will increase in quality. I also recommend this book to any daring, young developers who are interested in gaining a deeper understanding of the full power of Objective-C and designing quality code. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-1936796955790815940?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=6z5IC7zYuFE:RhBzkUZZev4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=6z5IC7zYuFE:RhBzkUZZev4:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=6z5IC7zYuFE:RhBzkUZZev4:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=6z5IC7zYuFE:RhBzkUZZev4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=6z5IC7zYuFE:RhBzkUZZev4:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=6z5IC7zYuFE:RhBzkUZZev4:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/6z5IC7zYuFE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/1936796955790815940/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/08/ios-recipes-review.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/1936796955790815940?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/1936796955790815940?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/6z5IC7zYuFE/ios-recipes-review.html" title="iOS Recipes Review" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/08/ios-recipes-review.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcGRXw9fSp7ImA9WhdXEU4.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-5864269755973345241</id><published>2011-08-02T21:53:00.000-06:00</published><updated>2011-08-23T15:47:04.265-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-23T15:47:04.265-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="KVO" /><category scheme="http://www.blogger.com/atom/ns#" term="Best Practices" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="iOS" /><category scheme="http://www.blogger.com/atom/ns#" term="Memory Management" /><title>Objective-C @property Best Practices</title><content type="html">Now for my next rant on poor Objective-C code. Coming from other languages it's understandable that most developers don't take full advantage of the power of Objective-C 2.0. Here's a practice I hope that becomes more widespread. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Use @property&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;One feature of Objective-C that is underutilized is @property. The Objective-C compiler can write so much code for us, we just have to let it. Note that some of what I'm going to cover only works on the 64-bit (modern) Objective-C runtime. However, you probably won't find any situation where you need to write code for the 32-bit (legacy) runtime. The only reason we wrote legacy runtime code was because that’s what the iOS simulator used to run on (prior to iOS 4.0). That was fixed over a year ago. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Clean up your Headers&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;First, let's use @property to clean up our header files. The first thing to do is delete all of your ivars. Yes, delete all of them. They are no longer necessary. @synthesize will not only make your getters and setters, but it will also make your ivars. This was one of the major changes from the legacy to modern runtimes. This is nice because we don't need to be redundant about our instance variables anymore. Now, for all of your public ivars, make an equivalent @property. We'll handle the private and protected ivars in a moment. With just your public @propertys, your headers will now be much shorter and easier to read. Remember, headers are for public information. That is the whole idea behind encapsulation. You don't want your private information in your public headers. Even though I'm focusing on @propertys, you can apply the same ideas to methods too.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Categories and Class Extensions&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Before handling your private and protected ivars, you need to understand categories and class extensions. If you feel comfortable using class extensions, feel free to jump to the next section. &lt;br /&gt;&lt;br /&gt;A category is a way to extend the interface and functionality of an existing class. You declare them similarly to regular classes:&lt;br /&gt;&lt;br /&gt;// MyClassAdditions.h&lt;br /&gt;&lt;br /&gt;#import "MyClass.h"&lt;br /&gt;&lt;br /&gt;@interface MyClass (CategoryName)&lt;br /&gt;&lt;br /&gt;// Extra method declarations.&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// MyClassAdditions.m&lt;br /&gt;&lt;br /&gt;#import "MyClassAdditions.h"&lt;br /&gt;&lt;br /&gt;@implementation MyClass (CategoryName)&lt;br /&gt;&lt;br /&gt;// Extra method implementations.&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;br /&gt;Making a category is that simple. You just need to remember to #import your category when you want to use your extra methods. Class extensions, for all intents and purposes, are categories. The main differences are that only the original class can create a class extension for itself and you can declare @propertys in a class extension. So we will do just that. To create a class extension you simply create a category with no name. It will look something like this:&lt;br /&gt;&lt;br /&gt;// MyClass.m&lt;br /&gt;&lt;br /&gt;@interface MyClass ()&lt;br /&gt;&lt;br /&gt;@property (nonatomic, copy) NSString * myPrivateString;&lt;br /&gt;&lt;br /&gt;@end&lt;br /&gt;&lt;br /&gt;With your class extension in place, you just need an associated @synthesize myPrivateString; and you're done. It's that simple. You can do this with all of your private class variables with no problems.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Protected Data&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Now we are left with the protected variables. These are a little more tricky. Technically protected variables and methods don't exist with this technique. Then again “private” technically doesn't exist at all in Objective-C. The runtime won't stop you from calling private methods. Anyway, you should avoid protected data as often as possible. Sometimes that just isn't possible though. If you want a protected @property, just put it in your class extension like your private data. Then, any subclasses that need to access the protected property need to contain an identical @property in their class extensions. You will want to include some documentation about your protected @property. This does seem a little redundant to have identical @propertys, but it's bearable since Objective-C generates the important code for you.  Again, this also works for methods. This is particularly nice because the @protected key word doesn't work on methods like it does ivars. One thing to note is that you can't call super in a protected method using this technique (you will get an annoying warning). If you need to make a super call, then your protected method should be placed in a private header instead. This private header should contain just the prototypes and is ONLY imported by classes that need that information. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Readonly Getters&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;What about when you want to make a public getter but a private setter? Objective-C can do this for you too. In your public header you can do something like this:&lt;br /&gt;&lt;br /&gt;@property (nonatomic, copy, readonly) NSString * myPrivateString;&lt;br /&gt;&lt;br /&gt;Then in your class extension you make a similar declaration:&lt;br /&gt;&lt;br /&gt;@property (nonatomic, copy, readwrite) NSString * myPrivateString;&lt;br /&gt;&lt;br /&gt;You just need to make sure the two declarations mirror each other (i.e. nonatomic and nonatomic, retain and retain, copy and copy, etc.). From there you just use @synthesize and Objective-C takes care of the rest. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Other @property Modifiers&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;While speaking of @property modifiers, I should take a moment to discuss them for anyone unfamiliar. You may skip to the next section if you already know the modifiers. By default an @property is atomic, assign (or weak), and readwrite. I've never found a good reason for atomic. Atomic just means that Objective-C is going to use a lock to enforce thread safety. This will make your getters and setters slower since it has to acquire and release the lock. If you are using single-threaded code this is completely unnecessary. If you are using multi-threaded code, you really should be using Grand Central Dispatch (or NSOperationQueue) to take advantage of lockless exclusion. &lt;br /&gt;&lt;br /&gt;The next modifier is copy/retain/assign. For almost everything you do, you will use retain. It's good to know the exceptions though. When you have an NSString, NSArray, NSSet, or other object with mutable/immutable variants, you should use copy instead. If the object is immutable, it will be retained for efficiency, otherwise it will be copied.&lt;br /&gt;&lt;br /&gt;Assign (or weak when using ARC) also has some uses. Mostly you will use it when dealing with primitives, such as BOOL or int. Since they aren't objects you can't call -copy or -retain on them. You will also use assign when you have want to avoid a retain cycle by creating a weak relationship. This is common with delegates. &lt;br /&gt;&lt;br /&gt;You can also specify the names of your getters and setters. You specify getter=myGetterName or setter=mySetterName. This is often used with BOOLs. For example, you may create a property like this:&lt;br /&gt;&lt;br /&gt;@property (nonatomic, assign, getter=isOn) BOOL on;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Dealloc&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;When writing your -dealloc methods, you may wonder how you can release your instance data without direct access to your ivars. There is only one reasonable way to do this. You should call [self setMyProperty:nil];. This will set your ivar to nil and consequently release the old value. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Exceptions&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;All rules have their exceptions including @property. If you need to make a custom getter or setter, you will need to create an associated ivar. Technically you can actually access synthesized ivars directly. However, Apple considers this to be a “bug” and access to synthesized ivars may disappear in the future. You can add ivars to class extensions for your private properties. Be aware, though, this is only supported on Clang/modern runtime and may require &lt;a href="http://stackoverflow.com/questions/4048870/is-it-possible-to-define-ivars-in-objective-c-extension/4050816#4050816"&gt;additional settings&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Benefits&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Now that we've gone over all that, let's go over the benefits of these extra techniques:&lt;br /&gt;&lt;br /&gt;1. The obvious benefit is the compiler will write your getters and setters for you. The compiler not only writes your getters and setters but also makes them Key-Value Observing (KVO) compliant. This means you can observe the changes of any property on an object. KVO is especially useful when writing Model View Controller (MVC) code. Controllers can watch model objects for any changes and update the views as appropriate.&lt;br /&gt;&lt;br /&gt;2. You will have less memory bugs. When writing your actual code, you should always use your getters and setters instead of accessing ivars directly. This will make most of your memory management bugs disappear instantly. You won't need to remember to call retain/copy and release with your ivars. Your synthesized getters and setters will do that automatically for you. &lt;br /&gt;&lt;br /&gt;3. Your code will be better encapsulated. I've seen too much code where I've had to guess which ivars (and methods) I could safely use due to a lack of organization and no documentation. &lt;br /&gt;&lt;br /&gt;4. Last, but not least, your code will be more readable. Your headers won't be cluttered with private and protected data, and your implementation files won't be cluttered with standard getters and setters. Furthermore, your files will be better organized. You will know exactly where to find your public, private, and protected data. &lt;br /&gt;&lt;br /&gt;Employ these techniques and they will serve you well. Other people who have to use your code after you with thank you too. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Credits&lt;br /&gt;&lt;br /&gt;&lt;/strong&gt;The ideas in this article were strongly influenced by the &lt;a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html"&gt;Apple docs&lt;/a&gt;, &lt;a href="http://pragprog.com/book/cdirec/ios-recipes"&gt;iOS Recipes&lt;/a&gt; Recipe 35, various &lt;a href="http://developer.apple.com/videos/"&gt;WWDC videos&lt;/a&gt;, and a lot of personal experience (i.e. bugs). &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;----&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;Update: &lt;/strong&gt;August 23, 2011&lt;br /&gt;&lt;br /&gt;I have further refined and corrected this article through further study and experience on the topic, particularly ivars and custom accessors. &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-5864269755973345241?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=HC3hg_ecl5s:IPmH1JK-OaY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=HC3hg_ecl5s:IPmH1JK-OaY:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=HC3hg_ecl5s:IPmH1JK-OaY:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=HC3hg_ecl5s:IPmH1JK-OaY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=HC3hg_ecl5s:IPmH1JK-OaY:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=HC3hg_ecl5s:IPmH1JK-OaY:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/HC3hg_ecl5s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/5864269755973345241/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/08/objective-c-property.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/5864269755973345241?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/5864269755973345241?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/HC3hg_ecl5s/objective-c-property.html" title="Objective-C @property Best Practices" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/08/objective-c-property.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYBQHozfyp7ImA9WhdVE08.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-6329707549895083001</id><published>2011-07-30T20:41:00.000-06:00</published><updated>2011-09-17T23:19:11.487-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-17T23:19:11.487-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Dynamic Runtime" /><category scheme="http://www.blogger.com/atom/ns#" term="Design Pattern" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="iOS" /><category scheme="http://www.blogger.com/atom/ns#" term="Singleton" /><title>One singleton to rule them all</title><content type="html">One of the most common design patterns is the &lt;a href="http://en.wikipedia.org/wiki/Singleton_pattern"&gt;singleton&lt;/a&gt;. However, implementing singletons, especially in Objective-C, can be very repetitive. I often forget how to properly override all the memory management methods and need to look up a previous singleton. One of the goals of programming is to automate the repetetive, mundane tasks. Cocoa With Love has a great &lt;a href="http://projectswithlove.com/projects/SynthesizeSingleton.h.zip"&gt;synthesized singleton&lt;/a&gt; made from a C pre-processor macro. The problem with this is that it's not flexible. So, I made an Objective-C singleton that can be dropped in any project. By subclassing &lt;a href="https://gist.github.com/1116294"&gt;RBSingleton&lt;/a&gt; you can gain all the benefits of a singleton without adding any further code and you have full flexibility to customize each subclass. &lt;br /&gt;&lt;br /&gt;There are two main parts that make RBSingleton possible. First, it stores all the singleton instances in a class-wide dictionary. A singleton typically keeps a static pointer to the singleton instance. This works fine as long as it's not subclassed. When subclasses become involved, the subclass that allocates first defines the singleton instance for all subclasses. This restriction is normally beneficial to singletons, but breaks with subclassing. I could have required subclasses to provide a pointer to a static class pointer through a method call, but this imposes more on the subclass's implementation than I wanted. By using a class-wide dictionary, every subclass can store its singleton instance under a unique key. To guarantee a unique key, I simply use the subclass's name. &lt;br /&gt;&lt;br /&gt;Second, the singleton instance is allocated by dynamically calling NSObject's -allocWithZone: method as shown below. &lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 11pt; color: rgb(43,131,159);"&gt;Method&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;allocMethod = &lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(43,131,159);"&gt;class_getClassMethod&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;([&lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(43,131,159);"&gt;NSObject&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(43,131,159);"&gt;class&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;], &lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(0,0,255);"&gt;@selector&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(allocWithZone:));&lt;br /&gt;sharedInstance = [&lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(43,131,159);"&gt;method_invoke&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(&lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(0,0,255);"&gt;self&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;, allocMethod, &lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(0,0,255);"&gt;nil&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;) &lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(43,131,159);"&gt;initialize&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The trick here was to allocate the singleton as the class of the RBSingleton subclass but use NSObject's -allocWithZone: method to do so. This is similar to calling [super allocWIthZone:nil];. The difference is that it's jumping more than one level in the inheritance hierarchy. This is known as a grandsuper call. The Objective-C dynamic runtime makes it possible to make such a call. You will also notice that I hardcoded [NSObject class] into the code. I could have dynamically discovered the root class with the following code:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 11pt;"&gt;+ (&lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(43,131,159);"&gt;Class&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;)rootClass {&lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(43,131,159);"&gt;Class&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;rootClass = &lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(0,0,255);"&gt;nil&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(43,131,159);"&gt;Class&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;currentClass = [&lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(0,0,255);"&gt;self&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(43,131,159);"&gt;class&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;];&lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(0,0,255);"&gt;while&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;((currentClass = &lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(43,131,159);"&gt;class_getSuperclass&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;(currentClass)))&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;rootClass = currentClass;&lt;br /&gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(0,0,255);"&gt;return&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;rootClass;&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;If I instead needed to get a grandsuper class that isn't necessarily the root class and I know a subclass of the grandsuper I could use simpler code like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: 11pt;"&gt;[&lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(43,131,159);"&gt;RBSingleton&lt;/span&gt; &lt;span style="font-size: 11pt;"&gt;&lt;/span&gt;&lt;span style="font-size: 11pt; color: rgb(43,131,159);"&gt;superclass&lt;/span&gt;&lt;span style="font-size: 11pt;"&gt;];&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Since I know the specific grandsuper class I need, I hardcoded it for efficiency. If you use RBSingleton and find a need to dynamically discover a particular grandsuper class, you can use the above code to do so. I've uploaded RBSingleton as a Gist and you can find it &lt;a href="https://gist.github.com/1116294"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;One last note, to use RBSingleton you need to include libobjc.dylib for the dynamic runtime calls. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-6329707549895083001?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=4koc7dV-bcg:v8lNGvGxX4M:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=4koc7dV-bcg:v8lNGvGxX4M:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=4koc7dV-bcg:v8lNGvGxX4M:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=4koc7dV-bcg:v8lNGvGxX4M:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=4koc7dV-bcg:v8lNGvGxX4M:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=4koc7dV-bcg:v8lNGvGxX4M:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/4koc7dV-bcg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/6329707549895083001/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/07/one-singleton-to-rule-them-all.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/6329707549895083001?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/6329707549895083001?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/4koc7dV-bcg/one-singleton-to-rule-them-all.html" title="One singleton to rule them all" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/07/one-singleton-to-rule-them-all.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUYBQX84fyp7ImA9WhdVE08.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-1225327601873569817</id><published>2011-07-26T19:03:00.000-06:00</published><updated>2011-09-17T23:19:10.137-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-09-17T23:19:10.137-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="C" /><category scheme="http://www.blogger.com/atom/ns#" term="Best Practices" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="C++" /><title>#define Abuse</title><content type="html">Lately I've been encountering some terrible Objective-C code, and I have a few words to say about it. One of the first problems I've found is the overuse of #define. Don't get me wrong, #define has its place, but when it comes to constants #define should not be the first choice. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Anti-Patterns&lt;/strong&gt;&lt;br /&gt;One of the problems with #define is that it's simply a macro substitution. There is generally no type associated with the value. This makes is harder for the compiler to warn you of potential errors. Macros can also have side effects you may forget about. For example:&lt;br /&gt;&lt;br /&gt;#define MY_STRING_CONSTANT [[NSString alloc] initWithFormat:@"Hello World!"]    // Very bad.&lt;br /&gt;&lt;br /&gt;The above example will cause a memory leak unless you remember to release the value each time. Just a side note, Apple's static analyzer will pick up this error if you turn it on. I should also mention that the following, related example is not preferable. I have actually seen this used in production code before.&lt;br /&gt;&lt;br /&gt;#define MY_STRING_CONSTANT [NSString stringWithFormat:@"Hello World!"]    // Still not great.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Numbers&lt;/strong&gt;&lt;br /&gt;With a couple anti-patterns out of the way, let's go over the proper way to define constants. You will find that it doesn't take much more effort to properly define constants. Numbers are the simplest and one of the most common, so we'll start with them. In your .m file (applies to .c or .cpp too) you will define your constant like the following:&lt;br /&gt;&lt;br /&gt;const NSInteger kMyInt = -100;&lt;br /&gt;const NSUInteger kMyUnsignedInt = 42;&lt;br /&gt;const CGFloat kMyFloat = 3.14;&lt;br /&gt;&lt;br /&gt;You could instead use 'int', 'unsigned int', and 'float' if you prefer, but the above types are generally the preferred data types. If you want to keep your constant visible to just your implementation file, then you are done. If not, you need to do one last thing. In your header file, you will need to use the following:&lt;br /&gt;&lt;br /&gt;extern const NSInteger kMyInt;&lt;br /&gt;extern const NSUInteger kMyUnsignedInt;&lt;br /&gt;extern const CGFloat kMyFloat;&lt;br /&gt;&lt;br /&gt;The reserved word 'extern' makes a promise to the compiler. You are letting the compiler know that you are not defining the value right away, but at link time, that value will exist. In this case, it's defined in your implementation file. With that in place, you are now done; your constant is defined and other classes can #import (#include for C and C++) your header file and use your number constants.&lt;br /&gt;&lt;br /&gt;You may wonder why you can't define the constant right in your header file. If you do, you will get an error message that looks like this: "&lt;span style="font-size: 11pt;"&gt;ld: duplicate symbol &amp;lt;Constant Name&amp;gt; in &amp;lt;File 1&amp;gt; and &amp;lt;File 2&amp;gt;.&lt;/span&gt;" Generally #import handles duplicate imports properly; however, it doesn't work for constants. I figure this error is why developers unaware of 'extern' default to #define. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Enumerations&lt;/strong&gt;&lt;br /&gt;Closely related to numbers are enumerations. If you ever have a series of related number constants, you probably want an enum. For example:&lt;br /&gt;&lt;br /&gt;// A contrived example but should get the idea across.&lt;br /&gt;enum {&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kJanuary = 1,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kFebruary = 2,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kMarch = 3,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kApril = 4,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kMay = 5,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kJune = 6,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kJuly = 7,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kAugust = 8,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kSeptember = 9,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kOctober = 10,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kNovember = 11,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kDecember = 12,&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Enumerations are great for bit masks too.&lt;br /&gt;&lt;br /&gt;// Another contrived example.&lt;br /&gt;enum {&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kBit1 = 1 &amp;lt;&amp;lt; 0,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kBit2 = 1 &amp;lt;&amp;lt; 1,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kBit3 = 1 &amp;lt;&amp;lt; 2,&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;kBit4 = 1 &amp;lt;&amp;lt; 3,&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;Enumerations are where type checking really helps. Say you are using a switch statement, the compiler can warn you if you didn't include one of your enum values as a switch case. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Strings&lt;/strong&gt;&lt;br /&gt;Strings are also very common in Cocoa programming. There is one extra detail that makes them different from numbers. At first you may want to make a constant like this:&lt;br /&gt;&lt;br /&gt;const NSString * kMyString = @"Hello World!";    // Wrong - String Anti-Pattern 1&lt;br /&gt;&lt;br /&gt;This is wrong for a couple different reasons. First, NSString is immutable, meaning that it can't be changed. This essentially makes it a constant by default. However, there is a big flaw with the above anti-pattern. I will first show the proper way:&lt;br /&gt;&lt;br /&gt;NSString * const kMyString = @"Hello World!";    // Right&lt;br /&gt;&lt;br /&gt;At first glance, you are probably wondering why 'const' is next to the constant name. The difference between the number and string examples is that the NSString is a pointer. The first string example tells the system that the value @"Hello World!" can't change, but the pointer value can change. You probably wouldn't, but you could do the following:&lt;br /&gt;&lt;br /&gt;kMyString = @"Goodbye World!";    // Very bad, but allowed in String Anti-Pattern 1.&lt;br /&gt;&lt;br /&gt;You didn't change the value of @"Hello World!", but you did change what kMyString pointed to. That doesn't sound like a constant at all. &lt;br /&gt;&lt;br /&gt;By the way, the following is also permissible, but wrong.&lt;br /&gt;&lt;br /&gt;const NSString * const kMyString = @"Hello World!";    // Wrong - String Anti-Pattern 2&lt;br /&gt;&lt;br /&gt;This makes both the value and the pointer constant. However, the first 'const' changes the data type of the constants. None of the Cocoa frameworks accept a const NSString * (since it's redundant). This means that you will have a compiler warning anytime you try to pass your constant to a Cocoa framework method. You might do something similar with other objects, but in Objective-C, such cases should be very rare. This is something more common in C or C++. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Objects&lt;/strong&gt;&lt;br /&gt;Objects other than strings can be a little more tricky. You can't do the following:&lt;br /&gt;&lt;br /&gt;MyObject * const kObject = [[MyObject alloc] init];    // Wrong - Object Anti-Pattern 1&lt;br /&gt;&lt;br /&gt;The problems is the right-hand side does not evaluate to a compile time constant. Furthermore, if it was possible, it would be difficult to configure the object properly. This requires a different technique.&lt;br /&gt;&lt;br /&gt;// Right&lt;br /&gt;+ (MyObject *)MyConstObject {&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;static MyObject * obj = nil;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;if (!obj) {&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;obj = [[MyObject alloc] init];&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;// Any other initial setup.&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;return obj;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Looking at the return type of MyObject *, you may think this has the same problem that String Anti-Pattern 1 had. This is not the case here. The original constant pointer is protected within the method; it can't be changed externally. When you call the method, you receive a copy of the object's address. You can change it if you want, but it won't affect anyone else. Naively you may want to change the return type to MyObject * const, but a const pointer doesn't affect the data type. You could do the following regardless:&lt;br /&gt;&lt;br /&gt;MyObject * obj = [[self class] MyConstObject];    // Type MyObject * is the same as MyObject * const&lt;br /&gt;&lt;br /&gt;One last note about object constants is that they are technically memory leaks. However, they are permissible for the same reason that &lt;a href="http://en.wikipedia.org/wiki/Singleton_pattern"&gt;singletons&lt;/a&gt; are permissible. What's more interesting is that Apple's latest static analyzer now flags singletons as memory leaks but still doesn't catch the above constant. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;When to use #define&lt;/strong&gt;&lt;br /&gt;I should probably include a kind word about #define. If you want to use any pre-processor macros such as #if or #ifdef, then #define is your only choice. #define is also good for simple, inline functions or when you want to write some code that will do automatic renaming (see Cocoa With Love's &lt;a href="http://projectswithlove.com/projects/SynthesizeSingleton.h.zip"&gt;synthesized singleton&lt;/a&gt;). #define has countless valuable uses, but when it comes to constants, try something else first. &lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-1225327601873569817?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=DxxZqXzxoS0:bzWbWXgopv4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=DxxZqXzxoS0:bzWbWXgopv4:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=DxxZqXzxoS0:bzWbWXgopv4:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=DxxZqXzxoS0:bzWbWXgopv4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=DxxZqXzxoS0:bzWbWXgopv4:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=DxxZqXzxoS0:bzWbWXgopv4:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/DxxZqXzxoS0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/1225327601873569817/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/07/define-abuse.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/1225327601873569817?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/1225327601873569817?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/DxxZqXzxoS0/define-abuse.html" title="#define Abuse" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/07/define-abuse.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQDSX8-eSp7ImA9WhdSEU4.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-5612088338431193047</id><published>2011-07-19T20:59:00.000-06:00</published><updated>2011-07-19T21:59:38.151-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-19T21:59:38.151-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Pragmatic Bookshelf" /><category scheme="http://www.blogger.com/atom/ns#" term="Management" /><category scheme="http://www.blogger.com/atom/ns#" term="Book Review" /><title>Driving Technical Change Review</title><content type="html">One particular book that caught my eye some time ago is &lt;em&gt;&lt;a href="http://pragprog.com/book/trevan/driving-technical-change"&gt;Driving Technical Change&lt;/a&gt;&lt;/em&gt; by Terrence Ryan. In his book, Ryan teaches the skills necessary to convince others to adopt your ideas. Though the book focuses around technical fields, most of the skills taught apply to other disciplines. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br /&gt;Ryan begins his book by classifying different types of people, such as the Cynic, the Uniformed, and the Irrational. From there he progresses to the skills needed to use on the different categories including delivering your message, gaining trust, and getting publicity. Ryan then concludes with how to strategically employ the needed skills. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;br /&gt;The book is written in a way that it can in whatever order fits your needs. Once you have identified the category (or categories) of people you are working with, you can jump straight to the recommended skills and techniques. The chapters are short and easy to read. Every skeptic category and rhetoric technique includes short examples to illustrate the ideas. &lt;br /&gt;&lt;br /&gt;Most of the ideas covered seem common sense. Yet there are some examples that I had never thought of employing. For example, Ryan suggests one way to get coworkers to accept a framework you've built is to open source it. If many people start using it, or even contributing to it, then your coworkers will be much more open to using your framework. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;br /&gt;Ryan tends to dodge confronting the Irrational. It is true that little can be done to convince an irrational person. However, he doesn't offer many suggestions besides avoid them and/or have management mandate a policy. Management mandate may be the silver bullet, but what about the situation when management is irrational? Perhaps the best solution at that point is to find a new job. &lt;br /&gt;&lt;br /&gt;Before reading this book, I was expecting Ryan to go into more detail on leadership skills. However, many skills such as gaining trust are left with few examples or explanation of how to gain trust. I do like the succinctness of Ryan's writing, but sometimes I'm left wanting more concrete examples. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Recommendation&lt;/strong&gt;&lt;br /&gt;If you are one of the many that feel your voice isn't heard, this book likely has some skills you haven't tried yet. Ryan shares his secret to leadership: "you can be promoted to management, but no one appoints you a leader." &lt;em&gt;Driving Technical Change&lt;/em&gt; can help you take initiative and become a leader. &lt;br /&gt;&lt;br /&gt;You can purchase &lt;em&gt;Driving Technical Change&lt;/em&gt; &lt;a href="http://pragprog.com/book/trevan/driving-technical-change"&gt;here&lt;/a&gt; from &lt;a href="http://pragprog.com/"&gt;The Pragmatic Bookshelf&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-5612088338431193047?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=6BKmcmjZZAA:57RnQ6wbgEQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=6BKmcmjZZAA:57RnQ6wbgEQ:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=6BKmcmjZZAA:57RnQ6wbgEQ:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=6BKmcmjZZAA:57RnQ6wbgEQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=6BKmcmjZZAA:57RnQ6wbgEQ:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=6BKmcmjZZAA:57RnQ6wbgEQ:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/6BKmcmjZZAA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/5612088338431193047/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/07/driving-technical-change-review.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/5612088338431193047?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/5612088338431193047?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/6BKmcmjZZAA/driving-technical-change-review.html" title="Driving Technical Change Review" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/07/driving-technical-change-review.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQDR3k6eCp7ImA9WhdSEU4.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-4215403715288910451</id><published>2011-06-21T11:30:00.000-06:00</published><updated>2011-07-19T21:59:36.710-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-19T21:59:36.710-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Pragmatic Bookshelf" /><category scheme="http://www.blogger.com/atom/ns#" term="Book Review" /><category scheme="http://www.blogger.com/atom/ns#" term="UX" /><category scheme="http://www.blogger.com/atom/ns#" term="Design" /><title>Designed For Use Review</title><content type="html">I've been anticipating the release of &lt;em&gt;&lt;a href="http://pragprog.com/titles/lmuse/designed-for-use"&gt;Designed for Use: Create Usable Interfaces for Applications and the Web&lt;/a&gt;&lt;/em&gt; for a while now. I was a little disappointed that it was delayed by almost a week from its original release date. Nevertheless, I bought it and finished it right away.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Summary&lt;/strong&gt;&lt;br /&gt;Lukas Mathis breaks the design process into three distinct parts: research, design, and implementation. Each category is subdivided into smaller steps classified as either idea-based or skill-based. The progression is logical, but also is written in a way that steps can be skipped or read out of order according to the needs of the product. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;br /&gt;When I first saw the book, I expected a focus strictly on what Mathis terms the "design phase" (Part 2 of 3). Design to me, before reading this book, meant wireframes, prototypes, and usability testing. The book gives much more. Mathis shows that the design process extends throughout the entire development cycle. &lt;br /&gt;&lt;br /&gt;&lt;em&gt;Designed for Use&lt;/em&gt; includes countless links to other resources. Mathis cites many prominent UX and Design blogs, books, videos, etc. Most are web based, so they are freely and widely available. &lt;br /&gt;&lt;br /&gt;Many great techniques are suggested that I never thought of as part of "design." Mathis includes mock press releases, job shadowing, and feature sorting. Not only does he teach several techniques, but he also gives low-budget suggestions. He removes any excuse for not following certain steps such as usability testing.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;br /&gt;Overall the book seems to have a bias towards desktop and web applications. There are several references to developing mobile applications, but there are few resources mentioned. I was expecting to see services such as Flurry and TestFlight included in the sections on user feedback and testing. Nevertheless, the ideas and techniques still apply.&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Recommendation&lt;/strong&gt;&lt;br /&gt;In general product development I often see two areas that lack: design and documentation. Mathis hits on both topics. Every step of the design process is covered succinctly and thoroughly making it quick and easy to read yet includes many references for further indulgence. I would highly recommend this book to both young and experienced developers. &lt;em&gt;Designed for Use&lt;/em&gt; can be purchased &lt;a href="http://pragprog.com/titles/lmuse/designed-for-use"&gt;here&lt;/a&gt; on &lt;a href="http://pragprog.com"&gt;pragprog.com&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-4215403715288910451?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=pbyqJMtnJCE:bdlUhej_2x4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=pbyqJMtnJCE:bdlUhej_2x4:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=pbyqJMtnJCE:bdlUhej_2x4:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=pbyqJMtnJCE:bdlUhej_2x4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=pbyqJMtnJCE:bdlUhej_2x4:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=pbyqJMtnJCE:bdlUhej_2x4:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/pbyqJMtnJCE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/4215403715288910451/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/06/designed-for-use-review.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/4215403715288910451?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/4215403715288910451?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/pbyqJMtnJCE/designed-for-use-review.html" title="Designed For Use Review" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/06/designed-for-use-review.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkAFR3gzeSp7ImA9WhZUFEQ.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-7666487611157930228</id><published>2011-06-07T19:54:00.000-06:00</published><updated>2011-06-07T20:05:16.681-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-07T20:05:16.681-06:00</app:edited><title>Git Repos</title><content type="html">I've recently created a few Git repos on Github. So far I have included a bug reporting tool, a file previewer, and a load of handy categories. I will also be moving my samples to Github. Check them out at &lt;a href="https://github.com/rob-brown"&gt;https://github.com/rob-brown&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-7666487611157930228?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=CMBGg2MJs0c:bb9rN-1GiO4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=CMBGg2MJs0c:bb9rN-1GiO4:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=CMBGg2MJs0c:bb9rN-1GiO4:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=CMBGg2MJs0c:bb9rN-1GiO4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=CMBGg2MJs0c:bb9rN-1GiO4:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=CMBGg2MJs0c:bb9rN-1GiO4:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/CMBGg2MJs0c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/7666487611157930228/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/06/git-repos.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/7666487611157930228?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/7666487611157930228?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/CMBGg2MJs0c/git-repos.html" title="Git Repos" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/06/git-repos.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAESHc8eip7ImA9WhZUEk8.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-8055052185134567240</id><published>2011-06-03T16:22:00.007-06:00</published><updated>2011-06-04T15:58:29.972-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-04T15:58:29.972-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Key-Value Coding" /><category scheme="http://www.blogger.com/atom/ns#" term="KVC" /><category scheme="http://www.blogger.com/atom/ns#" term="KVV" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="Key-Value Validation" /><category scheme="http://www.blogger.com/atom/ns#" term="iOS" /><category scheme="http://www.blogger.com/atom/ns#" term="Core Data" /><title>Key-Value Validation</title><content type="html">Along with all the other features of Key-Value Coding, there are methods in the API for validating the properties of an object. These methods are known as Key-Value Validation (KVV). The format for a validation method is -(BOOL)validate&amp;lt;Key&amp;gt;:(id*)error: (NSError**) where “Key” is the name of the property to validate. You must be sure to spell the property name properly, otherwise the validator may not be called properly. When calling a validator, you have two choices. First you can call the validator directly. Second, you can call -(BOOL)validateValue:(id*)forKey:(NSString*)error:(NSError**). The second choice will infer the name of the validator method, which is why it is important to spell the method name properly. &lt;br /&gt;&lt;br /&gt;The following gives a simple template of how to implement a validator. This template may be copied directly into Xcode. &lt;br /&gt;&lt;br /&gt;- (BOOL)validate&amp;lt;#Key#&amp;gt;:(id *)ioValue error:(NSError **)outError {&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;if (&amp;lt;#Value is not valid#&amp;gt;) {&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;// Try to coerce the value into a valid value.&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;// The coerced value must be autoreleased.&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;*ioValue = &amp;lt;#Some valid value#&amp;gt;;&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;if (&amp;lt;#Value cannot be coerced#&amp;gt;) {&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;if (error != NULL) {&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;// Create an error object. &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;// Merge errors if necessary.&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;return NO;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;}&lt;br /&gt;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;return YES;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Implementing validators has several gotchas to watch for. One of the things to notice is the value being passed in for validation is of type id*. This means that you can return a new value by reference. For example, if you want to ensure that a name is unique, you can use the validator to append a number to the name to coerce it to be unique. &lt;br /&gt;&lt;br /&gt;Coercing a value has some critical memory management issues. The value passed in for validation must be autoreleased, and a coerced value, if any, must likewise be autoreleased. Furthermore, if you do return a coerced value it must be return a new value rather than modifying the old value, even if the old value is mutable.&lt;br /&gt;&lt;br /&gt;When implementing a validator you must never call -set&amp;lt;Key&amp;gt; within the validator. The validator is responsible for validating, not setting.&lt;br /&gt;&lt;br /&gt;Primitives cannot be validated since the validators expect an object. However, you may wrap the primitive value in an NSValue or NSNumber object. &lt;br /&gt;&lt;br /&gt;Another gotcha to note is that validators are not called automatically. It is up to your discretion when you want your objects to be validated. When calling a validator, there is a general form to follow as shown below:&lt;br /&gt;&lt;br /&gt;// Note that the value is autoreleased.&lt;br /&gt;NSString * someName = [[[NSString alloc] initWithFormat”@“Timmy”] autorelease];&lt;br /&gt;NSError * error = nil;&lt;br /&gt;&lt;br /&gt;if ([obj validateName:&amp;someName error:&amp;error) {&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;// The setter is called since the value could have been coerced and to properly retain the value.&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;[obj setName:someName];&lt;br /&gt;}&lt;br /&gt;else {&lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;// Report an error to the user or whatever else you want.&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Aside from the above template, you could validate the parameters of your Objective-C setters by using NSParameterAssert([obj validateValue:&amp;someValue forKey:@“someKey” error:NULL]). This is good for debugging since asserts can be disabled by defining NS_BLOCK_ASSERTIONS. &lt;br /&gt;&lt;br /&gt;Core Data extends the ability of KVV. Although KVC does not automatically call validation methods, Core Data provides three points which validators can be called automatically. These methods are -(BOOL)validateForInsert:(NSError**), -(BOOL)validateForUpdate:(NSError**), and -(BOOL)validateForDelete:(NSError**). These methods are called when an NSManagedObject is inserted into a managed object context, updated, or deleted, respectively. You may override these methods in your subclasses of NSManagedObject to call your validators. Additionally, you may perform inter-property validation here. There may be instances where certain combinations of values are incorrect. For example, in a family tree, it is incorrect to set a female person as someone’s father. &lt;br /&gt;&lt;br /&gt;When using the Core Data validation methods, you must be careful to not recursively dirty the managed object context. Dirtying the MOC can be done in numerous ways such as coercing property values on every validation request. If you do recursively dirty the MOC, then you will get a message like this: ‘&lt;span style="font-size: 11pt;"&gt;&lt;strong&gt;Failed to process pending changes before save.  The context is still dirty after 100 attempts.  Typically this recursive dirtying is caused by a bad validation method, -willSave, or notification handler.&lt;/strong&gt;&lt;/span&gt;’ If you face this situation, you will either need to find another way to implement your validator or don’t have your validator called automatically. If you opt to not call your validator automatically, then you will probably want to call your validator anytime you try to set the associated property. &lt;br /&gt;&lt;br /&gt;In order to avoid your validators from being called automatically you have a few options. You could avoid calling NSManagedObject’s -validateForX: methods (where ‘X’ is ‘Insert’, ‘Update’, or ‘Delete’) by not calling [super validateForX:&amp;error]. However, this may not be wise since NSManagedObject may do more than call each of the validators. You could instead try having your object reject one or more validation messages from itself. The easiest and best option is to make a validator that is not KVC-compliant. In other words, name the validator method so it doesn’t match with a property name. &lt;br /&gt;&lt;br /&gt;When using the Core Data validation methods, you may have multiple errors occur. You have two options to handle this. First, you can return the first error as soon as it is reached. Second, you can merge the errors into a single error with error code NSValidationMultipleErrorsError.&lt;br /&gt;&lt;br /&gt;KVV is very useful, especially for Core Data. I’m surprised it isn’t used more frequently. However, Core Data does automatically generate some basic KVV methods from the MOM file.  Hopefully, this tutorial will increase the custom usage of KVV. &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-8055052185134567240?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=2kanGQhO68M:0YA70APOP-U:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=2kanGQhO68M:0YA70APOP-U:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=2kanGQhO68M:0YA70APOP-U:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=2kanGQhO68M:0YA70APOP-U:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=2kanGQhO68M:0YA70APOP-U:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=2kanGQhO68M:0YA70APOP-U:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/2kanGQhO68M" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/8055052185134567240/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/06/key-value-validation.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/8055052185134567240?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/8055052185134567240?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/2kanGQhO68M/key-value-validation.html" title="Key-Value Validation" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/06/key-value-validation.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkANR3w_fyp7ImA9WhdRE0g.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-6977613985767338783</id><published>2011-04-29T22:09:00.000-06:00</published><updated>2011-08-02T23:53:16.247-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-02T23:53:16.247-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Best Practices" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="iOS" /><category scheme="http://www.blogger.com/atom/ns#" term="Memory Management" /><category scheme="http://www.blogger.com/atom/ns#" term="Delegate" /><title>Delegates and Memory Management</title><content type="html">The iOS SDK uses the delegate pattern everywhere. Occasionally, you may want to create your own delegate protocol for some custom object. When doing so, keep in mind the subtleties of memory management. Always use @property (nonatomic, assign) rather than @property (nonatomic, retain) with delegates. It is often habit to use “retain,” but a delegate must use “assign.” &lt;br /&gt;&lt;br /&gt;Consider the following scenario. When creating an object, its delegate is often set to “self.” Using retain as the setter policy will cause the object to retain itself. The problem is that objects (usually) don’t ever call release on delegates. Hypothetically, if a delegate is released, it’s likely to be done in -dealloc. Since the object retained itself, -dealloc will never be called. The result is a memory leak. Xcode’s static analyzer will not be able to catch this type of leak. One of the major pitfalls of reference counting is circular dependencies. The only solutions in iOS are to avoid such dependencies or force the cycle to be broken somewhere. The first option is highly preferred. &lt;br /&gt;&lt;br /&gt;By using assign, we avoid a circular dependency. However, this doesn’t mean we can’t retain a delegate if needed. It just has to be done manually. For example: [self setDelegate:[aDelegate retain]];. This also means that the release must be done manually. Typically this can be done in -dealloc. Additionally, you may want to include a check for delegate != self. Sending [self release] in -dealloc will result in an infinite loop. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-6977613985767338783?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=fj8h_KHxHjs:5vU6o07G3dQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=fj8h_KHxHjs:5vU6o07G3dQ:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=fj8h_KHxHjs:5vU6o07G3dQ:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=fj8h_KHxHjs:5vU6o07G3dQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=fj8h_KHxHjs:5vU6o07G3dQ:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=fj8h_KHxHjs:5vU6o07G3dQ:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/fj8h_KHxHjs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/6977613985767338783/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/04/delegates-and-memory-management.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/6977613985767338783?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/6977613985767338783?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/fj8h_KHxHjs/delegates-and-memory-management.html" title="Delegates and Memory Management" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/04/delegates-and-memory-management.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUcDSH4-eSp7ImA9WhZTEkw.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-2443460667856492260</id><published>2011-03-15T13:15:00.000-06:00</published><updated>2011-03-15T13:24:39.051-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-03-15T13:24:39.051-06:00</app:edited><title>BYU CocoaHeads Presentations</title><content type="html">Recently, I have added links to my presentations I have given for the BYU CocoaHeads. You can find them in the right-hand column of my blog. Among the presentations, I have include Grand Central Dispatch, Core Data, and Quick Look for iOS. Each of the presentations are shared via &lt;a href="http://iWork.com"&gt;iWork.com&lt;/a&gt;. If there is interest, I may also add links for my sample projects. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-2443460667856492260?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=eLR6fyRmfYg:ICn9WaOO334:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=eLR6fyRmfYg:ICn9WaOO334:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=eLR6fyRmfYg:ICn9WaOO334:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=eLR6fyRmfYg:ICn9WaOO334:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=eLR6fyRmfYg:ICn9WaOO334:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=eLR6fyRmfYg:ICn9WaOO334:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/eLR6fyRmfYg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/2443460667856492260/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/03/byu-cocoaheads-presentations.html#comment-form" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/2443460667856492260?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/2443460667856492260?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/eLR6fyRmfYg/byu-cocoaheads-presentations.html" title="BYU CocoaHeads Presentations" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>1</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/03/byu-cocoaheads-presentations.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4HRXcyfip7ImA9Wx9bF00.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-4202957325058523352</id><published>2011-02-25T22:55:00.000-07:00</published><updated>2011-02-25T23:15:34.996-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-25T23:15:34.996-07:00</app:edited><title>Blog Traffic</title><content type="html">Ever since I blogged about raster map overlays for iOS back in August, I have been getting some substantial traffic. In fact, my raster map post shows up as the first three results on Google. If you don’t believe me, do a Google search for “WWDC10 Tilemap.” Regardless of the high traffic, no one has left any comments. My goal is to help answer many iOS developers’ questions. So far I have been using Blogger analytics to gauge what my readers want. Analytics can only do so much though. If a post helped you or didn’t answer what you were looking for, let me know. I would love your feedback. &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-4202957325058523352?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=p5-4v1Ib46A:0Jc_oRvKdjA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=p5-4v1Ib46A:0Jc_oRvKdjA:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=p5-4v1Ib46A:0Jc_oRvKdjA:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=p5-4v1Ib46A:0Jc_oRvKdjA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=p5-4v1Ib46A:0Jc_oRvKdjA:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=p5-4v1Ib46A:0Jc_oRvKdjA:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/p5-4v1Ib46A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/4202957325058523352/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/02/blog-traffic.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/4202957325058523352?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/4202957325058523352?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/p5-4v1Ib46A/blog-traffic.html" title="Blog Traffic" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/02/blog-traffic.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MCSHY-fip7ImA9WhdRFUU.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-4686052943356550860</id><published>2011-02-21T13:09:00.001-07:00</published><updated>2011-08-05T17:04:29.856-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-05T17:04:29.856-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Quick Look" /><category scheme="http://www.blogger.com/atom/ns#" term="iOS" /><title>Quick Look for iOS</title><content type="html">Many apps work directly with files. Quick Look is the perfect framework for previewing those files. Right out of the box, it supports all the common file formats. Like many of Apple’s other frameworks, it takes very few lines of code to add. Quick Look has been in Mac OS X for a while now and has recently been made available for iOS in 4.0. &lt;br /&gt;&lt;br /&gt;Adding Quick Look is a few easy steps:&lt;br /&gt;&lt;ol style="list-style-type: decimal"&gt;&lt;li&gt;Import QuickLook.framework.&lt;/li&gt;&lt;li&gt;Create a QLPreviewItem (or NSURL).&lt;/li&gt;&lt;li&gt;Create a QLPreviewControllerDataSource.&lt;/li&gt;&lt;li&gt;Create a QLPreviewControllerDelegate.&lt;/li&gt;&lt;li&gt;Present a QLPreviewController.&lt;/li&gt;&lt;/ol&gt;Any item can be previewed. It simply needs to conform to the QLPreviewItem protocol. This protocol only has two methods. The first, previewItemURL, returns the URL to locate the file to preview. The second, previewItemTitle, returns the title to show for the document. If this method is not defined, then the document name will be the title. One important item to note is that NSURL conforms to the QLPreviewItem protocol. You may use NSURLs instead of making a class that conforms to the protocol. Another important gotcha, any URLs returned from previewItemURL must use the file protocol (ex. file://some/file/path.txt). This is easily done with [NSURL fileURLWithPath:someFilePath]. If you don’t use the file scheme, then you will get an error message like this: “UIDocumentInteractionController: invalid scheme (null).  Only the file scheme is supported.”&lt;br /&gt;&lt;br /&gt;Next, setup a QLPreviewControllerDataSource and QLPreviewControllerDelegate. QLPreviewControllerDataSource needs to know how many QLPreviewItems you want to show (numberOfPreviewItemsInPreviewController:) and which QLPreviewItem is at each index (previewController:previewItemAtIndex:). These are often one line if you already have your documents in an array. Once the delegate and data source are set up, all you need to do is present the view however you like. The most convenient way on iPhone is [self presentModalViewController:previewController animated:YES];. QLPreviewControllerDelegate adds some extra callbacks that may be helpful, but it may be unnecessary depending on your needs. &lt;br /&gt;&lt;br /&gt;Quick Look also comes with other features for free. First, it presents the option to open the file in another app that accepts that file format. For example, CSV files can be opened in Numbers and PDFs can be opened in iBooks. Second, files can be printed. If you don’t have a printer to test it on, Apple provides Printer Simulator in the developer tools. &lt;br /&gt;&lt;br /&gt;Simple table views works well for managing file previews; however, you may want a more custom UI and more control. UIDocumentInteractionController is the class to use for that. I won’t go into details on document interaction. Session 106 of WWDC 2010 goes into great detail about UIDocumentInteractionController. The sample code is also available in the developer docs. &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;EDIT: &lt;/strong&gt;&lt;br /&gt;Since writing this post I have written a subclass of QLPreviewController that includes many conveniences, and have removed the old sample code. If you are using my old Quick Look sample, you should switch over to RBFilePreviewer. You can find it &lt;a href="https://github.com/rob-brown/RBFilePreviewer"&gt;here&lt;/a&gt; on Github. You can also find a demo of RBFilePreviewer in my &lt;a href="https://github.com/rob-brown/Demos"&gt;demo repository&lt;/a&gt;. &lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-4686052943356550860?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=c9Y8B0f13zw:gZ4FnKASvUM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=c9Y8B0f13zw:gZ4FnKASvUM:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=c9Y8B0f13zw:gZ4FnKASvUM:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=c9Y8B0f13zw:gZ4FnKASvUM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=c9Y8B0f13zw:gZ4FnKASvUM:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=c9Y8B0f13zw:gZ4FnKASvUM:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/c9Y8B0f13zw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/4686052943356550860/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2011/02/quick-look-for-ios_21.html#comment-form" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/4686052943356550860?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/4686052943356550860?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/c9Y8B0f13zw/quick-look-for-ios_21.html" title="Quick Look for iOS" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>6</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2011/02/quick-look-for-ios_21.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkANRHk8eip7ImA9Wx9bE08.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-2771734898863972440</id><published>2010-08-26T21:35:00.001-06:00</published><updated>2011-02-21T15:53:15.772-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-21T15:53:15.772-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Map Kit" /><category scheme="http://www.blogger.com/atom/ns#" term="GDAL" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="iOS" /><title>Raster Map Overlays for iPhone</title><content type="html">The release of iOS 4.0 included the ability to add custom image overlays to maps.  I recently took advantage of this in FastTrac. Previously, FastTrac was using OpenGL to handle the map.  This worked well but required an unreasonable amount of memory.  It also wasn’t easy to maintain.  Changing to a map overlay fixed both problems.  Session 127 of WWDC10 covered briefly how to implement such a map.  Some sample code is also available to all developers that makes the process much easier.  This session gives a good overview, but is missing some of the fine details.  It is my intent to fill in the gaps.  I will start with my own overview.  &lt;br /&gt;
&lt;br /&gt;
&lt;ol style="list-style-type: decimal;"&gt;&lt;li&gt;Download and install GDAL (available at &lt;a href="http://gdal.org/"&gt;gdal.org&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Download the TileMap sample project. &lt;/li&gt;
&lt;li&gt;Get the coordinates of your image’s bounding rect.&lt;/li&gt;
&lt;li&gt;Generate a .vrt file.&lt;/li&gt;
&lt;li&gt;Generate the mercator projected map tiles.&lt;/li&gt;
&lt;li&gt;Add the tiles to the sample project.&lt;/li&gt;
&lt;/ol&gt;First, download and install Geospatial Data Abstraction Library (GDAL).  This can be found at &lt;a href="http://gdal.org/"&gt;gdal.org&lt;/a&gt;.  It can also be installed with MacPorts by using “sudo port install gdal”.  Make sure you set your PATH variable properly.  I won’t go into any details of how to do this.  This shouldn’t be hard.  &lt;br /&gt;
&lt;br /&gt;
Next, download the TileMap sample project.  This is available to all iOS developers through the WWDC10 website &lt;a href="http://developer.apple.com/videos/wwdc/2010/"&gt;http://developer.apple.com/videos/wwdc/2010/&lt;/a&gt;.  The sample code can be hard to find.  It’s on the iTunes page where you download WWDC10 session videos.  Between GDAL and this sample project, you as a developer won’t need to do much to get your map working. &lt;br /&gt;
&lt;br /&gt;
This is where things get interesting.  You will need to find the coordinates of the bounding rect of your image to overlay.  Google Earth makes this easy.  I got this tip from a fellow developer on the Apple developer forums.  First, find the area you want to place the image overlay.  Next, right click on ‘My Places’ (it’s on the left column).  Select Add &amp;gt; Image Overlay.  This will open a pop up window.  From here you can open your image, change the opacity, and move/resize your image.  Make your image transparent enough to see both your image and the underlying map.  Once you have adjusted your image to match, click on the ‘Location’ tab.  There you will find your latitudes/longitudes.  You will need to convert those to a decimal value.  A quick Google search will turn up a tool to make that conversion for you.  &lt;br /&gt;
&lt;br /&gt;
Now to put GDAL to work.  The first part is to generate a .vrt (virtual raster) file.  This is probably the hardest part of the process.  It’s very easy to make a mistake.  You will use gdal_translate to map your corner pixels to the coordinates you just found.  The terminal command is as follows:  &lt;br /&gt;
&lt;br /&gt;
gdal_translate -of VRT -a_srs EPSG:4326 \&lt;br /&gt;
-gcp x1 y1 long1 lat1 \&lt;br /&gt;
-gcp x2 y2 long2 lat2 \&lt;br /&gt;
-gcp x3 y3 long3 lat3 \&lt;br /&gt;
-gcp x4 y4 long4 lat4 \&lt;br /&gt;
image.jpg image.vrt&lt;br /&gt;
&lt;br /&gt;
There are a few things to note.  First, your map image doesn’t have to be .jpg.  Several formats are supported.  Also, be very careful with your coordinates.  Small errors make big problems.  Notice that longitude comes first.  I had them backwards and spent two days trying to figure out why it wouldn’t work.  As for the x and y values, these are your pixel coordinates.  (0,0) is the top left of the image.  &lt;br /&gt;
&lt;br /&gt;
If you have done everything correctly, the rest is easy.  gdal2tiles.py will take your .vrt file and image overlay and generate mercator projected map tiles.  The command is simple - “gdal2tiles.py -p mercator image.vrt.”  You only need to give it the .vrt file.  The .vrt file keeps a relative path to the image overlay.  gdal2tiles.py will generate your map tiles along with other various files.  If you don’t want these extra files there are command line options to skip them.  &lt;br /&gt;
&lt;br /&gt;
With your new map tiles, you simply need to add them to the TileMap project.  First, delete the old tiles in the sample.  Make sure they are deleted both in XCode and the source directory.  If you have previously run the app, you may need to delete the app from your device/simulator.  Next, copy your map tiles into your project.  When copying your files, there is a vital gotcha to watch out for.  You will need to create folder references instead of groups (see image below).  Folder references will appear as a blue folder icon, whereas groups appear as a yellow folder icon.  The reason for this is because the code is dependent on not just the files but also the directory structure. &lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-8w3YWxXcI0A/TWLsyV1IycI/AAAAAAAAABA/veIgICp_q-E/s1600/Screen+shot+2011-02-21+at+2.01.10+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="298" src="http://2.bp.blogspot.com/-8w3YWxXcI0A/TWLsyV1IycI/AAAAAAAAABA/veIgICp_q-E/s320/Screen+shot+2011-02-21+at+2.01.10+PM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
If you named your map tiles directory any other than “Tiles,” you will need to change the code to use your directory instead. Finally, run the app and everything should work.  If there is a problem, it likely occurred while generating your .vrt file.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-2771734898863972440?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=2Ax8HTCz_ME:eUODzfwLr7U:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=2Ax8HTCz_ME:eUODzfwLr7U:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=2Ax8HTCz_ME:eUODzfwLr7U:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=2Ax8HTCz_ME:eUODzfwLr7U:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=2Ax8HTCz_ME:eUODzfwLr7U:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=2Ax8HTCz_ME:eUODzfwLr7U:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/2Ax8HTCz_ME" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/2771734898863972440/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2010/08/raster-map-overlays-for-iphone.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/2771734898863972440?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/2771734898863972440?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/2Ax8HTCz_ME/raster-map-overlays-for-iphone.html" title="Raster Map Overlays for iPhone" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-8w3YWxXcI0A/TWLsyV1IycI/AAAAAAAAABA/veIgICp_q-E/s72-c/Screen+shot+2011-02-21+at+2.01.10+PM.png" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2010/08/raster-map-overlays-for-iphone.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0QGRHc-fCp7ImA9Wx9bFEs.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-5600563541821671700</id><published>2010-08-13T15:40:00.000-06:00</published><updated>2011-02-23T06:55:25.954-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-23T06:55:25.954-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="UITextField" /><category scheme="http://www.blogger.com/atom/ns#" term="UIAlertView" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="iOS" /><title>Using a UITextField in a UIAlertView</title><content type="html">In an app I have been working on, FastTrac WT, there is a UIAlertView with a UITextField added as a subview. Anytime the alert view was dismissed, the error “wait_fences: failed to receive reply:” would show up. It doesn’t make much sense without knowing what the problem is. That seems to be the irony of error messages. The problem turns out to be that the text field must resign its first responder status before it is released. Knowing this the error message makes more sense. The system couldn’t get a reply from the first responder. The solution to this is to resign the first responder status in the alertView:didDismissWithButtonIndex: method. Using it here makes a smooth animation. The alert view will be dismissed followed by the keyboard. An alternative is to resign the first responder status in alertView:willDismissWithButtonIndex:. The alert view and the keyboard will be dismissed at the same time and the alert view will fade and move downwards with the keyboard. This animation also looks nice and the transition is faster. However, resigning the first responder status in alertView:didDismissWithButtonIndex: does not create a smooth animation. The keyboard is dismissed before the alert view. This creates a sudden jump as the alert view re-centers itself to the viewable area. Either of the first two methods are good candidates for fixing this error. Try both and judge which animation fits best with your app.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-5600563541821671700?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=GWsp7QxZyWM:SsfO5d7rNNM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=GWsp7QxZyWM:SsfO5d7rNNM:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=GWsp7QxZyWM:SsfO5d7rNNM:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=GWsp7QxZyWM:SsfO5d7rNNM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=GWsp7QxZyWM:SsfO5d7rNNM:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=GWsp7QxZyWM:SsfO5d7rNNM:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/GWsp7QxZyWM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/5600563541821671700/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2010/08/using-uitextfield-in-uialertview.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/5600563541821671700?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/5600563541821671700?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/GWsp7QxZyWM/using-uitextfield-in-uialertview.html" title="Using a UITextField in a UIAlertView" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2010/08/using-uitextfield-in-uialertview.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUFRHs9fCp7ImA9Wx5SE0w.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-1671839672564216437</id><published>2010-08-07T13:55:00.000-06:00</published><updated>2010-08-08T19:26:55.564-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-08T19:26:55.564-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Quartz Composer" /><title>My First Quartz Composition</title><content type="html">&lt;p&gt;Quartz composer is often used for making screensavers.  So, to learn QC, I decided to make a screensaver of my own.  I started with a simple concept, two spheres orbiting around each other.  I thought it would be simple anyway.  All of the motion is accomplished through the use of LFOs (low-frequency oscillators).  At first, I thought I could use three LFOs, one for each axis, to generate the desired motion.  I couldn’t find anyway to get this to work.  In the end, I found an alternative solution.    Each sphere has two LFOs that cause the sphere to orbit in the yz-plane.  From there, I used a 3D transformation patch to rotate the two spheres about the y and z axes.  This achieved the movement I mentally envisioned.  Much of my efforts were trial and error.  There is very little documentation available for QC.  I hope this to change in time.  &lt;/p&gt;&lt;p&gt;Below is a link to my Quartz Composition for anyone interested.  &lt;/p&gt;&lt;p&gt;&lt;a href="http://dl.dropbox.com/u/2998162/Quartz Composer/Orbiting_Spheres.qtz"&gt;http://dl.dropbox.com/u/2998162/Quartz%20Composer/Orbiting_Spheres.qtz&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-1671839672564216437?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=71IfC4ATGIM:9y1ug4bR8wQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=71IfC4ATGIM:9y1ug4bR8wQ:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=71IfC4ATGIM:9y1ug4bR8wQ:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=71IfC4ATGIM:9y1ug4bR8wQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=71IfC4ATGIM:9y1ug4bR8wQ:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=71IfC4ATGIM:9y1ug4bR8wQ:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/71IfC4ATGIM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/1671839672564216437/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2010/08/my-first-quartz-composition.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/1671839672564216437?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/1671839672564216437?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/71IfC4ATGIM/my-first-quartz-composition.html" title="My First Quartz Composition" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2010/08/my-first-quartz-composition.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkEHRnw6cSp7ImA9Wx9bE08.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-1792835746063660408</id><published>2010-08-07T13:06:00.000-06:00</published><updated>2011-02-21T15:50:37.219-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-02-21T15:50:37.219-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Quartz Composer" /><title>My First Quartz Composer Patches</title><content type="html">While playing around with some of the standard Quartz Composer patches, I discovered the Apple remote patch.  I just so happen to have an Apple remote, so I wanted to give it a try.  I found it to work well.  However, the remote only emitted a quick “true” signal.  For what I wanted to do, I needed to store a boolean state.  A previous electrical engineering course helped me come up with the solution.  I built an RS flip flop patch.  An RS flip flop is a simple electrical circuit that stores a single state.  It consists of only two NOR gates that are cross-coupled.  By setting one wire high (true) the stored bit will go high.  When the other wire is set high, the stored bit will go low (false).  While both wires are low, the bit will remain unchanged.  However, both wires shouldn’t ever both be set high.  The result is undefined.  &lt;br /&gt;&lt;br /&gt;This new patch suited me well.  The only problem was that it required using two buttons and those buttons couldn’t be pressed simultaneously.  I, of course, could do better.  I added a few more components to my patch and changed it to a toggle switch.  This permitted one button to toggle between the two states.  I later discovered that there is a standard toggle patch, but it can toggle between any two numbers.  Mine specifically uses boolean values.  &lt;br /&gt;&lt;br /&gt;Below are links to download the two patches I developed for those who are interested.  Note that since these are patches, not macros, the underlying logic is not available to view.  &lt;br /&gt;&lt;br /&gt;&lt;a href="http://dl.dropbox.com/u/2998162/Quartz Composer/RS_Flip_Flop.qtz"&gt;http://dl.dropbox.com/u/2998162/Quartz%20Composer/RS_Flip_Flop.qtz&lt;/a&gt;&lt;br /&gt;&lt;a href="http://dl.dropbox.com/u/2998162/Quartz Composer/Toggle_Switch.qtz"&gt;http://dl.dropbox.com/u/2998162/Quartz%20Composer/Toggle_Switch.qtz&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-1792835746063660408?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=Y2-bpOmLRKI:VMUSMIVoigM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=Y2-bpOmLRKI:VMUSMIVoigM:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=Y2-bpOmLRKI:VMUSMIVoigM:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=Y2-bpOmLRKI:VMUSMIVoigM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=Y2-bpOmLRKI:VMUSMIVoigM:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=Y2-bpOmLRKI:VMUSMIVoigM:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/Y2-bpOmLRKI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/1792835746063660408/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2010/08/my-first-quartz-composer-patches.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/1792835746063660408?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/1792835746063660408?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/Y2-bpOmLRKI/my-first-quartz-composer-patches.html" title="My First Quartz Composer Patches" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2010/08/my-first-quartz-composer-patches.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D08ESXo6eSp7ImA9WxFbFUw.&quot;"><id>tag:blogger.com,1999:blog-8850989183226537471.post-9003174839439433689</id><published>2010-07-06T22:28:00.000-06:00</published><updated>2010-07-07T09:16:48.411-06:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-07T09:16:48.411-06:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Template" /><category scheme="http://www.blogger.com/atom/ns#" term="C++" /><title>C++ Templates</title><content type="html">&lt;p&gt;Today I was working on some standard C++ data structures for a CS class.  I wanted to make them generic so that they could be used to hold any primitive or object.  C++ offers this flexibility with templates.  I found some simple tutorials and went at it.  When I was finished, I couldn’t get them to work.  I kept getting an undefined reference error during the linking process.  What made it the most challenging is that everything was syntactically correct.  I had to scour the internet to find the answer.  It turns out that with C++ templates, the implementation must be included in the header file.  There are a few ways to accomplish this.  First, is to use the “export” keyword just before declaring the template.  This option isn’t supported by most compilers.  I have been using g++ which does not support this feature.  Second, the .cpp file can be #included at the end of the .h file.  I didn’t prefer that approach.  Third, the implementation can be copied to the end of the header file.  This is essentially the same as the second option.  The fourth option is to simply define each method as soon as it is declared.  Any of these four options will essentially merge the implementation and header files directly or indirectly.  I took the last option.  Once my files were merged, my data structures worked perfectly.  Again, it is always the fine details that create the biggest problems.  &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8850989183226537471-9003174839439433689?l=robsprogramknowledge.blogspot.com' alt='' /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=c-fEIv5a3d4:md1to3sIXeA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=c-fEIv5a3d4:md1to3sIXeA:4cEx4HpKnUU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=c-fEIv5a3d4:md1to3sIXeA:4cEx4HpKnUU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=c-fEIv5a3d4:md1to3sIXeA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?a=c-fEIv5a3d4:md1to3sIXeA:-BTjWOF_DHI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/ProgrammingKnowledgeBase?i=c-fEIv5a3d4:md1to3sIXeA:-BTjWOF_DHI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/ProgrammingKnowledgeBase/~4/c-fEIv5a3d4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://robsprogramknowledge.blogspot.com/feeds/9003174839439433689/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://robsprogramknowledge.blogspot.com/2010/07/c-templates.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/9003174839439433689?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/8850989183226537471/posts/default/9003174839439433689?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/ProgrammingKnowledgeBase/~3/c-fEIv5a3d4/c-templates.html" title="C++ Templates" /><author><name>Rob</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="22" height="32" src="http://3.bp.blogspot.com/-3qd6C4lxhkY/TW53LSyJ4pI/AAAAAAAAABI/esLov61eQYA/s220/Robert%2BBrown.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://robsprogramknowledge.blogspot.com/2010/07/c-templates.html</feedburner:origLink></entry></feed>

