tag:blogger.com,1999:blog-37331147513863599862024-03-24T00:10:00.963-07:00Christian Kienle's BlogThoughts about Cocoa, Cappuccino, Objective-C/J and other random stuff.Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.comBlogger21125tag:blogger.com,1999:blog-3733114751386359986.post-70147058689079373552013-09-07T06:06:00.001-07:002013-09-07T06:06:09.698-07:00New Blog<span style="background-color: white; color: #333333; font-family: Gafata, sans-serif; font-size: 15px; line-height: 28px;">I have blogged at </span><span style="color: black;"><a href="http://christiankienle.blogspot.de/">christiankienle.blogspot.de</a></span><span style="background-color: white; color: #333333; font-family: Gafata, sans-serif; font-size: 15px; line-height: 28px;"> since 2009. This has come to an end. From now on I will publish new posts at my new blog at </span><span style="color: #333333; font-family: Gafata, sans-serif;"><span style="font-size: 15px; line-height: 28px;"><a href="http://thermal-core.com/Blog">thermal-core.com/Blog</a></span></span><span style="background-color: white; color: #333333; font-family: Gafata, sans-serif; font-size: 15px; line-height: 28px;"> . The topics will more or less stay the same.</span><br />
<span style="background-color: white; color: #333333; font-family: Gafata, sans-serif; font-size: 15px; line-height: 28px;"><br /></span>
<span style="background-color: white; color: #333333; font-family: Gafata, sans-serif; font-size: x-large; line-height: 28px;"><a href="http://thermal-core.com/Blog/">Go to my new blog</a></span>Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.comtag:blogger.com,1999:blog-3733114751386359986.post-90208020051912254612013-08-03T10:00:00.002-07:002013-08-03T10:00:42.003-07:00Introducing OCFWebServerI am glad to be able to announce <a href="https://github.com/Objective-Cloud/OCFWebServer"><span id="goog_1613629125"></span>OCFWebServer<span id="goog_1613629126"></span></a> to you.<br />
<br />
<a href="https://github.com/Objective-Cloud/OCFWebServer">OCFWebServer</a> is a lightweight, modern and asynchronous HTTP (version 1.1) server written in Objective-C. It was forked from <a href="https://github.com/swisspol/GCDWebServer">GCDWebServer</a> and modified to fit the needs of <a href="http://objective-cloud.com/">Objective-Cloud.com</a> and hopefully other people's needs as well.<br />
<br />
<a href="https://github.com/Objective-Cloud/OCFWebServer">OCFWebServer</a> is also the foundation for another framework that will be open source as well shortly.<br />
<br />
Happy coding.Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.comtag:blogger.com,1999:blog-3733114751386359986.post-8004738371446675582013-07-04T00:19:00.001-07:002013-07-04T00:25:46.920-07:00Why I am not validating Mac App Store ReceiptsWhen someone buys one of your apps in the Mac App Store you can check a receipt using cryptography to make sure it has been paid for. I am not doing this. I never have. I never will. Why? Because I am still traumatized and excited from childhood experiences. Here is what happened:<br />
<br />
As kids, my brother and myself enjoyed playing a video game called "<a href="https://en.wikipedia.org/wiki/The_Settlers_(video_game)">The Settlers</a>". It was a game where you slowly built your own settlement. You could build farms, mine gold, coal and ore and combine your goods to make new stuff.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEMEFpyELBhIuor0hB2l2b2q8iYj4Gy8CxL3mJ9DYWO3FIHvdKJoF9WXScHei6sPHcDau8yF0_plwWkTya7ufhKaTD2iMBR4lEaaZzvYMlr62-XktpHhYWlDeKYCNyxshgtdmbGAEaXPX7/s400/The_Settlers_SVGA.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiEMEFpyELBhIuor0hB2l2b2q8iYj4Gy8CxL3mJ9DYWO3FIHvdKJoF9WXScHei6sPHcDau8yF0_plwWkTya7ufhKaTD2iMBR4lEaaZzvYMlr62-XktpHhYWlDeKYCNyxshgtdmbGAEaXPX7/s1600/The_Settlers_SVGA.png" /></a></div>
<br />
<div style="text-align: center;">
Source: <a href="https://en.wikipedia.org/wiki/File:The_Settlers_SVGA.png">Wikipedia</a></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: left;">
At some point the next major version of "The Settlers" came out. It cost a lot. My brother and myself had to save up weeks of our weekly allowance to get enough money. After a couple of weeks saving every penny we finally were able to buy The Settlers 3. The gameplay was great. The story was great. But there was a problem…</div>
<br />
In order to expand you sometimes have to fight AI enemies with your own warriors. You create new warriors by combining coal, ore and gold. You use the coal and ore to build new weapons. Your settlers are then equipped with those weapons and turn into warriors. At least in theory. That is what the manual said. That is what common sense dictates. The problem was that our forges produced meat instead of swords. Meat was the last thing we needed in order to build an army.<br />
<br />
<div style="text-align: center;">
<span style="font-size: large;">WE WANTED TO GO TO WAR!</span></div>
<div style="text-align: center;">
<br /></div>
We spent weeks if not months and tried to work around this problem. There must be another way to get weapons. We must have done something wrong. Maybe we needed more gold? Maybe we had to produce a certain amount of meat before the forge finally realized that it was time for war. Maybe we had to burn the forge down a couple of times to make the blacksmith angry so that he produces weapons instead of meat.<br />
<br />
We had no luck. All of our attempts to fix the meat issue failed. We gave up because we were not able to really play this game. Without expanding to new territory you ran out of resources quite quickly. And without weapons there was no efficient was to fight your enemies. My brother and myself thought that the meat issue was just a bug. At that time there was no internet for us: No updates. So we went back to do other things.<br />
<br />
Years later we found out that the meat issue was indeed a bug but not a bug in the actual game. It was a bug in the copy protection. The Settlers 3 was one of the first games that had a copy protection. It was a special kind of copy protection: If the game thought you had not bought it then nothing special would happen at first. It would still be playable but in a special mode. In this mode coal and ore turned into meat and trees never grew back which made the game unplayable in the mid and end game.<br />
<br />
This happened to a lot of people. The copy protection was pretty buggy in that it hit the wrong people: People who bought the game for money. People like my brother and myself.<br />
<br />
Now you know why I am still traumatized by copy protection. You never want this to happen to anybody.<br />
<br />
But wait: There is more to it.<br />
<br />
At some point my brother and myself got a new computer. A friend gave us a copy of a game called StarCraft I but he forgot to give us the serial number for the game.<br />
<br />
<i>I have to mention that at it is legal to do that in Germany. Even if he had given us the serial number it would still have been legal to do so - at least to my knowledge.</i><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghyphenhyphenx2AuTUzE0LErn8WEXX8exELqmX2g6XX5b9qQtvODvsAJ1_rpuIfZ3TUZSilwmOgsfhc4kVXvQJ2qWEqxEGr4NY2BfMvw9gc9hEWBKhNMFV5tENqPp4v_XyHEXSUVUMRyZwOgPZx34sV/s413/starcraft_broodwar_logo.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEghyphenhyphenx2AuTUzE0LErn8WEXX8exELqmX2g6XX5b9qQtvODvsAJ1_rpuIfZ3TUZSilwmOgsfhc4kVXvQJ2qWEqxEGr4NY2BfMvw9gc9hEWBKhNMFV5tENqPp4v_XyHEXSUVUMRyZwOgPZx34sV/s1600/starcraft_broodwar_logo.jpg" /></a></div>
<br />
<br />
When you start StarCraft I it plays a nice sound effect and shows a nice intro. This made us very excited. But then the game asked us for a serial key. We had none! Out of frustration I entered a number in the serial number text field:<br />
<br />
<div style="text-align: center;">
<span style="font-family: Courier New, Courier, monospace; font-size: large;">123-456-789-012-3</span></div>
<div style="text-align: center;">
<br /></div>
Something like that. AND IT WORKED!<br />
<br />
We played StarCraft I for months! It was the best game we have ever played. We fought against each other.<br />
<br />
<div style="text-align: center;">
<span style="font-size: large;">WE FINALLY HAD OUR WAR! WITH NUKES! WITH BATTLE CRUISERS. WITH CARRIERS. IT WAS GREAT! </span></div>
<div style="text-align: center;">
<br /></div>
Years later, StarCraft II came out. Because of that great experience (and because I like to pay for software/games) I bought many copies of StarCraft II: For myself, for my brother and for friends. Today I am a huge StarCraft II fanboy. I am watching tournaments and I pay casters to get access to good commentary. The experience would be even better if Blizzard had decided to relax the copy protection for StarCraft II. The fact that they have a strong copy protection in place may weaken my point but the fact is: I bought StarCraft II not because it has strong copy protection but because I had a good experience with it in the past.<br />
<br />
Copy protection can really be bad for your business and make children unhappy and avoid your company for the next 60 years.Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.comtag:blogger.com,1999:blog-3733114751386359986.post-41800275034231080672013-06-10T02:23:00.000-07:002013-06-10T04:26:47.428-07:00Xcode productivity tip: Jump to the next issueA couple of weeks ago I began to use a feature of Xcode that improved my productivity quite a lot. For some of you this feature may be old news. To be honest: It was old news for me as well. I knew about this feature but I never used it because I could not believe that it was that useful.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYfTB9fuSAJfZM1zduE-UV9v5Sj3YagL7MUo4Zur4QEzM1umg1zSfVn1KASl_YqDbHQxB-afytFGjMopqSsC-Hx6YC0q0qK7Apep9qPFvXHN3Hn_9h8mBII8DpHGXMHk05KvG98kHVqiB_/s1600/Screen+Shot+2013-06-10+at+11.17.12+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="305" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYfTB9fuSAJfZM1zduE-UV9v5Sj3YagL7MUo4Zur4QEzM1umg1zSfVn1KASl_YqDbHQxB-afytFGjMopqSsC-Hx6YC0q0qK7Apep9qPFvXHN3Hn_9h8mBII8DpHGXMHk05KvG98kHVqiB_/s400/Screen+Shot+2013-06-10+at+11.17.12+AM.png" width="400" /></a></div>
<h3>
Quickly jumping to the next issue</h3>
There is a keyboard shortcut in Xcode which let's you jump to the next issue (warning or error). The default shortcut for this is ⌘'. This is extremely handy - especially if you have a "zero-warning policy" because then every issue is worth fixing immediately: You won't jump to an issue which you can fix later or which is not really an issue.<br />
<br />
I decided to assign the "Jump to Next Issue" command a simple shortcut just to make things easier for me. Because I have a German keyboard i am using ⌘Ä to jump to the next issue and ⌘Ö to jump to the previous issue.<br />
<br />
Update:<br />
You may have to restart Xcode for the new key bindings to take effect.Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com1tag:blogger.com,1999:blog-3733114751386359986.post-55634993365085991412013-05-23T04:33:00.002-07:002013-05-23T04:38:46.337-07:00Core Data Editor and RestKit<a href="http://www.yourlocalstudio.dk/">Lasse Moos</a>, a user of Core Data Editor, contacted me because when he tried to use Core Data Editor all he got was this:<br />
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6gjlu2H66EFCpJayg_k6uYKxji2OsC1vC_X7KIU1kc1uTZhZ2OiW_Mv660Ok5Qo4M0-4_VGrJQA8Gj5K3GkAHPTjifG03rZQ1_ifyVBG7ysjVpVtbewbK28g4cp3F3CvDrftTWaK1qkei/s1600/Screen+Shot+2013-05-23+at+1.19.00+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="218" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6gjlu2H66EFCpJayg_k6uYKxji2OsC1vC_X7KIU1kc1uTZhZ2OiW_Mv660Ok5Qo4M0-4_VGrJQA8Gj5K3GkAHPTjifG03rZQ1_ifyVBG7ysjVpVtbewbK28g4cp3F3CvDrftTWaK1qkei/s400/Screen+Shot+2013-05-23+at+1.19.00+PM.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
(The managed object model version used to open the persistent store is incompatible with the one that was used to create the persistent store.)</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
We wrote back and forth but with no success. Luckily Lasse agreed to share his screen with me. In that session I had access to his Xcode project and was able to look at the issue first hand. At some point he mentioned that he is using <a href="http://restkit.org/">RestKit</a> in this project. When I first had a look at RestKit when it came out I knew that this framework was not made for me. But this is a totally different story. What I did not know about RestKit is that RestKit seems to modify the managed object model at runtime to do it's magic. This is a problem for Core Data Editor because the managed object model of your store file has to match the version of your model which is inside your app bundle.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I know that many people around the globe are using RestKit and I will try to offer some kind of workaround although I don't want to support RestKit in any way. :)</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I am glad to finally know why a relatively large user base has problems with Core Data Editor. Thank you Lasse.</div>
<div>
<br /></div>
Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com1tag:blogger.com,1999:blog-3733114751386359986.post-46593126870029709262012-05-28T00:48:00.001-07:002012-05-28T00:48:30.557-07:00Flashcards Pro for iPad released<div class="p1">
It was a long journey but I am pleased to announce that <a href="http://christian-kienle.de/Flashcards-Pro/">Flashcards Pro for iPad</a> is now available in the App Store. Flashcards Pro is beautiful and easy to use application, that helps you learn new things quickly and efficiently. Here is a short video I made that should give you a good impression:</div>
<div class="p1">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/41NUHWIiQwY?feature=player_embedded' frameborder='0'></iframe></div>
<div class="p2">
<br /></div>
<div class="p2">
<br /></div>
<div class="p1">
Over the next several months the iPad application will become a universal application that also runs on your iPhone and iPod Touch. The Mac application will also get a major update. The plan is to enable iCloud as soon the Mac application has been updated or the iPad app became universal. If you have feedback please <a href="mailto:me@christian-kienle.de">send it directly to me via email</a>.</div>Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.comtag:blogger.com,1999:blog-3733114751386359986.post-88632674837926251602012-04-21T02:18:00.002-07:002012-04-21T02:18:59.746-07:00Flashcards for iPad: Status<div class="separator" style="clear: both; text-align: left;">
Flashcards for iPad is doing well. The beta test has started approximately one week ago. Flashcards for iPad is more or less feature complete and with the help of the beta testers I am able to work out the rough edges. Once Flashcards for iPad has been released I will work on a major new version of <a href="http://christian-kienle.de/Flashcards">Flashcards for Mac</a> in order to enable iCloud syncing.</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBRiHUsWZ1HTNb3YyDhlrhUdtoDfgjV3Tq5XGL3u-UTjGR7tgBLh4uWdlt3e3nD7r1faeiHUhwr94KzfzLa4lvvGZIifHf-H_uEOhkj4HogaEdfc04obPx1tVU305cVqz0z3B-_6mpgoKK/s1600/iOS+Simulator+Screen+shot+Apr+21,+2012+11.14.32+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBRiHUsWZ1HTNb3YyDhlrhUdtoDfgjV3Tq5XGL3u-UTjGR7tgBLh4uWdlt3e3nD7r1faeiHUhwr94KzfzLa4lvvGZIifHf-H_uEOhkj4HogaEdfc04obPx1tVU305cVqz0z3B-_6mpgoKK/s320/iOS+Simulator+Screen+shot+Apr+21,+2012+11.14.32+AM.png" width="320" /></a></div>
<br />Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com0tag:blogger.com,1999:blog-3733114751386359986.post-2485977072706593782012-04-12T03:53:00.000-07:002012-04-12T03:53:10.155-07:00Creating an iOS based Core Data Editor project (Video Tutorial)<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: -webkit-auto;">
I got it. The setup of an iOS project in <a href="http://christian-kienle.de/CoreDataEditor">Core Data Editor</a> is not obvious. I promise to make it easier is one of the next releases of <a href="http://christian-kienle.de/CoreDataEditor">Core Data Editor</a>. But until the improvements are released I don't want to leave you alone. This is why I made a short video tutorial that shows how to create an iOS project in<a href="http://christian-kienle.de/CoreDataEditor"> Core Data Editor</a>. So here it is:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/KlUffdd1fZ4?feature=player_embedded' frameborder='0'></iframe></div>
<br />
I will release more video tutorials of this kind so if you want to know something particular <a href="mailto:support@christian-kienle.de">let me know</a>.Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com0tag:blogger.com,1999:blog-3733114751386359986.post-21982270063069043812012-04-10T03:44:00.000-07:002012-04-10T03:44:13.062-07:00Objective-C needs Java's Annotations<em>TL;DR: Java's annotations feature allow a developer to annotate code. These annotations can be used either at run-time or compile-time to do awesome stuff. Objective-C needs this as well so that we can let mogenerator and other cool tools do its work more efficiently.</em><br />
<br />
I am addicted to Objective-C. In my opinion Objective-C is a very nice and pragmatic language with a neat syntax and I have used it a lot during the last eight years. Lately I had to use Java a little bit. It was fun but I still like Objective-C more – although there is one thing about Java that I fell in love with and would like to see in Objective-C as well: Annotations.<br />
First I will try to explain what Java annotations are and then I will describe which problems could be solved by having something like Java's annotations available in Objective-C.<br />
<h3>
Java Annotations</h3>
Java annotations allow a developer to add metadata to the code (e.g. to classes, methods, fields or packages). Every annotation has a name and the actual metadata in the form of key-value pairs. An annotation can be processed either at run-time (by using Java's reflection capabilities) or at compile-time (by providing a compiler plug-in – a so called annotation processor)). When an annotation is being processed a developer can do all sorts of things like executing existing code (at run-time) or by creating new code (at compile-time).<br />
<h3>
Annotations could be useful in Objective-C as well</h3>
Now it's time to talk about how annotations could be used to solve Objective-C related problems.<br />
<strong><br />
</strong><br />
<strong>Eliminate the need to write boilerplate code</strong><br />
Writing code makes fun as long the code is not trivial. When working with Core Data (an object graph management framework used to persist data) a developer usually has to write a lot of boilerplate code. This (boilerplate) code is used to avoid compiler warnings, improve the performance, make your application code more read/writable and make it easier to debug. So usually a developer wants to have the benefits of the boilerplate code without writing it. This is why there are tools like mogenerator which generate the boilerplate code automatically. This is cool but manually generated code is a bad practice when developing an application: You have to manually regenerate the code when the model changes and new team members have to get familiar with the generator. It would be ideal to let the compiler generate the code that is usually generated by mogenerator. This would be possible if we had annotations. An annotation processor is basically a compiler plugin that can generate code, as already mentioned. You still get all the benefits of manually generated code (code competition, higher performance, ...) but without the drawbacks.<br />
<br />
Remark: Core Data can also be used without the generated or handwritten boilerplate code. The framework generates the code at runtime but in order to avoid compiler warnings one usually writes/generates the code.<br />
<br />
<strong>Typos are found by the compiler</strong><br />
Java has a few built in annotations. One annotation I found quite useful is the @Override annotation. You attach it to a method you intent to override. Why is this useful? Imagine you have a typo in the name of the method you intent to override: Your implementation never would get called. This is a problem that is also acknowledge by Apple in the form of a technical Q&A: "<a href="http://developer.apple.com/library/mac/#qa/qa1554/_index.html">Common mistakes with delegation in Cocoa</a>":<br />
<blockquote class="tr_bq">
<cite>Capitalization errors are often the hardest to catch. Any of the methods of the NSTableDataSource informal protocol are likely candidates for subtle miscapitalization. For example, numberOfRowsInTableView: is often mistakenly entered as numberOfRowsInTableview:.</cite></blockquote>
Apple goes even further and suggest to copy & paste code in order to prevent these errors:<br />
<blockquote class="tr_bq">
<cite>Perhaps the safest habit to develop is to simply always cut and paste the method selector.</cite></blockquote>
Wait. Using copy and paste to prevent errors in code? Questionable… That's where a @Override-annoation would come into play. The annotation could check at compile time if one is actually overriding a method or not. My friend <a href="https://blogs.reucon.com/srt/">Stefan Reuter</a> told me about another benefit of @Override: Imagine a developer is overriding a method of a class provided by a third party. A few months later the third party decides to remove this method. If the developer annotated the method with @Override then the compiler will complain about a method that is overridden but which is no longer present. Sweet isn't it?<br />
<br />
Remark: I think that in the case of Objective-C protocols we already have something similar. Starting with Objective-C 2.0 a message defines in a @protocol definition can be marked as required (@required) or as optional (@optional). If a class declares that it conforms to a protocol the developer is warned if the class does not respond to the messages marked as required.<br />
<br />
<h3>
We already have annotations!</h3>
Objective-C already had an "annotation-like" feature: properties: <br />
<blockquote>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">@property (key1=value1, key2=value2, ...) Class *name; </span></blockquote>
With @property we tell the compiler how @synthesize generates code. So what I want to see in Objective-C is a generalized way to do the same thing @property/@synthesize does.Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com32tag:blogger.com,1999:blog-3733114751386359986.post-73032784199488006862012-04-03T00:42:00.000-07:002012-04-03T00:42:58.852-07:00Core Data Editor 4.2I am pleased to announce the release of <a href="http://itunes.apple.com/app/core-data-editor/id403025957?mt=12&uo=4">Core Data Editor 4.2</a> - finally after a three month long journey of submitting, rejection, re-submitting, … (you get the idea). So what is new with 4.2?
<br />
<h3>
Shortcuts</h3>
I have improved the most important shortcuts:
<br />
<ul>
<li>Create a managed object by pressing ⌘N</li>
<li>Create a new project by pressing ⌘⇧N</li>
<li>Reload the store file by pressing ⌘R</li>
<li>Delete a managed object by pressing ⌫</li>
</ul>
So creating a new project in Core Data Editor has the exact same shortcut than in Xcode.
<br />
<h3>
Entities Table View</h3>
Some of you have very long entity names. Now you can make the entities table view wider than before. Have a look:
<img alt="Big Table" border="0" height="238" src="http://lh4.ggpht.com/-Huu53LmjYag/T3qmDm0z_vI/AAAAAAAAAZI/-AvPthhRMXk/Big%252520Table.png?imgmax=800" title="Big Table.png" width="531" />
<br />
<h3>
Bugfixes</h3>
In addition I have also fixed two annoying bugs:
<br />
<ul>
<li>Date attribute text field now responds to the tab key.</li>
<li>Refreshing the editor view (by clicking on the refresh button in the lower left corner) is much more stable.</li>
</ul>
Thank you all for your patience and stay tuned for the next release of Core Data Editor which will actually bring new features and more bug fixes. And a special thanks goes to everyone who reported bugs and provided freed back.
<br />
<br />
<strong>Happy Coding.</strong><br />
<b><br /></b><br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.youtube.com/embed/zMDDyrweXjU?feature=player_embedded' frameborder='0'></iframe></div>
<strong><br /></strong>Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com0tag:blogger.com,1999:blog-3733114751386359986.post-33272120671380766412011-11-12T07:58:00.001-08:002011-11-12T08:10:07.146-08:00If you need a good designer...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?<br />
<br />
Me to Designer: Are you available for design work?<br />
Designer: Yes. Sure.<br />
<br />
Me explains everything in great detail.<br />
<br />
Designer: No problem. I will do it.<br />
<br />
-- 2 Weeks later --<br />
<br />
Me to Designer: Hello.<br />
<br />
-- No response. 2 Weeks later ---<br />
<br />
<br />
Me to Designer: Hello - are you there?<br />
<br />
-- and so on --<br />
<br />
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. :)<br />
<br />
<div style="text-align: center;">
Thank you <a href="http://ilovecolorz.net/">Tomas Bartko</a>.</div>
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://ilovecolorz.net/"><img border="0" src="http://ilovecolorz.net/images/logo.png" /></a></div>
<br />Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com4tag:blogger.com,1999:blog-3733114751386359986.post-71992737633003611362011-10-15T23:55:00.000-07:002011-10-15T23:55:52.634-07:00Status Report: Flashcards for iPadI 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:<br />
<br />
<blockquote>
Flashcards for iPad won't sync with Flashcards for Mac from day one.</blockquote>
<br />
<h3>
Yeah. Its a simple as that and here is why:</h3>
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.<br />
<h3>
So what is the plan?</h3>
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.<br />
<br />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.<br />
<br />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.<br />
<br />
Ah - and here are two screenshots that show the current status of Flashcards for iPad:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKBUBMRXJGTomO7plCCg81PnDA9-ocTiQl8arD6oo7ylozRP4RJ3ztRZQgO8laNy2TVePCgov5Vkqkv8THLOY7MlZhNx8OaOVp2OJ6hTXdzdCifU5jiODbSQFTlwQ2LUsDl2MUMhFYSlvt/s1600/Screen+Shot+2011-10-16+at+8.51.52+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgKBUBMRXJGTomO7plCCg81PnDA9-ocTiQl8arD6oo7ylozRP4RJ3ztRZQgO8laNy2TVePCgov5Vkqkv8THLOY7MlZhNx8OaOVp2OJ6hTXdzdCifU5jiODbSQFTlwQ2LUsDl2MUMhFYSlvt/s320/Screen+Shot+2011-10-16+at+8.51.52+AM.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy7ViR7QamSMA2CKFAcFNtjReWpVqL8jqRJrIqEgOR5vWwandXAHWcFwGGR88Xz8ThtDFLLJHBRrOzZDHFmz8zxHDi8EbUeh1H6MsY0WN3OWKLlXozMU9SMME5EZRKE5zmDz8HXQ5F5FDF/s1600/Screen+Shot+2011-10-16+at+8.52.01+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy7ViR7QamSMA2CKFAcFNtjReWpVqL8jqRJrIqEgOR5vWwandXAHWcFwGGR88Xz8ThtDFLLJHBRrOzZDHFmz8zxHDi8EbUeh1H6MsY0WN3OWKLlXozMU9SMME5EZRKE5zmDz8HXQ5F5FDF/s320/Screen+Shot+2011-10-16+at+8.52.01+AM.png" width="320" /></a></div>
<br />Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com0tag:blogger.com,1999:blog-3733114751386359986.post-17655006686053771492011-10-11T00:09:00.001-07:002011-10-11T00:50:26.551-07:00Flashcards data lossThe 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:<br />
<ul>
<li>Close Flashcards</li>
<li>Use Spotlight to find an application called "Terminal"</li>
</ul>
<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" /><br />
<ul>
<li>Launch Terminal- Paste in the following text:</li>
</ul>
<pre>cp ~/Library/Application\ Support/Ebbinghaus3/Ebbinghaus3.sql \</pre>
<pre> ~/Library/Flashcards/Flashcards.sqlite</pre>
<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" /><br />
<ul>
<li>Press enter- Restart Flashcards</li>
</ul>
If you need any additional assistance please send an email to <a href="mailto:support@christian-kienle.de">support@christian-kienle.de</a>.<br />
<br />
<em>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.</em><br />
<br />
<br />
Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com0tag:blogger.com,1999:blog-3733114751386359986.post-87457141502464549992011-05-30T04:13:00.001-07:002011-05-30T04:13:01.435-07:00How to sync your flash-cards between multiple Macs<p>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 <a href="http://itunes.apple.com/app/flashcards/id403021928?mt=12">Flashcards</a> (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.</p><p>1. Go to <a href="https://www.dropbox.com/">Dropbox.com</a> sign up. If you already have a Dropbox account you can of course skip this step.</p><p><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" /></p><p>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.</p><p>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.</p><p><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" /></p><p>4. Move the file Ebbinghaus3.sql to your Dropbox folder.</p><p>5. Open the Terminal and type in the following commands:</p><p><pre style="margin: 8px;">$ cd "Library/Application Support/Ebbinghaus3"/<br />$ ln -s ~/Dropbox/Ebbinghaus3.sql Ebbinghaus3.sql</pre></p><p><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" /></p><p>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.</p><p>7. Perform step 4 and 5 on every Mac that you own.</p><p>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.</p><p>Have fun!</p>Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com0tag:blogger.com,1999:blog-3733114751386359986.post-33052506561879590462011-03-13T09:19:00.001-07:002011-03-13T09:19:45.001-07:00Statistics: Pricing in the Mac App Store<p>This post is about the pricing in the Mac App Store and it answers several very important questions:</p><ol><li>What is the average price of an app in the Mac App Store?</li><li>How does the development of the average prices look like?</li><li>Which categories contain the highest/lowest priced apps?</li></ol><p>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 <a href="http://store-news-app.com/">Store News</a>. 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.</p><p>I used the snapshots created between 13. January 2011 and 1. March 2011.</p><p>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%).</p><p> </p><p><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" /></p><p>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?</p><p>The next chart shows the average price broken down by category.</p><p><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" /></p><p>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.</p><p>I will create new charts during the next two weeks that I will share with you via this blog.</p>Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com3tag:blogger.com,1999:blog-3733114751386359986.post-69939535523539242892011-03-11T12:27:00.001-08:002011-03-11T12:27:54.699-08:00Drops 1.1 — the ultimate tool for uploading files<p>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.</p><p><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" /></p><p>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.</p><p><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" /></p><p>There are many things about Drops that will make your life easier.</p><ul><li>Manage multiple FTP servers: Simply create as many connections you need.</li><li>Drops can copy the URL of an uploaded file to the clipboard automatically.</li><li>Drops can shorten the URL automatically.</li><li>Drops can compress files before uploading.</li><li>Drops can compress folders before uploading.</li></ul><p>You can buy Drops at the Mac App Store - more information and a link to the store can be found at <a href="http://christian-kienle.de/Drops/">my website</a>.</p><p> </p>Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com0tag:blogger.com,1999:blog-3733114751386359986.post-65114324807948666732010-10-17T09:57:00.000-07:002010-10-18T05:18:53.396-07:00Handling Initialization FailureA 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.<br />
<ul>
<li>Only return nil (in an initializer) if you can't perform the initialization. If a caller passes your 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.</li>
<li>Don't return nil if you can find a nice "workaround" for a problem during initialization such as replacing a missing argument with a sensible default value.</li>
<li>If you want to return nil and you haven't sent a initialization message to super yet perform the following steps: <br /><ul>
<li>cleanup any resources you may have created,</li>
<li>call [self release]; and then</li>
<li>return nil</li>
</ul>
</li>
<li>If you want to return nil and already have sent a initialization message to super (which returned nil) perform the following steps: <br /><ul>
<li>cleanup any resources you may have created,</li>
<li>return nil</li>
</ul>
</li>
</ul>
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 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 <em>Person</em>. A <em>Person</em> 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 -<span style="font-family: Helvetica;">initWithFirstName:lastName:error</span>: creates an error object, sends release to self and returns nil.<br />
<br />
<pre style="color: #e00005; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"><span style="color: #7e4726;">#import </span>"Person.h"</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"></pre>
<pre style="color: #cb00a5; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">enum<span style="color: black;"> {</span></pre>
<pre style="color: #265a5e; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"><span style="color: black;"> </span>PersonErrorCodeFirstLastNameNotValid<span style="color: black;"> = </span><span style="color: #4800de;">0</span></pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">};</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"><span style="color: #cb00a5;">typedef</span> NSInteger PersonErrorCodes;</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"></pre>
<pre style="color: #cb00a5; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">@implementation<span style="color: black;"> Person</span></pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"></pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"><span style="color: #cb00a5;">@synthesize</span> firstName, lastName;</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"></pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">- (<span style="color: #cb00a5;">id</span>)initWithFirstName:(<span style="color: #7e1aad;">NSString</span> *)initFirstName </pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> lastName:(<span style="color: #7e1aad;">NSString</span> *)initLastName </pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> error:(<span style="color: #7e1aad;">NSError</span> **)error {</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> <span style="color: #cb00a5;">if</span>(initFirstName == <span style="color: #cb00a5;">nil</span> || initLastName == <span style="color: #cb00a5;">nil</span>) {</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> <span style="color: #cb00a5;">if</span>(error != <span style="color: #cb00a5;">NULL</span>) {</pre>
<pre style="color: #7e1aad; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"><span style="color: black;"> </span>NSMutableDictionary<span style="color: black;"> *u = [</span>NSMutableDictionary <span style="color: black;"></span><span style="color: #490085;">dictionary</span><span style="color: black;">];</span></pre>
<pre style="color: #e00005; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"><span style="color: black;"> [u </span><span style="color: #490085;">setValue</span><span style="color: black;">:</span>@"first/last name not valid."<span style="color: black;"> </span></pre>
<pre style="color: #7e1aad; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"><span style="color: black;"> </span><span style="color: #490085;">forKey</span><span style="color: black;">:</span>NSLocalizedDescriptionKey<span style="color: black;">];</span></pre>
<pre style="color: #265a5e; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"><span style="color: black;"> </span><span style="color: #428288;">PersonErrorCodes</span><span style="color: black;"> c = </span>PersonErrorCodeFirstLastNameNotValid<span style="color: black;">;</span></pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> *error = [<span style="color: #7e1aad;">NSError</span><span style="color: #490085;">errorWithDomain</span>:<span style="color: #e00005;">@"com.example.unique"</span> </pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> <span style="color: #490085;">code</span>:c </pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> <span style="color: #490085;">userInfo</span>:u];</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> }</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> [<span style="color: #cb00a5;">self </span><span style="color: #490085;">release</span>];</pre>
<pre style="color: #cb00a5; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"><span style="color: black;"> </span>return <span style="color: black;"></span>nil<span style="color: black;">;</span></pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> }</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> <span style="color: #cb00a5;">self</span> = [<span style="color: #cb00a5;">super </span><span style="color: #490085;">init</span>];</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> <span style="color: #cb00a5;">if</span>(<span style="color: #cb00a5;">self</span> != <span style="color: #cb00a5;">nil</span>) {</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> <span style="color: #cb00a5;">self</span>.<span style="color: #428288;">firstName</span> = initFirstName;</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> <span style="color: #cb00a5;">self</span>.<span style="color: #428288;">lastName</span> = initLastName;</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> }</pre>
<pre style="color: #cb00a5; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"><span style="color: black;"> </span>return<span style="color: black;"></span>self<span style="color: black;">; </span></pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">}</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"></pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">- (<span style="color: #cb00a5;">id</span>)initWithFirstName:(<span style="color: #7e1aad;">NSString</span> *)initFirstName </pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> lastName:(<span style="color: #7e1aad;">NSString</span> *)initLastName {</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> <span style="color: #cb00a5;">return</span> [<span style="color: #cb00a5;">self </span><span style="color: #265a5e;">initWithFirstName</span>:initFirstName </pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> <span style="color: #265a5e;">lastName</span>:<span style="color: #428288;">lastName</span> </pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> <span style="color: #265a5e;">error</span>:<span style="color: #cb00a5;">NULL</span>];</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">}</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"></pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">- (<span style="color: #cb00a5;">id</span>)init {</pre>
<pre style="color: #265a5e; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"><span style="color: black;"> </span><span style="color: #cb00a5;">return</span><span style="color: black;"> [</span><span style="color: #cb00a5;">self </span><span style="color: black;"></span>initWithFirstName<span style="color: black;">:[</span><span style="color: #7e1aad;">NSString </span><span style="color: black;"></span><span style="color: #490085;">string</span><span style="color: black;">] </span></pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> <span style="color: #265a5e;">lastName</span>:[<span style="color: #7e1aad;">NSString </span><span style="color: #490085;">string</span>]];</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">}</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"></pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">- (<span style="color: #cb00a5;">void</span>)dealloc {</pre>
<pre style="color: #428288; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"><span style="color: black;"> </span><span style="color: #cb00a5;">self</span><span style="color: black;">.</span>firstName<span style="color: black;"> = </span><span style="color: #cb00a5;">nil</span><span style="color: black;">;</span></pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> <span style="color: #cb00a5;">self</span>.<span style="color: #428288;">lastName</span> = <span style="color: #cb00a5;">nil</span>;</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;"> [<span style="color: #cb00a5;">super </span><span style="color: #490085;">dealloc</span>];</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">}</pre>
<pre style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;"></pre>
<pre style="color: #cb00a5; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">@end</pre>
<div>
</div>
<span style="font-family: Helvetica; white-space: normal;">As you can see, this class has three initializers: -init, -initWithFirstName:lastName: and -initWithFirstName:lastName:error:. The designated initializer is -initWithFirstName:lastName:error:, which is used by a caller which is interested in the cause of a failed initialization. -initWithFirstName:lastName: can be used by a caller which only wants to create a </span><span style="font-family: Helvetica; white-space: normal;"><em>Person</em></span><span style="font-family: Helvetica; white-space: normal;"> and see if it worked or not.</span>Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com0tag:blogger.com,1999:blog-3733114751386359986.post-78476322373258385882010-08-17T03:09:00.001-07:002010-08-17T03:16:46.396-07:00Core Data Editor 3.0 released<p>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:</p><ul><li>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.</li><li>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.</li><li>Updates are now delivered via Sparkle.</li><li>Help is now available and integrated in the app and will be constantly improved.</li></ul><p><span style="font-size: 14px; font-weight: bold;"><a href="http://christian-kienle.de/CoreDataEditor/">Core Data Editor Website</a></span></p><p>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?</p><p><a href="http://christian-kienle.de/christiankienle-blog/CoreDataEditor3-Sync/CoreDataEditorSync.mov"><img src="http://lh5.ggpht.com/_wKQ1LlKXgSg/TGpf3wIH9bI/AAAAAAAAAIw/RBReNN-XFkc/SyncThumbnail.png?imgmax=800" border="0" alt="SyncThumbnail.png" width="300" height="402" /></a></p><p>(Click on the image above to watch the screen cast.)</p><p>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.</p><p><span style="font-size: 14px; font-weight: bold;"><a href="http://christian-kienle.de/CoreDataEditor/">Core Data Editor Website</a></span></p>Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com0tag:blogger.com,1999:blog-3733114751386359986.post-81734194397750288892010-07-18T03:04:00.001-07:002010-07-18T03:04:33.779-07:00Drawing Patterns<p>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.</p><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #e00005;"><span style="color: #7e4726;">#import </span>"PatternView.h"</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"><br /></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #cb00a5;">@implementation<span style="color: #000000;"> PatternView</span></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"><br /></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #cb00a5;">void</span>)drawRect:(<span style="color: #7e1aad;">NSRect</span>)dirtyRect {</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> [<span style="color: #cb00a5;">super</span><span style="color: #490085;">drawRect</span>:dirtyRect];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"><br /></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> <span style="color: #7e1aad;">NSImage</span> *bg = [<span style="color: #7e1aad;">NSImage</span><span style="color: #490085;">imageNamed</span>:<span style="color: #e00005;">@"bg"</span>];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> <span style="color: #7e1aad;">NSColor</span> *backgroundColor = [<span style="color: #7e1aad;">NSColor</span><span style="color: #490085;">colorWithPatternImage</span>:bg];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><span style="white-space: pre;"></span>[backgroundColor <span style="color: #490085;">set</span>];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #490085;"><span style="color: #000000;"> </span>NSRectFill<span style="color: #000000;">([</span><span style="color: #cb00a5;">self</span><span style="color: #000000;"></span>bounds<span style="color: #000000;">]);</span></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"><br /></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #cb00a5;">@end</pre><p>This might not be what you have expected. Let me show you how the above code behaves in action.</p><p><a href="http://christian-kienle.de/christiankienle-blog/Pattern/Pattern1-Web-Computer.m4v"><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" /></a></p><p>(Click on the image above to see the video)</p><p>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.</p><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #e00005;"><span style="color: #7e4726;">#import </span>"PatternView.h"</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"><br /></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #cb00a5;">@implementation<span style="color: #000000;"> PatternView</span></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"><br /></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">- (<span style="color: #cb00a5;">void</span>)drawRect:(<span style="color: #7e1aad;">NSRect</span>)dirtyRect {</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> [<span style="color: #cb00a5;">super</span><span style="color: #490085;">drawRect</span>:dirtyRect];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> <span style="color: #7e1aad;">NSSize</span> size = [<span style="color: #cb00a5;">self</span><span style="color: #490085;">bounds</span>].<span style="color: #7e1aad;">size</span>;</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><br /></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #008c00;"><span style="color: #000000;"> </span>// Create a new image and make it as big as the view</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> <span style="color: #7e1aad;">NSImage</span> *bigImage = [[[<span style="color: #7e1aad;">NSImage</span><span style="color: #490085;">alloc</span>] <span style="color: #490085;">initWithSize</span>:size] <span style="color: #490085;">autorelease</span>];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><br /></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #008c00;"><span style="color: #000000;"> </span>// Prepare for drawing onto the new image</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> [bigImage <span style="color: #490085;">lockFocus</span>];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><br /></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> <span style="color: #7e1aad;">NSImage</span> *bg = [<span style="color: #7e1aad;">NSImage</span><span style="color: #490085;">imageNamed</span>:<span style="color: #e00005;">@"bg"</span>];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> <span style="color: #7e1aad;">NSColor</span> *backgroundColor = [<span style="color: #7e1aad;">NSColor</span><span style="color: #490085;">colorWithPatternImage</span>:bg];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> [backgroundColor <span style="color: #490085;">set</span>];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #490085;"><span style="color: #000000;"> </span>NSRectFill<span style="color: #000000;">([</span><span style="color: #cb00a5;">self</span><span style="color: #000000;"></span>bounds<span style="color: #000000;">]);</span></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #490085;"><span style="color: #000000;"><br /></span></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> [bigImage <span style="color: #490085;">unlockFocus</span>];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"><br /></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #008c00;"><span style="color: #000000;"> </span>// Now draw the image to the view</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> [bigImage <span style="color: #490085;">drawInRect</span>:[<span style="color: #cb00a5;">self</span><span style="color: #490085;">bounds</span>] </pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> <span style="color: #490085;">fromRect</span>:<span style="color: #7e1aad;">NSZeroRect</span> </pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #490085;"><span style="color: #000000;"> </span>operation<span style="color: #000000;">:</span>NSCompositeSourceOver<span style="color: #000000;"> </span></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> <span style="color: #490085;">fraction</span>:<span style="color: #4800de;">1.0f</span>];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;">}</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; min-height: 13.0px;"><br /></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #cb00a5;">@end</pre><div></div><p>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.</p><div><a href="http://christian-kienle.de/christiankienle-blog/Pattern/Pattern2-Web-Computer.m4v"><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" /></a></div><div>(Click on the above image to see the video)</div><p>Feel free to <a href="http://christian-kienle.de/christiankienle-blog/Pattern/PatternExamples.zip">download the examples</a>.</p><p> </p>Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com0tag:blogger.com,1999:blog-3733114751386359986.post-81784900002230794502010-05-16T02:17:00.001-07:002010-05-17T01:02:15.628-07:00Cocoa Tip: Detecting Arrow Down Key Events<p>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:</p><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #490085;"><span style="color: #000000;"> [</span><span style="color: #7e1aad;">NSEvent</span><span style="color: #000000;"> </span>addLocalMonitorForEventsMatchingMask<span style="color: #000000;">:</span>NSKeyDownMask<span style="color: #000000;"> </span>handler<span style="color: #000000;">:^(</span><span style="color: #7e1aad;">NSEvent</span><span style="color: #000000;"> *event) {</span></pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> <span style="color: #7e1aad;">NSString</span> *characters = [event <span style="color: #490085;">characters</span>];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> <span style="color: #7e1aad;">unichar</span> character = [characters <span style="color: #490085;">characterAtIndex</span>:<span style="color: #4800de;">0</span>];</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> <span style="color: #cb00a5;">if</span>(character == <span style="color: #490085;">NSDownArrowFunctionKey</span>) {</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> <span style="color: #490085;">NSLog</span>(<span style="color: #e00005;">@"key down"</span>);</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> } </pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> <span style="color: #cb00a5;">return</span> event;</pre><pre style="margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo;"> }];</pre><p>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.</p><p>Edit: You can remove a monitor by calling +removeMonitor: (NSEvent).</p>Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com1tag:blogger.com,1999:blog-3733114751386359986.post-83372521346841407202009-12-13T06:59:00.000-08:002009-12-13T07:04:34.563-08:00Using NSSet instead of plain old C-Enums and bitwise operationsIn 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.<br />
<div>
<br />
</div>
<div>
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:<br />
</div>
<br />
<div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
- (<span style="color: #c600a1;">void</span>)setAutoresizingMask:(NSUInteger)mask<br /></div>
<br />
</div>
<div>
Parameters<br />
</div>
<div>
mask<br />
</div>
<div>
An integer bit mask. mask can be specified by combining using the C bitwise OR operator any of the options described in "Resizing masks".<br />
</div>
<div>
<br />
</div>
<div>
The possible "values" that can be used to composite an auto resizing mask are also well documented:<br />
</div>
<div>
<br />
<div style="color: #c600a1; font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
enum<span style="color: black;"> {</span><br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSViewNotSizable = <span style="color: #1e16d6;">0</span>,<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSViewMinXMargin = <span style="color: #1e16d6;">1</span>,<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSViewWidthSizable = <span style="color: #1e16d6;">2</span>,<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSViewMaxXMargin = <span style="color: #1e16d6;">4</span>,<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSViewMinYMargin = <span style="color: #1e16d6;">8</span>,<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSViewHeightSizable = <span style="color: #1e16d6;">16</span>,<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSViewMaxYMargin = <span style="color: #1e16d6;">32</span><br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
};<br /></div>
<br />
</div>
<div>
So, how does setting the auto resizing mask typically look like? Let's recap:<br />
</div>
<div>
<br />
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
[aView setAutoresizingMask:(NSViewWidthSizable |<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSViewHeightSizable)];<br /></div>
<br />
</div>
<div>
One questions immediately pops up: Why does it have to be so complicated? There are good reasons.<br />
</div>
<div>
<br />
<ul>
<li>Bit masks are usually very "small" and thus save memory.</li>
<li>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, ...</li>
</ul>
<br />
</div>
<div>
What is wrong with that? 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.<br /><br />
</div>
<div>
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.<br />
</div>
<div>
<br />
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSString *kViewNotSizable = <span style="color: #de091f;">@"kViewNotSizable"</span>;<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSString *kViewMinXMargin = <span style="color: #de091f;">@"kViewMinXMargin"</span>;<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSString *kViewWidthSizable = <span style="color: #de091f;">@"kViewWidthSizable"</span>;<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSString *kViewMaxXMargin = <span style="color: #de091f;">@"kViewMaxXMargin"</span>;<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSString *kViewMinYMargin = <span style="color: #de091f;">@"kViewMinYMargin"</span>;<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSString *kViewHeightSizable = <span style="color: #de091f;">@"kViewHeightSizable"</span>;<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSString *kViewMaxYMargin = <span style="color: #de091f;">@"kViewMaxYMargin"</span>;<br /></div>
<br />
</div>
<div>
We would also have to rewrite the accessors for the auto resizing mask to use NSSet.<br />
</div>
<div>
<br />
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
- (<span style="color: #c600a1;">void</span>)setAutoresizingMask:(NSSet *)mask;<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
- (NSSet *)autoresizingMask;<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
<br /></div>
</div>
<div>
Thats basically it. Setting the auto resizing mask by using this new pattern would look like this:<br />
</div>
<div>
<br />
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
[aView setAutoresizingMask:[NSSet setWithObjects:<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
kViewWidthSizable,<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
kViewHeightSizable, <span style="color: #c600a1;">nil</span>];<br /></div>
<br />
</div>
<div>
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:<br />
</div>
<div>
<br />
</div>
<div>
Checking if the view should resize it's height:<br />
</div>
<div>
<br />
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #c600a1;">if</span>([[aView autoresizingMask] containsObject:kViewHeightSizable])<br /></div>
<br />
</div>
<div>
Checking if the auto resizing mask is "valid":<br />
</div>
<div>
<br />
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
NSSet *maxMask = [NSSet setWithObjects:<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
kViewNotSizable,<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
kViewMinXMargin,<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
kViewWidthSizable,<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
kViewMaxXMargin,<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
kViewMinYMargin,<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
kViewHeightSizable,<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
kViewMaxYMargin];<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 13.0px;">
<br /></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #c600a1;">if</span>([[aView autoresizingMask] isSubsetOfSet:maxMask])<br /></div>
<br />
</div>
<div>
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.<br />
</div>
<div>
<br />
</div>
<div>
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. :)<br />
</div>
<div>
<br />
</div>
<div>
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.<br />
</div>Christian Kienlehttp://www.blogger.com/profile/03701216649543730169noreply@blogger.com6