tag:blogger.com,1999:blog-88509891832265374712024-02-21T10:38:24.543-07:00Programming Knowledge BaseA collection of obscure errors and elegant solutions.Unknownnoreply@blogger.comBlogger42125tag:blogger.com,1999:blog-8850989183226537471.post-84276476841051147392013-12-07T19:31:00.000-07:002013-12-07T22:09:57.719-07:00A Successful Programmer: Reading<div style="text-align: left;">
I’ve been thinking a long while about some of the things that have made me a successful programmer. One in particular is reading. I have read and continue to read many books. The books I read vary in topic and not all are technical. I will just to focus on technical books for now.</div>
<br />
<div style="text-align: left;">
Even though I work professionally as an iOS developer. I keep my eyes open for useful or emerging technologies. There is something to learn from every field, technology, or language. When I find a useful technique, I adopt it into my current practices. Recently I’ve been incorporating more functional programming techniques. The idea of limiting mutable state greatly simplifies debugging later. </div>
<br />
<div style="text-align: left;">
One of my favorite publishers is <a href="http://pragprog.com/">The Pragmatic Bookshelf</a>. They publish books for programmers authored by programmers. They have books on almost any topic and at varying levels of expertise. Additionally their publications are easily affordable. They offer physical books, ebooks, and screencasts. Updated digital publications can be automatically synced with Dropbox. When I want to pick up a new technology and be assured I’m learning best practice, this is my first source. At the time of this writing, I own 31 of their books.</div>
<br />
<div style="text-align: left;">
I also read many older books. There is much to learn from the past. One book I often reference is <a href="http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612/ref=sr_1_1">Design Patterns: Elements of Reusable Object-Oriented Software</a>. Knowing good code design is fundamental to writing maintainable code. I love Don Norman’s <a href="http://www.amazon.com/The-Design-Everyday-Things-Expanded/dp/0465050654/ref=sr_1_1">Design of Everyday Things</a> to better understand building usable apps. Fred Brook’s <a href="http://www.amazon.com/The-Mythical-Man-Month-Engineering-Anniversary/dp/0201835959/ref=sr_1_1">The Mythical Man Month</a> is great for avoiding common pitfalls in managing technical projects. There are countless other classics I could mention, but these books are among my favorites. </div>
<br />
<div style="text-align: left;">
I’ve often heard as a rule of thumb that every programmer should learn a new language every year. This is certainly not enough time to master the language. It is, however, sufficiently long to learn the unique features of the language. I personally try to read several books per year, both related and unrelated to my current work. Lately I have been studying distributed computing and Erlang/Elixir. I love parallel processing, and big data is one of the next big problems that needs to be solved. Though these studies are not directly related to iOS development, it helps me in building scalable web backends to service iOS apps.</div>
<br />
<div style="text-align: left;">
Everyone has different learning patterns. If reading books doesn’t suit you, find other ways to learn new technologies and techniques. </div>
<br />
<div style="text-align: left;">
As a disclaimer, I am not receiving any compensation from any publishers or authors. I have found the mentioned books useful and believe that they will benefit others.</div>
<br />Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-47174063247925252792013-07-27T17:23:00.000-06:002013-07-27T19:02:11.828-06:00Update<div style="text-align: left;">
For many months my blog has been left idle. Ever since I started working full-time, I have been unable to blog about many of the projects I work on. When I get off work for the day, I have little desire to work on Apple-related technologies. However, I have been working on other personal projects. These projects don’t fit the mold of what I usually blog about here. Here are a few of those projects.</div>
<br />
<div style="text-align: left;">
I have been involved with robotics for years. It’s a field that has always fascinated and is what got me into programming. While attending Brigham Young University, I didn’t have the time nor the financial means to support my hobby in robotics. In the last year I have built a couple robots. The first is a <a href="http://www.flickr.com/photos/92242245@N04/sets/72157632614529537/">hexapod</a>. For the most part, I used a kit from <a href="http://www.trossenrobotics.com/phantomx-ax-hexapod.aspx">Trossen Robotics</a>. The default code is open source. I found the <a href="http://en.wikipedia.org/wiki/Inverse_kinematics">inverse kinematics engine</a> most fascinating to study. I reprogrammed the hexapod with simple autonomous navigation using a sonar sensor. I also built a dashboard and control system for running and controlling the hexapod from my laptop. </div>
<br />
<div style="text-align: left;">
The second robot I built is a quadcopter which I have named <a href="http://www.flickr.com/photos/92242245@N04/sets/72157633406204346/">Tetra</a>. I designed the frame using Inventor Fusion and printed each of the pieces using my 3D printer. The electronics are from <a href="http://ardupilot.com/">ArduPilot</a>. After many <a href="https://vimeo.com/69731932">flights</a>, both successful and unsuccessful, I learned a great deal about multi-copter flight and structural integrity. </div>
<br />
<div style="text-align: left;">
I already have a third robot lined up. This one is a <a href="http://www.hobbyking.com/hobbyking/store/__23790__Turnigy_Talon_Hexcopter_V1_0_Carbon_Fiber_Frame_625mm.html">hexcopter</a> made of carbon fiber. The main idea behind this one is to have a greater ratio of flight time to repair time. </div>
<br />
<div style="text-align: left;">
As I previously mentioned I have been working with 3D printing. Not only have I printed Tetra, but I have also printed many <a href="http://www.flickr.com/photos/92242245@N04/sets/72157633413293182/">trinkets</a>. 3D printing is a young and exciting field. It’s especially great for robotics since I can quickly and easily make any parts I need. I have a few larger ideas lined up, which I may post later. </div>
<br />
<div style="text-align: left;">
Outside robotics, I have been working on other projects. I have been teaching myself <a href="http://pragprog.com/book/jaerlang2/programming-erlang">Erlang</a> and <a href="http://pragprog.com/book/elixir/programming-elixir">Elixir</a>. I am fascinated with parallel processing. Quite some time ago, I reached the peak of all I could learn about parallel processing from Grand Central Dispatch. Now I am expanding into more advanced techniques. In order to learn these languages, I started work on a simple <a href="https://github.com/rob-brown/Forecastex">wrapper</a> around <a href="http://forecast.io/">Forecast.io</a>. I have also been using Elixir to solve problems in <a href="http://projecteuler.net/">Project Euler</a>. Elixir makes many of the problems trivial relative to other languages. It’s great for heavy computation, and makes it easy to take full advantage of all my laptop’s cores. As cloud computing continues to expand, I expect that Erlang, Elixir, and similar languages will play a great role. </div>
<br />
<div style="text-align: left;">
Hopefully in the coming months my blog won’t be as silent. Though, the topics may be different from those I have done in the past. </div>
<div style="text-align: left;">
<br /></div>
Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-18937363760319276092012-11-03T12:31:00.000-06:002012-11-03T14:23:25.572-06:00Clang Language Extensions: __builtin_unreachable()<div style="text-align: left;">
Sometimes when programming, we encounter impossible situations. Unfortunately, the compiler isn’t as smart as we are. It can’t identify impossible situations like we can. For these situations, we can help the compiler by instructing it that a code path is impossible. For this we use __builtin_unreachable().</div>
<br />
<div style="text-align: left;">
Let’s say we have an enum as follows:</div>
<br />
<div style="text-align: left;">
<span style="color: #760f50; font-size: 14pt;">typedef</span> <span style="font-size: 14pt;"></span><span style="color: #643820; font-size: 14pt;">NS_ENUM</span><span style="font-size: 14pt;">(NSInteger, MyEnum) {</span></div>
<div style="text-align: left;">
<span style="font-size: 14pt;"> MyEnumA,</span></div>
<div style="text-align: left;">
<span style="font-size: 14pt;"> MyEnumB,</span></div>
<div style="text-align: left;">
<span style="font-size: 14pt;"> MyEnumC,</span></div>
<div style="text-align: left;">
<span style="font-size: 14pt;"> MyEnumD,</span></div>
<div style="text-align: left;">
<span style="font-size: 14pt;">};</span></div>
<br />
<div style="text-align: left;">
Now let’s say we have a switch statement that uses two of the four enum values, but the other two are impossible in this situation. Not including them in the switch will generate a compiler warning. However, including them doesn’t make sense. We can use __builtin_unreachable() to get rid of the warnings. </div>
<br />
<div style="text-align: left;">
<span style="color: #3f6e74; font-size: 14pt;">MyEnum</span> <span style="font-size: 14pt;">value = </span><span style="color: #236e25; font-size: 14pt;">// some value.</span></div>
<br />
<div style="text-align: left;">
<span style="color: #760f50; font-size: 14pt;">switch</span> <span style="font-size: 14pt;">(value) {</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 14pt;"></span><span style="font-size: 19px;"> </span><span style="font-size: 19px;"> </span><span style="color: #760f50; font-size: 14pt;">case</span> <span style="font-size: 14pt;">MyEnumA:</span></div>
<div style="text-align: left;">
<span style="color: #236e25; font-size: 14pt;">// Handle case A</span></div>
<div style="text-align: left;">
<span style="font-size: 14pt;"></span><span style="font-size: 19px;"> </span><span style="font-size: 19px;"> </span><span style="font-size: 19px;"> </span><span style="font-size: 19px;"> </span><span style="color: #760f50; font-size: 14pt;">break</span><span style="font-size: 14pt;">;</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 14pt;"></span><span style="font-size: 19px;"> </span><span style="font-size: 19px;"> </span><span style="color: #760f50; font-size: 14pt;">case</span> <span style="font-size: 14pt;">MyEnumB:</span></div>
<div style="text-align: left;">
<span style="color: #236e25; font-size: 14pt;">// Handle case B</span></div>
<div style="text-align: left;">
<span style="font-size: 14pt;"></span><span style="font-size: 19px;"> </span><span style="font-size: 19px;"> </span><span style="font-size: 19px;"> </span><span style="font-size: 19px;"> </span><span style="color: #760f50; font-size: 14pt;">break</span><span style="font-size: 14pt;">;</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 19px;"> </span><span style="font-size: 19px;"> </span><span style="color: #760f50; font-size: 14pt;">default</span><span style="font-size: 14pt;">:</span></div>
<div style="text-align: left;">
<span style="font-size: 14pt;"> </span><span style="font-size: 19px;"> </span><span style="font-size: 19px;"> </span><span style="font-size: 14pt;">NSLog(</span><span style="color: #891315; font-size: 14pt;">@"Cases C and D are impossible"</span><span style="font-size: 14pt;">);</span></div>
<div style="text-align: left;">
<span style="font-size: 14pt;"> </span><span style="font-size: 19px;"> </span><span style="font-size: 19px;"> </span><span style="font-size: 14pt;">__builtin_unreachable();</span></div>
<div style="text-align: left;">
<span style="font-size: 14pt;">}</span></div>
<br />
<div style="text-align: left;">
We can also make a macro that we can use to mark a method as not implemented like the following: </div>
<br />
<div style="text-align: left;">
<span style="font-size: 14pt;">- (</span><span style="color: #5c2699; font-size: 14pt;">NSString</span> <span style="font-size: 14pt;">*)someMethod {</span></div>
<div style="text-align: left;">
<span style="font-size: 14pt;"></span><span style="font-size: 19px;"> </span><span style="font-size: 19px;"> </span><span style="color: #643820; font-size: 14pt;">NOT_IMPLEMENTED</span><span style="font-size: 14pt;">;</span></div>
<div style="text-align: left;">
<span style="font-size: 14pt;">}</span></div>
<br />
<div style="text-align: left;">
By using __builtin_unreachable(), this macro also makes it so we don’t need to return a bogus value to suppress the no return value warning. The macro looks like this:</div>
<br />
<div style="text-align: left;">
<span style="color: #683821; font-size: 14pt;">#define NOT_IMPLEMENTED \</span></div>
<div style="text-align: left;">
<span style="color: #683821; font-size: 14pt;">NSAssert1(NO, @</span><span style="color: #891315; font-size: 14pt;">"Method: %@ not implemented."</span><span style="color: #683821; font-size: 14pt;">, NSStringFromSelector(_cmd)); \</span></div>
<div style="text-align: left;">
<span style="color: #683821; font-size: 14pt;">__builtin_unreachable();</span></div>
<br />
<div style="text-align: left;">
Another perk of this macro is that it prints an error to the console including the name of the method that is not implemented. </div>
<br />
<div style="text-align: left;">
Related to __builtin_unreachable() is the ‘noreturn’ attribute. This allows us to mark any function or method that once called, it will never return. This attribute is great for abort methods. We can mark methods like so: </div>
<br />
<div style="text-align: left;">
<span style="font-size: 14pt;">- (</span><span style="color: #760f50; font-size: 14pt;">void</span><span style="font-size: 14pt;">)gracefulAbort </span><span style="color: #760f50; font-size: 14pt;">__attribute__</span><span style="font-size: 14pt;">((noreturn));</span></div>
<br />
<div style="text-align: left;">
Let’s say our app encounters a terminal Core Data error and we need to gracefully terminate the app. We can encapsulate this into a method. This method obviously will never return since it will cause the app to close. By marking it with the noreturn attribute, we will gain the same benefits as if we did the following: </div>
<br />
<div style="text-align: left;">
<span style="font-size: 14pt;">[</span><span style="color: #760f50; font-size: 14pt;">self</span> <span style="font-size: 14pt;"></span><span style="color: #26474b; font-size: 14pt;">gracefulAbort</span><span style="font-size: 14pt;">];</span></div>
<div style="text-align: left;">
<span style="color: #26474b; font-size: 14pt;">__builtin_unreachable</span><span style="font-size: 14pt;">();</span></div>
<br />
<div style="text-align: left;">
The above cases I described are few and far between, but when they come up, __builtin_unreachable() is useful. To learn more about this and other Clang language extensions, check out the <a href="http://clang.llvm.org/docs/LanguageExtensions.html#__builtin_unreachable">clang docs</a>. </div>
<br />Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-62703321346423867012012-10-13T11:42:00.000-06:002012-10-13T13:15:07.306-06:00Clang Language Extensions: instancetype<div style="text-align: left;">
Clang added several features to the Objective-C language. One of these features is the ‘instancetype’ keyword. When creating objects, we frequently use methods in the alloc and init families. They have a return type of id, but the compiler knows that they will return an object that matches the class being used. For example, [[NSString alloc] init] returns an NSString and [[NSMutableString alloc] init] returns an NSMutableString.</div>
<br />
<div style="text-align: left;">
There are several methods that will automatically infer the return type from the method name. They must follow standard camel-case naming and start with the following words:</div>
<br />
<div style="text-align: left;">
For class methods:</div>
<div style="text-align: left;">
alloc</div>
<div style="text-align: left;">
new</div>
<br />
<div style="text-align: left;">
For instance methods:</div>
<div style="text-align: left;">
autorelease</div>
<div style="text-align: left;">
init</div>
<div style="text-align: left;">
retain</div>
<div style="text-align: left;">
self</div>
<br />
<div style="text-align: left;">
For any methods that do not follow this naming convention, we use the keyword instancetype. Let’s say we have the following objects:</div>
<br />
<div style="text-align: left;">
<span style="color: #760f50; font-size: 14pt;">@interface</span> <span style="font-size: 14pt;">Animal : </span><span style="color: #5c2699; font-size: 14pt;">NSObject</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 14pt;">+ (</span><span style="color: #5c2699; font-size: 14pt;">instancetype</span><span style="font-size: 14pt;">)createAnimalWithName:(</span><span style="color: #5c2699; font-size: 14pt;">NSString</span> <span style="font-size: 14pt;">*)name;</span></div>
<br />
<div style="text-align: left;">
<span style="color: #760f50; font-size: 14pt;">@end</span></div>
<br />
<div style="text-align: left;">
<span style="color: #760f50; font-size: 14pt;">@interface</span> <span style="font-size: 14pt;">SnowLeopard : </span><span style="color: #3f6e74; font-size: 14pt;">Animal</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 14pt;">- (</span><span style="color: #760f50; font-size: 14pt;">void</span><span style="font-size: 14pt;">)pounce;</span></div>
<br />
<div style="text-align: left;">
<span style="color: #760f50; font-size: 14pt;">@end</span></div>
<br />
<div style="text-align: left;">
<span style="color: #760f50; font-size: 14pt;">@interface</span> <span style="font-size: 14pt;">MountainLion : </span><span style="color: #3f6e74; font-size: 14pt;">Animal</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 14pt;">- (</span><span style="color: #760f50; font-size: 14pt;">void</span><span style="font-size: 14pt;">)roar;</span></div>
<br />
<div style="text-align: left;">
<span style="color: #760f50; font-size: 14pt;">@end</span></div>
<br />
<div style="text-align: left;">
Now let’s say we create an object and call a method on it like so:</div>
<br />
<div style="text-align: left;">
<span style="font-size: 14pt;">[[</span><span style="color: #3f6e74; font-size: 14pt;">MountainLion</span> <span style="font-size: 14pt;"></span><span style="color: #26474b; font-size: 14pt;">createAnimalWithName</span><span style="font-size: 14pt;">:</span><span style="color: #891315; font-size: 14pt;">@"Maxwell"</span><span style="font-size: 14pt;">] </span><span style="color: #26474b; font-size: 14pt;">roar</span><span style="font-size: 14pt;">];</span></div>
<br />
<div style="text-align: left;">
If +createAnimalWithName: returns id or instancetype, then the compiler accepts this just fine. If it returns an Animal object, then the compiler gives the warning: “Animal may not respond to roar.”</div>
<br />
<div style="text-align: left;">
So, when does instancetype have an advantage over id? Let’s say we do this instead: </div>
<br />
<div style="text-align: left;">
<span style="font-size: 14pt;">[[</span><span style="color: #3f6e74; font-size: 14pt;">MountainLion</span> <span style="font-size: 14pt;"></span><span style="color: #26474b; font-size: 14pt;">createAnimalWithName</span><span style="font-size: 14pt;">:</span><span style="color: #891315; font-size: 14pt;">@"Maxwell"</span><span style="font-size: 14pt;">] </span><span style="color: #26474b; font-size: 14pt;">lastObject</span><span style="font-size: 14pt;">];</span></div>
<br />
<div style="text-align: left;">
A MountainLion is clearly not an NSArray; however, the compiler will happily accept this if +createAnimalWithName: returns an id. It’s not until we run the app that the we find the error when our app crashes due to an unrecognized selector method exception.</div>
<br />
<div style="text-align: left;">
In summary, the instancetype keyword helps the compiler help you know when something is wrong. If for any reason you need to know if the compiler supports this feature, you can use the macro __has_feature(objc_instancetype). </div>
<br />
<div style="text-align: left;">
If you want to learn more about instancetype and other Clang features, check out the <a href="http://clang.llvm.org/docs/LanguageExtensions.html#objc_instancetype">Clang docs</a>. </div>
<br />Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-55129389351703043902012-06-10T18:32:00.000-06:002012-06-10T19:50:04.993-06:00Linking Storyboards<div style="text-align: left;">
<strong>Summary</strong></div>
<br />
<div style="text-align: left;">
Previously I wrote about <a href="http://robsprogramknowledge.blogspot.com/2012/01/uistoryboard-best-practices.html">best practices with UIStoryboards</a>. Since then I have continued to explore the possibilities of storyboards. With today being the eve of WWDC 2012, I wanted to share one of the tricks I have learned. </div>
<br />
<div style="text-align: left;">
A key practice of storyboards is to break them down into natural, reusable modules. The downfall to this decomposition is when we need to transition from one storyboard to another. Storyboards were supposed to save us from the tedious transition code, but decomposition brings some of it back. Fortunately, there is a way to remove this pain.</div>
<br />
<div style="text-align: left;">
Before I go into any details, I want to start with a disclaimer. I am not going to label this as best practice…at least not yet. All good design patterns need to stand the test of time. I have not used this trick enough to know if it works in all cases. Also, with this week being WWDC, Apple may expand UIStoryboards to include segues between storyboards. </div>
<br />
<div style="text-align: left;">
<strong>Implementing</strong></div>
<br />
<div style="text-align: left;">
You should first download my code from <a href="https://github.com/rob-brown/RBStoryboardLink">GitHub</a>. Following along will help in understanding how everything works. </div>
<br />
<div style="text-align: left;">
The first thing to do is build your storyboards as you normally would. It's best if you break them down into natural modules. The rule of thumb is, if you can give each storyboard a meaningful name, then you have probably decomposed them well.</div>
<br />
<div style="text-align: left;">
Now that you have your various storyboards, you can begin connecting them. To do this, you need to identify where you will transition into a different storyboard. At each of these points, create a blank UIViewController. This will represent the view in the other storyboard you will transition to. </div>
<br />
<div style="text-align: left;">
Next you need to create a segue to each of these surrogate scenes. You can choose a Push, Modal, or custom segue according to your needs. They should look something like the picture below: </div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4w8MiSEgfsFW2FKcUY-VgB5tVZPqgsRdBWpaV3snYyjJUX2dFscIF-Bc26Tus8UDy1zJQI2S2l4C0ok3Quq1PAtgI4i0BbGFDA6Xo3y6O41hR8Js8Qu8BCP26LoAkj8ACb0fNheLFaGY/s1600/Screen+Shot+2012-06-10+at+6.30.19+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="222" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4w8MiSEgfsFW2FKcUY-VgB5tVZPqgsRdBWpaV3snYyjJUX2dFscIF-Bc26Tus8UDy1zJQI2S2l4C0ok3Quq1PAtgI4i0BbGFDA6Xo3y6O41hR8Js8Qu8BCP26LoAkj8ACb0fNheLFaGY/s320/Screen+Shot+2012-06-10+at+6.30.19+PM.png" width="320" /></a></div>
<br />
<br />
<div style="text-align: left;">
Once you have your surrogate scene in place, we can make the magic happen. We get to use a little-known tool of Interface Builder. It is the User Defined Runtime Attributes tool. This tool is hidden away in the Identity Inspector (3rd tab of the utility view). Up until now, you have probably used this inspector only to set a custom class. It also allows us to set the values of any property of any view we may be using in the storyboard. </div>
<br />
<div style="text-align: left;">
First, we need to change the surrogate's class to RBStoryboardLink. Don't forget to include my RBStoryboardLink class in your app. Next, we can add a couple properties instructing the link what to transition to. The first, and required, attribute is "storyboardName" This is the name of the storyboard file you are going to transition to (without the .storyboard extension). The second attribute is optional. It called "sceneIdentifier". This is the UIStoryboard identifier you have given to a scene in the destination storyboard. If you ignore this attribute, then RBStoryboardLink will simply transition to the first scene in the storyboard. This is often what you want. Your Identity Inspector should now look something like the picture below:</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgIMXqB_bDojCQf0HijkDE5vTK1eiANHR-TtMcEM9R2gNaiQ9rcSnt05nITgLklbOHsCQeXXIl_rVujJ1923ISeozMSkIA5FAo9UEFOVUOs2hV-uRzERYmxiSdXl6Wb0-s7d8TPvrqoXc/s1600/Screen+Shot+2012-06-10+at+6.31.32+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjgIMXqB_bDojCQf0HijkDE5vTK1eiANHR-TtMcEM9R2gNaiQ9rcSnt05nITgLklbOHsCQeXXIl_rVujJ1923ISeozMSkIA5FAo9UEFOVUOs2hV-uRzERYmxiSdXl6Wb0-s7d8TPvrqoXc/s1600/Screen+Shot+2012-06-10+at+6.31.32+PM.png" /></a></div>
<br />
<br />
<div style="text-align: left;">
<strong>Explanation</strong></div>
<br />
<div style="text-align: left;">
RBStoryboardLink works much like a symbolic link in your file system. A symbolic link essentially looks and acts like file. Likewise, RBStoryboardLink looks and acts much like a storyboard scene. </div>
<br />
<div style="text-align: left;">
The idea behind RBStoryboardLink is simple. At a high level, it does the following:</div>
<ol style="list-style-type: decimal;">
<li style="text-align: left;">Creates the destination scene.</li>
<li style="text-align: left;">Adds the view controller as a child of itself using the iOS 5 container API.</li>
<li style="text-align: left;">Copies all the destination scene's properties into RBStoryboardLink.</li>
</ol>
<strong>Conclusion</strong><br />
<br />
<div style="text-align: left;">
RBStoryboardLink is a clean, easy-to-use technique to link storyboards without leaving Interface Builder. With WWDC this week, Apple may release similar functionality built directly into Interface Builder. If not, expect to use this technique frequently in your projects. </div>
<br />Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-65204895469765550442012-05-07T20:23:00.000-06:002012-05-07T22:21:27.180-06:00UIStoryboards and UITabBarController<div style="text-align: left;">
<span style="font-size: 12pt;">Previously I wrote about <a href="http://robsprogramknowledge.blogspot.com/2012/01/uistoryboard-best-practices.html">decomposing UIStoryboards into modules</a>. One of the most natural modules are the tabs of a tab bar controller. Since segues can't cross storyboards, we can't use a UITabBarController in a storyboard. This means the UITabBarController must be written in code. I have put together an easy pattern for building UITabBarControllers in code.</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;"><strong>UIStoryboard Category</strong></span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;">The first step is to write a category on UIStoryboard. It will look something like this:</span></div>
<br />
<div style="text-align: left;">
<span style="color: blue;">@implementation</span> UIStoryboard (YourExtras)</div>
<br />
<div style="text-align: left;">
+ (<span style="color: #2b839f;">UIStoryboard</span> *)searchStoryboard {</div>
<div style="text-align: left;">
<span style="color: blue;"> return</span> [<span style="color: #2b839f;">UIStoryboard</span> <span style="color: #2b839f;">storyboardWithName</span>:<span style="color: #a31515;">@"SearchStoryboard"</span> <span style="color: #2b839f;">bundle</span>:<span style="color: blue;">nil</span>];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
+ (<span style="color: #2b839f;">UIStoryboard</span> *)mapStoryboard {</div>
<div style="text-align: left;">
<span style="color: blue;"> <span class="Apple-style-span" style="color: blue;"> </span>return</span> [<span style="color: #2b839f;">UIStoryboard</span> <span style="color: #2b839f;">storyboardWithName</span>:<span style="color: #a31515;">@"MapStoryboard"</span> <span style="color: #2b839f;">bundle</span>:<span style="color: blue;">nil</span>];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
+ (<span style="color: #2b839f;">UIStoryboard</span> *)listStoryboard {</div>
<div style="text-align: left;">
<span style="color: blue;"> <span class="Apple-style-span" style="color: blue;"> </span>return</span> [<span style="color: #2b839f;">UIStoryboard</span> <span style="color: #2b839f;">storyboardWithName</span>:<span style="color: #a31515;">@"ListStoryboard"</span> <span style="color: #2b839f;">bundle</span>:<span style="color: blue;">nil</span>];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
+ (<span style="color: #2b839f;">UIStoryboard</span> *)favoritesStoryboard {</div>
<div style="text-align: left;">
<span style="color: blue;"> <span class="Apple-style-span" style="color: blue;"> </span>return</span> [<span style="color: #2b839f;">UIStoryboard</span> <span style="color: #2b839f;">storyboardWithName</span>:<span style="color: #a31515;">@"FavoritesStoryboard"</span> <span style="color: #2b839f;">bundle</span>:<span style="color: blue;">nil</span>];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
+ (<span style="color: #2b839f;">UIStoryboard</span> *)contactStoryboard {</div>
<div style="text-align: left;">
<span style="color: blue;"> <span class="Apple-style-span" style="color: blue;"> </span>return</span> [<span style="color: #2b839f;">UIStoryboard</span> <span style="color: #2b839f;">storyboardWithName</span>:<span style="color: #a31515;">@"ContactStoryboard"</span> <span style="color: #2b839f;">bundle</span>:<span style="color: blue;">nil</span>];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
+ (<span style="color: #2b839f;">UIStoryboard</span> *)homeStoryboard {</div>
<div style="text-align: left;">
<span style="color: blue;"> <span class="Apple-style-span" style="color: blue;"> </span>return</span> [<span style="color: #2b839f;">UIStoryboard</span> <span style="color: #2b839f;">storyboardWithName</span>:<span style="color: #a31515;">@"HomeStoryboard"</span> <span style="color: #2b839f;">bundle</span>:<span style="color: blue;">nil</span>];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
<span style="color: blue;">@end</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;">The purpose of this category is to abstract away the storyboard file names. Should the storyboard name (or bundle) change, we will only need to change it in one place. Such methods are useful not just tabs but also for any storyboard module. For the purpose of tabs, each storyboard generally should have a UINavigationController as its initial view.</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;"><strong>UITabBarController Category</strong></span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;">The next step involves a category I wrote. It takes in an array of UIStoryboards, then instantiates each storyboard as a tab. It saves writing a little bit of code between each project. </span></div>
<br />
<div style="text-align: left;">
<span style="color: blue;">@implementation</span> UITabBarController (RBExtras)</div>
<br />
<div style="text-align: left;">
+ (<span style="color: #2b839f;">UITabBarController</span> *)tabBarControllerWithStoryboardTabs:(<span style="color: #2b839f;">NSArray</span> *)tabs {</div>
<br />
<div style="text-align: left;">
<span style="color: #2b839f;"><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>UITabBarController</span> * tabBarController = [<span style="color: #2b839f;">UITabBarController</span> <span style="color: #2b839f;">new</span>];</div>
<div style="text-align: left;">
<span style="color: #2b839f;"><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>NSMutableArray</span> * instantiatedTabs = [<span style="color: #2b839f;">NSMutableArray</span> <span style="color: #2b839f;">arrayWithCapacity</span>:[tabs <span style="color: #2b839f;">count</span>]];</div>
<br />
<div style="text-align: left;">
<span style="color: green;"><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>// Instantiates each of the storyboards.</span></div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>[tabs <span style="color: #2b839f;">enumerateObjectsUsingBlock</span>:^(<span style="color: blue;">id</span> obj, <span style="color: #2b839f;">NSUInteger</span> idx, <span style="color: blue;">BOOL</span> * stop) {</div>
<br />
<div style="text-align: left;">
<span style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span style="color: blue;"><span class="Apple-style-span" style="color: blue;"> </span>NSAssert</span>([obj <span style="color: #2b839f;">isKindOfClass</span>:[<span style="color: #2b839f;">UIStoryboard</span> <span style="color: #2b839f;">class</span>]],</div>
<div style="text-align: left;">
<span style="color: #a31515;"><span class="Apple-style-span" style="color: blue;"> </span></span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span style="color: #a31515;">@"Expected UIStoryboard, got %@"</span>,</div>
<div style="text-align: left;">
<span style="color: #2b839f;"><span class="Apple-style-span" style="color: blue;"> </span></span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span style="color: #2b839f;"><span class="Apple-style-span" style="color: blue;"> </span>NSStringFromClass</span>([obj <span style="color: #2b839f;">class</span>]));</div>
<br />
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>[instantiatedTabs <span style="color: #2b839f;">addObject</span>:[obj <span style="color: #2b839f;">instantiateInitialViewController</span>]];</div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>}];</div>
<br />
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>[tabBarController <span style="color: #2b839f;">setViewControllers</span>:instantiatedTabs];</div>
<br />
<div style="text-align: left;">
<span style="color: blue;"> <span class="Apple-style-span" style="color: blue;"> </span>return</span> tabBarController;</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
<span style="color: blue;">@end</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;">This category can be found on <a href="https://github.com/rob-brown/RBCategories">my Github</a>. </span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;"><strong>App Delegate Superclass</strong></span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;">Next is an app delegate superclass I wrote. This saves a few more lines of code from each tab-based app. </span></div>
<br />
<div style="text-align: left;">
<span style="color: blue;">@implementation</span> RBAppDelegate</div>
<br />
<div style="text-align: left;">
<span style="color: blue;">@synthesize</span> window = <span style="color: #2b839f;">_window</span>;</div>
<br />
<div style="text-align: left;">
- (<span style="color: blue;">void</span>)setUpTabBasedAppWithTabs:(<span style="color: #2b839f;">NSArray</span> *)tabs block:(<span style="color: #2b839f;">RBTabBarCustomizationBlock</span>)block {</div>
<br />
<div style="text-align: left;">
<span style="color: blue;"> <span class="Apple-style-span" style="color: blue;"> </span>NSAssert</span>(tabs, <span style="color: #a31515;">@"No tabs given."</span>);</div>
<div style="text-align: left;">
<span style="color: blue;"> <span class="Apple-style-span" style="color: blue;"> </span>NSAssert</span>([tabs <span style="color: #2b839f;">count</span>] >= 2, <span style="color: #a31515;">@"Insufficient number of tabs."</span>);</div>
<br />
<div style="text-align: left;">
<span style="color: green;"><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>// Sets up the tab bar controller.</span></div>
<div style="text-align: left;">
<span style="color: #2b839f;"><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>UITabBarController</span> * tabBarController = [<span style="color: #2b839f;">UITabBarController</span> <span style="color: #2b839f;">tabBarControllerWithStoryboardTabs</span>:tabs];</div>
<br />
<div style="text-align: left;">
<span style="color: green;"><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>// The block is called to allow customization of the tab bar controller.</span></div>
<div style="text-align: left;">
<span style="color: blue;"> <span class="Apple-style-span" style="color: blue;"> </span>if</span> (block) block(tabBarController);</div>
<br />
<div style="text-align: left;">
<span style="color: green;"><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>// Sets up the window.</span></div>
<div style="text-align: left;">
<span style="color: #2b839f;"><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>UIWindow</span> * window = [<span style="color: #2b839f;">UIWindow</span> <span style="color: #2b839f;">new</span>];</div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>[window <span style="color: #2b839f;">setScreen</span>:[<span style="color: #2b839f;">UIScreen</span> <span style="color: #2b839f;">mainScreen</span>]];</div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>[window <span style="color: #2b839f;">setRootViewController</span>:tabBarController];</div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>[window <span style="color: #2b839f;">makeKeyAndVisible</span>];</div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>[<span style="color: blue;">self</span> <span style="color: #2b839f;">setWindow</span>:window];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
<span style="color: blue;">@end</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;">This superclass completes the set up of the tab bar controller. It provides a block for any customizations of the tab bar controller. You can also find this on <a href="https://github.com/rob-brown/RBCategories">my Github</a>. </span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;"><strong>Your App Delegate</strong></span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;">The final step is to call the set up method. Don't forget to subclass RBAppDelegate first. </span></div>
<br />
<div style="text-align: left;">
- (<span style="color: blue;">BOOL</span>)application:(<span style="color: #2b839f;">UIApplication</span> *)application didFinishLaunchingWithOptions:(<span style="color: #2b839f;">NSDictionary</span> *)launchOptions {</div>
<br />
<div style="text-align: left;">
<span style="color: green;"><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>// Creates the tabs.</span></div>
<div style="text-align: left;">
<span style="color: #2b839f;"><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>NSArray</span> * tabs = [<span style="color: #2b839f;">NSArray</span> <span style="color: #2b839f;">arrayWithObjects</span>:</div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>[<span style="color: #2b839f;">UIStoryboard</span> <span style="color: #2b839f;">mapStoryboard</span>],</div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>[<span style="color: #2b839f;">UIStoryboard</span> <span style="color: #2b839f;">listStoryboard</span>],</div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>[<span style="color: #2b839f;">UIStoryboard</span> <span style="color: #2b839f;">searchStoryboard</span>],</div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>[<span style="color: #2b839f;">UIStoryboard</span> <span style="color: #2b839f;">favoritesStoryboard</span>],</div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>[<span style="color: #2b839f;">UIStoryboard</span> <span style="color: #2b839f;">contactStoryboard</span>],</div>
<div style="text-align: left;">
<span style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span style="color: blue;"><span class="Apple-style-span" style="color: blue;"> </span>nil</span>];</div>
<br />
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>[<span style="color: blue;">self</span> <span style="color: #2b839f;">setUpTabBasedAppWithTabs</span>:tabs</div>
<div style="text-align: left;">
<span style="color: #2b839f;"><span class="Apple-style-span" style="color: blue;"> </span></span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span style="color: #2b839f;"><span class="Apple-style-span" style="color: blue;"> </span>block</span>:</div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>^(<span style="color: #2b839f;">UITabBarController</span> * tabBarController) {</div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>tabBarController.<span style="color: #2b839f;">tabBar</span>.<span style="color: #2b839f;">selectedImageTintColor</span> = [<span style="color: #2b839f;">UIColor</span> <span style="color: #2b839f;">greenColor</span>];</div>
<div style="text-align: left;">
<span class="Apple-style-span" style="color: blue;"> </span><span class="Apple-style-span" style="color: blue;"> </span>}];</div>
<br />
<div style="text-align: left;">
<span style="color: blue;"> <span class="Apple-style-span" style="color: blue;"> </span>return</span> <span style="color: blue;">YES</span>;</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;">The block for customizing the tab bar controller is optional, but I have shown the potential use of such a block. In this case I am setting the color of the selected tab icons. </span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;"><strong>Conclusion</strong></span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 12pt;">Within a few lines of code, we can have a tab-based app constructed from several storyboards. Other UIStoryboard patterns can be created using similar techniques. </span></div>
<br />Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-1683646373945606212012-05-06T13:41:00.000-06:002012-05-06T15:41:14.474-06:00Reverse Segues<div style="text-align: left;">
UIStoryboards make transitioning between views very easy. However, segues work strictly in one direction. I have been asked several times what is the best way to send information back to the previous view controller. Unfortunately, there is no such thing as a reverse segue. In response, I have found four clean, useful patterns to create the needed behavior:</div>
<ol style="list-style-type: decimal;">
<li style="text-align: left;">Delegate</li>
<li style="text-align: left;">Block</li>
<li style="text-align: left;">Shared memory</li>
<li style="text-align: left;">NSNotificationCenter</li>
</ol>
Each one has its advantages and disadvantages. I will discuss each one in turn.<br />
<br />
<div style="text-align: left;">
<strong>Delegate</strong></div>
<br />
<div style="text-align: left;">
<em>Summary</em></div>
<br />
<div style="text-align: left;">
Cocoa uses delegates everywhere, so why not here too? </div>
<br />
<div style="text-align: left;">
<em>Code Sample</em></div>
<br />
<div style="text-align: left;">
Let's say view controller X pushes view controller Y via segue. Y specifies a delegate protocol that it will call to pass the needed information. X conforms to that protocol and sets itself as Y's delegate. When Y is dismissed, it calls the delegate method. </div>
<br />
<div style="text-align: left;">
// In view controller X</div>
<div style="text-align: left;">
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {</div>
<div style="text-align: left;">
[[segue destinationViewController] setDelegate:self];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
- (void)objectUpdated:(id)object {</div>
<div style="text-align: left;">
// Do something with the object.</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
// In view controller Y</div>
<div style="text-align: left;">
@protocol MyDelegateProtocol</div>
<div style="text-align: left;">
- (void)objectUpdated:(id object);</div>
<div style="text-align: left;">
@end</div>
<br />
<div style="text-align: left;">
- (void)viewWillDisappear:(bool)animated {</div>
<div style="text-align: left;">
[super viewWillDisappear:animated];</div>
<br />
<div style="text-align: left;">
[[self delegate] objectUpdated:[self object]];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
<em>Pros/Cons</em></div>
<br />
<div style="text-align: left;">
Delegation is easy enough to implement. However, in this case, the delegate protocol probably has just one method. This hardly seems worth the effort to create the protocol. Because of this, I do not recommend delegates. I instead favor the next option: blocks. If you need more than one callback, a delegate may be more appropriate. </div>
<br />
<div style="text-align: left;">
<strong>Blocks</strong></div>
<br />
<div style="text-align: left;">
<em>Summary</em></div>
<br />
<div style="text-align: left;">
Blocks are great for making callbacks and can easily replace any delegate. </div>
<br />
<div style="text-align: left;">
<em>Code Sample</em></div>
<br />
<div style="text-align: left;">
Now when X pushes Y, it also gives Y a block. When Y finishes, it calls the given block and hands it the information to pass on. The block can then do whatever it needs with that information. </div>
<br />
<div style="text-align: left;">
// In view controller X</div>
<div style="text-align: left;">
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {</div>
<div style="text-align: left;">
[[segue destinationViewController] setBlock:^(id object) {</div>
<div style="text-align: left;">
// Do something with the object.</div>
<div style="text-align: left;">
}];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
// In view controller Y</div>
<div style="text-align: left;">
typedef void(^MyBlock)(id object);</div>
<br />
<div style="text-align: left;">
- (void)viewWillDisappear:(bool)animated {</div>
<div style="text-align: left;">
[super viewWillDisappear:animated];</div>
<br />
<div style="text-align: left;">
if (self.block)</div>
<div style="text-align: left;">
self.block(self.object);</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
<em>Pros/Cons</em></div>
<br />
<div style="text-align: left;">
Blocks have two great advantages over delegates. First, they don't require a protocol. For convenience, you may write a one-line block typedef, but that is all. Second, blocks keep code where it is relevant, rather in a different method. For most cases, you should favor blocks. </div>
<br />
<div style="text-align: left;">
<strong>Shared Memory</strong></div>
<br />
<div style="text-align: left;">
<em>Summary</em></div>
<br />
<div style="text-align: left;">
Sometimes you may push a new view so it can edit an object. In this case, you can avoid a callback entirely.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<em>Code Sample</em></div>
<br />
<div style="text-align: left;">
When pushing Y, just pass it a pointer to the object of interest. Any changes Y makes to the shared object will directly affect X.</div>
<br />
<div style="text-align: left;">
// In view controller X</div>
<div style="text-align: left;">
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {</div>
<div style="text-align: left;">
[[segue destinationViewController] setObject:[self object]];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
<em>Pros/Cons</em></div>
<br />
<div style="text-align: left;">
This solution is the simplest of the four. However, it may not be suitable in some situations. One place this pattern doesn't do well is if you want view controller Y to have a Done and Cancel button. You would need to undo all the changes made to your object if the Cancel button is pressed. This could be made easier by using an NSUndoManager, but that may be overkill for what you want.</div>
<br />
<div style="text-align: left;">
There is one particular place that this pattern is especially useful. When using Core Data with iOS 5, you may want view controller Y to have an NSManagedObjectContext that is a child of view controller X's NSManagedObjectContext. All you need to do is create the MOC in X, set the MOC's parent, and pass it on to Y.</div>
<br />
<div style="text-align: left;">
<strong>NSNotificationCenter</strong></div>
<br />
<div style="text-align: left;">
<em>Summary</em></div>
<br />
<div style="text-align: left;">
Using NSNotificationCenter to pass around information is the least used option and the most work, but it can have some nice advantages worth mentioning. </div>
<br />
<div style="text-align: left;">
<em>Code Sample</em></div>
<br />
<div style="text-align: left;">
Rather than have X tell Y it is interested in its information, X lets NSNotificationCenter know it is interested in an event. </div>
<br />
<div style="text-align: left;">
// In view controller X</div>
<div style="text-align: left;">
- (void)viewDidLoad {</div>
<div style="text-align: left;">
[super viewDidLoad];</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
[[NSNotificationCenter defaultCenter] addObserver:self</div>
<div style="text-align: left;">
selector:@selector(consumeNotifcation:)</div>
<div style="text-align: left;">
name:MyNotification</div>
<div style="text-align: left;">
object:nil];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
- (void)viewDidUnload {</div>
<div style="text-align: left;">
[[NSNotificationCenter defaultCenter] removeObserver:self</div>
<div style="text-align: left;">
name:MyNotification</div>
<div style="text-align: left;">
object:nil];</div>
<div style="text-align: left;">
[super viewDidUnload];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
- (void)consumeNotification:(NSNotification * notification) {</div>
<div style="text-align: left;">
// Grab the information from the notification.</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
// In view controller Y</div>
<div style="text-align: left;">
NSString * const MyNotification = @"MyNotification";</div>
<div style="text-align: left;">
NSString * const MyObject = @"MyObject";</div>
<br />
<div style="text-align: left;">
- (void)viewWillDisappear:(bool)animated {</div>
<div style="text-align: left;">
[super viewWillDisappear:animated];</div>
<br />
<div style="text-align: left;">
NSDictionary * userInfo = [NSDictionary dictionaryWithObjectsAndKeys:</div>
<div style="text-align: left;">
[self object], MyObject,</div>
<div style="text-align: left;">
nil];</div>
<br />
<div style="text-align: left;">
[[NSNotificationCenter defaultCenter] postNotificationName:MyNotification</div>
<div style="text-align: left;">
object:self</div>
<div style="text-align: left;">
userInfo:userInfo];</div>
<div style="text-align: left;">
}</div>
<br />
<div style="text-align: left;">
<em>Pros/Cons</em></div>
<br />
<div style="text-align: left;">
Obviously this is a lot more code than the other options. It comes with two key advantages. First, this pattern makes multiple, unrelated observers very easy. Second, it allows for looser coupling between views. X and Y (and any other views/non-views) essentially don't know anything about each other. They simply send or receive information through NSNotificationCenter. One place I use this pattern is with an app-wide settings view. When the settings are changed, different parts of the app may need to know immediately when the change is made. For example, I may have a setting that can turn off downloading over the cell network. Both the networking code and the UI will need to know about this change. The notification makes sure that they are informed immediately without needing to hard code the interactions. </div>
<br />
<div style="text-align: left;">
<strong>Conclusion</strong></div>
<br />
<div style="text-align: left;">
When passing information to a previous view controller, favor blocks. However, keep the other options in mind. They have their advantages too. </div>
<br />
<div style="text-align: left;">
<strong>Other Information</strong></div>
<br />
<div style="text-align: left;">
For more information on UIStoryboards, check out my <a href="http://robsprogramknowledge.blogspot.com/2012/01/uistoryboard-best-practices.html">best practices</a>. </div>
<br />Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-63715372492889715382012-04-23T10:42:00.000-06:002012-04-23T12:42:56.970-06:00Unique Email Channels<div style="text-align: left;">
If you are anything like me, you probably have more than one email account. One account is only for trusted friends and colleagues. The other is for everyone else. I am always paranoid that I will get spammed from some service, like Facebook. Other times I want to get the newsletters or notifications from some site, but I may lose interest in them over time and want to quickly stop the emails. </div>
<br />
<div style="text-align: left;">
<strong>The Problem</strong></div>
<br />
<div style="text-align: left;">
Every service I give my email address to needs to be handled differently. Gmail is really good about creating rules for handling emails. However, I don't know what email addresses I can possibly receive from. I also cannot feasibly create a rule for every email address a service has. For example, one web service alone may have a customer service email, a bug report email, a no reply email, and many others. This just won't work. </div>
<br />
<div style="text-align: left;">
Another option is to create a new email account for every web service I use. I could have one email account each for Twitter, Stack Overflow, GitHub, etc. Creating an entirely separate email account is overkill though. </div>
<br />
<div style="text-align: left;">
<strong>The Solution</strong></div>
<br />
<div style="text-align: left;">
Fortunately, there is a way. Many email providers allow for arbitrary tags to be added to an email address. For example, with Gmail, I can create an email account with the address <a href="mailto:my.email@gmail.com">my.email@gmail.com</a>. Then, I can use <a href="mailto:my.email+twitter@gmail.com">my.email+twitter@gmail.com</a>, <a href="mailto:my.email+stackoverflow@gmail.com">my.email+stackoverflow@gmail.com</a>, and <a href="mailto:my.email+github@gmail.com">my.email+github@gmail.com</a>. All these email addresses will go to the same account. Most email providers have similar systems. </div>
<br />
<div style="text-align: left;">
<strong>How it Works</strong></div>
<br />
<div style="text-align: left;">
You can think of the tags on an email address like a subdomain of a URL. The base email guarantees uniqueness and the tag allows for routing. These email addresses are known as <a href="http://en.wikipedia.org/wiki/Disposable_email_address">disposable email addresses</a>. I like to call them unique email channels. By giving every service a different email address, I can control the communication channel. If that email address is ever compromised by a spammer or I get tired of the emails, I just need to sever the channel. </div>
<br />
<div style="text-align: left;">
Since all the unique email channels are delivered to the same email account, they are not immediately useful. We need to bring in the rule system. Gmail allows for rules to be based on the To: field. For example, I can have a rule that says, when I get an email sent to <a href="mailto:my.email+twitter@gmail.com">my.email+twitter@gmail.com</a>, mark it as read, label it as Twitter, and archive it. I can have all sorts of complex rules that are specific to my needs for each service. I can even have Gmail forward an email to another email account.</div>
<br />
<div style="text-align: left;">
Personally, I have one email account that just handles mail sorting. It takes in email from all my services, marks them as read, labels them appropriately, and archives them. If I get an email from a service I am interested in, I forward it on to my real email account. This allows me to build up an archive of newsletters and notifications, but I never see them if I don't want to. When I get tired of seeing a notification, I don't cancel it. Instead, I just change the rule. The rule system keeps the interface to all my notifications consistent. This way I don't need to dig through some website trying to figure out how to cancel my subscription. </div>
<br />
<div style="text-align: left;">
<strong>Potential Problems</strong></div>
<br />
<div style="text-align: left;">
What if some spammer gets smart and decides to remove the tag? This problem is easy to solve. Just create a rule that deletes all emails sent directly to <a href="mailto:my.email@gmail.com">my.email@gmail.com</a>. </div>
<br />
<div style="text-align: left;">
What if some spammer gets smart and tries to guess which tags I use? This is much harder to protect against, especially since +twitter or +github would be easy to guess. Using unique email channels has been around for years and is still not in widespread use. I don't foresee this becoming largely popular to the general user anytime soon. So, there is little chance that someone will attempt this. </div>
<br />
<div style="text-align: left;">
If that is not comforting enough, you can use tags that are not easily guessable. For example, you could use +apple20934 or +i.love.steve.jobs for your unique Apple email channel. This is admittedly security through obscurity, but it makes guessing channels even less likely. It's a similar security problem as passwords. Again, it is highly unlikely that spammers will be guessing email channels anytime soon. </div>
<br />
<div style="text-align: left;">
If you know what exactly email address(es) you will receive from, you can have rules that only filter if both the To: and From: fields match your expectations. This almost guarantees safety from spammers, but may not be feasible for all situations. This approach could be foiled by worms or email spoofing, but again it would be hard to guess your rules. The key to security is to make spamming you more effort than it's worth. Spammers have plenty of low hanging fruit to spend their time on. </div>
<br />
<div style="text-align: left;">
<strong>Advantages</strong></div>
<ol style="list-style-type: decimal;">
<li style="text-align: left;">Better spam protection than Gmail or any one service alone can provide.</li>
<li style="text-align: left;">Specific email handling rules for each service. </li>
<li style="text-align: left;">Don't need to tell your friends that you made a new email address if your email address is compromised by spammers. </li>
<li style="text-align: left;">Don't need to hunt down the subscription options to cancel email subscriptions. </li>
</ol>
<strong>Disadvantages</strong><br />
<ol style="list-style-type: decimal;">
<li style="text-align: left;">If you want to change the types of email notifications you receive from a service, you still need to go to the website. </li>
<li style="text-align: left;">It takes a little bit of time to set up a rule when creating a channel for a new service. </li>
<li style="text-align: left;">It takes a lot of time to change all your existing services to use your new, unique email channel. </li>
</ol>
<strong>Conclusion</strong><br />
<br />
<div style="text-align: left;">
Though it does take some time up front to set up, unique email channels are worth it for anyone who is paranoid about spammers or wants to automate how their email is handled. I expect to see similar patterns emerge in other communication systems as the event-driven web and personal cloud networks continue to develop. </div>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-59256488198802418532012-04-18T13:28:00.000-06:002012-04-18T18:53:26.743-06:00PaintCode App Review<div style="text-align: left;">
With the new iPad and its Retina Display, iOS apps are getting even larger due to the various sizes of assets. When a user downloads your app from the store, you want them to get it quickly. You especially don't want them to be forced to download from wifi if you can help it. Fortunately, a new app called PaintCode has been released just in time by PixelCut to help remedy this problem. </div>
<br />
<div style="text-align: left;">
<strong>Summary</strong></div>
<br />
<div style="text-align: left;">
PaintCode is a vector image editor. What makes it special is that PaintCode generates Core Graphics code for both Mac OS X and iOS. The idea is that we can draw many of our graphics rather than include a series of rasters in the app's main bundle. PaintCode also serves as a bridge between graphics artists and developers. The graphics artist can generate the assets using PaintCode, then the developer can take the generated code and tweak it as needed.</div>
<br />
<div style="text-align: left;">
<strong>Test Run</strong></div>
<br />
<div style="text-align: left;">
To really see if PaintCode could fill my needs, I stress tested it with a fairly complicated image: the Siri button. The Siri button touches nearly every feature of PaintCode, including arbitrary shapes, linear/radial gradients, and inside/outside shadows. </div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://github.com/rob-brown/Demos/raw/master/Siri%20Icon/Siri%20Button@2x.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://github.com/rob-brown/Demos/raw/master/Siri%20Icon/Siri%20Button@2x.png" /></a></div>
<br />
<div style="text-align: left;">
Within a few hours, I had all the intricate details worked out. I consider myself an amateur graphics artist, but PaintCode made the process very easy. Most of the controls are intuitive and easy to learn. The provided <a href="http://www.paintcodeapp.com/examples.html">examples and videos</a> also helped.</div>
<br />
<div style="text-align: left;">
I then put the code to the test. I simply dropped the code into a custom UIView. To make things more interesting, I applied some affine transformations. </div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://github.com/rob-brown/Demos/raw/master/Siri%20Icon/Siri%20Icon%20Screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://github.com/rob-brown/Demos/raw/master/Siri%20Icon/Siri%20Icon%20Screenshot.png" width="170" /></a></div>
<br />
<div style="text-align: left;">
I found that the transformations worked perfectly with everything except, inside shadows. The inside shadows will translate properly, but won't rotate or scale properly. I am not entirely sure why they don't work. I expect this bug will be fixed in a future release. </div>
<br />
<div style="text-align: left;">
<strong>Pros</strong></div>
<br />
<div style="text-align: left;">
Again, PaintCode made generating vector assets very easy. I tried out the trial of a competing app, Opacity, but I found PaintCode to be much more intuitive. I also appreciate the great attention to aesthetic detail, yet minimalistic style. </div>
<br />
<div style="text-align: left;">
Everything in PaintCode is drawn using Core Graphics. So, whatever you see on the canvas is exactly what will appear in your own app. </div>
<br />
<div style="text-align: left;">
The generated code may not be perfect, but it's pretty good. The advantage of PaintCode is it does the hard, tedious work. Once the image is finished, a developer can easily tweak details as needed to make the drawing more dynamic. </div>
<br />
<div style="text-align: left;">
<strong>Cons</strong></div>
<br />
<div style="text-align: left;">
Though PaintCode generates some good Core Graphics code, it is not truly resolution independent. You will notice this particularly with the radial gradient on the button. I wanted to alternate colors about once every pixel or two. PaintCode only allowed 21 discrete steps for a gradient. Furthermore, since the number of steps is fixed, changing the scale changes the appearance. Fortunately, this can be remedied by tweaking the generated code. A simple for loop can dynamically change the number of steps as the scale changes. </div>
<br />
<div style="text-align: left;">
As any graphics artist knows, vector images are not a silver bullet. There are some relationships that are not 1:1 linear transformations. For example, one object may scale twice as fast as another. The scale could even be x<span style="vertical-align: super;">2</span>. This scaling problem can be fixed in code though. Also, when the size changes, details often need to be added or removed. The code could be modified to do this automatically as the scale changes, but this is probably outside the scope of PaintCode and may be more trouble than it is worth. </div>
<br />
<div style="text-align: left;">
<strong>My Wishlist</strong></div>
<br />
<div style="text-align: left;">
If there is anything I could have added to this app, it would be import SVG. Every graphics artist has his or her favorite vector editor. It would be amazing if PaintCode could import an SVG file (or AI file) and convert it to Core Graphics code. I have no doubt such a feature would be a large undertaking, but if PaintCode could do this, it would be worth so much more than $80. </div>
<br />
<div style="text-align: left;">
<strong>Recommendation</strong></div>
<br />
<div style="text-align: left;">
If you have an app that is getting large, you should really look into getting PaintCode and converting some of your assets to Core Graphics. Or if you are trying to draw something in Core Graphics and find debugging too hard, PaintCode will make save you many hours. </div>
<br />
<div style="text-align: left;">
<strong>Code</strong></div>
<br />
<div style="text-align: left;">
If you want a copy of my PaintCode file or Xcode project, you can find them on my <a href="https://github.com/rob-brown/Demos/tree/master/Siri%20Icon">GitHub account</a>. </div>
<br />
<div style="text-align: left;">
<strong>Disclaimer</strong></div>
<br />
<div style="text-align: left;">
I received a copy of PaintCode free for the purposes of reviewing. However, I do not receive any compensation if you purchase PaintCode. </div>
<br />Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-46131812203810465382012-03-06T19:37:00.000-07:002012-03-06T21:49:26.943-07:00Hidden iOS Simulator Hotkeys<div style="text-align: left;">
Apple's iOS Simulator app is a helpful tool in building iOS apps. However, there is more than what appears on the surface. Recently a hack has been discovered to allow <a href="http://modmyi.com/content/7073-new-hack-allows-retina-testing-ipad-apps-ios-simulator.html">iPad Retina Display testing.</a> I have also found a couple hidden features. As far as I know, these hidden hotkeys only work on the iOS 5 simulator.</div>
<br />
<div style="text-align: left;">
The first, and least interesting, is the "Toggle Slow Animations" feature. This feature slows down animations making it easier to see the fine details. I've found this useful when "debugging" animations. This feature is normally toggled through the drop-down menu: Debug > Toggle Slow Animations. However, it can also be toggled by double tapping Cmd+Shift. If you ever have slow animations mysteriously turn on, then you may have accidentally activated this hotkey.</div>
<br />
<div style="text-align: left;">
The second hotkey is more peculiar. I often use the hotkey Cmd+Shift+4+Space to take screenshots of the simulator. I noticed that sometimes a popup would show up that displays the keyboard localization languages I have turned on. It took a while, but I can almost consistently reproduce it. I first disabled the screenshot hotkeys: (Apple) > System Preferences > Keyboard > Keyboard Shortcuts > Screen Shots > Uncheck all hotkeys. Then I opened the iOS simulator and used the hotkey Cmd+Shift+4+Space. Sometimes it takes a few tries. Other times I need to open/close an app and try again. Again, this hotkey only appears to work on the iOS 5 Simulator. You may also need to have more than one keyboard language activated.<br />
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL5JDUolwz8OPrDI1Aq6KaoPxw0QLJQbXWhbR-Fek3cCd8HRZmpKidn6E8mafjwHzX0cI3irF0sats3JCjg52P5vlDFCA4diBM9VsO6M57fm_bgNnrxWXy2CfTXqApJvbBxQvVjcsX9Fw/s1600/iPhone+Keyboard+Language.png" imageanchor="1"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL5JDUolwz8OPrDI1Aq6KaoPxw0QLJQbXWhbR-Fek3cCd8HRZmpKidn6E8mafjwHzX0cI3irF0sats3JCjg52P5vlDFCA4diBM9VsO6M57fm_bgNnrxWXy2CfTXqApJvbBxQvVjcsX9Fw/s320/iPhone+Keyboard+Language.png" width="166" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div style="text-align: left;">
When the keyboard language popup shows up, you can click on of the languages to change your keyboard language. The effect is not immediately apparent unless you have the keyboard visible while changing languages.</div>
<br />
<div style="text-align: left;">
I'm not entirely sure why this hidden feature exists in the simulator. If the multiple keyboards are setup, they can be easily changed using the language key on the keyboard. What is more interesting is Apple likely has many other hidden features. </div>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-20432013703398219802012-01-13T15:40:00.000-07:002012-01-13T17:57:20.957-07:00UIStoryboard Best Practices<div style="text-align: left;">
UIStoryboard is a hot topic right now in iOS. However, there have been many misconceptions on the topic. The first reaction to storyboards (what I have seen anyway) is that they are a panacea for all situations. Following that reaction I saw many people claim that storyboards are awful and broken. The truth is, both these ideas are wrong. During WWDC 2011 Apple may have over-promoted storyboards, thus giving the wrong impression and leading to unmet expectations. Let me correct this now: UIStoryboard is not an all-purpose solution, it is another tool for your toolbox.</div>
<br />
<div style="text-align: left;">
My intent here is to provide the best practices for UIStoryboard. I will list my lessons learned, but there are probably more yet to learn. I expect over time that this list will expand to include other best practices for UIStoryboard.</div>
<br />
<div style="text-align: left;">
<strong>Break your storyboard into modules</strong></div>
<br />
<div style="text-align: left;">
The first mistake developers have been making with storyboarding is producing large, monolithic storyboards. A single storyboard may be suitable for small apps but certainly not for large apps. Don't forget one of the key principles of programming and abstraction: <em>decomposition</em>. We decompose our code into modules to make them more reusable and reduce maintenance costs. The same is true for user interfaces, and it applies whether you are using UIStoryboards, XIBs, or anything else. There is an even deeper principle wanting to emerge: when code and user interfaces are decomposed <em>together</em>, then you have truly useful and reusable code, user interfaces, and products (you can quote me on this). </div>
<br />
<div style="text-align: left;">
The first question to ask is "how do I identify the natural modules of my app?" Let's start with something easy. Many apps are based on a tab bar controller. Each tab is a natural module and you hence you can put them in their own storyboard. Next, if you have two tabs (or any two views for that matter) with a segue to a common view, then that common view (and its following hierarchy) is almost certainly another natural module. Once you have pruned your view hierarchy, you will probably find that each module can be given a name. For example, you may have your login storyboard, settings storyboard, about storyboard, main storyboard, etc. If you can give a fitting name to each module, then you have decomposed your hierarchy well. </div>
<br />
<div style="text-align: left;">
Keep in mind that having a single view in a storyboard is not a bad thing. This is particularly true with table views. The power of static and prototype table view cells is very useful. </div>
<br />
<div style="text-align: left;">
You should also note that breaking storyboards into modules makes them more friendly to version control and sharing among a team. </div>
<br />
<div style="text-align: left;">
<strong>You don't need to convert everything at once</strong></div>
<br />
<div style="text-align: left;">
When you first saw storyboards, you may have had an urge to convert everything over to UIStoryboard. I know I did. Be aware that this does take time and you may not gain any immediate benefits from switching everything. Fortunately, you don't need to do it all at once. You can switch over the parts of your app that will benefit the most now. Then over time you can slowly switch out others. </div>
<br />
<div style="text-align: left;">
<strong>Make custom UITableViewCell subclasses for prototype cells</strong></div>
<br />
<div style="text-align: left;">
Probably the best feature of UIStoryboard is prototype cells. They make custom table view cells easy. Prototype cells can be easily customized; however, the UITableViewCell class may not specify the IBOutlets you need. A custom subclass also gives you another advantage. You can create a -setupWith<#Object#>: method. This takes your setup code out of your table view controller and into the cell itself. This is where you can gain some great reuse. </div>
<br />
<div style="text-align: left;">
Not only can you create custom UITableViewCell subclasses, but you can have one subclass service many prototype cells. For example, you may have a cell that takes a Person object. In one table view your cell may have main label on the left and a detail label on the right. A different table view may use the same cell but have a main label above and a detail label below. Your cell subclass handles the content, but the prototype cell handles the look and feel. Again we gain great reuse and flexibility by decomposing code and views together.</div>
<br />
<div style="text-align: left;">
<strong>Don't forget about IBAction, IBOutlet, and IBOutletCollection</strong></div>
<br />
<div style="text-align: left;">
Segues are nice and can do a lot, but don't forget about the other IB fundamentals. Segues can't cross storyboards, but IBActions can. IBActions can also clean up an unnecessary spaghetti segue mess and reduce the need for custom segues. Everything has their place and their use; they are all tools at your disposal. </div>
<br />
<div style="text-align: left;">
While on the topic of IBActions and family, I should cover encapsulation. Most, if not all, your actions and outlets do not need to be public. So, rather than put them in your public headers, put them in a class extension. See <a href="http://robsprogramknowledge.blogspot.com/2011/08/objective-c-property.html">here</a> for more details. Xcode/Interface Builder didn't handle this well in the past but now there are no problems. This keeps your interfaces much cleaner and easier for others to understand. </div>
<br />
<div style="text-align: left;">
<strong>Don't forget about XIBs</strong></div>
<br />
<div style="text-align: left;">
Even though storyboards are very similar to XIBs, they still have a place. Simple, one-view modules may be better represented as XIBs. Also, XIBs can hold custom views without an associated view controller. UIStoryboard requires that view controllers be the basic unit. </div>
<br />
<div style="text-align: left;">
<strong>You don't need to have a main storyboard</strong></div>
<br />
<div style="text-align: left;">
You may have noticed your app settings now has a "Main Storyboard" setting. To use UIStoryboard you are not required to use this. In fact, my latest project has neither a main storyboard nor a main XIB. It uses a programmatic UITabBarController. From there I load all my tab storyboards. The beauty of it all is that it doesn't matter whether I use UIStoryboards, XIBs, or code. All three options are flexible enough to work with each other in any combination.</div>
<br />
<div style="text-align: left;">
<strong>Specify the name of your app delegate in main.m</strong></div>
<br />
<div style="text-align: left;">
As I mentioned <a href="http://robsprogramknowledge.blogspot.com/2011/12/migrating-to-uistoryboard.html">the other day</a>, you may need to change your main.m file if it doesn't specify your app delegate's name. It should look something like this:</div>
<br />
<div style="text-align: left;">
<span style="color: #2b839f; font-size: 11pt;">UIApplicationMain</span><span style="font-size: 11pt;">(argc, argv, </span><span style="color: blue; font-size: 11pt;">nil</span><span style="font-size: 11pt;">, </span><span style="color: #2b839f; font-size: 11pt;">NSStringFromClass</span><span style="font-size: 11pt;">([</span><span style="color: #2b839f; font-size: 11pt;">MyAppDelegate</span> <span style="font-size: 11pt;"></span><span style="color: #2b839f; font-size: 11pt;">class</span><span style="font-size: 11pt;">]))</span></div>
<br />
<div style="text-align: left;">
<strong>Put your storyboards in a category</strong></div>
<br />
<div style="text-align: left;">
To get one of your storyboards, you need to call +storyboardWithName:bundle:. Be wary any time you need to hard code a string for a key, especially one that can change frequently. Should you ever need to rename your storyboard, you will have to change all references to that storyboard. My favorite way to handle this is with a category. It looks something like this:</div>
<br />
<div style="text-align: left;">
<span style="color: blue; font-size: 11pt;">@implementation</span> <span style="font-size: 11pt;">UIStoryboard (MyApp)</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;">+ (</span><span style="color: #2b839f; font-size: 11pt;">UIStoryboard</span> <span style="font-size: 11pt;">*)mainStoryboard {</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: blue; font-size: 11pt;"> return</span> <span style="font-size: 11pt;">[</span><span style="color: #2b839f; font-size: 11pt;">UIStoryboard</span> <span style="font-size: 11pt;"></span><span style="color: #2b839f; font-size: 11pt;">storyboardWithName</span><span style="font-size: 11pt;">:</span><span style="color: #a31515; font-size: 11pt;">@"MainStoryboard" </span><span style="color: #2b839f; font-size: 11pt;">bundle</span><span style="font-size: 11pt;">:</span><span style="color: blue; font-size: 11pt;">nil</span><span style="font-size: 11pt;">];</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;">}</span></div>
<br />
<div style="text-align: left;">
<span style="color: blue; font-size: 11pt;">@end</span></div>
<br />
<div style="text-align: left;">
The benefit of the category approach is that if you ever rename a storyboard, you only need to change the hard coded string in one place. It also makes your code more readable.</div>
<br />
<div style="text-align: left;">
<strong>Summary</strong></div>
<br />
<div style="text-align: left;">
If you take anything from this post you should remember these:</div>
<ol style="list-style-type: decimal;">
<li style="text-align: left;">Decompose your code and your views.</li>
<li style="text-align: left;">UIStoryboard is a great tool, but it's not the only tool.</li>
</ol>
I hope these tips and best practices help promote proper use of UIStoryboard. I invite all my readers to let me know of other best practices they encounter. <br />
<br />Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-65776772304849243162011-12-15T19:21:00.000-07:002012-05-07T22:31:52.753-06:00Migrating to UIStoryboard<div style="text-align: left;">
I’ve just recently started using UIStoryboard and so far I’ve been very pleased with it. Building the UI is faster, easier, and requires less code. It’s also immensely helpful to get a bird’s eye view of your full workflow. However, when migrating an old app from using regular XIBs to UIStoryboard I did encounter some troubles. When launching the app, I would get the following error messages:</div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;"><strong>“The app delegate must implement the window property if it wants to use a main storyboard file.”</strong></span></div>
<div style="text-align: left;">
and</div>
<div style="text-align: left;">
<span style="font-size: 11pt;"><strong>“Applications are expected to have a root view controller at the end of application launch.”</strong></span> </div>
<br />
<div style="text-align: left;">
I could clearly see that my app delegate was implementing the window property as expected. Fortunately, <a href="http://stackoverflow.com/a/7730798/371357">StackOverflow</a> came to the rescue. It turns out that main.m needs to be modified when switching to UIStoryboard from XIBs (in older projects). The change looks like this:</div>
<br />
<div style="text-align: left;">
<span style="color: #007400; font-size: 11pt;">// Old main.m</span></div>
<div style="text-align: left;">
<span style="color: #2e0d6e; font-size: 11pt;">UIApplicationMain</span><span style="font-size: 11pt;">(argc, argv, </span><span style="color: #aa0d91; font-size: 11pt;">nil</span><span style="font-size: 11pt;">, </span><span style="color: #aa0d91; font-size: 11pt;">nil</span><span style="font-size: 11pt;">);</span></div>
<br />
<div style="text-align: left;">
<span style="color: #007400; font-size: 11pt;">// New main.m</span></div>
<div style="text-align: left;">
<span style="color: #2e0d6e; font-size: 11pt;">UIApplicationMain</span><span style="font-size: 11pt;">(argc, argv, </span><span style="color: #aa0d91; font-size: 11pt;">nil</span><span style="font-size: 11pt;">, </span><span style="color: #2e0d6e; font-size: 11pt;">NSStringFromClass</span><span style="font-size: 11pt;">([</span><span style="color: #3f6e74; font-size: 11pt;">MyAppDelegate</span> <span style="font-size: 11pt;"></span><span style="color: #2e0d6e; font-size: 11pt;">class</span><span style="font-size: 11pt;">]));</span></div>
<br />
<div style="text-align: left;">
The documentation for this parameter reads:</div>
<br />
<span style="font-size: 13pt;">The name of the class from which the application delegate is instantiated. If principalClassName designates a subclass of </span><span style="color: #535353; font-size: 13pt;">UIApplication</span><span style="font-size: 13pt;">, you may designate the subclass as the delegate; the subclass instance receives the application-delegate messages. Specify </span><span style="color: #535353; font-size: 13pt;">nil</span> <span style="font-size: 13pt;">if you load the delegate object from your application’s main nib file.</span><br />
<br />
<div style="text-align: left;">
Basically, if you aren’t using XIBs, you must let UIApplication know what your app delegate’s name is. You will also notice that any new projects created with the latest version of Xcode will specify the app delegate, even if you are using XIBs. This prevents any problems should you migrate to UIStoryboard later. </div>
<div style="text-align: left;">
<br /></div>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-58005774622955398602011-12-15T17:00:00.000-07:002011-12-15T17:28:19.313-07:00UIColor Category<div style="text-align: left;">
For a long time I’ve wanted more convenience methods for UIColor. The set Apple provides is a nice starting point but I often find myself wanting more. In particular, the Mac color picker has a crayon box color picker with common colors. Sadly, there are no convenience methods for these colors. Since I use them so frequently, I decided to put them all in a category. This was tedious work since I had to do them one-by-one by hand. </div>
<br />
After getting these 48 convenience methods I figured why stop there. I moved on to the HTML colors. At the time I didn’t realize how many standard HTML colors exist (147). After seeing that number I almost threw out the idea, but I remembered that <a href="https://twitter.com/#!/alesplin">@alesplin</a> taught how to use Vim macros in the November BYU CocoaHeads meeting. Using a list of HTML colors and their associated hex values, I had all 147 HTML color convenience methods finished within minutes. Vim may be an old, crusty text editor, but its macro editing power is unmatched by modern IDEs.<br />
<br />
If you want a copy of my UIColor category, you can find it in my <a href="https://github.com/rob-brown/RBCategories/blob/master/UIColor+RBExtras.m">RBCategories repo</a> on Github.Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-83532282650322378442011-11-30T19:18:00.000-07:002011-11-30T20:58:00.291-07:00Read/Write Lockless Exclusion<div style="text-align: left;">
With the recent release of iOS 5, GCD now has a simple and elegant solution to the <a href="http://en.wikipedia.org/wiki/Readers-writers_problem">reader writer problem</a> that utilizes lockless exclusion. In summary, this involves using dispatch_async (or dispatch_sync) to enqueue "reader" blocks onto a user concurrent queue. These blocks may be used to read some kind of data but not write to it. If we need write access, then we can use the new dispatch_barrier_async (or dispatch_barrier_sync) function. This will put a special barrier block on the queue. The blocks are still dequeued in FIFO order. However, when there are one or more reader blocks running, then a writer block may not be dequeued. While a single writer block is running, no other blocks may be dequeued, including other writer blocks. This guarantees that writer blocks have exclusive access and reader blocks may share access.</div>
<br />
<div style="text-align: left;">
The new barrier blocks and user concurrent queues are immensely valuable. Lately, I've been considering how they relate to my recently developed Lockless Exclusion Accessor (LEA) design pattern. If you are not already familiar with my LEA pattern, you should first read <a href="http://robsprogramknowledge.blogspot.com/2011/09/lockless-exclusion-accessor-pattern.html">my LEA article</a>. The intent of a LEA is to make mutual exclusion easy and efficient. Since we want to be efficient, let's push efficiency further by allowing shared read access. Here is some generic code that does just that: </div>
<br />
<div style="text-align: left;">
<span style="color: green; font-size: 11pt;">/// Block type to use when accessing the shared memory.</span></div>
<div style="text-align: left;">
<span style="color: green; font-size: 11pt;">/// The type is 'id' just to be generic. With a real</span></div>
<div style="text-align: left;">
<span style="color: green; font-size: 11pt;">/// LEA, you should use the exact type.</span></div>
<div style="text-align: left;">
<span style="color: blue; font-size: 11pt;">typedef</span> <span style="font-size: 11pt;"></span><span style="color: blue; font-size: 11pt;">void</span><span style="font-size: 11pt;">(^LEABlock)(</span><span style="color: #2b839f; font-size: 11pt;">id</span> <span style="font-size: 11pt;">sharedMemory);</span></div>
<br />
<div style="text-align: left;">
<span style="color: green; font-size: 11pt;">/// Class extension for holding the private, shared memory</span></div>
<div style="text-align: left;">
<span style="color: green; font-size: 11pt;">/// and its associated queue.</span></div>
<div style="text-align: left;">
<span style="color: blue; font-size: 11pt;">@interface</span> <span style="font-size: 11pt;"></span><span style="color: #2b839f; font-size: 11pt;">MyObject</span> <span style="font-size: 11pt;">()</span></div>
<br />
<div style="text-align: left;">
<span style="color: blue; font-size: 11pt;">@property</span> <span style="font-size: 11pt;">(</span><span style="color: blue; font-size: 11pt;">nonatomic</span><span style="font-size: 11pt;">, </span><span style="color: blue; font-size: 11pt;">strong</span><span style="font-size: 11pt;">) </span><span style="color: #2b839f; font-size: 11pt;">id</span> <span style="font-size: 11pt;">sharedMemory;</span></div>
<div style="text-align: left;">
<span style="color: blue; font-size: 11pt;">@property</span> <span style="font-size: 11pt;">(</span><span style="color: blue; font-size: 11pt;">nonatomic</span><span style="font-size: 11pt;">, </span><span style="color: blue; font-size: 11pt;">assign</span><span style="font-size: 11pt;">) </span><span style="color: #2b839f; font-size: 11pt;">dispatch_queue_t</span> <span style="font-size: 11pt;">leaQueue;</span></div>
<br />
<div style="text-align: left;">
<span style="color: blue; font-size: 11pt;">@end</span></div>
<br />
<div style="text-align: left;">
<span style="color: blue; font-size: 11pt;">@implementation</span> <span style="font-size: 11pt;">MyObject</span></div>
<br />
<div style="text-align: left;">
<span style="color: blue; font-size: 11pt;">@synthesize</span> <span style="font-size: 11pt;">sharedMemory = </span><span style="color: #2b839f; font-size: 11pt;">_sharedMemory</span><span style="font-size: 11pt;">;</span></div>
<div style="text-align: left;">
<span style="color: blue; font-size: 11pt;">@synthesize</span> <span style="font-size: 11pt;">leaQueue = </span><span style="color: #2b839f; font-size: 11pt;">_leaQueue</span><span style="font-size: 11pt;">;</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;">- (</span><span style="color: blue; font-size: 11pt;">id</span><span style="font-size: 11pt;">)init {</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: blue; font-size: 11pt;"> if</span> <span style="font-size: 11pt;">((</span><span style="color: blue; font-size: 11pt;">self</span> <span style="font-size: 11pt;">= [</span><span style="color: blue; font-size: 11pt;">super</span> <span style="font-size: 11pt;"></span><span style="color: #2b839f; font-size: 11pt;">init</span><span style="font-size: 11pt;">])) {</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: green; font-size: 11pt;"> // The queue MUST be concurrent to gain shared readership.</span></div>
<div style="text-align: left;">
<span style="color: #2b839f; font-size: 11pt;"> dispatch_queue_t</span> <span style="font-size: 11pt;">queue = </span><span style="color: blue; font-size: 11pt;">NULL</span><span style="font-size: 11pt;">;</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"> queue = </span><span style="color: #2b839f; font-size: 11pt;">dispatch_queue_create</span><span style="font-size: 11pt;">(</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"> </span><span style="color: #a31515; font-size: 11pt;">"com.RobBrown.LEAQueue"</span><span style="font-size: 11pt;">,</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"> </span><span style="color: blue; font-size: 11pt;">DISPATCH_QUEUE_CONCURRENT</span><span style="font-size: 11pt;">);</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"> [</span><span style="color: blue; font-size: 11pt;">self</span> <span style="font-size: 11pt;"></span><span style="color: #2b839f; font-size: 11pt;">setLeaQueue</span><span style="font-size: 11pt;">:queue];</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: green; font-size: 11pt;"> // Initialize shared memory here.</span></div>
<span class="Apple-style-span" style="font-size: 15px;">}</span><br />
<span style="font-size: 11pt;"> </span><span style="color: blue; font-size: 11pt;">return</span> <span style="font-size: 11pt;"></span><span style="color: blue; font-size: 11pt;">self</span><span style="font-size: 11pt;">;</span><br />
<div style="text-align: left;">
<span style="font-size: 11pt;">}</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;">- (</span><span style="color: blue; font-size: 11pt;">void</span><span style="font-size: 11pt;">)accessSharedMemoryReadWriteAsync:(</span><span style="color: #2b839f; font-size: 11pt;">LEABlock</span><span style="font-size: 11pt;">)block {</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: green; font-size: 11pt;"> // Block must not be nil.</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: blue; font-size: 11pt;"> NSParameterAssert</span><span style="font-size: 11pt;">(block);</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: green; font-size: 11pt;"> // Executes the block asynchronously with exclusive access.</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: #2b839f; font-size: 11pt;"> dispatch_barrier_async</span><span style="font-size: 11pt;">([</span><span style="color: blue; font-size: 11pt;">self</span> <span style="font-size: 11pt;"></span><span style="color: #2b839f; font-size: 11pt;">leaQueue</span><span style="font-size: 11pt;">], ^{</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"> block([</span><span style="color: blue; font-size: 11pt;">self</span> <span style="font-size: 11pt;"></span><span style="color: #2b839f; font-size: 11pt;">sharedMemory</span><span style="font-size: 11pt;">]);</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"> });</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;">}</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;">- (</span><span style="color: blue; font-size: 11pt;">void</span><span style="font-size: 11pt;">)accessSharedMemoryReadOnlyAsync:(</span><span style="color: #2b839f; font-size: 11pt;">LEABlock</span><span style="font-size: 11pt;">)block {</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: green; font-size: 11pt;"> // Block must not be nil.</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: blue; font-size: 11pt;"> NSParameterAssert</span><span style="font-size: 11pt;">(block);</span></div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: green; font-size: 11pt;"> // Executes the block asynchronously with shared access.</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: #2b839f; font-size: 11pt;"> dispatch_async</span><span style="font-size: 11pt;">([</span><span style="color: blue; font-size: 11pt;">self</span> <span style="font-size: 11pt;"></span><span style="color: #2b839f; font-size: 11pt;">leaQueue</span><span style="font-size: 11pt;">], ^{</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"> block([</span><span style="color: blue; font-size: 11pt;">self</span> <span style="font-size: 11pt;"></span><span style="color: #2b839f; font-size: 11pt;">sharedMemory</span><span style="font-size: 11pt;">]);</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"> });</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;">}</span></div>
<br />
<div style="text-align: left;">
<span style="color: blue; font-size: 11pt;">@end</span></div>
<br />
<div style="text-align: left;">
The first thing to note is that the dispatch queue is now concurrent instead of serial. If you use a serial queue then you will have no added benefits. The next thing to note is that every previous LEA in your object splits in two: a readonly version and a read write version. It's only four extra lines for a potentially great increase in efficiency. </div>
<br />
<div style="text-align: left;">
As always, you should favor dispatch_async over dispatch_sync. If you must have synchronous access, then you can add synchronous variants too. You must, however, never use my <a href="http://robsprogramknowledge.blogspot.com/2011/11/dispatchsyncsafe-deprecated.html">dispatch_sync_checked function</a>. It is not and never will be compatible with barrier blocks. </div>
<br />
<div style="text-align: left;">
By introducing the readonly LEA, we now introduce a potential point of failure. What if we write some code that uses a readonly LEA, then we later change the code to modify the shared memory without switching to a read write LEA? This could introduce race conditions. If needed, you can add a sanity check to your readonly LEA. Here are a few options:</div>
<ol style="list-style-type: decimal;">
<li style="text-align: left;">If the object you are passing back has mutable and immutable variants, create two block types. The read write LEA will use the mutable variant and the readonly LEA will use the immutable variant. This is the best solution. </li>
<li style="text-align: left;">If you don't have mutable and immutable variants, then you can simply pass a copy of the shared memory to the readonly block. This can potentially mask errors since you won't know if you accidentally use a readonly LEA when you meant to use a read write LEA. </li>
<li style="text-align: left;">Before calling the block, you copy the shared memory. Then after calling the block, you check that the shared memory was not changed by comparing it to the earlier copy. If it was changed, then throw an exception. Although Objective-C rarely throws exceptions, this is an appropriate place to do so. Overall, this solution can be tedious work. You should also use a pre-processor macro to remove this check from release builds for efficiency. </li>
<li style="text-align: left;">You can create a subclass of NSProxy. Instead of passing back the shared memory you can pass it the proxy. This proxy should throw an exception if any setters are called. This too can be tedious work. You may want to use a pre-processor macro here as well to remove the proxy in release builds. </li>
</ol>
Don't forget that user concurrent queues and barrier blocks are iOS 5 (and Mac OS X Lion) only. If you are using iOS 5 and you need mutual exclusion, I highly recommend using Read/Write LEAs (or at least regular LEAs). They make mutual exclusion fast and easy. <br />
<br />Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-46699761528803514912011-11-28T18:33:00.000-07:002011-11-28T19:27:24.959-07:00dispatch_sync_safe Deprecated<div style="text-align: left;">
A while back I wrote a <a href="https://github.com/rob-brown/RBCategories/blob/master/GCD+RBExtras.c">pseudo-category for GCD</a> and posted it to Github. It contains several convenience functions. One of them was a method that makes synchronous calls “safe,” or so I thought. The code looked like this:</div>
<br />
<div style="text-align: left;">
<span style="color: #aa0d91; font-size: 11pt;">void</span> <span style="font-size: 11pt;">dispatch_sync_safe(</span><span style="color: #5c2699; font-size: 11pt;">dispatch_queue_t</span> <span style="font-size: 11pt;">queue, </span><span style="color: #5c2699; font-size: 11pt;">dispatch_block_t</span> <span style="font-size: 11pt;">block) {</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: #007400; font-size: 11pt;"> // If we're already on the given queue, just run the block.</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: #aa0d91; font-size: 11pt;"> if</span> <span style="font-size: 11pt;">(</span><span style="color: #2e0d6e; font-size: 11pt;">dispatch_get_current_queue</span><span style="font-size: 11pt;">() == queue)</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"> block();</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: #007400; font-size: 11pt;"> // Otherwise, dispatch to the given queue.</span></div>
<span class="Apple-style-span" style="color: #aa0d91; font-size: 15px;">else</span><br />
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: #2e0d6e; font-size: 11pt;"> dispatch_sync</span><span style="font-size: 11pt;">(queue, block);</span></div>
<span class="Apple-style-span" style="font-size: 15px;">}</span><br />
<br />
<div style="text-align: left;">
The idea is that when doing a synchronous dispatch to a queue, I check if the program was already running on that queue. If it is, then the block is immediately executed. Otherwise, the block is run with a regular dispatch_sync. In my naïve implementation I thought this would prevent deadlock. The idea is nice but not correct. Consider the case when we dispatch_sync_safe to queue A. Next, we dispatch_sync_safe to queue B. Finally, we dispatch_sync_safe back to queue A. This is guaranteed deadlock. </div>
<br />
<div style="text-align: left;">
As a result of this case, I immediately marked dispatch_sync_safe as deprecated in my Github repo. Anyone using this function thinking it is perfectly safe should think again. I did, however, add another function called dispatch_sync_checked. It is actually the same implementation as dispatch_sync_safe just under a different name. I recognize that this simple function has great value, but the old name was misleading. The moral of the story is, use dispatch_async (or one of my dispatch_async convenience methods) whenever possible. If you must run code synchronously, use dispatch_sync_checked and be very cautious of deadlock. </div>
<br />
<div style="text-align: left;">
As I mentioned previously, dispatch_sync_checked still has great value. There is at least one case where you can guarantee you won’t deadlock. Consider the case when you have an object with a private serial dispatch queue. This queue is used to serialize access to some shared memory within the object. Using dispatch_sync_checked on the private queue allows you to keep your object’s methods synchronous and thread safe. This requires following two conditions in your critical code:</div>
<ol style="list-style-type: decimal;">
<li style="text-align: left;">Do not make synchronous calls to external objects (which could synchronously call the calling object again).</li>
<li style="text-align: left;">Do not call dispatch_sync on any queue (or dispatch_sync_checked on any queue except the private queue).</li>
</ol>
Also, since these methods check for running on the private queue, they can call each other without worrying about deadlock. This gives similar behavior to a recursive lock without the overhead. If @synchronized(self) { … } just isn’t fast enough, consider switching to dispatch_sync_checked(_queue, ^{ … }).Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-62223242032734340162011-10-17T12:24:00.000-06:002011-10-17T13:49:53.148-06:00My Philosophy on Language<div style="text-align: left;">
When I was called to serve a mission in Canada for The Church of Jesus Christ of Latter-day Saints, I was called to English-speaking assignment. During my mission, I spent six months in a French-speaking assignment since I had taken three years of French in high school. After serving in that assignment for quite some time, I found that my thoughts had become detached from all language. This skill was useful (and probably resulted) because I spent all day switching between French and English. When I thought of something, I would mentally envision the object or idea rather than thinking of the English or French equivalent. This way I could mentally transition between languages without any loss of context.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
I think language can limit our mental capacities. If we all view the world in the context of our native language, then we can only express ideas that already exist in that language. Language, however, is necessary so we can communicate our thoughts to others. Ironically, I must write this short article in a language, which makes it somewhat difficult to express such an abstract idea.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
So, how does this relate to computer science? Programming languages are just as much languages as the natural languages, such as English or French. The difference is that programming languages can express different ideas from natural languages. Like natural languages, not all programming languages can express the same ideas. This may limit what you as a developer can mentally design and express. For example, if your language doesn’t support blocks, then you probably don’t know what continuations are. One reason that I like Objective-C so much is that it allows me to express many ideas freely, especially when playing with the dynamic runtime.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
Likewise, if we only think in the context of our favorite programming language(s), then we can only develop ideas that already exist in that/those languages(s). By becoming detached from all languages (both natural and programmatic) we open ourselves to think of ideas that don’t exist yet. Once we create a new idea, we are then obligated to express that idea in a language or change our language to allow us to express that idea to other people. Again, the language we express our idea in can be natural or programmatic.</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
By the way, my ideas on language have a direct connection to <a href="http://dl.acm.org/citation.cfm?id=352194">The Five Orders of Ignorance by Philip Armour</a>. Briefly, Armour argues that in order to ask questions and find answers about some idea, we must first develop a framework for thinking about that idea. I think that language is indirectly, and often directly, related to developing mental frameworks for thinking.</div>Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-52932537562185651962011-10-06T07:57:00.000-06:002011-10-06T08:22:08.034-06:00A Tribute to Steve JobsThe world is mourning the loss of a great man. I just hope that his great vision has not been lost as well. Steve lived his dreams. He was never content and continually pushed the boundaries of technology. His quest for perfection led to unparalleled products and user experiences. Perhaps it is best said of him what was said back in 1997:<br /><br />Here’s to the crazy one. The misfit. The rebel. The trouble-maker. The Square peg in the round holes. The one who saw things differently. He wasn’t fond of rules, and he had no respect for the status quo. You can quote him, disagree with him, glorify, or vilify him. About the only thing you can’t do is ignore him. Because he changed things. He pushed the human race forward. And while some may see him as the crazy one, we see genius. Because he was crazy enough to think he could change the world, and he did! <br /><br />Thank you for everything Steve Jobs. Because of you I have a job I love. The technology you developed has made life better and the world more connected. Through your example, others have strived to push their limits, including me. Rest in peace Steve and may God watch over your family. Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-33212228350440845692011-09-17T21:46:00.000-06:002011-11-30T20:56:14.348-07:00Lockless Exclusion Accessor Pattern<div style="text-align: left;">
With all the work I have been doing with blocks and Grand Central Dispatch (GCD), I have developed a useful design pattern for handling mutual exclusion. I haven’t seen any patterns quite like this one, so I’ll claim it as my own. </div>
<br />
<div style="text-align: left;">
Mutual exclusion is always a challenge when multithreading any application. GCD makes mutual exclusion substantially easier by using queues instead of locks. Nevertheless, there are still some challenges. When creating shared data I often include a warning in my documentation that it must only be accessed within a certain serial GCD queue. However, other developers that use my code may not read my documentation. Even I forget occasionally that some particular data isn’t thread safe. So, how do we make this easier? This is a situation for what I call the Lockless Exclusion Accessor pattern. I’ll call it LEA for short. (I also thought of calling it a “letter” since it’s closely related to a getter, but that seemed too silly and generic.)</div>
<br />
<div style="text-align: left;">
Before going into the details of LEAs, we need to first understand why encapsulation is important. Most object-oriented languages have the ability to make variables private so they can only be directly accessed internal to the class. Limited access is given to the outside through getters and setters. This prevents classes on the outside making arbitrary changes to another classes internal data. To see how to encapsulate @propertys in Objective-C check out my <a href="http://robsprogramknowledge.blogspot.com/2011/08/objective-c-property.html">@property article</a>. We will apply the same principles to our shared data. </div>
<br />
<div style="text-align: left;">
First, move your shared data into a class extension so it will not be externally visible. Second, you will want to typdef your block type. This keeps your code cleaner and easier to read. For this example, I’m going to use an NSManagedObjectContext as my shared data. So, my block typedef looks like this:</div>
<br />
<div style="text-align: left;">
<span style="color: #aa0d91; font-size: 11pt;">typedef</span> <span style="font-size: 11pt;"></span><span style="color: #aa0d91; font-size: 11pt;">void</span><span style="font-size: 11pt;">(^RBMOCBlock)(NSManagedObjectContext * moc);</span></div>
<br />
<div style="text-align: left;">
Next, you need to create an accessor method. Outside classes will only be able to access your shared data through this method. It will look something like this:</div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;">- (</span><span style="color: #aa0d91; font-size: 11pt;">void</span><span style="font-size: 11pt;">)accessMOCAsync:(</span><span style="color: #3f6e74; font-size: 11pt;">RBMOCBlock</span><span style="font-size: 11pt;">)block {</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: #2e0d6e; font-size: 11pt;">dispatch_async</span><span style="font-size: 11pt;">(</span><span style="color: #643820; font-size: 11pt;">dispatch_get_main_queue</span><span style="font-size: 11pt;">(), ^{</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;">block([</span><span style="color: #aa0d91; font-size: 11pt;">self</span> <span style="font-size: 11pt;">managedObjectContext]);</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;">});</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;">}</span></div>
<br />
<div style="text-align: left;">
The dispatch_async takes the passed in block and runs it on the main queue. We could (and really should) modify this code to run on a private serial queue instead. We also pass the shared data to the block. This grants the block exclusive access to that data (as long as the dispatch queue is a serial queue). You’ll also notice that this is an asynchronous call. If needed, we can also make a synchronous LEA. It looks nearly identical:</div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;">- (</span><span style="color: #aa0d91; font-size: 11pt;">void</span><span style="font-size: 11pt;">)accessMOCSync:(</span><span style="color: #3f6e74; font-size: 11pt;">RBMOCBlock</span><span style="font-size: 11pt;">)block {</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: #2e0d6e; font-size: 11pt;">dispatch_sync</span><span style="font-size: 11pt;">(</span><span style="color: #643820; font-size: 11pt;">dispatch_get_main_queue</span><span style="font-size: 11pt;">(), ^{</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;">block([</span><span style="color: #aa0d91; font-size: 11pt;">self</span> <span style="font-size: 11pt;"></span><span style="color: #26474b; font-size: 11pt;">managedObjectContext</span><span style="font-size: 11pt;">]);</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;">});</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;">}</span></div>
<br />
<div style="text-align: left;">
Now that we’ve built our asynchronous and synchronous LEAs, let’s use one. </div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;">[</span><span style="color: #3f6e74; font-size: 11pt;">object</span> <span style="font-size: 11pt;"></span><span style="color: #26474b; font-size: 11pt;">accessMOCAsync</span><span style="font-size: 11pt;">:^(</span><span style="color: #5c2699; font-size: 11pt;">NSManagedObjectContext</span> <span style="font-size: 11pt;">* context) {</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: #007400; font-size: 11pt;">// Critical code goes here.</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;">}];</span></div>
<br />
<div style="text-align: left;">
That’s all there is to it. Just wrap your critical code in a block and you get exclusive, local access to the NSManagedObjectContext. LEAs are perfect for Core Data MOCs since they are not thread safe and are often the cause of much grief. </div>
<br />
<div style="text-align: left;">
LEAs are also quite flexible. For example, you can merge multiple LEAs into one like this:</div>
<br />
<div style="text-align: left;">
<span style="font-size: 11pt;">[</span><span style="color: #3f6e74; font-size: 11pt;">object</span> <span style="font-size: 11pt;"></span><span style="color: #26474b; font-size: 11pt;">accessMOCAsync</span><span style="font-size: 11pt;">:^(</span><span style="color: #5c2699; font-size: 11pt;">NSManagedObjectContext</span> <span style="font-size: 11pt;">* context, </span><span style="color: #5c2699; font-size: 11pt;">NSDictionary</span> <span style="font-size: 11pt;">* userInfo) {</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;"></span><span style="color: #007400; font-size: 11pt;">// Critical code goes here.</span></div>
<div style="text-align: left;">
<span style="font-size: 11pt;">}];</span></div>
<br />
<div style="text-align: left;">
The above LEA gives the block exclusive access to two shared variables at once. You can extend this as far as you want. This way to don’t need to write multiple LEAs per class and you don’t need to nest LEAs. However, this comes with a tradeoff. You gain convenience at the cost of more contention for shared data. </div>
<br />
<div style="text-align: left;">
Now, LEAs don’t perfectly protect shared data. It’s as good as Objective-C can get though. Rogue developers could pass the pointer to the MOC out of the block. They could also use the dynamic runtime to call the internal getters and setters. However, any developer doing either of these things is asking for a lot of trouble and should not be permitted to write Objective-C code. </div>
<br />
<div style="text-align: left;">
For more GCD and block design patterns, check out these sources. </div>
<br />
<div style="text-align: left;">
<a href="http://public.iwork.com/document/?a=p1060057446&d=GCD_Presentation_Sep2011.key">GCD Design Patterns Presentation</a></div>
<div style="text-align: left;">
<a href="http://www.mikeash.com/pyblog/friday-qa-2009-08-14-practical-blocks.html">Mike Ash</a></div>
<div style="text-align: left;">
<a href="http://cocoasamurai.blogspot.com/2011/02/practical-design-patterns-with-blocks.html">Cocoa Samurai</a></div>
<br />
<div style="text-align: left;">
<strong>UPDATE:</strong></div>
<br />
<div style="text-align: left;">
I've removed all references to SyncSafe due to <a href="http://robsprogramknowledge.blogspot.com/2011/11/dispatchsyncsafe-deprecated.html">problems</a> I've discovered. </div>
<br />Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-19367969557908159402011-08-23T15:58:00.000-06:002011-08-23T16:39:05.748-06:00iOS Recipes ReviewHere’s a book I couldn’t recommend more. <em><a href="http://pragprog.com/book/cdirec/ios-recipes">iOS Recipes</a></em> by Paul Warren and Matt Drance has done more to improve my code than any other book. <br /><br /><strong>Summary</strong><br /><br /><em>iOS Recipes</em> gives 40 code samples to improve common or useful iOS code. The recipes are grouped into five categories: UI, Table/Scroll Views, Graphics, Networking, and Runtime. The book is organized so you can read it in whatever order suits your needs. The wide range of recipes guarantees there is something that will benefit you. <br /><br /><strong>Pros</strong><br /><br /><em>iOS Recipes</em> includes many code samples that can be dropped into any project and will just work without any extra modification. Any project could benefit from using at least one of the included recipes. For example, the common table view cell production/customization process typically takes 20+ lines of code. I now write the same code in 3 lines of code and it is fully Interface Builder customizable. <br /><br />The greatest value of this book, however, is the explanation of how these recipes were designed. Warren and Drance explain exactly why they, for example, chose blocks over delegation or vice versa. By applying their same reasoning to other code, you can create your own quality recipes. This is further encouraged by not giving recipes that do everything. Some extensions are left as an exercise to the reader. <br /><br /><strong>Cons</strong><br /><br />There’s nothing I can say against this book. It really is a great book.<br /><br /><strong>Recommendation<br /><br /></strong>Every experienced iOS developer should own this book. By following the principles taught in <em>iOS Recipes</em>, your code will increase in quality. I also recommend this book to any daring, young developers who are interested in gaining a deeper understanding of the full power of Objective-C and designing quality code. Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-58642697559733452412011-08-02T21:53:00.000-06:002011-08-23T15:47:04.265-06:00Objective-C @property Best PracticesNow for my next rant on poor Objective-C code. Coming from other languages it's understandable that most developers don't take full advantage of the power of Objective-C 2.0. Here's a practice I hope that becomes more widespread. <br /><br /><strong>Use @property</strong><br /><br />One feature of Objective-C that is underutilized is @property. The Objective-C compiler can write so much code for us, we just have to let it. Note that some of what I'm going to cover only works on the 64-bit (modern) Objective-C runtime. However, you probably won't find any situation where you need to write code for the 32-bit (legacy) runtime. The only reason we wrote legacy runtime code was because that’s what the iOS simulator used to run on (prior to iOS 4.0). That was fixed over a year ago. <br /><br /><strong>Clean up your Headers</strong><br /><br />First, let's use @property to clean up our header files. The first thing to do is delete all of your ivars. Yes, delete all of them. They are no longer necessary. @synthesize will not only make your getters and setters, but it will also make your ivars. This was one of the major changes from the legacy to modern runtimes. This is nice because we don't need to be redundant about our instance variables anymore. Now, for all of your public ivars, make an equivalent @property. We'll handle the private and protected ivars in a moment. With just your public @propertys, your headers will now be much shorter and easier to read. Remember, headers are for public information. That is the whole idea behind encapsulation. You don't want your private information in your public headers. Even though I'm focusing on @propertys, you can apply the same ideas to methods too.<br /><br /><strong>Categories and Class Extensions</strong><br /><br />Before handling your private and protected ivars, you need to understand categories and class extensions. If you feel comfortable using class extensions, feel free to jump to the next section. <br /><br />A category is a way to extend the interface and functionality of an existing class. You declare them similarly to regular classes:<br /><br />// MyClassAdditions.h<br /><br />#import "MyClass.h"<br /><br />@interface MyClass (CategoryName)<br /><br />// Extra method declarations.<br /><br />@end<br /><br /><br />// MyClassAdditions.m<br /><br />#import "MyClassAdditions.h"<br /><br />@implementation MyClass (CategoryName)<br /><br />// Extra method implementations.<br /><br />@end<br /><br />Making a category is that simple. You just need to remember to #import your category when you want to use your extra methods. Class extensions, for all intents and purposes, are categories. The main differences are that only the original class can create a class extension for itself and you can declare @propertys in a class extension. So we will do just that. To create a class extension you simply create a category with no name. It will look something like this:<br /><br />// MyClass.m<br /><br />@interface MyClass ()<br /><br />@property (nonatomic, copy) NSString * myPrivateString;<br /><br />@end<br /><br />With your class extension in place, you just need an associated @synthesize myPrivateString; and you're done. It's that simple. You can do this with all of your private class variables with no problems.<br /><br /><strong>Protected Data</strong><br /><br />Now we are left with the protected variables. These are a little more tricky. Technically protected variables and methods don't exist with this technique. Then again “private” technically doesn't exist at all in Objective-C. The runtime won't stop you from calling private methods. Anyway, you should avoid protected data as often as possible. Sometimes that just isn't possible though. If you want a protected @property, just put it in your class extension like your private data. Then, any subclasses that need to access the protected property need to contain an identical @property in their class extensions. You will want to include some documentation about your protected @property. This does seem a little redundant to have identical @propertys, but it's bearable since Objective-C generates the important code for you. Again, this also works for methods. This is particularly nice because the @protected key word doesn't work on methods like it does ivars. One thing to note is that you can't call super in a protected method using this technique (you will get an annoying warning). If you need to make a super call, then your protected method should be placed in a private header instead. This private header should contain just the prototypes and is ONLY imported by classes that need that information. <br /><br /><strong>Readonly Getters</strong><br /><br />What about when you want to make a public getter but a private setter? Objective-C can do this for you too. In your public header you can do something like this:<br /><br />@property (nonatomic, copy, readonly) NSString * myPrivateString;<br /><br />Then in your class extension you make a similar declaration:<br /><br />@property (nonatomic, copy, readwrite) NSString * myPrivateString;<br /><br />You just need to make sure the two declarations mirror each other (i.e. nonatomic and nonatomic, retain and retain, copy and copy, etc.). From there you just use @synthesize and Objective-C takes care of the rest. <br /><br /><strong>Other @property Modifiers</strong><br /><br />While speaking of @property modifiers, I should take a moment to discuss them for anyone unfamiliar. You may skip to the next section if you already know the modifiers. By default an @property is atomic, assign (or weak), and readwrite. I've never found a good reason for atomic. Atomic just means that Objective-C is going to use a lock to enforce thread safety. This will make your getters and setters slower since it has to acquire and release the lock. If you are using single-threaded code this is completely unnecessary. If you are using multi-threaded code, you really should be using Grand Central Dispatch (or NSOperationQueue) to take advantage of lockless exclusion. <br /><br />The next modifier is copy/retain/assign. For almost everything you do, you will use retain. It's good to know the exceptions though. When you have an NSString, NSArray, NSSet, or other object with mutable/immutable variants, you should use copy instead. If the object is immutable, it will be retained for efficiency, otherwise it will be copied.<br /><br />Assign (or weak when using ARC) also has some uses. Mostly you will use it when dealing with primitives, such as BOOL or int. Since they aren't objects you can't call -copy or -retain on them. You will also use assign when you have want to avoid a retain cycle by creating a weak relationship. This is common with delegates. <br /><br />You can also specify the names of your getters and setters. You specify getter=myGetterName or setter=mySetterName. This is often used with BOOLs. For example, you may create a property like this:<br /><br />@property (nonatomic, assign, getter=isOn) BOOL on;<br /><br /><strong>Dealloc</strong><br /><br />When writing your -dealloc methods, you may wonder how you can release your instance data without direct access to your ivars. There is only one reasonable way to do this. You should call [self setMyProperty:nil];. This will set your ivar to nil and consequently release the old value. <br /><br /><strong>Exceptions</strong><br /><br />All rules have their exceptions including @property. If you need to make a custom getter or setter, you will need to create an associated ivar. Technically you can actually access synthesized ivars directly. However, Apple considers this to be a “bug” and access to synthesized ivars may disappear in the future. You can add ivars to class extensions for your private properties. Be aware, though, this is only supported on Clang/modern runtime and may require <a href="http://stackoverflow.com/questions/4048870/is-it-possible-to-define-ivars-in-objective-c-extension/4050816#4050816">additional settings</a>. <br /><br /><strong>Benefits</strong><br /><br />Now that we've gone over all that, let's go over the benefits of these extra techniques:<br /><br />1. The obvious benefit is the compiler will write your getters and setters for you. The compiler not only writes your getters and setters but also makes them Key-Value Observing (KVO) compliant. This means you can observe the changes of any property on an object. KVO is especially useful when writing Model View Controller (MVC) code. Controllers can watch model objects for any changes and update the views as appropriate.<br /><br />2. You will have less memory bugs. When writing your actual code, you should always use your getters and setters instead of accessing ivars directly. This will make most of your memory management bugs disappear instantly. You won't need to remember to call retain/copy and release with your ivars. Your synthesized getters and setters will do that automatically for you. <br /><br />3. Your code will be better encapsulated. I've seen too much code where I've had to guess which ivars (and methods) I could safely use due to a lack of organization and no documentation. <br /><br />4. Last, but not least, your code will be more readable. Your headers won't be cluttered with private and protected data, and your implementation files won't be cluttered with standard getters and setters. Furthermore, your files will be better organized. You will know exactly where to find your public, private, and protected data. <br /><br />Employ these techniques and they will serve you well. Other people who have to use your code after you with thank you too. <br /><br /><strong>Credits<br /><br /></strong>The ideas in this article were strongly influenced by the <a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html">Apple docs</a>, <a href="http://pragprog.com/book/cdirec/ios-recipes">iOS Recipes</a> Recipe 35, various <a href="http://developer.apple.com/videos/">WWDC videos</a>, and a lot of personal experience (i.e. bugs). <br /><br /><strong>----</strong><br /><strong>Update: </strong>August 23, 2011<br /><br />I have further refined and corrected this article through further study and experience on the topic, particularly ivars and custom accessors. <br />Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-63297075498950830012011-07-30T20:41:00.000-06:002011-09-17T23:19:11.487-06:00One singleton to rule them allOne of the most common design patterns is the <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton</a>. However, implementing singletons, especially in Objective-C, can be very repetitive. I often forget how to properly override all the memory management methods and need to look up a previous singleton. One of the goals of programming is to automate the repetetive, mundane tasks. Cocoa With Love has a great <a href="http://projectswithlove.com/projects/SynthesizeSingleton.h.zip">synthesized singleton</a> made from a C pre-processor macro. The problem with this is that it's not flexible. So, I made an Objective-C singleton that can be dropped in any project. By subclassing <a href="https://gist.github.com/1116294">RBSingleton</a> you can gain all the benefits of a singleton without adding any further code and you have full flexibility to customize each subclass. <br /><br />There are two main parts that make RBSingleton possible. First, it stores all the singleton instances in a class-wide dictionary. A singleton typically keeps a static pointer to the singleton instance. This works fine as long as it's not subclassed. When subclasses become involved, the subclass that allocates first defines the singleton instance for all subclasses. This restriction is normally beneficial to singletons, but breaks with subclassing. I could have required subclasses to provide a pointer to a static class pointer through a method call, but this imposes more on the subclass's implementation than I wanted. By using a class-wide dictionary, every subclass can store its singleton instance under a unique key. To guarantee a unique key, I simply use the subclass's name. <br /><br />Second, the singleton instance is allocated by dynamically calling NSObject's -allocWithZone: method as shown below. <br /><br /><span style="font-size: 11pt; color: rgb(43,131,159);">Method</span> <span style="font-size: 11pt;">allocMethod = </span><span style="font-size: 11pt; color: rgb(43,131,159);">class_getClassMethod</span><span style="font-size: 11pt;">([</span><span style="font-size: 11pt; color: rgb(43,131,159);">NSObject</span> <span style="font-size: 11pt;"></span><span style="font-size: 11pt; color: rgb(43,131,159);">class</span><span style="font-size: 11pt;">], </span><span style="font-size: 11pt; color: rgb(0,0,255);">@selector</span><span style="font-size: 11pt;">(allocWithZone:));<br />sharedInstance = [</span><span style="font-size: 11pt; color: rgb(43,131,159);">method_invoke</span><span style="font-size: 11pt;">(</span><span style="font-size: 11pt; color: rgb(0,0,255);">self</span><span style="font-size: 11pt;">, allocMethod, </span><span style="font-size: 11pt; color: rgb(0,0,255);">nil</span><span style="font-size: 11pt;">) </span><span style="font-size: 11pt; color: rgb(43,131,159);">initialize</span><span style="font-size: 11pt;">];</span><br /><br />The trick here was to allocate the singleton as the class of the RBSingleton subclass but use NSObject's -allocWithZone: method to do so. This is similar to calling [super allocWIthZone:nil];. The difference is that it's jumping more than one level in the inheritance hierarchy. This is known as a grandsuper call. The Objective-C dynamic runtime makes it possible to make such a call. You will also notice that I hardcoded [NSObject class] into the code. I could have dynamically discovered the root class with the following code:<br /><br /><span style="font-size: 11pt;">+ (</span><span style="font-size: 11pt; color: rgb(43,131,159);">Class</span><span style="font-size: 11pt;">)rootClass {<br /> <br />        </span><span style="font-size: 11pt; color: rgb(43,131,159);">Class</span> <span style="font-size: 11pt;">rootClass = </span><span style="font-size: 11pt; color: rgb(0,0,255);">nil</span><span style="font-size: 11pt;">;<br />        </span><span style="font-size: 11pt; color: rgb(43,131,159);">Class</span> <span style="font-size: 11pt;">currentClass = [</span><span style="font-size: 11pt; color: rgb(0,0,255);">self</span> <span style="font-size: 11pt;"></span><span style="font-size: 11pt; color: rgb(43,131,159);">class</span><span style="font-size: 11pt;">];<br /> <br />        </span><span style="font-size: 11pt; color: rgb(0,0,255);">while</span> <span style="font-size: 11pt;">((currentClass = </span><span style="font-size: 11pt; color: rgb(43,131,159);">class_getSuperclass</span><span style="font-size: 11pt;">(currentClass)))<br />                rootClass = currentClass;<br /> <br />        </span><span style="font-size: 11pt; color: rgb(0,0,255);">return</span> <span style="font-size: 11pt;">rootClass;<br />}</span><br /><br />If I instead needed to get a grandsuper class that isn't necessarily the root class and I know a subclass of the grandsuper I could use simpler code like this:<br /><br /><span style="font-size: 11pt;">[</span><span style="font-size: 11pt; color: rgb(43,131,159);">RBSingleton</span> <span style="font-size: 11pt;"></span><span style="font-size: 11pt; color: rgb(43,131,159);">superclass</span><span style="font-size: 11pt;">];</span><br /><br />Since I know the specific grandsuper class I need, I hardcoded it for efficiency. If you use RBSingleton and find a need to dynamically discover a particular grandsuper class, you can use the above code to do so. I've uploaded RBSingleton as a Gist and you can find it <a href="https://gist.github.com/1116294">here</a>.<br /><br />One last note, to use RBSingleton you need to include libobjc.dylib for the dynamic runtime calls. Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-12253276018735698172011-07-26T19:03:00.000-06:002011-09-17T23:19:10.137-06:00#define AbuseLately I've been encountering some terrible Objective-C code, and I have a few words to say about it. One of the first problems I've found is the overuse of #define. Don't get me wrong, #define has its place, but when it comes to constants #define should not be the first choice. <br /><br /><strong>Anti-Patterns</strong><br />One of the problems with #define is that it's simply a macro substitution. There is generally no type associated with the value. This makes is harder for the compiler to warn you of potential errors. Macros can also have side effects you may forget about. For example:<br /><br />#define MY_STRING_CONSTANT [[NSString alloc] initWithFormat:@"Hello World!"] // Very bad.<br /><br />The above example will cause a memory leak unless you remember to release the value each time. Just a side note, Apple's static analyzer will pick up this error if you turn it on. I should also mention that the following, related example is not preferable. I have actually seen this used in production code before.<br /><br />#define MY_STRING_CONSTANT [NSString stringWithFormat:@"Hello World!"] // Still not great.<br /><br /><strong>Numbers</strong><br />With a couple anti-patterns out of the way, let's go over the proper way to define constants. You will find that it doesn't take much more effort to properly define constants. Numbers are the simplest and one of the most common, so we'll start with them. In your .m file (applies to .c or .cpp too) you will define your constant like the following:<br /><br />const NSInteger kMyInt = -100;<br />const NSUInteger kMyUnsignedInt = 42;<br />const CGFloat kMyFloat = 3.14;<br /><br />You could instead use 'int', 'unsigned int', and 'float' if you prefer, but the above types are generally the preferred data types. If you want to keep your constant visible to just your implementation file, then you are done. If not, you need to do one last thing. In your header file, you will need to use the following:<br /><br />extern const NSInteger kMyInt;<br />extern const NSUInteger kMyUnsignedInt;<br />extern const CGFloat kMyFloat;<br /><br />The reserved word 'extern' makes a promise to the compiler. You are letting the compiler know that you are not defining the value right away, but at link time, that value will exist. In this case, it's defined in your implementation file. With that in place, you are now done; your constant is defined and other classes can #import (#include for C and C++) your header file and use your number constants.<br /><br />You may wonder why you can't define the constant right in your header file. If you do, you will get an error message that looks like this: "<span style="font-size: 11pt;">ld: duplicate symbol <Constant Name> in <File 1> and <File 2>.</span>" Generally #import handles duplicate imports properly; however, it doesn't work for constants. I figure this error is why developers unaware of 'extern' default to #define. <br /><br /><strong>Enumerations</strong><br />Closely related to numbers are enumerations. If you ever have a series of related number constants, you probably want an enum. For example:<br /><br />// A contrived example but should get the idea across.<br />enum {<br />        kJanuary = 1,<br />        kFebruary = 2,<br />        kMarch = 3,<br />        kApril = 4,<br />        kMay = 5,<br />        kJune = 6,<br />        kJuly = 7,<br />        kAugust = 8,<br />        kSeptember = 9,<br />        kOctober = 10,<br />        kNovember = 11,<br />        kDecember = 12,<br />};<br /><br />Enumerations are great for bit masks too.<br /><br />// Another contrived example.<br />enum {<br />        kBit1 = 1 << 0,<br />        kBit2 = 1 << 1,<br />        kBit3 = 1 << 2,<br />        kBit4 = 1 << 3,<br />};<br /><br />Enumerations are where type checking really helps. Say you are using a switch statement, the compiler can warn you if you didn't include one of your enum values as a switch case. <br /><br /><strong>Strings</strong><br />Strings are also very common in Cocoa programming. There is one extra detail that makes them different from numbers. At first you may want to make a constant like this:<br /><br />const NSString * kMyString = @"Hello World!"; // Wrong - String Anti-Pattern 1<br /><br />This is wrong for a couple different reasons. First, NSString is immutable, meaning that it can't be changed. This essentially makes it a constant by default. However, there is a big flaw with the above anti-pattern. I will first show the proper way:<br /><br />NSString * const kMyString = @"Hello World!"; // Right<br /><br />At first glance, you are probably wondering why 'const' is next to the constant name. The difference between the number and string examples is that the NSString is a pointer. The first string example tells the system that the value @"Hello World!" can't change, but the pointer value can change. You probably wouldn't, but you could do the following:<br /><br />kMyString = @"Goodbye World!"; // Very bad, but allowed in String Anti-Pattern 1.<br /><br />You didn't change the value of @"Hello World!", but you did change what kMyString pointed to. That doesn't sound like a constant at all. <br /><br />By the way, the following is also permissible, but wrong.<br /><br />const NSString * const kMyString = @"Hello World!"; // Wrong - String Anti-Pattern 2<br /><br />This makes both the value and the pointer constant. However, the first 'const' changes the data type of the constants. None of the Cocoa frameworks accept a const NSString * (since it's redundant). This means that you will have a compiler warning anytime you try to pass your constant to a Cocoa framework method. You might do something similar with other objects, but in Objective-C, such cases should be very rare. This is something more common in C or C++. <br /><br /><strong>Objects</strong><br />Objects other than strings can be a little more tricky. You can't do the following:<br /><br />MyObject * const kObject = [[MyObject alloc] init]; // Wrong - Object Anti-Pattern 1<br /><br />The problems is the right-hand side does not evaluate to a compile time constant. Furthermore, if it was possible, it would be difficult to configure the object properly. This requires a different technique.<br /><br />// Right<br />+ (MyObject *)MyConstObject {<br /><br />        static MyObject * obj = nil;<br /><br />        if (!obj) {<br />                obj = [[MyObject alloc] init];<br /><br />        // Any other initial setup.<br />        }<br /><br />        return obj;<br />}<br /><br />Looking at the return type of MyObject *, you may think this has the same problem that String Anti-Pattern 1 had. This is not the case here. The original constant pointer is protected within the method; it can't be changed externally. When you call the method, you receive a copy of the object's address. You can change it if you want, but it won't affect anyone else. Naively you may want to change the return type to MyObject * const, but a const pointer doesn't affect the data type. You could do the following regardless:<br /><br />MyObject * obj = [[self class] MyConstObject]; // Type MyObject * is the same as MyObject * const<br /><br />One last note about object constants is that they are technically memory leaks. However, they are permissible for the same reason that <a href="http://en.wikipedia.org/wiki/Singleton_pattern">singletons</a> are permissible. What's more interesting is that Apple's latest static analyzer now flags singletons as memory leaks but still doesn't catch the above constant. <br /><br /><strong>When to use #define</strong><br />I should probably include a kind word about #define. If you want to use any pre-processor macros such as #if or #ifdef, then #define is your only choice. #define is also good for simple, inline functions or when you want to write some code that will do automatic renaming (see Cocoa With Love's <a href="http://projectswithlove.com/projects/SynthesizeSingleton.h.zip">synthesized singleton</a>). #define has countless valuable uses, but when it comes to constants, try something else first. <br /><br />Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-56120883384311930472011-07-19T20:59:00.000-06:002011-07-19T21:59:38.151-06:00Driving Technical Change ReviewOne particular book that caught my eye some time ago is <em><a href="http://pragprog.com/book/trevan/driving-technical-change">Driving Technical Change</a></em> by Terrence Ryan. In his book, Ryan teaches the skills necessary to convince others to adopt your ideas. Though the book focuses around technical fields, most of the skills taught apply to other disciplines. <br /><br /><strong>Summary</strong><br />Ryan begins his book by classifying different types of people, such as the Cynic, the Uniformed, and the Irrational. From there he progresses to the skills needed to use on the different categories including delivering your message, gaining trust, and getting publicity. Ryan then concludes with how to strategically employ the needed skills. <br /><br /><strong>Pros</strong><br />The book is written in a way that it can in whatever order fits your needs. Once you have identified the category (or categories) of people you are working with, you can jump straight to the recommended skills and techniques. The chapters are short and easy to read. Every skeptic category and rhetoric technique includes short examples to illustrate the ideas. <br /><br />Most of the ideas covered seem common sense. Yet there are some examples that I had never thought of employing. For example, Ryan suggests one way to get coworkers to accept a framework you've built is to open source it. If many people start using it, or even contributing to it, then your coworkers will be much more open to using your framework. <br /><br /><strong>Cons</strong><br />Ryan tends to dodge confronting the Irrational. It is true that little can be done to convince an irrational person. However, he doesn't offer many suggestions besides avoid them and/or have management mandate a policy. Management mandate may be the silver bullet, but what about the situation when management is irrational? Perhaps the best solution at that point is to find a new job. <br /><br />Before reading this book, I was expecting Ryan to go into more detail on leadership skills. However, many skills such as gaining trust are left with few examples or explanation of how to gain trust. I do like the succinctness of Ryan's writing, but sometimes I'm left wanting more concrete examples. <br /><br /><strong>Recommendation</strong><br />If you are one of the many that feel your voice isn't heard, this book likely has some skills you haven't tried yet. Ryan shares his secret to leadership: "you can be promoted to management, but no one appoints you a leader." <em>Driving Technical Change</em> can help you take initiative and become a leader. <br /><br />You can purchase <em>Driving Technical Change</em> <a href="http://pragprog.com/book/trevan/driving-technical-change">here</a> from <a href="http://pragprog.com/">The Pragmatic Bookshelf</a>.Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-42154037152889104512011-06-21T11:30:00.000-06:002011-07-19T21:59:36.710-06:00Designed For Use ReviewI've been anticipating the release of <em><a href="http://pragprog.com/titles/lmuse/designed-for-use">Designed for Use: Create Usable Interfaces for Applications and the Web</a></em> for a while now. I was a little disappointed that it was delayed by almost a week from its original release date. Nevertheless, I bought it and finished it right away.<br /><br /><strong>Summary</strong><br />Lukas Mathis breaks the design process into three distinct parts: research, design, and implementation. Each category is subdivided into smaller steps classified as either idea-based or skill-based. The progression is logical, but also is written in a way that steps can be skipped or read out of order according to the needs of the product. <br /><br /><strong>Pros</strong><br />When I first saw the book, I expected a focus strictly on what Mathis terms the "design phase" (Part 2 of 3). Design to me, before reading this book, meant wireframes, prototypes, and usability testing. The book gives much more. Mathis shows that the design process extends throughout the entire development cycle. <br /><br /><em>Designed for Use</em> includes countless links to other resources. Mathis cites many prominent UX and Design blogs, books, videos, etc. Most are web based, so they are freely and widely available. <br /><br />Many great techniques are suggested that I never thought of as part of "design." Mathis includes mock press releases, job shadowing, and feature sorting. Not only does he teach several techniques, but he also gives low-budget suggestions. He removes any excuse for not following certain steps such as usability testing.<br /><br /><strong>Cons</strong><br />Overall the book seems to have a bias towards desktop and web applications. There are several references to developing mobile applications, but there are few resources mentioned. I was expecting to see services such as Flurry and TestFlight included in the sections on user feedback and testing. Nevertheless, the ideas and techniques still apply.<br /><br /><strong>Recommendation</strong><br />In general product development I often see two areas that lack: design and documentation. Mathis hits on both topics. Every step of the design process is covered succinctly and thoroughly making it quick and easy to read yet includes many references for further indulgence. I would highly recommend this book to both young and experienced developers. <em>Designed for Use</em> can be purchased <a href="http://pragprog.com/titles/lmuse/designed-for-use">here</a> on <a href="http://pragprog.com">pragprog.com</a>.Unknownnoreply@blogger.comtag:blogger.com,1999:blog-8850989183226537471.post-76664876111579302282011-06-07T19:54:00.000-06:002011-06-07T20:05:16.681-06:00Git ReposI've recently created a few Git repos on Github. So far I have included a bug reporting tool, a file previewer, and a load of handy categories. I will also be moving my samples to Github. Check them out at <a href="https://github.com/rob-brown">https://github.com/rob-brown</a>.Unknownnoreply@blogger.com