<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3733114751386359986</id><updated>2012-02-08T17:51:13.693-08:00</updated><category term='Cocoa'/><category term='Objective-C Cocoa CoreData'/><category term='Objective-C Cocoa Pattern GoodStyle'/><category term='Flashcards'/><category term='Tip'/><category term='Objective-J Cappuccino Atlas Cool 280North'/><category term='Programming'/><category term='Statistics'/><category term='Objective-C'/><category term='Politics'/><title type='text'>Christian Kienle's Blog</title><subtitle type='html'>Thoughts about Cocoa, Cappuccino, Objective-C/J and other random stuff.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>21</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-3327212067138076641</id><published>2011-11-12T07:58:00.001-08:00</published><updated>2011-11-12T08:10:07.146-08:00</updated><title type='text'>If you need a good designer...</title><content type='html'>I have worked with a lot of designers over the last couple of years. Some of them did a fantastic job and I happily paid good money for their work. But in my experience designers are highly "volatile" - like gas. What do I mean by that?&lt;br /&gt;&lt;br /&gt;Me to Designer: Are you available for design work?&lt;br /&gt;Designer: Yes. Sure.&lt;br /&gt;&lt;br /&gt;Me explains everything in great detail.&lt;br /&gt;&lt;br /&gt;Designer: No problem. I will do it.&lt;br /&gt;&lt;br /&gt;-- 2 Weeks later --&lt;br /&gt;&lt;br /&gt;Me to Designer: Hello.&lt;br /&gt;&lt;br /&gt;-- No response. 2 Weeks later ---&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Me to Designer: Hello - are you there?&lt;br /&gt;&lt;br /&gt;-- and so on --&lt;br /&gt;&lt;br /&gt;All this is over. I found a really good designer. He is friendly. Very creative. Motivated. Smart. Open minded. Loyal. And most importantly: Not like any gas I know. :)&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;Thank you &lt;a href="http://ilovecolorz.net/"&gt;Tomas Bartko&lt;/a&gt;.&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://ilovecolorz.net/"&gt;&lt;img border="0" src="http://ilovecolorz.net/images/logo.png" /&gt;&lt;/a&gt;&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/3733114751386359986-3327212067138076641?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/3327212067138076641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2011/11/if-you-need-good-designer.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/3327212067138076641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/3327212067138076641'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2011/11/if-you-need-good-designer.html' title='If you need a good designer...'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-7199273763300361136</id><published>2011-10-15T23:55:00.000-07:00</published><updated>2011-10-15T23:55:52.634-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flashcards'/><title type='text'>Status Report: Flashcards for iPad</title><content type='html'>I just wanted to let you know that I am heavily working on Flashcards for iPad and that you can expect something usable at the end of this year. However I have bad news for everyone who is using Flashcards today:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Flashcards for iPad won't sync with Flashcards for Mac from day one.&lt;/blockquote&gt;&lt;br /&gt;&lt;h3&gt;Yeah. Its a simple as that and here is why:&lt;/h3&gt;In order to make Flashcards possible on the iPad I had to remove a lot of features from the original Flashcards application and replace them with something more or less equivalent. These minor and major differences make the data formats incompatible. Syncing would lead to corrupt data and or would be indefinitely complex to implement. Take rich text editing with inline images as an example. That is absolutely no problem on the Mac. On the iPad this is a major problem. Rich text editing is possible in theory - but not with inline images and not with that kind of layout I have in mind. You can't even read and convert RTFD with the iOS SDK with a reasonable amount of effort.&lt;br /&gt;&lt;h3&gt;So what is the plan?&lt;/h3&gt;Here is comes: I will release Flashcards for iPad sometime next year. Then I will begin wot work on the next major version of Flashcards for Mac. The next major version will be stripped down and rearchitectured from the group up. At the same time this will enable iCloud syncing. You won't loose any data.&lt;br /&gt;&lt;br /&gt;But here is something you may be interested in: With the release of Flashcards for iPad I will also release a minor update for Flashcards for Mac which will be able to export all of your cards and decks to your iPad - once. Then you have to live without syncing for a few months and then everything should be fine again.&lt;br /&gt;&lt;br /&gt;Please let me know if you have any problems with this plan. I thought about many alternatives but if you think you have a better solution in mind please let me know.&lt;br /&gt;&lt;br /&gt;Ah - and here are two screenshots that show the current status of Flashcards for iPad:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-HzM0bNAieHg/Tpp_zEIYsfI/AAAAAAAAAWE/fYuYhr0cm_k/s1600/Screen+Shot+2011-10-16+at+8.51.52+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="246" src="http://1.bp.blogspot.com/-HzM0bNAieHg/Tpp_zEIYsfI/AAAAAAAAAWE/fYuYhr0cm_k/s320/Screen+Shot+2011-10-16+at+8.51.52+AM.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-mbWa_egIGkM/Tpp_0gybiaI/AAAAAAAAAWM/ZU2UyicwQ0M/s1600/Screen+Shot+2011-10-16+at+8.52.01+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="246" src="http://3.bp.blogspot.com/-mbWa_egIGkM/Tpp_0gybiaI/AAAAAAAAAWM/ZU2UyicwQ0M/s320/Screen+Shot+2011-10-16+at+8.52.01+AM.png" width="320" /&gt;&lt;/a&gt;&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/3733114751386359986-7199273763300361136?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/7199273763300361136/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2011/10/status-report-flashcards-for-ipad.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/7199273763300361136'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/7199273763300361136'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2011/10/status-report-flashcards-for-ipad.html' title='Status Report: Flashcards for iPad'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/-HzM0bNAieHg/Tpp_zEIYsfI/AAAAAAAAAWE/fYuYhr0cm_k/s72-c/Screen+Shot+2011-10-16+at+8.51.52+AM.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-1765500668605377149</id><published>2011-10-11T00:09:00.001-07:00</published><updated>2011-10-11T00:50:26.551-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Flashcards'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>Flashcards data loss</title><content type='html'>The latest Flashcards update has a bug which causes your data to disappear. I am very sorry that this happened. The good thing is that you data is not lost. You can "restore" it by executing the following steps:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Close Flashcards&lt;/li&gt;&lt;li&gt;Use Spotlight to find an application called "Terminal"&lt;/li&gt;&lt;/ul&gt;&lt;img alt="Find Termina with Spotlight" border="0" height="120" src="http://lh5.ggpht.com/-igsAPTTryx8/TpPrXRiw-mI/AAAAAAAAAVU/thJgT3YYQxI/1.png?imgmax=800" style="border: 0px initial initial; display: block; margin-left: auto; margin-right: auto;" title="1.png" width="447" /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Launch Terminal- Paste in the following text:&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;cp ~/Library/Application\ Support/Ebbinghaus3/Ebbinghaus3.sql \&lt;/pre&gt;&lt;pre&gt; ~/Library/Flashcards/Flashcards.sqlite&lt;/pre&gt;&lt;img alt="Screen Shot 2011 10 11 at 9 07 12 AM" border="0" height="121" src="http://lh3.ggpht.com/-lGd6q2b202E/TpPrdPK78DI/AAAAAAAAAVc/2GnTF3hw-To/Screen%252520Shot%2525202011-10-11%252520at%2525209.07.12%252520AM.png?imgmax=800" style="border: 0px initial initial; display: block; margin-left: auto; margin-right: auto;" title="Screen Shot 2011-10-11 at 9.07.12 AM.png" width="600" /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Press enter- Restart Flashcards&lt;/li&gt;&lt;/ul&gt;If you need any additional assistance please send an email to &lt;a href="mailto:support@christian-kienle.de"&gt;support@christian-kienle.de&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Update: A fix has already been submitted to Apple a few days ago but Flashcards is still waiting for review. I will keep you posted.&lt;/em&gt;&lt;br /&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/3733114751386359986-1765500668605377149?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/1765500668605377149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2011/10/flashcards-data-loss.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/1765500668605377149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/1765500668605377149'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2011/10/flashcards-data-loss.html' title='Flashcards data loss'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/-igsAPTTryx8/TpPrXRiw-mI/AAAAAAAAAVU/thJgT3YYQxI/s72-c/1.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-9136178197890524682</id><published>2011-09-03T13:30:00.000-07:00</published><updated>2011-09-04T13:07:58.035-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><title type='text'>Privacy issues with PDFs created using Preview.app</title><content type='html'>I just found a small privacy issue affecting Preview.app. If you wanna see a demonstration simply watch the video below. I am making this issue public so that every user can find out about it and is able to prevent bad things from happening with their (private) data. In addition to that I have already reported this issue to Apple. What do you think about this?&lt;br /&gt;&lt;br /&gt;&lt;iframe frameborder="0" height="600" src="http://player.vimeo.com/video/28554467?byline=0&amp;amp;portrait=0" width="530"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;a href="http://dl.dropbox.com/u/29925418/PreviewFlaw.m4v"&gt;&lt;span class="Apple-style-span" style="font-size: large;"&gt;Download the video&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can add you comment here and/or ping me on &lt;a href="http://twitter.com/#!/CocoaPimper"&gt;Twitter&lt;/a&gt;. :)&lt;br /&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/3733114751386359986-9136178197890524682?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/9136178197890524682/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2011/09/privacy-issues-with-pdfs-created-using.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/9136178197890524682'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/9136178197890524682'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2011/09/privacy-issues-with-pdfs-created-using.html' title='Privacy issues with PDFs created using Preview.app'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-857877288106705368</id><published>2011-06-18T02:34:00.001-07:00</published><updated>2011-06-18T02:36:34.990-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>My applications and the iCloud</title><content type='html'>My good friend &lt;a href="http://eternalstorms.at/"&gt;Matthias from Eternal Storms Software&lt;/a&gt;&amp;nbsp;&lt;a href="http://eternalstorms.wordpress.com/2011/06/15/my-applications-and-the-icloud/"&gt;wrote about the impact that iCloud might have on his applications&lt;/a&gt;. Since I found his post very interesting (from the standpoint of a devoted user of &lt;a href="http://eternalstorms.at/ScreenFloat/ScreenFloat/ScreenFloat_-_make_your_shots_fly%21.html"&gt;one of his products&lt;/a&gt; and from the standpoint of a developer myself) I will summarize my thoughts about iCloud and how my apps might use iCloud in the future.&lt;br /&gt;﻿ &lt;img alt="NewImage.jpg" border="0" height="128" src="http://lh3.ggpht.com/-QPGiWqjrDiM/TfxvrKBqe6I/AAAAAAAAALc/b2xkg0GzLq4/NewImage.jpg?imgmax=800" style="border: 0px initial initial; display: block; margin-left: auto; margin-right: auto;" width="128" /&gt;&lt;br /&gt;&lt;h3&gt;What does iCloud mean for Flashcards?&lt;/h3&gt;&lt;a href="http://christian-kienle.de/Flashcards/"&gt;Flashcards&lt;/a&gt; is a flash-card application which is﻿&amp;nbsp;only&amp;nbsp;available for Mac OS X. Wouldn't it be great to have your flash-cards available on all of your Macs? In a &lt;a href="http://christiankienle.blogspot.com/2011/05/how-to-sync-your-flash-cards-between.html"&gt;previous blog post I showed you how to do this&lt;/a&gt; by using Flashcards in combination with Dropbox. This works quite well and it will work well for the current version of Flashcards. I haven't announced my plans for the next major version of Flashcards yet - well up until now: The next version of Flashcards will be a complete rewrite and it will be available as an iPad and Mac app from the beginning. This makes the need for a perfect syncing solution even more obvious and Dropbox won't be good enough. iCloud seems to be the perfect fit for the next major version of Flashcards. Maybe it will be possible to use iCloud to publicly share your flash-cards with your friends.&lt;br /&gt;&lt;br /&gt;&lt;img alt="NewImage.jpg" border="0" height="128" src="http://lh6.ggpht.com/-O2bj7S1zEG0/Tfxve3oqWZI/AAAAAAAAALY/z47ier8u-m8/NewImage.jpg?imgmax=800" style="display: block; margin-left: auto; margin-right: auto;" width="128" /&gt;&lt;br /&gt;&lt;h3&gt;﻿What does iCloud mean for Drops?&lt;/h3&gt;&lt;a href="http://christian-kienle.de/Drops/"&gt;Drops&lt;/a&gt; is the ultimate tool for uploading files. At the moment files can only be uploads via FTP and require you to have some kind of FTP server at hand. I think it would be great to use iClouds storage capabilities to make files publicly available. I don't know if that is possible with iCloud. So we will see.&lt;br /&gt;&lt;br /&gt;&lt;img alt="Audio Extractor - Regular Application Icon (256x256) copy.png" border="0" height="128" src="http://lh5.ggpht.com/-CJWcybDM-Is/Tfxv5-BhlgI/AAAAAAAAALg/jlIzRonn1ME/Audio%252520Extractor%252520-%252520Regular%252520Application%252520Icon%252520%252528256x256%252529%252520copy.jpg?imgmax=800" style="border: 0px initial initial; display: block; margin-left: auto; margin-right: auto;" width="128" /&gt;&lt;br /&gt;&lt;h3&gt;﻿What does iCloud mean for Audio Extractor?&lt;/h3&gt;With &lt;a href="http://audio-extractor.com/"&gt;Audio Extractor&lt;/a&gt; you simply drop your video files on a drop zone, get something to drink, relax and a few minutes/hours later (depending on the video's size) you can start syncing the audio files onto your iPod, iPhone and iPad. Wouldn't it be great if there was an option to send it to iCloud so that you have the audio file available on all of your devices?&lt;br /&gt;I think that iCloud will make so many apps work even better - including my own and I can't wait to get my hands on the iCloud SDK.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3733114751386359986-857877288106705368?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/857877288106705368/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2011/06/my-applications-and-icloud.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/857877288106705368'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/857877288106705368'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2011/06/my-applications-and-icloud.html' title='My applications and the iCloud'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/-QPGiWqjrDiM/TfxvrKBqe6I/AAAAAAAAALc/b2xkg0GzLq4/s72-c/NewImage.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-8745714150246454999</id><published>2011-05-30T04:13:00.001-07:00</published><updated>2011-05-30T04:13:01.435-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Flashcards'/><title type='text'>How to sync your flash-cards between multiple Macs</title><content type='html'>&lt;p&gt;I am a developer and I try to sell my applications the right way. What do I mean by that? If you buy one of my applications you can install and use them on as many Macs you like. You pay for the app once and then you can use it everywhere. Other developers don't like that and take action to enforce this policy. But what do customers do when you allow them to use your application everywhere? Well, they do. Especially in the case of my application﻿ &lt;a href="http://itunes.apple.com/app/flashcards/id403021928?mt=12"&gt;Flashcards&lt;/a&gt; (a flash-cards application for OS X) my "liberal" policy raises a problem: Flashcards has no built in sync functionality but people would like to work with the same data everywhere. I will now explain how to enable sync in Flashcards although Flashcards has no built in sync functionality. The process I am describing can be applied to a lot of other applications as well (at your own risk of course). So let's get started.&lt;/p&gt;&lt;p&gt;1. Go to &lt;a href="https://www.dropbox.com/"&gt;Dropbox.com&lt;/a&gt; sign up. If you already have a Dropbox account you can of course skip this step.&lt;/p&gt;&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://lh4.ggpht.com/-CJ3f1S3SLhQ/TeN6ZbfniYI/AAAAAAAAALE/tjyW7JcRToM/Screen%252520shot%2525202011-05-30%252520at%25252013.06.26%252520.png?imgmax=800" border="0" alt="Screen shot 2011-05-30 at 13.06.26 .png" width="400" height="146" /&gt;&lt;/p&gt;&lt;p&gt;2. Open the Finder and go to Libary - Application Support. This folder contains a lot of folders - usually you will find a folder for each application you are using. An application typically stores user data inside its application support folder. Note: If you don't find the application folder in Application Support navigate back to the Library folder. Some applications prefer to have their folder located there.&lt;/p&gt;&lt;p&gt;3. In the case of Flashcards open the folder called Ebbinghaus3. The folder is called Ebbinghaus3 and not Flashcards because a few months ago Ebbinghaus was renamed to Flashcards.&lt;/p&gt;&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://lh3.ggpht.com/-xjYEhci7ufQ/TeN63vrtzwI/AAAAAAAAALI/X5TvODcoleg/Screen%252520shot%2525202011-05-30%252520at%25252013.08.26%252520.png?imgmax=800" border="0" alt="Screen shot 2011-05-30 at 13.08.26 .png" width="400" height="162" /&gt;&lt;/p&gt;&lt;p&gt;4. Move the file Ebbinghaus3.sql to your Dropbox folder.&lt;/p&gt;&lt;p&gt;5. Open the Terminal and type in the following commands:&lt;/p&gt;&lt;p&gt;&lt;pre style="margin: 8px;"&gt;﻿$ cd "Library/Application Support/Ebbinghaus3"/&lt;br /&gt;$ ln -s ~/Dropbox/Ebbinghaus3.sql Ebbinghaus3.sql&lt;/pre&gt;&lt;/p&gt;&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://lh4.ggpht.com/-h3E8aUjuMYg/TeN7gPus7KI/AAAAAAAAALM/7jtIRBFvWvk/Screen%252520shot%2525202011-05-30%252520at%25252013.11.33%252520.jpg?imgmax=800" border="0" alt="Screen shot 2011-05-30 at 13.11.33 .png" width="400" height="190" /&gt;&lt;/p&gt;&lt;p&gt;6. The above command creates a link called Ebbinghaus3.sql which points to the real Ebbinghaus3.sql file which is now located in your Dropbox folder.&lt;/p&gt;&lt;p&gt;7. Perform step 4 and 5 on every Mac that you own.&lt;/p&gt;&lt;p&gt;From now on every time you hit command + s in Flashcards the data is stored in the Dropbox folder and gets synced with your other Macs.&lt;/p&gt;&lt;p&gt;Have fun!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3733114751386359986-8745714150246454999?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/8745714150246454999/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2011/05/how-to-sync-your-flash-cards-between.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/8745714150246454999'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/8745714150246454999'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2011/05/how-to-sync-your-flash-cards-between.html' title='How to sync your flash-cards between multiple Macs'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/-CJ3f1S3SLhQ/TeN6ZbfniYI/AAAAAAAAALE/tjyW7JcRToM/s72-c/Screen%252520shot%2525202011-05-30%252520at%25252013.06.26%252520.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-3305250656187959046</id><published>2011-03-13T09:19:00.001-07:00</published><updated>2011-03-13T09:19:45.001-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Statistics'/><title type='text'>Statistics: Pricing in the Mac App Store</title><content type='html'>&lt;p&gt;This post is about the pricing in the Mac App Store and it answers several very important questions:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;What is the average price of an app in the Mac App Store?&lt;/li&gt;&lt;li&gt;How does the development of the average prices look like?&lt;/li&gt;&lt;li&gt;Which categories contain the highest/lowest priced apps?&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Before I go into the details I would like to explain how I created the statistics I am about to share with you. I am the developer of &lt;a href="http://store-news-app.com/"&gt;Store News&lt;/a&gt;. Store News is a simple app that shows the best deals in the Mac App Store. The best deals are determined by observing the price of every application in the store and list it in Store News as soon its price drops. The observation results in a daily "snapshot" of the whole Mac App Store. I used these snapshot to create the following statistics.&lt;/p&gt;&lt;p&gt;I used the snapshots created between 13. January 2011 and 1. March 2011.&lt;/p&gt;&lt;p&gt;The following chart shows the development of the average price of an app. Initially the average price was $18.46 and it dropped to $14.92 which is a delta of ﻿-$3.54 (-19.17%).&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://lh6.ggpht.com/_wKQ1LlKXgSg/TXzugo_rlZI/AAAAAAAAAK4/GfDUH37kFG8/Screen%20shot%202011-03-12%20at%2016.21.01%20.png?imgmax=800" border="0" alt="Screen shot 2011-03-12 at 16.21.01 .png" width="448" height="319" /&gt;&lt;/p&gt;&lt;p&gt;As you can see the price dropped almost constantly. The average price of Apples own apps sold via the Mac App Store is $29.80 which is round about twice as much. Is this a good thing or a bad thing? I can't tell since I don't know the number of sales. What do you think?&lt;/p&gt;&lt;p&gt;The next chart shows the average price broken down by category.&lt;/p&gt;&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://lh6.ggpht.com/_wKQ1LlKXgSg/TXzukxvyzdI/AAAAAAAAAK8/5qgdUd2dmdg/Screen%20shot%202011-03-12%20at%2016.21.06%20.png?imgmax=800" border="0" alt="Screen shot 2011-03-12 at 16.21.06 .png" width="429" height="513" /&gt;&lt;/p&gt;&lt;p&gt;If you don't know how to price your app it can't hurt to look at the chart above. What surprised me is the "Developer Tools" category since I thought that it contains many "pro-like" apps that make money by selling an app at a high price and in low volume. The category "Education" also caught my eyes since the average price is about $20.00 and I always thought that students don't have a lot of money.&lt;/p&gt;&lt;p&gt;I will create new charts during the next two weeks that I will share with you via this blog.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3733114751386359986-3305250656187959046?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/3305250656187959046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2011/03/statistics-pricing-in-mac-app-store.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/3305250656187959046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/3305250656187959046'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2011/03/statistics-pricing-in-mac-app-store.html' title='Statistics: Pricing in the Mac App Store'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_wKQ1LlKXgSg/TXzugo_rlZI/AAAAAAAAAK4/GfDUH37kFG8/s72-c/Screen%20shot%202011-03-12%20at%2016.21.01%20.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-1117573427289915061</id><published>2011-03-11T22:53:00.001-08:00</published><updated>2011-03-11T22:53:10.124-08:00</updated><title type='text'>To the people of Japan</title><content type='html'>&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://lh3.ggpht.com/_wKQ1LlKXgSg/TXsYUUo2q2I/AAAAAAAAAKw/CWteAK1SLvA/japanlove.png?imgmax=800" border="0" alt="japanlove.png" width="400" height="290" /&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3733114751386359986-1117573427289915061?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/1117573427289915061/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2011/03/to-people-of-japan.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/1117573427289915061'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/1117573427289915061'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2011/03/to-people-of-japan.html' title='To the people of Japan'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_wKQ1LlKXgSg/TXsYUUo2q2I/AAAAAAAAAKw/CWteAK1SLvA/s72-c/japanlove.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-6993953552353924289</id><published>2011-03-11T12:27:00.001-08:00</published><updated>2011-03-11T12:27:54.699-08:00</updated><title type='text'>Drops 1.1 — the ultimate tool for uploading files</title><content type='html'>&lt;p&gt;I am very happy to announce﻿ the release of Drops 1.1. Drops is the ultimate tool for uploading files. Simply drop files or folders on the Drops icon in your menu bar. In a blink of an eye your files will be uploaded to your server and the URL copied to the clipboard. You can now simply paste the URL wherever you want. Drops can also automatically shorten the URL for you. Let's have a closer look.&lt;/p&gt;&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://lh3.ggpht.com/_wKQ1LlKXgSg/TXqFvu-SYcI/AAAAAAAAAKg/G6cNJC1JMPI/Menu.png?imgmax=800" border="0" alt="Menu.png" width="313" height="298" /&gt;&lt;/p&gt;&lt;p&gt;This is Drop's menu. It shows a history of uploaded files. The icon can change its color so that you can see what Drops is doing at the moment.&lt;/p&gt;&lt;p&gt;&lt;img style="display: block; margin-left: auto; margin-right: auto;" src="http://lh4.ggpht.com/_wKQ1LlKXgSg/TXqFxucfVUI/AAAAAAAAAKk/Ihzr0JHmcD8/Status.png?imgmax=800" border="0" alt="Status.png" width="313" height="73" /&gt;&lt;/p&gt;&lt;p&gt;There are many things about Drops that will make your life easier.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Manage multiple FTP servers: Simply create as many connections you need.&lt;/li&gt;&lt;li&gt;Drops can copy the URL of an uploaded file to the clipboard automatically.&lt;/li&gt;&lt;li&gt;Drops can shorten the URL automatically.&lt;/li&gt;&lt;li&gt;Drops can compress files before uploading.&lt;/li&gt;&lt;li&gt;Drops can compress folders before uploading﻿.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;You can buy Drops at the Mac App Store - more information and a link to the store can be found at &lt;a href="http://christian-kienle.de/Drops/"&gt;my website&lt;/a&gt;.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3733114751386359986-6993953552353924289?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/6993953552353924289/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2011/03/drops-11-ultimate-tool-for-uploading.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/6993953552353924289'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/6993953552353924289'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2011/03/drops-11-ultimate-tool-for-uploading.html' title='Drops 1.1 — the ultimate tool for uploading files'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_wKQ1LlKXgSg/TXqFvu-SYcI/AAAAAAAAAKg/G6cNJC1JMPI/s72-c/Menu.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-5771347800247718123</id><published>2010-12-05T01:29:00.001-08:00</published><updated>2010-12-05T01:29:32.992-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Politics'/><title type='text'>About WikiLeaks</title><content type='html'>&lt;p&gt;This post is not about Objective-C, Cocoa nor anything technological. It is about something more important: WikiLeaks.&lt;/p&gt;&lt;p&gt;I am sure you have already heard﻿ that WikiLeaks recently published "United States diplomatic cables". Five major newspapers "helped" to spread the word about the published diplomatic cables. Around the globe people discussed the contents and thought about the impact such a publication might have on various things like international relations and mutual trust. Quickly the government of the United States recognized what has happened and took devastating actions:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Denial-of-service-attacks on WikiLeaks's servers&lt;/li&gt;&lt;li&gt;Content removal&lt;/li&gt;&lt;li&gt;Killing WikiLeak's domains &lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If this weren't enough companies all over the world are starting to "attack" WikiLeaks. Let me give you an example:&lt;/p&gt;&lt;p&gt;The Wau Holland Foundation is located in Germany. In the past the Wau Holland Foundation collected donations for WikiLeaks.  ﻿A few days ago PayPal closed the account of the Wau Holland Foundation. This means that nobody can donate via the Wau Holland Foundation anymore and that the already collected money seems to be lost. I donated hours before PayPal closed the account of the Wau Holland Foundation. I already asked PayPal for a refund so that I can donate the money via other channels. But hey - what PayPal did is not fair:&lt;/p&gt;&lt;p&gt;I am very angry about that what happened. Angry because I think that everybody is overreacting. We all know how much governments all over the world know about us. With us I mean the citizens of the world. The German government is passing law after law after law that allows them to know everything about us. The same is true for most governments these days which means that this is an international problem. All that a "normal" citizen can do is to demonstrate against those laws. Now look at our governments. Look at how they behave. Listen to what they are saying. Are they standing together as one demonstrating for their own rights on privacy? No! They behave like a child whose lolly pop fell on the dirty ground. No. Worse. They behave like a criminal.&lt;/p&gt;&lt;p&gt;There is so much going on at Twitter at the moment. Allow me to quote a few interesting Tweets:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;@﻿DanOnymity wrote: We elect Governments not to dictate our freedoms, but to support our liberty. They serve us, we do not serve them. #imwikileaks&lt;/p&gt;&lt;p&gt;@HansRottier wrote: Courage is what it takes to stand up and speak; courage is also what it takes to sit down and listen. #imwikileaks&lt;/p&gt;&lt;p&gt;@jdispinziere wrote: why are none of these trending? looks like twitter is censoring. #imwikileaks #wikileaks #cablegate&lt;/p&gt;&lt;p&gt;@voxhumanum wrote: The Big Brother is watching you. But, WikiLeaks is watching the Big Brother, for you. #imwikileaks&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;What do you think?&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3733114751386359986-5771347800247718123?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/5771347800247718123/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2010/12/about-wikileaks.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/5771347800247718123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/5771347800247718123'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2010/12/about-wikileaks.html' title='About WikiLeaks'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-6511432480794866673</id><published>2010-10-17T09:57:00.000-07:00</published><updated>2010-10-18T05:18:53.396-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>Handling Initialization Failure</title><content type='html'>A few months ago a friend of mine asked me the following question: "What should I do if I want to return nil in one of my initializers?" Returning nil in an initializer is nothing fancy. I do it all the time. However, there are a few rules you should be aware of.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;﻿Only return nil (in an initializer) if you can't perform the initialization. If a caller passes your&amp;nbsp;initializer﻿ a path to a file that does not exist and the object can't work without a file it would make sense to return nil.&lt;/li&gt;&lt;li&gt;Don't return nil if you can find a nice "workaround" for a problem during&amp;nbsp;initialization﻿ such as replacing a missing argument with a sensible default value.&lt;/li&gt;&lt;li&gt;If you want to return nil and you haven't sent a&amp;nbsp;initialization&amp;nbsp;﻿message to super yet perform the following steps: &lt;br /&gt;&lt;ul&gt;&lt;li&gt;cleanup any resources you may have created,&lt;/li&gt;&lt;li&gt;call [self release]; and then&lt;/li&gt;&lt;li&gt;return nil﻿&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;If you want to return nil and&amp;nbsp;already have sent a&amp;nbsp;initialization&amp;nbsp;﻿message to super (which returned nil) perform the following steps:﻿ &lt;br /&gt;&lt;ul&gt;&lt;li&gt;cleanup any resources you may have created,&lt;/li&gt;&lt;li&gt;return nil﻿﻿&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;If you return nil you must have a good reason. It is a good idea to let the caller know what went wrong during the&amp;nbsp;initialization﻿ process. In Objective-C/Foundation we can simply use NSError to pass the cause of a problem back to the caller. Imagine a class called &lt;em&gt;Person&lt;/em&gt;. A &lt;em&gt;Person&lt;/em&gt; has a first and a last name. One can create a Person by using -initWithFirstName:lastName:error:. If the passed first and/or last name is nil&amp;nbsp;-&lt;span style="font-family: Helvetica;"&gt;initWithFirstName:lastName:error&lt;/span&gt;:﻿ creates an error object, sends release to self and returns nil.&lt;br /&gt;&lt;br /&gt;&lt;pre style="color: #e00005; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: #7e4726;"&gt;#import &lt;/span&gt;"Person.h"&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"&gt;&lt;/pre&gt;&lt;pre style="color: #cb00a5; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;enum&lt;span style="color: black;"&gt; {&lt;/span&gt;&lt;/pre&gt;&lt;pre style="color: #265a5e; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: black;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;PersonErrorCodeFirstLastNameNotValid&lt;span style="color: black;"&gt; = &lt;/span&gt;&lt;span style="color: #4800de;"&gt;0&lt;/span&gt;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;};&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: #cb00a5;"&gt;typedef&lt;/span&gt; NSInteger PersonErrorCodes;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"&gt;&lt;/pre&gt;&lt;pre style="color: #cb00a5; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;@implementation&lt;span style="color: black;"&gt; Person&lt;/span&gt;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"&gt;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: #cb00a5;"&gt;@synthesize&lt;/span&gt; firstName, lastName;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"&gt;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;- (&lt;span style="color: #cb00a5;"&gt;id&lt;/span&gt;)initWithFirstName:(&lt;span style="color: #7e1aad;"&gt;NSString&lt;/span&gt; *)initFirstName&amp;nbsp;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; lastName:(&lt;span style="color: #7e1aad;"&gt;NSString&lt;/span&gt; *)initLastName&amp;nbsp;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; error:(&lt;span style="color: #7e1aad;"&gt;NSError&lt;/span&gt; **)error {&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #cb00a5;"&gt;if&lt;/span&gt;(initFirstName == &lt;span style="color: #cb00a5;"&gt;nil&lt;/span&gt; || initLastName == &lt;span style="color: #cb00a5;"&gt;nil&lt;/span&gt;) {&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #cb00a5;"&gt;if&lt;/span&gt;(error != &lt;span style="color: #cb00a5;"&gt;NULL&lt;/span&gt;) {&lt;/pre&gt;&lt;pre style="color: #7e1aad; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: black;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;NSMutableDictionary&lt;span style="color: black;"&gt; *u = [&lt;/span&gt;NSMutableDictionary &lt;span style="color: black;"&gt;&lt;/span&gt;&lt;span style="color: #490085;"&gt;dictionary&lt;/span&gt;&lt;span style="color: black;"&gt;];&lt;/span&gt;&lt;/pre&gt;&lt;pre style="color: #e00005; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: black;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [u &lt;/span&gt;&lt;span style="color: #490085;"&gt;setValue&lt;/span&gt;&lt;span style="color: black;"&gt;:&lt;/span&gt;@"first/last name not valid."&lt;span style="color: black;"&gt;&amp;nbsp;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="color: #7e1aad; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: black;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span style="color: #490085;"&gt;forKey&lt;/span&gt;&lt;span style="color: black;"&gt;:&lt;/span&gt;NSLocalizedDescriptionKey&lt;span style="color: black;"&gt;];&lt;/span&gt;&lt;/pre&gt;&lt;pre style="color: #265a5e; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: black;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style="color: #428288;"&gt;PersonErrorCodes&lt;/span&gt;&lt;span style="color: black;"&gt; c = &lt;/span&gt;PersonErrorCodeFirstLastNameNotValid&lt;span style="color: black;"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; *error = [&lt;span style="color: #7e1aad;"&gt;NSError&lt;/span&gt;&lt;span style="color: #490085;"&gt;errorWithDomain&lt;/span&gt;:&lt;span style="color: #e00005;"&gt;@"com.example.unique"&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&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; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span style="color: #490085;"&gt;code&lt;/span&gt;:c&amp;nbsp;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&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; &amp;nbsp;&lt;span style="color: #490085;"&gt;userInfo&lt;/span&gt;:u];&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; [&lt;span style="color: #cb00a5;"&gt;self &lt;/span&gt;&lt;span style="color: #490085;"&gt;release&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="color: #cb00a5; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: black;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;return &lt;span style="color: black;"&gt;&lt;/span&gt;nil&lt;span style="color: black;"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #cb00a5;"&gt;self&lt;/span&gt; = [&lt;span style="color: #cb00a5;"&gt;super &lt;/span&gt;&lt;span style="color: #490085;"&gt;init&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #cb00a5;"&gt;if&lt;/span&gt;(&lt;span style="color: #cb00a5;"&gt;self&lt;/span&gt; != &lt;span style="color: #cb00a5;"&gt;nil&lt;/span&gt;) {&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #cb00a5;"&gt;self&lt;/span&gt;.&lt;span style="color: #428288;"&gt;firstName&lt;/span&gt; = initFirstName;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="color: #cb00a5;"&gt;self&lt;/span&gt;.&lt;span style="color: #428288;"&gt;lastName&lt;/span&gt; = initLastName;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;&lt;pre style="color: #cb00a5; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: black;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;return&lt;span style="color: black;"&gt;&lt;/span&gt;self&lt;span style="color: black;"&gt;;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;}&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"&gt;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;- (&lt;span style="color: #cb00a5;"&gt;id&lt;/span&gt;)initWithFirstName:(&lt;span style="color: #7e1aad;"&gt;NSString&lt;/span&gt; *)initFirstName&amp;nbsp;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; lastName:(&lt;span style="color: #7e1aad;"&gt;NSString&lt;/span&gt; *)initLastName {&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #cb00a5;"&gt;return&lt;/span&gt; [&lt;span style="color: #cb00a5;"&gt;self &lt;/span&gt;&lt;span style="color: #265a5e;"&gt;initWithFirstName&lt;/span&gt;:initFirstName&amp;nbsp;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&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; &lt;span style="color: #265a5e;"&gt;lastName&lt;/span&gt;:&lt;span style="color: #428288;"&gt;lastName&lt;/span&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&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; &lt;span style="color: #265a5e;"&gt;error&lt;/span&gt;:&lt;span style="color: #cb00a5;"&gt;NULL&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;}&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"&gt;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;- (&lt;span style="color: #cb00a5;"&gt;id&lt;/span&gt;)init {&lt;/pre&gt;&lt;pre style="color: #265a5e; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: black;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #cb00a5;"&gt;return&lt;/span&gt;&lt;span style="color: black;"&gt; [&lt;/span&gt;&lt;span style="color: #cb00a5;"&gt;self &lt;/span&gt;&lt;span style="color: black;"&gt;&lt;/span&gt;initWithFirstName&lt;span style="color: black;"&gt;:[&lt;/span&gt;&lt;span style="color: #7e1aad;"&gt;NSString &lt;/span&gt;&lt;span style="color: black;"&gt;&lt;/span&gt;&lt;span style="color: #490085;"&gt;string&lt;/span&gt;&lt;span style="color: black;"&gt;]&amp;nbsp;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&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; &lt;span style="color: #265a5e;"&gt;lastName&lt;/span&gt;:[&lt;span style="color: #7e1aad;"&gt;NSString &lt;/span&gt;&lt;span style="color: #490085;"&gt;string&lt;/span&gt;]];&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;}&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"&gt;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;- (&lt;span style="color: #cb00a5;"&gt;void&lt;/span&gt;)dealloc {&lt;/pre&gt;&lt;pre style="color: #428288; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: black;"&gt;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span style="color: #cb00a5;"&gt;self&lt;/span&gt;&lt;span style="color: black;"&gt;.&lt;/span&gt;firstName&lt;span style="color: black;"&gt; = &lt;/span&gt;&lt;span style="color: #cb00a5;"&gt;nil&lt;/span&gt;&lt;span style="color: black;"&gt;;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &lt;span style="color: #cb00a5;"&gt;self&lt;/span&gt;.&lt;span style="color: #428288;"&gt;lastName&lt;/span&gt; = &lt;span style="color: #cb00a5;"&gt;nil&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; [&lt;span style="color: #cb00a5;"&gt;super &lt;/span&gt;&lt;span style="color: #490085;"&gt;dealloc&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;}&lt;/pre&gt;&lt;pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"&gt;&lt;/pre&gt;&lt;pre style="color: #cb00a5; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;@end&lt;/pre&gt;&lt;div&gt;﻿&lt;/div&gt;﻿&lt;span style="font-family: Helvetica; white-space: normal;"&gt;As you can see, this class has three&amp;nbsp;initializers﻿: -init, -initWithFirstName:lastName: and&amp;nbsp;-initWithFirstName:lastName:error:﻿. The designated initializer is&amp;nbsp;-initWithFirstName:lastName:error:﻿, which is used by a caller which is interested in the cause of a failed&amp;nbsp;initialization﻿.&amp;nbsp;-initWithFirstName:lastName:﻿ can be used by a caller which only wants to create a &lt;/span&gt;&lt;span style="font-family: Helvetica; white-space: normal;"&gt;&lt;em&gt;Person&lt;/em&gt;&lt;/span&gt;&lt;span style="font-family: Helvetica; white-space: normal;"&gt; and see if it worked or not.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3733114751386359986-6511432480794866673?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/6511432480794866673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2010/10/handling-initialization-failure.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/6511432480794866673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/6511432480794866673'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2010/10/handling-initialization-failure.html' title='Handling Initialization Failure'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-4857362827717262196</id><published>2010-10-13T00:45:00.001-07:00</published><updated>2010-10-13T00:45:55.543-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>Singletons to hell</title><content type='html'>&lt;p&gt;In my talk about "Complex Projects with Cocoa" at a German iOS and OS X developer conference I warned the audience about the singleton design pattern. This warning resulted in something that I would call a small flame war about singletons. Although I have nothing against controversial discussions I was a bit surprised that many people tried to defend the singleton design pattern. For the rest of the conference I asked myself two simple questions:&lt;/p&gt;&lt;ol&gt;&lt;li&gt;Why are so many people defending the singleton design pattern?&lt;/li&gt;&lt;li&gt;How can these people be convinced that they are defending bullshit?&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;I will try to answer them both.&lt;/p&gt;&lt;h3&gt;Why are so many people defending the singleton design pattern?﻿&lt;/h3&gt;&lt;p&gt;I think this is because the singleton design pattern is easy to understand. Most books and tutorials about design patterns first demonstrate the singleton pattern before anything else. So, every developer knows and understands the singleton design pattern. If this wouldn't be enough a singleton is often used by beginners to solve basic problems.&lt;/p&gt;&lt;p&gt;&lt;em&gt;"I don't know how to pass an array from instance to instance. What do I do?"&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Five minuted pass.&lt;/p&gt;&lt;p&gt;&lt;em&gt;"Ah! LETS MAKE A SINGLETON!"&lt;/em&gt;&lt;/p&gt;&lt;p&gt;Another five minutes later and the poor developer has a singleton that holds the array of objects that can and will be access from everywhere. This makes the developer happy. He used a singleton to (superficially) solve a problem. One does not like to abandon﻿ something familiar. We all know that.&lt;/p&gt;&lt;h3&gt;How can these people be convinced that they are defending bullshit?﻿&lt;/h3&gt;&lt;p&gt;Yes, there are singletons that make sense. No, I don't repeat what makes singletons so bad. So how do I convince you? Simply by quoting Erich Gamma. In an &lt;a href="http://www.informit.com/articles/article.aspx?p=1404056"&gt;interview&lt;/a&gt; Erich Gamma, one of the authors of the famous book "&lt;a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/ref=sr_1_1?ie=UTF8&amp;amp;qid=1286383220&amp;amp;sr=8-1"&gt;Design Patterns: Elements of Reusable Object-Oriented Software&lt;/a&gt;", was asked the question "How would you refactor "Design Patterns?".&lt;/p&gt;&lt;p&gt;His answer:&lt;/p&gt;&lt;p&gt;&lt;em&gt;"[...] When discussing which patterns to drop, we found that we still love them all. (Not really—I'm in favor of dropping Singleton. Its use is almost always a design smell.) &lt;/em&gt;&lt;em&gt;[...]﻿&lt;/em&gt;&lt;em&gt;"&lt;/em&gt;&lt;/p&gt;&lt;p&gt;This should convince everybody.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3733114751386359986-4857362827717262196?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/4857362827717262196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2010/10/singletons-to-hell.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/4857362827717262196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/4857362827717262196'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2010/10/singletons-to-hell.html' title='Singletons to hell'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-2424741485342675325</id><published>2010-08-18T02:13:00.001-07:00</published><updated>2010-08-18T02:21:43.644-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>Google please don't stand in the way of innovation.</title><content type='html'>&lt;p&gt;Google Reader is a really cool web application. I use it myself and I like it very much. Over the last couple of month I have been working on a Cocoa based news reader for Mac OS X. I have not yet released it because we are still working on the design. But this it how it looks:&lt;/p&gt;&lt;p&gt;&lt;img src="http://lh4.ggpht.com/_wKQ1LlKXgSg/TGuj_fnnqnI/AAAAAAAAAI4/hjL0EFg1py4/Screenshot%20Headline.png?imgmax=800" border="0" alt="Screenshot Headline.png" width="400" height="295" /&gt;&lt;/p&gt;&lt;p&gt;Yes, the application is living in the menu bar. But it can also be used as a window based application:&lt;/p&gt;&lt;p&gt;&lt;img src="http://lh3.ggpht.com/_wKQ1LlKXgSg/TGukELavdpI/AAAAAAAAAI8/D4as5iIMjXU/Screen%20shot%202010-08-18%20at%2010.46.41%20.png?imgmax=800" border="0" alt="Screen shot 2010-08-18 at 10.46.41 .png" width="400" height="194" /&gt;&lt;/p&gt;&lt;p&gt;But the most important part about this news reader is that it is integrated into Mac OS X very well. In fact the application is just a PubSub front end. PubSub is a framework provided by Apple that is managing a system wide database that knows which applications have subscribed to which feeds. This has some nice side effects. If you read something in our application it is also marked as read in another application (Mail, Safari) that is subscribed to the same feed (and vice versa). When we started developing the application one of our goals was to support Google Reader. The basic idea was to sync your whole PubSub database with Google Reader. This would automatically sync all PubSub-enabled applications with Google Reader. Even if one or more of these apps do not even know what Google Reader is.&lt;/p&gt;&lt;p&gt;&lt;img src="http://lh5.ggpht.com/_wKQ1LlKXgSg/TGukJQdkFGI/AAAAAAAAAJA/btFABtNVhY4/Arch.png?imgmax=800" border="0" alt="Arch.png" width="400" height="214" /&gt;&lt;/p&gt;&lt;p&gt;To say it again: This would enable every app that uses PubSub to automatically sync with Google Reader. There are already a lot of apps that make use of PubSub: Mail, Safari, Xcode, Times, our app, .... It is very easy to adopt PubSub. The problem is that Google has not yet released an official API for Google Reader. There exists an unofficial documentation and there are many apps that are using Google Reader today. They all rely on a private API that is not documented very well. We have decided not to support Google Reader in any form because of that. I would love to see a public API. Then we would have a Google Reader Sync Agent in weeks. This sync agent would be so cool in my opinion.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3733114751386359986-2424741485342675325?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/2424741485342675325/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2010/08/google-please-don-stand-in-way-of.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/2424741485342675325'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/2424741485342675325'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2010/08/google-please-don-stand-in-way-of.html' title='Google please don&amp;#39;t stand in the way of innovation.'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_wKQ1LlKXgSg/TGuj_fnnqnI/AAAAAAAAAI4/hjL0EFg1py4/s72-c/Screenshot%20Headline.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-7847632237325838588</id><published>2010-08-17T03:09:00.001-07:00</published><updated>2010-08-17T03:16:46.396-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>Core Data Editor 3.0 released</title><content type='html'>&lt;p&gt;Yesterday I finally released Core Data Editor 3.0. It took me about ten months to get from a beta version of Core Data Editor 3.0 to the final version. What is new:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;Core Data Editor automatically observes the file system and tries to figure out when a persistent store file is changed by another application. If Core Data Editor detects a change it automatically reloads the file and refreshes its UI. Many thanks to Stuart Connolly, the developer of SCEvent, which makes observing the file system very easy.&lt;/li&gt;&lt;li&gt;Better support for iOS applications: In Core Data Editor 2 you could only specify the location of the iPhone Simulator directory, globally. This makes no sense anymore. Apple changed the locations where the Simulator places application data which broke Core Data Editor. Now you have to specify the location of the applications folder in each configuration. This allows you to use Core Data Editor for different versions of the SDK.&lt;/li&gt;&lt;li&gt;Updates are now delivered via Sparkle.&lt;/li&gt;&lt;li&gt;Help is now available and integrated in the app and will be constantly improved.&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;span style="font-size: 14px; font-weight: bold;"&gt;&lt;a href="http://christian-kienle.de/CoreDataEditor/"&gt;Core Data Editor Website&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The following screen cast shows Core Data Editor and a third party app. As I add objects in the third party app Core Data Editor refreshes it's UI to reflect the changes. Neat - isn't it?&lt;/p&gt;&lt;p&gt;&lt;a href="http://christian-kienle.de/christiankienle-blog/CoreDataEditor3-Sync/CoreDataEditorSync.mov"&gt;&lt;img src="http://lh5.ggpht.com/_wKQ1LlKXgSg/TGpf3wIH9bI/AAAAAAAAAIw/RBReNN-XFkc/SyncThumbnail.png?imgmax=800" border="0" alt="SyncThumbnail.png" width="300" height="402" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;(Click on the image above to watch the screen cast.)&lt;/p&gt;&lt;p&gt;Starting with version 3.0 Core Data Editor costs $20. Everyone who already donated $20 will receive a free license for Core Data Editor 3.0. Just drop me an e-mail if I forgot you. I hope you like the latest version of Core Data Editor.&lt;/p&gt;&lt;p&gt;&lt;span style="font-size: 14px; font-weight: bold;"&gt;&lt;a href="http://christian-kienle.de/CoreDataEditor/"&gt;Core Data Editor Website﻿&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3733114751386359986-7847632237325838588?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/7847632237325838588/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2010/08/core-data-editor-30-released.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/7847632237325838588'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/7847632237325838588'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2010/08/core-data-editor-30-released.html' title='Core Data Editor 3.0 released'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_wKQ1LlKXgSg/TGpf3wIH9bI/AAAAAAAAAIw/RBReNN-XFkc/s72-c/SyncThumbnail.png?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-8173419439775028889</id><published>2010-07-18T03:04:00.001-07:00</published><updated>2010-07-18T03:04:33.779-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Programming'/><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>Drawing Patterns</title><content type='html'>&lt;p&gt;Imagine you have a nice wooden texture that you want to use in some kind of navigation bar. You want the wooden texture to be repeatedly drawn along the x-axis. Your first approach might look something like this.&lt;/p&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #e00005;"&gt;&lt;span style="color: #7e4726;"&gt;#import &lt;/span&gt;"PatternView.h"&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #cb00a5;"&gt;@implementation&lt;span style="color: #000000;"&gt; PatternView&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;- (&lt;span style="color: #cb00a5;"&gt;void&lt;/span&gt;)drawRect:(&lt;span style="color: #7e1aad;"&gt;NSRect&lt;/span&gt;)dirtyRect {&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;   [&lt;span style="color: #cb00a5;"&gt;super&lt;/span&gt;&lt;span style="color: #490085;"&gt;drawRect&lt;/span&gt;:dirtyRect];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;   &lt;span style="color: #7e1aad;"&gt;NSImage&lt;/span&gt; *bg = [&lt;span style="color: #7e1aad;"&gt;NSImage&lt;/span&gt;&lt;span style="color: #490085;"&gt;imageNamed&lt;/span&gt;:&lt;span style="color: #e00005;"&gt;@"bg"&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;   &lt;span style="color: #7e1aad;"&gt;NSColor&lt;/span&gt; *backgroundColor = [&lt;span style="color: #7e1aad;"&gt;NSColor&lt;/span&gt;&lt;span style="color: #490085;"&gt;colorWithPatternImage&lt;/span&gt;:bg];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;&lt;span style="white-space: pre;"&gt;&lt;/span&gt;[backgroundColor &lt;span style="color: #490085;"&gt;set&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #490085;"&gt;&lt;span style="color: #000000;"&gt;   &lt;/span&gt;NSRectFill&lt;span style="color: #000000;"&gt;([&lt;/span&gt;&lt;span style="color: #cb00a5;"&gt;self&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;/span&gt;bounds&lt;span style="color: #000000;"&gt;]);&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;}&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #cb00a5;"&gt;@end&lt;/pre&gt;&lt;p&gt;This might not be what you have expected. Let me show you how the above code behaves in action.&lt;/p&gt;&lt;p&gt;&lt;a href="http://christian-kienle.de/christiankienle-blog/Pattern/Pattern1-Web-Computer.m4v"&gt;&lt;img src="http://lh6.ggpht.com/_wKQ1LlKXgSg/TELRn6oUfpI/AAAAAAAAAIk/nSdWuRe6nBc/Pattern1-Web.jpg?imgmax=800" border="0" alt="Pattern1-Web.jpg" width="334" height="402" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;(Click on the image above to see the video)&lt;/p&gt;&lt;p&gt;As you can see when resizing the window the displayed texture is changing as well. This is because of the fact that patterns are always drawn relative to the containing window. Of course this works fine for patterns that should repeat along both axes. In this case however, we don't want that. Let me show you how to fix that.&lt;/p&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #e00005;"&gt;&lt;span style="color: #7e4726;"&gt;#import &lt;/span&gt;"PatternView.h"&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #cb00a5;"&gt;@implementation&lt;span style="color: #000000;"&gt; PatternView&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;- (&lt;span style="color: #cb00a5;"&gt;void&lt;/span&gt;)drawRect:(&lt;span style="color: #7e1aad;"&gt;NSRect&lt;/span&gt;)dirtyRect {&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;   [&lt;span style="color: #cb00a5;"&gt;super&lt;/span&gt;&lt;span style="color: #490085;"&gt;drawRect&lt;/span&gt;:dirtyRect];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;   &lt;span style="color: #7e1aad;"&gt;NSSize&lt;/span&gt; size = [&lt;span style="color: #cb00a5;"&gt;self&lt;/span&gt;&lt;span style="color: #490085;"&gt;bounds&lt;/span&gt;].&lt;span style="color: #7e1aad;"&gt;size&lt;/span&gt;;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #008c00;"&gt;&lt;span style="color: #000000;"&gt;   &lt;/span&gt;// Create a new image and make it as big as the view&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;   &lt;span style="color: #7e1aad;"&gt;NSImage&lt;/span&gt; *bigImage = [[[&lt;span style="color: #7e1aad;"&gt;NSImage&lt;/span&gt;&lt;span style="color: #490085;"&gt;alloc&lt;/span&gt;] &lt;span style="color: #490085;"&gt;initWithSize&lt;/span&gt;:size] &lt;span style="color: #490085;"&gt;autorelease&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #008c00;"&gt;&lt;span style="color: #000000;"&gt;   &lt;/span&gt;// Prepare for drawing onto the new image&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;   [bigImage &lt;span style="color: #490085;"&gt;lockFocus&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;   &lt;span style="color: #7e1aad;"&gt;NSImage&lt;/span&gt; *bg = [&lt;span style="color: #7e1aad;"&gt;NSImage&lt;/span&gt;&lt;span style="color: #490085;"&gt;imageNamed&lt;/span&gt;:&lt;span style="color: #e00005;"&gt;@"bg"&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;   &lt;span style="color: #7e1aad;"&gt;NSColor&lt;/span&gt; *backgroundColor = [&lt;span style="color: #7e1aad;"&gt;NSColor&lt;/span&gt;&lt;span style="color: #490085;"&gt;colorWithPatternImage&lt;/span&gt;:bg];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;   [backgroundColor &lt;span style="color: #490085;"&gt;set&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #490085;"&gt;&lt;span style="color: #000000;"&gt;   &lt;/span&gt;NSRectFill&lt;span style="color: #000000;"&gt;([&lt;/span&gt;&lt;span style="color: #cb00a5;"&gt;self&lt;/span&gt;&lt;span style="color: #000000;"&gt;&lt;/span&gt;bounds&lt;span style="color: #000000;"&gt;]);&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #490085;"&gt;&lt;span style="color: #000000;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;   [bigImage &lt;span style="color: #490085;"&gt;unlockFocus&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #008c00;"&gt;&lt;span style="color: #000000;"&gt;   &lt;/span&gt;// Now draw the image to the view&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;   [bigImage &lt;span style="color: #490085;"&gt;drawInRect&lt;/span&gt;:[&lt;span style="color: #cb00a5;"&gt;self&lt;/span&gt;&lt;span style="color: #490085;"&gt;bounds&lt;/span&gt;] &lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;               &lt;span style="color: #490085;"&gt;fromRect&lt;/span&gt;:&lt;span style="color: #7e1aad;"&gt;NSZeroRect&lt;/span&gt; &lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #490085;"&gt;&lt;span style="color: #000000;"&gt;              &lt;/span&gt;operation&lt;span style="color: #000000;"&gt;:&lt;/span&gt;NSCompositeSourceOver&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;               &lt;span style="color: #490085;"&gt;fraction&lt;/span&gt;:&lt;span style="color: #4800de;"&gt;1.0f&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;}&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #cb00a5;"&gt;@end&lt;/pre&gt;&lt;div&gt;﻿&lt;/div&gt;&lt;p&gt;The trick is to create a new empty image and size it correctly. Then you simply have to draw as shown in the first example. This results in exactly what we want.&lt;/p&gt;&lt;div&gt;&lt;a href="http://christian-kienle.de/christiankienle-blog/Pattern/Pattern2-Web-Computer.m4v"&gt;&lt;img src="http://lh3.ggpht.com/_wKQ1LlKXgSg/TELRq3BRuOI/AAAAAAAAAIo/GIDPRl62Ofg/Pattern2-Web.jpg?imgmax=800" border="0" alt="Pattern2-Web.jpg" width="342" height="480" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;(Click on the above image to see the video)&lt;/div&gt;&lt;p&gt;Feel free to &lt;a href="http://christian-kienle.de/christiankienle-blog/Pattern/PatternExamples.zip"&gt;download the examples&lt;/a&gt;.&lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3733114751386359986-8173419439775028889?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/8173419439775028889/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2010/07/drawing-patterns.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/8173419439775028889'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/8173419439775028889'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2010/07/drawing-patterns.html' title='Drawing Patterns'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_wKQ1LlKXgSg/TELRn6oUfpI/AAAAAAAAAIk/nSdWuRe6nBc/s72-c/Pattern1-Web.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-8178490000223079450</id><published>2010-05-16T02:17:00.001-07:00</published><updated>2010-05-17T01:02:15.628-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tip'/><category scheme='http://www.blogger.com/atom/ns#' term='Cocoa'/><title type='text'>Cocoa Tip: Detecting Arrow Down Key Events</title><content type='html'>&lt;p&gt;We all know the Spotlight Search item in the top right corner of the screen. You can enter something and Spotlight instantly finds all matching files. The results view below the search field can be accessed by pressing the down arrow key. Usually pressing the down arrow key has the effect that the cursor jumps to the end of the text field's content. How can we override the default behavior? One solution would be to subclass NSTextView and provide an instance of this text view as the field editor of the cell. Luckily we have an alternative solution for this:&lt;/p&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #490085;"&gt;&lt;span style="color: #000000;"&gt;   [&lt;/span&gt;&lt;span style="color: #7e1aad;"&gt;NSEvent&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;addLocalMonitorForEventsMatchingMask&lt;span style="color: #000000;"&gt;:&lt;/span&gt;NSKeyDownMask&lt;span style="color: #000000;"&gt; &lt;/span&gt;handler&lt;span style="color: #000000;"&gt;:^(&lt;/span&gt;&lt;span style="color: #7e1aad;"&gt;NSEvent&lt;/span&gt;&lt;span style="color: #000000;"&gt; *event) {&lt;/span&gt;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;      &lt;span style="color: #7e1aad;"&gt;NSString&lt;/span&gt; *characters = [event &lt;span style="color: #490085;"&gt;characters&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;      &lt;span style="color: #7e1aad;"&gt;unichar&lt;/span&gt; character = [characters &lt;span style="color: #490085;"&gt;characterAtIndex&lt;/span&gt;:&lt;span style="color: #4800de;"&gt;0&lt;/span&gt;];&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;      &lt;span style="color: #cb00a5;"&gt;if&lt;/span&gt;(character == &lt;span style="color: #490085;"&gt;NSDownArrowFunctionKey&lt;/span&gt;) {&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;         &lt;span style="color: #490085;"&gt;NSLog&lt;/span&gt;(&lt;span style="color: #e00005;"&gt;@"key down"&lt;/span&gt;);&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;      } &lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;      &lt;span style="color: #cb00a5;"&gt;return&lt;/span&gt; event;&lt;/pre&gt;&lt;pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"&gt;   }];﻿&lt;/pre&gt;&lt;p&gt;This solution looks pretty straight forward. We could also return an alternative event. I don't want to say that this is my final solution but I am happy to see that common things are easy with Cocoa.&lt;/p&gt;&lt;p&gt;Edit: You can remove a monitor by calling +removeMonitor: (NSEvent).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3733114751386359986-8178490000223079450?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/8178490000223079450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2010/05/cocoa-tip-detecting-arrow-down-key.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/8178490000223079450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/8178490000223079450'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2010/05/cocoa-tip-detecting-arrow-down-key.html' title='Cocoa Tip: Detecting Arrow Down Key Events'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-7505263061844350060</id><published>2009-12-28T05:50:00.000-08:00</published><updated>2009-12-28T05:50:45.080-08:00</updated><title type='text'>It will die: Accessing instance variables in init and dealloc</title><content type='html'>Michael, the guy behind the&amp;nbsp;&lt;a href="http://mikeash.com/?page=pyblog/"&gt;NSBlog&lt;/a&gt;, wrote a&amp;nbsp;&lt;a href="http://mikeash.com/?page=pyblog/friday-qa-2009-11-27-using-accessors-in-init-and-dealloc.html"&gt;nice summery about the pros and cons of using accessors in -init* and -dealloc&lt;/a&gt;. He is right by pointing out the possibilities of certain side effects when using accessors in -init* and -dealloc. &amp;nbsp;On the other hand let's have a look at the near future. The Objective-C 2.0 language comes with a really nice new feature called Properties. Properties let you describe the - guess what - properties of a class very easily.&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;@interface Person : NSObject {&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;NSString *firstName;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;NSString *lastName;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&amp;nbsp;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;@property (nonatomic, copy) NSString *firstName;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;@property (nonatomic, copy) NSString *lastName;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;@end&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;Pretty easy stuff so far. But I don't know about you but I hate redundancy in my source code. I would love to be able to just write the following piece of code:&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;@interface Person : NSObject&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;@property (nonatomic, copy) NSString *firstName;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;@property (nonatomic, copy) NSString *lastName;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;@end&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;What happened? The instance variables are gone. But the cool thing is that you can do that. The code will compile assuming the usage of the 64-bit mode. Try it! Now let's face facts: Does Apple still build 32 bit computers? No. How long will it take until there are only 64 bit computers in use? A few years maybe. This all means that instance variables will die in the near future. Nobody wants to write redundant code. Now I am asking you: How to set/release an instance variable directly when you can't access it? You simply don't.&lt;br /&gt;&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/3733114751386359986-7505263061844350060?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/7505263061844350060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2009/12/it-will-die-accessing-instance.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/7505263061844350060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/7505263061844350060'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2009/12/it-will-die-accessing-instance.html' title='It will die: Accessing instance variables in init and dealloc'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-1699436418845336499</id><published>2009-12-18T01:28:00.000-08:00</published><updated>2009-12-18T01:28:38.952-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Objective-J Cappuccino Atlas Cool 280North'/><title type='text'>Atlas makes Objective-J/Cappuccino so much more fun</title><content type='html'>This blog post is about Atlas. Atlas is an IDE for Cappuccino/Objective-J applications. But first things first.&lt;br /&gt;&lt;br /&gt;Objective-J is a new programming language developed by the guys from 280 North. The cool thing about Objective-J is that it is a real superset of Java Script which means that every valid Java Script code is also valid Objective-J code. You can also find this paradigm in the Objective-C world because Objective-C is a real superset of C. Now the coolness begins: The guys from 280 North are geniuses. They built an Objective-J interpreter with Java Script. Which means that every browser that supports Java Script can also execute Objective-J code without the need of plugins. The Cappuccino toolset also contains an ahead of time compiler for Objective-J code. By the way: Cappuccino is the application development framework developed in Objective-J.&lt;br /&gt;&lt;br /&gt;That said it is now time to show you what the guy from 280 North built with Cappuccino and Objective-J. Open your favorite browser and go to &lt;a href="http://280slides.com/Editor/"&gt;http://280slides.com/Editor/&lt;/a&gt;. Yes, you are right. They built a Powerpoint killing web app by using Cappuccino and Objective-J.&lt;br /&gt;&lt;br /&gt;I hope that, at this point, you are all ears to what I have to say about Atlas because if gets even better and cooler.&lt;br /&gt;&lt;br /&gt;At this time the guys from 280 North have a cool programming language and an application development framework. Atlas brings it all together. Atlas lets you create new projects.&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/_wKQ1LlKXgSg/SytHdkrGWgI/AAAAAAAAAHc/SHFdEqAYkyE/s1600-h/New+Project.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_wKQ1LlKXgSg/SytHdkrGWgI/AAAAAAAAAHc/SHFdEqAYkyE/s320/New+Project.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Once created a new project Atlas opens up a window that lets you select a file and edit it's content.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_wKQ1LlKXgSg/SytIA5yJboI/AAAAAAAAAHk/oPNloj3_zfk/s1600-h/code.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_wKQ1LlKXgSg/SytIA5yJboI/AAAAAAAAAHk/oPNloj3_zfk/s320/code.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;As far I know Atlas is using &lt;a href="https://mozillalabs.com/bespin/"&gt;Bespin&lt;/a&gt;&amp;nbsp;as an editor component. Cappuccino applications usually have an user interface. Atlas makes it really easy to create and edit user interfaces. By opening the Resources folder and then clicking on "MainMenu.cib" an interface builder opens up that let's you visually edit the user interface by drag and drop.&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_wKQ1LlKXgSg/SytJmHeZvRI/AAAAAAAAAHs/mpWJLu2iqpI/s1600-h/ui+editor.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_wKQ1LlKXgSg/SytJmHeZvRI/AAAAAAAAAHs/mpWJLu2iqpI/s320/ui+editor.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;This makes developing rich web application front ends so much easier. One more extremely cool feature: &amp;nbsp;With Atlas you can target two platforms: A web browser and the real native desktop platform. By selecting "Native Desktop" in the platform popup menu and then clicking on "Build and Run" Atlas creates a real Mac OS X application for me: With its own window and icon in the dock.&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;a href="http://2.bp.blogspot.com/_wKQ1LlKXgSg/SytKsca7DoI/AAAAAAAAAH0/-Q544Jfr6BE/s1600-h/Screen+shot+2009-12-18+at+10.25.32+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_wKQ1LlKXgSg/SytKsca7DoI/AAAAAAAAAH0/-Q544Jfr6BE/s320/Screen+shot+2009-12-18+at+10.25.32+AM.png" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;Join the &lt;a href="https://atlas-beta.heroku.com/"&gt;Atlas Beta Program&lt;/a&gt; today.&lt;br /&gt;&lt;/div&gt;&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/3733114751386359986-1699436418845336499?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/1699436418845336499/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2009/12/atlas-makes-objective-jcappuccino-so.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/1699436418845336499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/1699436418845336499'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2009/12/atlas-makes-objective-jcappuccino-so.html' title='Atlas makes Objective-J/Cappuccino so much more fun'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_wKQ1LlKXgSg/SytHdkrGWgI/AAAAAAAAAHc/SHFdEqAYkyE/s72-c/New+Project.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-7742860519101643830</id><published>2009-12-17T11:27:00.000-08:00</published><updated>2009-12-17T11:27:30.108-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C Cocoa Pattern GoodStyle'/><title type='text'>Using Objective-C Categories: The safe way</title><content type='html'>&lt;span style="font-family: 'MS Shell Dlg'; font-size: small;"&gt;&lt;span style="font-size: 13px;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: 'MS Shell Dlg'; font-size: small;"&gt;&lt;span style="font-size: 13px;"&gt;&lt;div&gt;A Objective-C developer can add methods to an existing class by using categories. Let's assume you ever wanted NSString to have a -reverse method that returns the receiving string in reverse order. "Cocoa" would become "aocoC". So you extend NSString by writing a category that implements the reverse method.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Interface:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;@interface NSString (reverse)&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;-(NSString *) reverse;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;@end&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Implementation:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;@implementation NSString (reverse)&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;-(NSString *) reverse&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;NSMutableString *reversedStr;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;int len = [self length];&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;// Auto released string&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;reversedStr = [NSMutableString stringWithCapacity:len]; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;// Probably woefully inefficient...&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;while (len &amp;gt; 0)&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;[reversedStr appendString:&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [NSString stringWithFormat:@"%C", [self characterAtIndex:--len]]]; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;return reversedStr;&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;@end&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;The code above is adopted from &lt;/i&gt;&lt;a href="http://macdevelopertips.com/objective-c/objective-c-categories.html"&gt;&lt;i&gt;http://macdevelopertips.com/objective-c/objective-c-categories.html&lt;/i&gt;&lt;/a&gt;&lt;i&gt;.&lt;/i&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The actual code has no problem. The problem is the name of the method added by this category. What happens if you use a third party framework that also adds a reverse method to NSString? Well, the behavior is undefined. To solve this problem I suggest that you simply prefix methods you add by using categories with the same prefix you use to indicate "your" classes. To give an example: I prefix my classes with CMK which means that I prefix methods that I add by using a category with cmk_. In the example given above this means that reverse has to be renamed to cmk_reverse. This technique is also used by Google and &lt;a href="http://rentzsch.com/"&gt;Jonathan Rentzsch&lt;/a&gt; (in his method swizzle code).&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In general you should avoid adding too many categories. Use them wisely.&lt;br /&gt;&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3733114751386359986-7742860519101643830?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/7742860519101643830/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2009/12/using-objective-c-categories-safe-way.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/7742860519101643830'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/7742860519101643830'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2009/12/using-objective-c-categories-safe-way.html' title='Using Objective-C Categories: The safe way'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-4401012779221928835</id><published>2009-12-14T11:01:00.000-08:00</published><updated>2009-12-14T11:01:49.279-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C Cocoa CoreData'/><title type='text'>Last minute optimization and lazy fetching</title><content type='html'>This post is about how a tiny method saved me a lot of additional work. Maybe you know that I am the developer of &lt;a href="http://christian-kienle.de/Ebbinghaus/"&gt;Ebbinghaus&lt;/a&gt;. Ebbinghaus is a flash card application. It heavily uses Core Data. Like every good developer I didn't really care about performance issues too early. In fact I did test the performance of the whole application when it was done. I remembered the following quote.&lt;br /&gt;&lt;blockquote&gt;Premature optimization is the root of all evil. (Donald Knuth)&lt;br /&gt;&lt;/blockquote&gt;The performance tests showed that Ebbinghaus had only one performance related problem. Let me describe the problem: Ebbinghaus lets the user create decks. Every deck can contain cards. The user is also able to create smart decks. They work like smart playlists you know from iTunes.&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/_wKQ1LlKXgSg/SyaI44f2fTI/AAAAAAAAAHM/5LWT5Q4zciU/s1600-h/SmartDeck.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="223" src="http://2.bp.blogspot.com/_wKQ1LlKXgSg/SyaI44f2fTI/AAAAAAAAAHM/5LWT5Q4zciU/s320/SmartDeck.png" width="320" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;Filtering a lot of cards (+ 10.000) just was too slow. Scrolling the table view displaying the cards was not smooth at all. I asked myself how to solve this problem without having to write a lot of caching code myself. The solution was extremely easy. Maybe you already know: NSObjectController (and thus NSArrayController too) &amp;nbsp;has a method called -setUsesLazyFetching:. When setting -usesLazyFetching to YES the controller will try everything it can to improve performance by lazy fetching data. There is even a check box for this property so that you can set it directly in Interface Builder.&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_wKQ1LlKXgSg/SyaKm5UFjdI/AAAAAAAAAHU/dlwymBZMU5I/s1600-h/Lazy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="208" src="http://1.bp.blogspot.com/_wKQ1LlKXgSg/SyaKm5UFjdI/AAAAAAAAAHU/dlwymBZMU5I/s320/Lazy.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;Checking this check box did solve the performance problem. I am still thrilled about this. Imagine what it kind of ugly work I had to do then implementing that for myself. Of course lazy fetching does only work &amp;nbsp;in combination with Core Data. So be a smart developer and use Core Data whenever you can.&lt;/div&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/3733114751386359986-4401012779221928835?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/4401012779221928835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2009/12/last-minute-optimization-and-lazy.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/4401012779221928835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/4401012779221928835'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2009/12/last-minute-optimization-and-lazy.html' title='Last minute optimization and lazy fetching'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_wKQ1LlKXgSg/SyaI44f2fTI/AAAAAAAAAHM/5LWT5Q4zciU/s72-c/SmartDeck.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3733114751386359986.post-8337252134684140720</id><published>2009-12-13T06:59:00.000-08:00</published><updated>2009-12-13T07:04:34.563-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Objective-C Cocoa Pattern GoodStyle'/><title type='text'>Using NSSet instead of plain old C-Enums and bitwise operations</title><content type='html'>In my first blog post I would like to convince you that using C-Enums and bit operations when writing Objective-C code is not such a good idea anymore. In order to convince you I will first show you how we deal with enumerations today. In the second act I will explain why the current handling of enumerations is bad. And at last I will show you a alternative that you can use to improve you enum and bit operation code.&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now, please have a look at NSView's autoresizingMask property. The autoresizingMask lets a developer specify how the view will change it's frame when it is being resized. When setting the auto resizing behavior you have create a mask using bitwise OR operations. Apple explains that in the documentation quite well:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;- (&lt;span style="color: #c600a1;"&gt;void&lt;/span&gt;)setAutoresizingMask:(NSUInteger)mask&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Parameters&lt;br /&gt;&lt;/div&gt;&lt;div&gt;mask&lt;br /&gt;&lt;/div&gt;&lt;div&gt;An integer bit mask. mask can be specified by combining using the C bitwise OR operator any of the options described in "Resizing masks".&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The possible "values" that can be used to composite an auto resizing mask are also well documented:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="color: #c600a1; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;enum&lt;span style="color: black;"&gt; {&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; NSViewNotSizable &amp;nbsp; &amp;nbsp; = &lt;span style="color: #1e16d6;"&gt;0&lt;/span&gt;,&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; NSViewMinXMargin &amp;nbsp; &amp;nbsp; = &lt;span style="color: #1e16d6;"&gt;1&lt;/span&gt;,&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; NSViewWidthSizable &amp;nbsp; = &lt;span style="color: #1e16d6;"&gt;2&lt;/span&gt;,&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; NSViewMaxXMargin &amp;nbsp; &amp;nbsp; = &lt;span style="color: #1e16d6;"&gt;4&lt;/span&gt;,&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; NSViewMinYMargin &amp;nbsp; &amp;nbsp; = &lt;span style="color: #1e16d6;"&gt;8&lt;/span&gt;,&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; NSViewHeightSizable&amp;nbsp; = &lt;span style="color: #1e16d6;"&gt;16&lt;/span&gt;,&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; NSViewMaxYMargin &amp;nbsp; &amp;nbsp; = &lt;span style="color: #1e16d6;"&gt;32&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;};&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, how does setting the auto resizing mask typically look like? Let's recap:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;[aView setAutoresizingMask:(NSViewWidthSizable |&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&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; NSViewHeightSizable)];&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;One questions immediately pops up: Why does it have to be so complicated? There are good reasons.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Bit masks are usually very "small" and thus save memory.&lt;/li&gt;&lt;li&gt;Even though a resizing mask is nothing more than a single number it can describe nearly an infinite number of possible combinations. There is no need for setters/getters like -setHeightSizable:(BOOL)flag, ...&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What is wrong with that?&amp;nbsp;At the time Objective-C and Cocoa were first invented CPU speed and available memory were very limited resources. Thus using enumerations and bitwise operations to describe complex properties was a brilliant idea. But today, these concepts seem a little bit outdated, at least on the desktop platform. So let's improve that.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let's try to describe to autoresizingMask-property in a modern way. The first step is to find an equivalent to a "mask". The most obvious equivalent is a simple mathematical set that is able to contain the possible mask values. Fortunately Objective-C (Foundation) does already know what a set is. A set is just an instance of NSSet. Brilliant. But wait! It is not possible to add plain old C objects into a NSSet. Well, we don't have to. Instead of assigning the mask values like NSViewHeightSizable unsigned integer values we assign each of them a constant NSString.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;NSString *kViewNotSizable = &lt;span style="color: #de091f;"&gt;@"kViewNotSizable"&lt;/span&gt;;&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;NSString *kViewMinXMargin = &lt;span style="color: #de091f;"&gt;@"kViewMinXMargin"&lt;/span&gt;;&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;NSString *kViewWidthSizable = &lt;span style="color: #de091f;"&gt;@"kViewWidthSizable"&lt;/span&gt;;&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;NSString *kViewMaxXMargin = &lt;span style="color: #de091f;"&gt;@"kViewMaxXMargin"&lt;/span&gt;;&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;NSString *kViewMinYMargin = &lt;span style="color: #de091f;"&gt;@"kViewMinYMargin"&lt;/span&gt;;&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;NSString *kViewHeightSizable = &lt;span style="color: #de091f;"&gt;@"kViewHeightSizable"&lt;/span&gt;;&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;NSString *kViewMaxYMargin = &lt;span style="color: #de091f;"&gt;@"kViewMaxYMargin"&lt;/span&gt;;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We would also have to rewrite the accessors for the auto resizing mask to use NSSet.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;- (&lt;span style="color: #c600a1;"&gt;void&lt;/span&gt;)setAutoresizingMask:(NSSet *)mask;&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;- (NSSet *)autoresizingMask;&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Thats basically it. Setting the auto resizing mask by using this new pattern would look like this:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;[aView setAutoresizingMask:[NSSet setWithObjects:&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&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; &amp;nbsp; &amp;nbsp; kViewWidthSizable,&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&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; &amp;nbsp; &amp;nbsp; kViewHeightSizable, &lt;span style="color: #c600a1;"&gt;nil&lt;/span&gt;];&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;No more bitwise operations. But there is more: By using NSSet we can now use the "operations" that are already built in NSSet. Let me give you just two examples:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Checking if the view should resize it's height:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&lt;span style="color: #c600a1;"&gt;if&lt;/span&gt;([[aView autoresizingMask] containsObject:kViewHeightSizable])&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Checking if the auto resizing mask is "valid":&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;NSSet *maxMask = [NSSet setWithObjects:&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kViewNotSizable,&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kViewMinXMargin,&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kViewWidthSizable,&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kViewMaxXMargin,&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kViewMinYMargin,&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kViewHeightSizable,&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kViewMaxYMargin];&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"&gt;&amp;nbsp;&lt;span style="color: #c600a1;"&gt;if&lt;/span&gt;([[aView autoresizingMask] isSubsetOfSet:maxMask])&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I hope you get the idea. Sure, you have to write a few extra lines of code. But it becomes much more readable. In addition to that key value coding and key value observing are possible and safe without doing additional work. If you want that the size of a view should stay the same just assign is an empty set. You don't have to know or lookup the value that represents that.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I suggest that you try this pattern for yourself where you can. I am pretty sure that you will fall in love with it. You don't have to worry about performance of memory related problems because I am sure that it doesn't have a significant impact. When developing for the iPhone/iPod platform you may want to consider not using this pattern. I can imagine that it could have a negative effect there. But I haven' tried it. That is up to you. :)&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Let me know that you think about this "pattern". Will you try it? Are you already using it? Post a comment or send me an email.&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/3733114751386359986-8337252134684140720?l=christiankienle.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://christiankienle.blogspot.com/feeds/8337252134684140720/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://christiankienle.blogspot.com/2009/12/using-nsset-instead-of-plain-old-c-enum.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/8337252134684140720'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3733114751386359986/posts/default/8337252134684140720'/><link rel='alternate' type='text/html' href='http://christiankienle.blogspot.com/2009/12/using-nsset-instead-of-plain-old-c-enum.html' title='Using NSSet instead of plain old C-Enums and bitwise operations'/><author><name>Christian Kienle</name><uri>http://www.blogger.com/profile/03701216649543730169</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry></feed>
