<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" gd:etag="W/&quot;DUECQXc6fyp7ImA9WxNUFUo.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800</id><updated>2009-11-06T23:07:40.917-08:00</updated><title>Cocoa with Love</title><subtitle type="html">Advanced programming tips, tricks and hacks for Mac development in C/Objective-C and Cocoa.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://cocoawithlove.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>95</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/CocoaWithLove" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;DUECQXc5fSp7ImA9WxNUFUo.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-5498576471595968227</id><published>2009-11-06T22:59:00.001-08:00</published><updated>2009-11-06T23:07:40.925-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-06T23:07:40.925-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Graphics" /><title>Creating iPhone and Mac icons using Inkscape (Part 2 of 2)</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;In this part, I expand on the simple techniques presented in the first part by adding different line, effect and texture styles. I'll also present some Mac application icons and simple texturing.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Introduction&lt;/h4&gt;

&lt;p&gt;This series covers the creation of the following different icon styles:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvAqo04PsPI/AAAAAAAAAeg/d5Pvuu0d24I/all-icons.png?imgmax=800" alt="all-icons.png" border="0" width="550" height="111" /&gt;

&lt;p&gt;The first icon was created in the first part of the series. I'll go through the creation of the remaining variations on the checkbox/checkmark theme in this post.&lt;/p&gt;

&lt;p&gt;I'll assume that you've read the first part or are familiar with the techniques involved.&lt;/p&gt;

&lt;h4&gt;Icon 2: A brighter, more colorful iPhone icon&lt;/h4&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvUZp6qZJ2I/AAAAAAAAAf4/hj-veh__ZvE/icon2.png?imgmax=800" alt="icon2.png" border="0" width="147" height="146" style="float:right;padding-top:20px;padding-left:20px;padding-bottom:20px;"/&gt;

&lt;h5&gt;Goals in this section&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Use a radial gradient&lt;/li&gt;
&lt;li&gt;Learn to adjust all of the common stroke properties&lt;/li&gt;
&lt;li&gt;Learn to adjust a multi-effect filter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The icon developed in Part 1 is very simple &amp;mdash; really just a couple white lines over a typical iPhone icon background &amp;mdash; which is appropriate for a serious application but might not stand out as prominently against other icons.&lt;/p&gt;

&lt;p&gt;In this variation, I'll have the background reach a bright point behind the checkbox element and change the effect on the lines so that the lines look embossed into this bright point &amp;mdash; visually integrating the background and the overlayed element.&lt;/p&gt;

&lt;p&gt;I'll also introduce a complimentary (opposite hues) color scheme with an azure blue and a red.&lt;/p&gt;

&lt;h5&gt;A radial background&lt;/h5&gt;

&lt;p&gt;Starting with a 57x57 document as created in Part 1, add a rectangle filling the document area.&lt;/p&gt;

&lt;p&gt;Set the fill to a radial fill and edit the gradient. In the Gradient Editor, click "Add Stop" twice to make the gradient a four part gradient. Top to bottom, the four gradient colors should be:

&lt;ol&gt;&lt;li&gt;RGBA=(192,255,250,255)&lt;/li&gt;
&lt;li&gt;RGBA=(99,164,184,255), Offset 0.26&lt;/li&gt;
&lt;li&gt;RGBA=(5,74,119,255), Offset 0.62&lt;/li&gt;
&lt;li&gt;RGBA=(0,40,80,255)&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;We now have a bright spot in the center of the background.&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SvTkpP4P15I/AAAAAAAAAeo/IHV0VUh7340/blue-dot.png?imgmax=800" alt="blue-dot.png" border="0" width="300" height="301" /&gt;

&lt;p&gt;Over the top of this, paste (or recreate) the starburst effect from Part &amp;mdash; X,Y=(-15.7,-15.7) should center it perfectly.&lt;/p&gt;

&lt;p&gt;In the Fill and Stroke palette, set the opacity of the starburst to 100%.&lt;/p&gt;

&lt;p&gt;Now, to make the starburst smoother, open the Filter Editor (from the Filters menu) and find the starburst's blur effect (it should be selected in the filter column when the starburst itself is selected). Select the Gaussian Blur effect and set the standard deviation to 0.75.&lt;/p&gt;

&lt;h5&gt;Different stroke properties for the checkbox and checkmark&lt;/h5&gt;

&lt;p&gt;Create the checkbox and checkmark in the same way that they were created in the first part or copy them in. If you copy them in, select both the checkbox and the checkmark and choose Filters&amp;rarr;Remove Filters to remove the shadow and bevel effect applied in the first part.&lt;/p&gt;

&lt;p&gt;Remove the corner radius from the checkbox (select it using the rectangle tool and set the Rx and Ry to zero). In the Fill and Stroke Editor, select the Stroke Style Tab and set the Line Width to 4.0 "px" and the Join Style to rounded. The result of these steps is to create a slightly thicker line that is curved on the corners within its width.&lt;/p&gt;

&lt;p&gt;Select the checkmark and set the stroke color to RGBA=(255,42,42,255) and the stroke width to 4.0 "px".&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SvTrY2F85DI/AAAAAAAAAes/_d473sRTlp8/altered-strokes.png?imgmax=800" alt="altered-strokes.png" border="0" width="377" height="367" /&gt;

&lt;h5&gt;A customized "Cutout glow"&lt;/h5&gt;

&lt;p&gt;With both checkbox and checkmark selected, choose Filters&amp;rarr;Shadows and Glows&amp;rarr;Cutout Glow. Go to the Filter Editor and find this Cutout Glow filter. This filter will have 5 effect rows. Select the Offset row and set the X,Y offset to (0.8,0.8). Select the Gaussian Blur row and set the Standard Deviation to 1.0.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/SvTsJwuhnzI/AAAAAAAAAew/GQ5SZnlfRPg/cutout-glow.png?imgmax=800" alt="cutout-glow.png" border="0" width="550" height="310" /&gt;

&lt;p&gt;Now follow the instructions from the "Apply the gloss effect and round corners" subsection of the previous post to complete the icon.&lt;/p&gt;

&lt;h4&gt;Icon 3: A cartoonish style&lt;/h4&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SvUZ7a7Ft8I/AAAAAAAAAf8/Y0pMEqkFvyU/icon3.png?imgmax=800" alt="icon3.png" border="0" width="148" height="146" style="float:right;padding-top:20px;padding-left:20px;padding-bottom:20px;"/&gt;

&lt;h5&gt;Goals in this section&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;Directly edit paths for greater control&lt;/li&gt;
&lt;li&gt;See a Path Effect (Spiro Spline) in action&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This variation will forego the starburst effect and instead go for a smoother, more "cartoonish" approach. The checkbox and checkmark will then need to be more distinctive as they will be the only significant graphical elements&lt;/p&gt;

&lt;h5&gt;Creating a path&lt;/h5&gt;

&lt;p&gt;Start with the background rectangle from the "brighter, more colorful iPhone icon" created above (if you created a cloned version for the round corners, don't copy the cloned version as it will behave strangely).&lt;/p&gt;

&lt;p&gt;Select the Bezier Path tool (11th icon down in the Tool Area). We'll draw the rough loop first.&lt;/p&gt;

&lt;p&gt;You can use the Bezier Path tool in one of two ways: simple click-and-release to create corner points and straight line segments or click and drag to create curve points (the dragging then affects the curvature of each point).&lt;/p&gt;

&lt;p&gt;For simplicity here, I'll show you how to create the path using corner points and we'll apply the curve as a second step. When you're more comfortable with the Bezier Tool, this can be done as a single step.&lt;/p&gt;

&lt;p&gt;Create a point at the 12 o'clock position, then 9, 6, 3 and then underneath the original 12. Then another inside the second twelve and then inside the 3, 6, 9, and between the first and second 12's. Then close the path by clicking on the first point.&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvTwNZ2Uf7I/AAAAAAAAAe0/sI3PK7-FSq8/stroke-creation.png?imgmax=800" alt="stroke-creation.png" border="0" width="500" height="241" /&gt;

&lt;blockquote&gt;&lt;strong&gt;Bezier path creation&lt;/strong&gt;: If you make a mistake with the path, you can either fix it later or press escape to cancel the whole path. Pressing the return-key will end the path without closing it.&lt;/blockquote&gt;

&lt;h5&gt;Adjusting path control point properties&lt;/h5&gt;

&lt;p&gt;Using the Node Tool (2nd icon down in the Tool Area) ensure the path you just created is selected. Drag a selection box around the nodes at 3, 6 and 9 o'clock (don't select the nodes at 12 o'clock). In the toolbar at the top, select the "Make selected nodes smooth" button (should be 8th from the left in the toolbar immediately above the window).&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvTxDs_IToI/AAAAAAAAAe4/wGYYUbr8mX0/smooth-points.png?imgmax=800" alt="smooth-points.png" border="0" width="300" height="309" /&gt;

&lt;h5&gt;Applying a path effect&lt;/h5&gt;

&lt;p&gt;Leaving the path selected, choose the Path&amp;rarr;Path Effect Editor menu item. In the Path Effect Editor palette, select "Spiro Spline" from the popup menu and click the "Add" button. The "Spiro Spline" is an effect that makes smooth curved paths much easier than regular Bezier curves.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/SvTxbYCbAWI/AAAAAAAAAe8/9CnV7Lk-bkk/spiro-spline.png?imgmax=800" alt="spiro-spline.png" border="0" width="400" height="299" /&gt;

&lt;p&gt;Once this is done, you can tweak the nodes in the path (using the Node Tool) until it is the exact shape desired.&lt;/p&gt;

&lt;p&gt;In the Fill and Stroke Editer, remove any stroke, apply a faded yellow to faded orange linear gradient fill from left to right across the checkbox loop and it is done.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/SvTyBrC-f0I/AAAAAAAAAfA/nLLF9j_m60I/checkbox-loop.png?imgmax=800" alt="checkbox-loop.png" border="0" width="300" height="302" /&gt;

&lt;h5&gt;Stroke to path&lt;/h5&gt;

&lt;p&gt;Create the checkmark as for the previous icons but set the Stroke Width to 6 "px" and the Style Join and Cap to square corners. With the path selected, choose the menu item Path&amp;rarr;Stroke to Path. This will turn the line into a filled path. Set the stroke of this path to "no stroke" and set the fill to an orange to red linear gradient fill from left to right across the checkmark.&lt;/p&gt;

&lt;p&gt;Now we need to adjust the checkmark to have a looser aesthetic. Select the Node Tool and the checkmark. Drag the lines in the short stem upwards slightly and the lines in the long stem inwards slightly. Adjust the control points at the ends of each stem so that they are flared outwards a 
little.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/SvUYe-Go6RI/AAAAAAAAAfw/p7d7XnITuzo/checkmark-adjustment.png?imgmax=800" alt="checkmark-adjustment.png" border="0" width="381" height="400" /&gt;

&lt;p&gt;Follow the instructions from "Bevel effect and shadow" from Part 1 to apply these effects. Follow the instructions from the "Apply the gloss effect and round corners" subsection of the previous post to complete the icon.&lt;/p&gt;

&lt;h4&gt;Icon 4: A document-based Mac icon&lt;/h4&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvUaMmdeOWI/AAAAAAAAAgA/MPNcEaQXki8/icon4.png?imgmax=800" alt="icon4.png" border="0" width="179" height="182" style="float:right;padding-top:20px;padding-left:20px;padding-bottom:20px;"/&gt;

&lt;h5&gt;Goals in this section&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;See the common components of a Mac document-based application icon&lt;/li&gt;
&lt;li&gt;Use multiple overlapping gradients to achieve softer gradients&lt;/li&gt;
&lt;li&gt;Add a texture to a background by filling with text&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In terms of colors and effects, Mac icons tend to be far more subdued than iPhone icons. Where iPhone icons are only shown on the Home screen but are small and need to stand out, Mac icons may sit in the Dock for extended periods and shouldn't be distracting during this time.&lt;/p&gt;

&lt;p&gt;For this reason, Mac icon colors tend to be slightly more subdued than iPhone icon colors and are frequently much lighter overall.&lt;/p&gt;

&lt;p&gt;While Mac icons are typically larger (an average of around 64x64) they can also be shown at smaller resolutions. The approach to satisfying the size range is normally to compose the icon from two key parts:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;An object or item that is easily recognizable in silhouette or at small sizes&lt;/li&gt;
&lt;li&gt;Texture or subtler elements that fade away at smaller sizes but add structure and context at larger sizes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mac icons must also handle a range of different background colors as they may be shown against people's desktop backgrounds, white folder backgrounds or against the near black of a vertical Dock. To achieve good contrast against the background, most icons are generally light in color but with a subtle shadow behind them &amp;mdash; not for 3D effect but to contrast with lighter backgrounds. Many icons also incorporate a frame or boundary into the representation which further adds to the strength of the icon's silhouette.&lt;/p&gt;

&lt;h5&gt;A rotated background&lt;/h5&gt;

&lt;p&gt;To start the icon, create a 64x64 px document. This size will help us optimize for the expected screen resolution.&lt;/p&gt;

&lt;p&gt;Into this, draw a 44 by 50 rectangle. Give it an azure to deep blue linear gradient from left to right and a white 3px stroke.&lt;/p&gt;

&lt;p&gt;Using the Selection Tool (first in the Tool Area), select the rectangle. Initially, this will show the resizing arrows around the shape. Click a second time to switch these arrows to the rotating arrows (don't double click as that will switch to the Node Tool). Click and drag one of the corner arrows to rotate the rectangle by 8&amp;deg; (the rotated angle should be visible in the status bar at the bottom of the window while dragging but the exact angle isn't important).&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvT1-mjrgPI/AAAAAAAAAfI/bExN4UjjBw0/rotated-gradient.png?imgmax=800" alt="rotated-gradient.png" border="0" width="272" height="271" /&gt;

&lt;h5&gt;Some effects and another gradient&lt;/h5&gt;

&lt;p&gt;On its own, a single gradient isn't a very impressive effect. The trick in making a background effect that is both attractive and subtle, is normally to layer a few different effects on top of each other.&lt;/p&gt;

&lt;p&gt;With the rectangle selected, select "Path"&amp;rarr;"Union". This may seem like a weird thing to do but it actually recreates the object using a path at the rotated orientation. We do this because Effects in Inkscape (like the shadow we're just about to apply) look bad (pixelated) when rotated. Recreating the object at this rotation means the effect will not have a rotation applied.&lt;/p&gt;

&lt;p&gt;Copy and paste this rotated rectangle and put the copy next to the original. Apply a drop shadow to the original with 50% opacity, Offset of (1,1) and radius of 1.5.&lt;/p&gt;

&lt;p&gt;Now remove the stroke from the copy. You'll notice that without the white stroke covering 1.5 px of the copy, the gradient region of the copy actually looks slightly bigger than the original. We need this shape to be the same size as the colored area of the original, so use the Selection Tool and with the rezize arrows, adjust the two to match (set the color to a flat fill like red and overlap the two objects to make it easier).&lt;/p&gt;

&lt;p&gt;Now set the second object to have a top to bottom (parallel to its rotated axis) linear gradient fill with four color points:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;RGBA=(168,247,249,255)&lt;/li&gt;
&lt;li&gt;RGBA=(144,198,215,0), Offset 0.30&lt;/li&gt;
&lt;li&gt;RGBA=(95,144,175,0), Offset 0.70&lt;/li&gt;
&lt;li&gt;RGBA=(18,49,106,255)&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Since this second gradient is transparent in the middle, it will show the first gradient in varying amounts through the middle. Overlapping the two should result in a softer gradient that vaguely resembles diffuse lighting across a slightly convex surface.&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvT-EZgdikI/AAAAAAAAAfQ/TRbyiJqkCOY/second-gradient.png?imgmax=800" alt="second-gradient.png" border="0" width="266" height="267" /&gt;

&lt;h5&gt;A light text-based texture&lt;/h5&gt;

&lt;p&gt;The formatting of the following paragraph is not an mistake.&lt;/p&gt;

&lt;ul&gt;As indicated before, it&lt;br/&gt;helps to add a texture to&lt;br/&gt;your Mac icons. It is best&lt;br/&gt;if you have a texture or&lt;br/&gt;image that is related to&lt;br/&gt;your application &amp;mdash; for&lt;br/&gt;this icon I don't really&lt;br/&gt;have an application, so&lt;br/&gt;I'm going to use a block&lt;br/&gt;of arbitrary text (this&lt;br/&gt;paragraph, in fact).&lt;/ul&gt;

&lt;p&gt;The Text Tool is two icons above the Gradient Tool. Click on the document to create a text object and type the text shown and formatted as above. With the text object selected, choose the Zapfino font from the font popup menu in the top toolbar. I like Zapfino because when zoomed out, it seems ornate and indistinct.&lt;/p&gt;

&lt;p&gt;Now use the Selection Tool to scale and position the text object over the other gradient rectangles.&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvT-7D2tuhI/AAAAAAAAAfU/hCngBR1JQ3g/text.png?imgmax=800" alt="text.png" border="0" width="373" height="372" /&gt;

&lt;p&gt;To add a gloss effect over everything, create a 53 by 28 rectangle, with a flat RGBA=(255,255,255,60) fill and no stroke and rotate and position it over the top half of the existing shapes.&lt;/p&gt;

&lt;h5&gt;The "representative" element&lt;/h5&gt;

&lt;p&gt;For the representative element, I'll use a checkmark in an orange circle. Create a checkmark line (same as in previous icons) set a white 5 px stroke on the checkmark.&lt;/p&gt;

&lt;p&gt;Create a 43 by 43 circle (unlike the Rectangle Tool, you can't specify the size of a circle with the Circle Tool selected. If you want to do this, you'll need to use the Selection Tool). Set a red-orange to yellow-orange radial gradient on the object and no stroke.&lt;/p&gt;

&lt;p&gt;Using the Gradient Tool, drag the center control point of the gradient to the bottom-right corner of the circle's bounding box, the endpoint of the horizontal stem to the bottom-left corner and the vertical endpoint to the top-right corner.&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvT_glMbz4I/AAAAAAAAAfY/y9d6MF-D1Dg/representative-element.png?imgmax=800" alt="representative-element.png" border="0" width="369" height="277" /&gt;

&lt;p&gt;With the circle selected, use the menu item Filters&amp;rarr;ABCs&amp;rarr;Diffuse Light. Then use the Filter Editor to set the Gaussian Blur effect of this filter to a Standard Deviation of 1.0. Then apply a drop shadow to the circle.&lt;/p&gt;

&lt;p&gt;Finally, position everything together and the icon is complete.&lt;/p&gt;

&lt;h4&gt;Icon 5: A circular Mac icon&lt;/h4&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvUaRmY_4LI/AAAAAAAAAgE/xlc_g2hon1A/icon5.png?imgmax=800" alt="icon5.png" border="0" width="164" height="164" style="float:right;padding-top:20px;padding-left:20px;padding-bottom:20px;"/&gt;

&lt;h5&gt;Goals in this section&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;See the common components of a Mac "appliance" application icon&lt;/li&gt;
&lt;li&gt;Apply effects to a path to make the boundary shape more interesting and more distinct from the background&lt;/li&gt;
&lt;li&gt;Create a texture using an effect&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A circular icon is constructed in the same way as a rectangular backed icon. The only significant differences are:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;gradients tend to be various kinds of radial gradient to give a convex feel to the round shape&lt;/li&gt;
&lt;li&gt;the overlayed element will be more centered so it helps if it is less solid (thinner and lighter)&lt;/li&gt;&lt;/ul&gt;

&lt;h5&gt;Compose a round icon&lt;/h5&gt;

&lt;p&gt;Since you've seen how to put together basic shapes and radial fills before, I'll just show you the components I used to create this icon as a graphic:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvUBJ2fKIkI/AAAAAAAAAfg/KbRqImnvXWg/round-icon-components.png?imgmax=800" alt="round-icon-components.png" border="0" width="550" height="133" /&gt;

&lt;p&gt;Notice how bright the elements all are: Mac icons are normally quite bright &amp;mdash; you want to avoid a "muddy" effect with too many dark colors.&lt;/p&gt;

&lt;p&gt;When composing elements, if one of them is at the wrong depth (overlaps other objects wrong) you can change the depth by selecting the object and using the Page Up/Page Down keys (or by using the "Object"&amp;rarr;"Raise"/"Lower" menu items).&lt;/p&gt;

&lt;h5&gt;Make the checkmark look interesting&lt;/h5&gt;

&lt;p&gt;The checkmark must stand alone in this icon, which means that it should have a few special effects applied to it so that it doesn't look sterile and boring. I applied the following effects to the checkmark:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Filters&amp;rarr;Non-realistic 3D shaders&amp;rarr;Comics&lt;/li&gt;
&lt;li&gt;Filters&amp;rarr;Shadows and Glows&amp;rarr;Inner Glow. For this filter, I changed the Flood color to a medium blue and reduced the Gaussian Blur (now the second blur in the Effects list for this object after the Comics blur from the previous effect) to a Standard Deviation of 1.0.&lt;/li&gt;
&lt;li&gt;A drop shadow.&lt;/li&gt;
&lt;/ol&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SvUBnbY9_VI/AAAAAAAAAfk/Uu_3c10xwcc/checkmark-with-effects.png?imgmax=800" alt="checkmark-with-effects.png" border="0" width="146" height="165" /&gt;

&lt;p&gt;To texture the circle, I used the RGBA=(176,112,42,140) circle (middle element shown above) and applied a Filters&amp;rarr;Image effects, transparent&amp;rarr;Marbled ink effect. This gives a slightly moon cratered look that matches the somewhat planetoid shape of the object.&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SvUCNKDO7UI/AAAAAAAAAfo/LWBmMzSEkVM/textured-circle.png?imgmax=800" alt="textured-circle.png" border="0" width="212" height="228" /&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can &lt;a href="http://projectswithlove.com/projects/cocoawithlove-inkscape-icons-part1.svg"&gt;download an Inkscape SVG file containing all the icons and their compositions&lt;/a&gt; (482kB).&lt;/blockquote&gt;

&lt;p&gt;This two part series has been outside the normal domain of programming information that I provide. However, applications programmers will regularly find themselves needing to create, edit or adjust artwork-related assets in their applications. I hope I've given some useful tips on the way artwork assets are composed and ways you can make your artwork look good, even if it is very simple.&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvAqo04PsPI/AAAAAAAAAeg/d5Pvuu0d24I/all-icons.png?imgmax=800" alt="all-icons.png" border="0" width="550" height="111" /&gt;

&lt;p&gt;With iPhone or Mac icons, they are typically composed from the same elements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A background gradient (or two).&lt;/li&gt;
&lt;li&gt;A texture or additional effect.&lt;/li&gt;
&lt;li&gt;A gloss or lighting highlight.&lt;/li&gt;
&lt;li&gt;A foreground element or symbol representing your application which, after the other elements are applied, need only be very simple.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With gradients and effects, it is helpful to use a few so that your icon seems rich on close inspection but to keep each one very subtle since they shouldn't distract or make the icon harder to perceive (in a quick glance, the user shouldn't even see the effects you've added).&lt;/p&gt;

&lt;p&gt;Icons do not need to be complex; the most professional icons are often very basic. Lack of artistic skill need not be a hinderance if you keep it simple.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-5498576471595968227?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/5498576471595968227?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/5498576471595968227?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/11/creating-iphone-and-mac-icons-using_06.html" title="Creating iPhone and Mac icons using Inkscape (Part 2 of 2)" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;DkMDQ3czfCp7ImA9WxNUFUs.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-8239862947234112962</id><published>2009-11-03T01:17:00.001-08:00</published><updated>2009-11-06T19:27:52.984-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-06T19:27:52.984-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Graphics" /><title>Creating iPhone and Mac icons using Inkscape (Part 1 of 2)</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;In this two part series, I'll give a beginner's guide to creating iPhone and Mac application icons using Inkscape &amp;mdash; a free, vector illustration program. In this first part, I'll talk about the common styles and traits of icons on the Mac and iPhone and give a step-by-step guide to creating the first iPhone icon in Inkscape.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Introduction&lt;/h4&gt;

&lt;p&gt;This series will cover the creation of the following different icons:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SvAqo04PsPI/AAAAAAAAAeg/d5Pvuu0d24I/all-icons.png?imgmax=800" alt="all-icons.png" border="0" width="550" height="111" /&gt;

&lt;p&gt;Only the first icon will be created in this part. The remaining four will be covered in the second part.&lt;/p&gt;

&lt;p&gt;It may seem strange to be covering icon creation in a Cocoa programming blog but the icon is an important part of an application and Cocoa is primarily an application programming environment. While larger development teams have dedicated graphic artists to create icons and other artwork assets, the reality is that on smaller teams or on solo projects, a programmer may need to create icons themselves.&lt;/p&gt;

&lt;p&gt;The goal of this series is to show non-graphics professionals how to create graphics of an acceptable level for their applications that follow the established visual trends for iPhone and Mac apps.&lt;/p&gt;

&lt;h4&gt;A vector approach&lt;/h4&gt;

&lt;p&gt;This post is partly a response to &lt;a href="http://elitebydesign.com/design-the-itunes-icon-for-the-iphone-and-ipod-touch/"&gt;Elite By Design's "Design The iTunes Icon For The iPhone And iPod Touch"&lt;/a&gt; which produced an iTunes-style icon at 125x125 pixels in Photoshop.&lt;/p&gt;

&lt;p&gt;I wanted to show an alternative approach to the one suggested in that article. This alternative approach has the following advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Entirely vector artwork, so it will scale from 57x57 pixels up to 512x512 pixels as required for App Store submissions.&lt;/li&gt;
&lt;li&gt;Rounded corners and gloss are applied to a separate clone of the base artwork so the submission to Apple can be non-prerendered if you choose.&lt;/li&gt;
&lt;li&gt;Created using free software as non-professional artists don't always have access to Photoshop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to detailing iPhone icon creation, the second part will also cover basic Mac icon design.&lt;/p&gt;

&lt;h4&gt;Established styles&lt;/h4&gt;

&lt;p&gt;I continue to be surprised when I look at screenshots of the Windows 7 taskbar.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Su2-d_KQikI/AAAAAAAAAbw/wtr_tUW7Me8/window7taskbar.png?imgmax=800" alt="window7taskbar.png" border="0" width="250" height="40" /&gt;

&lt;p&gt;These are the first four icons that a Windows 7 user sees and they are the strangest collection of graphics I've ever seen. They share no obvious visual style; they are all drawn with different perspective, they all have different weights, some are glossy while others are matte, some have line edges while others are self-edged (no lines) and they don't share a color palette.&lt;/p&gt;

&lt;h5&gt;Icon styles on the Mac&lt;/h5&gt;

&lt;p&gt;By contrast, icons on the Mac tend to have more in common:&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Su5HiRMhRkI/AAAAAAAAAb8/LrCUmVxpV8I/dock-icons.png?imgmax=800" alt="dock-icons.png" border="0" width="521" height="78" /&gt;

&lt;p&gt;Ignoring the "Finder" icon (which is actually the "Mac OS" icon and predates Mac OS X by about 5 years), these icons come in three distinct styles:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Document applications (rectangular background angled 5-10&amp;deg; left).&lt;/li&gt;
&lt;li&gt;Appliance applications (round &amp;mdash; or at least non-rectangular &amp;mdash; background).&lt;/li&gt;
&lt;li&gt;Utilities (orthogonal rectangular background).&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Originally, Apple had the guideline that utilities should look like they were "items sitting on a shelf" but only the disk utitilies still follow that guideline.&lt;/p&gt;

&lt;p&gt;In addition to these three categories, the icons tend to:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Have approximately the same weight (fill roughly the same amount of their visual area).&lt;/li&gt;
&lt;li&gt;Use soft gradients, sometimes (but not always) with a light gloss or highlight.&lt;/li&gt;
&lt;li&gt;Use a generally bright but slightly desaturated palette of grays, azure blues, desaturated reds and sandy yellows (utility apps tend to use more blacks and darker colors).&lt;/li&gt;
&lt;li&gt;Indicate their function or concept with an overlayed or nested element.&lt;/li&gt;
&lt;li&gt;Are self-edged and have almost no internal lines (the outline of the icon is sometimes edged for contrast)&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Of course, none of these are immutable but following them will make it easier to create a simple icon that looks like it belongs on the Mac.&lt;/p&gt;

&lt;h5&gt;Icon styles on the iPhone&lt;/h5&gt;

&lt;p&gt;The iPhone has a style that is distinct from the Mac:&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Su5SKqL8VXI/AAAAAAAAAcI/gtN6HQAx5sI/iphone-home-screen.png?imgmax=800" alt="iphone-home-screen.png" border="0" width="240" height="360" /&gt;

&lt;p&gt;Aside from the obvious round cornered background and top-down gloss effect, iPhone icons tend to use:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Strongly saturated colors&lt;/li&gt;
&lt;li&gt;A bright gradient or colorburst in the background&lt;/li&gt;
&lt;li&gt;White silhouetted representative elements over the background&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;There is certainly variation and some icons that follow their own rules entirely (the "Notes" and "App Store" icons have little in common other than the rounded corners) but the easiest path to creating an icon that looks like it belongs on the iPhone is to incorporate these elements.&lt;/p&gt;

&lt;h4&gt;Inkscape&lt;/h4&gt;

&lt;p&gt;The tool that I will use to create the icons is Inkscape. Inkscape is a GPL-licensed SVG-based vector illustration program that you can download from &lt;a href="http://www.inkscape.org/"&gt;inkscape.org&lt;/a&gt;. It is available in a Universal binary for Mac OS X 10.3.9 and newer.&lt;/p&gt;

&lt;a href="http://inkscape.org"&gt;&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Su_OR85EEjI/AAAAAAAAAdY/_-UowpH1Eo0/inkscape.png?imgmax=800" alt="inkscape.png" border="0" width="208" height="241" /&gt;&lt;/a&gt;

&lt;p style="text-align:center;"&gt;&lt;em&gt;A nice multi-purpose icon but clearly not designed with "standard Mac app" as its primary goal.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You will need X11 installed and pre-Snow Leopard users will need an updated version of X11 (download new versions from here: &lt;a href="http://xquartz.macosforge.org/"&gt;http://xquartz.macosforge.org/&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Yes, Inkscape is an X11 program, which means that Open/Save dialogs are non-standard, windows may not come to the front when you expect them too and keyboard shortcuts are all Control-X instead of Command-X. Despite this, Inkscape is generally a good program &amp;mdash; certainly far better than most X11 applications on the Mac.&lt;/p&gt;

&lt;p&gt;If you prefer a different illustration program, most of the techniques in this guide will apply. The Filter Effects and the Path Effects are probably the points that will be most different but I'm sure you can find alternatives.&lt;/p&gt;

&lt;h4&gt;Page area&lt;/h4&gt;

&lt;p&gt;Let's start with a blank document in Inkscape.&lt;/p&gt;

&lt;p&gt;A new document will appear when you start Inkscape or you can create a new document from the "File"&amp;rarr;"New"&amp;rarr;"Default" menu.&lt;/p&gt;

&lt;p&gt;Go to the "File"&amp;rarr;"Document Properties". Set the Default Units to "px" and the custom document size to 57 by 57.&lt;/p&gt;

&lt;p&gt;The reason why we set the units and use the actual pixel sizes in a vector program is this will let us align points to whole value boundaries and avoid unnecessary anti-aliasing. For example, drawing a shape with its edge at Y=0.5 will cause the actual shape border to anti-alias across two different pixels when we render at 57x57 pixels but if we set the shape border's Y coordinates to 1.0, it won't have this problem.&lt;/p&gt;

&lt;p&gt;The page area will now look tiny in the window. You can zoom in using the middle mouse button (click and drag with the middle mouse button to pan) or the "+" key. Alternately, you can zoom the document area to fill the window by pressing the "5" key.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Zooming&lt;/strong&gt;: you will need to be comfortable with zooming in the program. The "+" and "-" keys will zoom in and out at any time. The 3 key will zoom to the selection and 4 will show all drawn elements. Clicking and dragging the middle mouse button will pan the document, clicking the middle mouse button will zoom and shift-middle mouse will zoom out.&lt;/blockquote&gt;

&lt;h4&gt;Creating the glossy round rectangle&lt;/h4&gt;

&lt;p&gt;The Tool Area is the column of buttons down the left side of the window. The 5th tool from the top is the rectangle tool.&lt;/p&gt;

&lt;h5&gt;Red round rectangle&lt;/h5&gt;

&lt;p&gt;Using the rectangle tool, drag out a rectangle to fill the document area.&lt;/p&gt;

&lt;p&gt;Open the Fill and Stroke palette (menu item "Object"&amp;rarr;"Fill and Stroke" or Control-Shift-F). With the rectangle we created selected in the window, select the Stroke tab of the Fill and Stroke Palette. Make certain there is no stroke (the "X" icon should be selected). Select the Fill tab of the palette. Set a solid color fill (the solid square icon) and use the sliders to set a bright red fill (this is just so that we can see the shape easily).&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/Su_JJ2MFq9I/AAAAAAAAAdQ/RAsa5hewfKM/fill-and-stroke-palette.png?imgmax=800" alt="fill-and-stroke-palette.png" border="0" width="450" height="287" /&gt;

&lt;blockquote&gt;&lt;strong&gt;Quick colors&lt;/strong&gt;: you can also set solid fill and stroke colors on the selected object by left clicking (fill) or shift-left-clicking (stroke) a swatch at the bottom of the window.&lt;/blockquote&gt;

&lt;p&gt;We now need to edit the rectangle properties. Using the rectangle tool again, click the rectangle to select it (if it isn't already selected). In rectangle edit mode, a toolbar will appear at the top of the window labelled "Change" with coordinates "W", "H", "Rx" and "Ry". Set the "W" and "H" to 57 &amp;mdash; this will make the rectangle exactly 57 pixels wide and high (if the rectangle auto-locked to the edges of the document, these values may already be set). Set the "Rx" and "Ry" to 10 &amp;mdash; this will set the corner radii to 10 (a round rect).&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Su_Jn4WeKnI/AAAAAAAAAdU/FWj-ddbVaCc/round-rect.png?imgmax=800" alt="round-rect.png" border="0" width="455" height="380" /&gt;

&lt;blockquote&gt;&lt;strong&gt;Numerical accuracy&lt;/strong&gt;: I'm going to quote a lot of coordinates and color values in this post but this is only so I can communicate what I'm doing. Most of the time, you do not need to be pixel accurate and can do things more approximately if you prefer.&lt;/blockquote&gt;

&lt;p&gt;Using the selection tool (the first tool in the Tool Area) select the rectangle. The object's "X" and "Y" coordinates will appear in the toolbar at the top. Set these to zero. The rectangle is now exactly the size of the document with round corners.&lt;/p&gt;

&lt;h5&gt;The gloss round rectangle&lt;/h5&gt;

&lt;p&gt;Copy the red round rectangle object (select it and press Control-C) and paste it (Control-V) somewhere else (when pasted, the object will be centered where the mouse is, so place the mouse over a different part of the document).&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Copy and Paste bug&lt;/strong&gt;: if the Copy and Paste fails (you get a bitmap instead of a proper editable object or nothing seems to happen), then you may be seeing a bug in Inkscape due to recent X11 changes. To work around this bug, go to the X11 preferences and on the Pasteboard tab, disable "Update Pasteboard when CLIPBOARD changes". Alternatively, you can use "Edit"&amp;rarr;"Duplicate" to duplicate without copying.&lt;/blockquote&gt;

&lt;p&gt;With the copy selected, go to the Fill tab of the Fill and Stroke palette. Set a radial fill for the object (4th icon from the left at the top). If you've set the red color, then the radial gradient will initially look like a red dot fading outwards.&lt;/p&gt;

&lt;p&gt;Click the "Edit" button in the Fill tab to edit the gradient. In the "Gradient Editor" that appears, the popup menu at the top will contain two items (the opaque red color and the fully transparent red color). Hit the "Add Stop" button twice to add two extra items in the gradient.&lt;/p&gt;

&lt;p&gt;Edit the topmost item in the list of colors (the opaque red color) and set it to white with an alpha value of 86. Set the second item to white with an alpha of 75. Set the third to black with an alpha of 60. Set the final item to white aith an alpha of 0.&lt;/p&gt;

&lt;p&gt;You also need to set the offset of the two middle colors. The black color should have an offset of 0.63. The white color should have an offset of 0.62.&lt;/p&gt;

&lt;p&gt;This round rectangle should now look like a faint gray donut. Select it and set its "X" and "Y" coordinates to (0,0) (so that it perfectly overlaps the original red round rectangle).&lt;/p&gt;

&lt;p&gt;With the faint gray donut selected, choose the Gradient Tool (second last in the Tool Area &amp;mdash; if your vertical screen resolution isn't very high, you may need to select the Gradient Tool from the popup menu at the bottom of the Tool Area). An "L" shape of control points should appear over the donut.&lt;/p&gt;

&lt;p&gt;Drag the control point that appears in the middle of the donut to the middle of the top edge of the round rect (it should lock onto the point with the text "Handle to bounding box").&lt;/p&gt;

&lt;p&gt;Drag the round control point at the end of the horizontal arm of the "L" to X=-50. You can see the "X" value of the cursor at the bottom right of the window. Hold down the "Control" key while doing this to ensure that the "Y" value remains the same. Similarly, drag the round control point at the end of the vertical arm to Y=12.&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Su_OtaO6UNI/AAAAAAAAAdc/9XU4VRXloOI/gradient-control-points.png?imgmax=800" alt="gradient-control-points.png" border="0" width="500" height="270" /&gt;

&lt;p&gt;On the Stroke tab of the Fill and Stroke palette, set a linear gradient stroke (third icon from the left at the top) for the gloss object. On the Stroke Style tab, set the line width to 1.0 px.&lt;/p&gt;

&lt;p&gt;On the Stroke tab, edit the gradient. Set the start color to white and the end color to RGBA=(255,255,255,0). Using the Gradient Tool, select the gloss object. There should now be an extra set of control points in a horizontal line across the middle of the object corresponding to the stroke's gradient. Drag the start point  of this line (square control point) to the top right corner of the object and the end point of the line (circular control point) to a position three quarters the way up the right-hand side of the object.&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SvAqCHnzXzI/AAAAAAAAAeY/OyHPG5n9c04/stroke-gradient.png?imgmax=800" alt="stroke-gradient.png" border="0" width="550" height="360" /&gt;

&lt;p&gt;Since the stroke added to the gloss object changed the size of the object, you will need to re-set the size of the gloss object to 57x57 at X,Y=(0,0).&lt;/p&gt;

&lt;p&gt;You should now have a glossy red round rectangle in the style of an iPhone icon. If you know what you're doing in Inkscape, you can move these objects to another layer and hide them now however, it's probably easiest just to save this document and copy these objects when they are needed later.&lt;/p&gt;

&lt;h4&gt;The first iPhone icon&lt;/h4&gt;

&lt;h5&gt;Blue-green background&lt;/h5&gt;

&lt;p&gt;Create a 57 by 57 rectangle at X,Y=(0,0) again, using the same approach as the red rectangle from the previous section but leave the corners square (you may need to explicitly set Rx and Ry to zero since it may remember the radius from before).&lt;/p&gt;

&lt;p&gt;Set the fill of this rectangle to a linear gradient (third icon from the left at the top of the Fill tab in the Fill and Stroke palette). Edit the gradient and set the start point to RGBA=(15,112,126,255) and the end point to RGBA=(0,0,53,255).&lt;/p&gt;

&lt;p&gt;Using the Gradient Tool from the Tool Area, select the rectangle and drag the gradient starting point (the square control point) to the center of the bottom edge of the rectangle. Drag the gradient end point (the round control point) to the center of the top edge of the rectangle.&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Su_Z-LnJJJI/AAAAAAAAAdw/O_6pFldbppw/blue-green-gradient.png?imgmax=800" alt="blue-green-gradient.png" border="0" width="550" height="407" /&gt;

&lt;blockquote&gt;&lt;strong&gt;Gradient colors&lt;/strong&gt;: almost every gradient you use should involve a hue shift. When you want an actual 3D or lighting effect, you can also apply a luminance shift. The gradient here shifts from blue into the green direction as it lightens (a common choice). The other most common gradient would probably be from a darker red or orange towards a lighter yellowy orange. Hues on the green side of yellow or purple hues are rarely ever used.&lt;/blockquote&gt;

&lt;h5&gt;Starburst object&lt;/h5&gt;

&lt;p&gt;Now, using the Stars and Polygons tool from the Tool Area (8th from the top) and drag out a shape (it will probably appear as a 5 point star &amp;mdash; if it isn't a star, click the star icon in the top toolbar). With the Stars and Polygons tool and the object still selected, you should be able to edit the properties of the star. Set the number of corners to 350, the spoke ratio to 0.3 and the Randomized property to 0.015. Choose the Select and Transform tool (first tool in the Tool Area) and select the star. You can now set the width and height both to 87 and the X,Y to (-15,-15).&lt;/p&gt;

&lt;p&gt;In the Fill and Stoke palette, set the opacity of the star to 50%.&lt;/p&gt;

&lt;p&gt;Then, set a radial fill on the star from a start color of RGBA=(255,255,255,0) to an end color of RGBA=(0,235,255,255). This radial gradient fades out in the middle which will help the checkbox stand out from the background more.&lt;/p&gt;

&lt;h5&gt;A blur effect on the starburst&lt;/h5&gt;

&lt;p&gt;With the star object still selected, select the menu item "Filters"&amp;rarr;"ABCs"&amp;rarr;"Simple Blur". Then select the "Filters"&amp;rarr;"Filter Editor..." menu item. This will display the Filter Editor palette.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Space limitations&lt;/strong&gt;: If the Fill and Stroke Palette is still showing when the Filter Editor appears, you'll notice that they don't fit well together down the right margin. I recommend you either close the Fill and Stroke Editor or drag the Filter Editor off into its own window.&lt;/blockquote&gt;

&lt;p&gt;There should be one filter listed in the list of filters &amp;mdash; this is the filter you just created. When you select the filter in the list, the Effect "Gaussian Blur" will appear in the Effect column at the right. Select the Gaussian Blur and the "Effect Parameters" tab will appear at the bottom. Set the "Standard Deviation" to 0.25.&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Su_aO4pc1LI/AAAAAAAAAd0/FucG8cgzj0Y/starburst.png?imgmax=800" alt="starburst.png" border="0" width="550" height="371" /&gt;

&lt;p&gt;You can also apply "Blur" using the Fill and Stroke palette. The blur radius at the bottom of this palette is 2.74 times the Standard Deviation applied here (no, I'm not really sure why the difference is 2.74 times).&lt;/p&gt;

&lt;h5&gt;The checkbox and checkmark objects&lt;/h5&gt;

&lt;p&gt;Now create a 29x29 round rectangle with corner radius 4 at X,Y=(14,14). This is the checkbox. This time, set no fill (the "X" icon on the Fill tab of the Fill and Stroke palette) and set a plain stroke (second icon from the left at the top of the Stroke tab) with a white color. On the "Stroke Style" tab, set the width to 3.0 "px". While here, set the "Cap" to round. It won't matter as much for this object, but we're just about to draw a line and we want it to have round endcaps.&lt;/p&gt;

&lt;p&gt;Select the Bezier Line tool (11th icon down in the Tool Area). Click the mouse and release to create points at X,Y = (19.5,30), (28.5,20) and (47,48). Press the return key when done to finish the path. This is the checkmark. Now select the Node Tool (second icon from the top of the Tool Area) and select the checkmark. Click and hold the mouse in the middle of each line segment and drag up slightly to give the lines a slight curve. You can use the control points to tweak the effect if you're not happy.&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Su_acYjqXsI/AAAAAAAAAd4/TNYVoVawgcc/node-tool.png?imgmax=800" alt="node-tool.png" border="0" width="295" height="292" /&gt;

&lt;h5&gt;Bevel effect and shadow&lt;/h5&gt;

&lt;p&gt;Select the checkmark and the checkbox. From the Filters menu select "Bevels"&amp;rarr;"Ridged Border". Then from the Filters menu select "Shadows and Glows"&amp;rarr;"Drop Shadow", set the blur to 2.0, the opacity to 35%, the offset to (3,3), hit the "Apply" button and close the Drop shadow dialog.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Speed tip&lt;/strong&gt;: when zoomed in on objects using effects, the rendering can get slow. To disable effects or to drop entirely into wireframe mode, choose "No Filters" or "Outline" from the "View"&amp;rarr;"Display Mode" menu or press Control-Keypad5. The "Ridged border" effect is especially slow in the current version of Inkscape &amp;mdash; I recommend zooming out before you apply it and turning effects off before you zoom in close.&lt;/blockquote&gt;

&lt;p&gt;If you want to fully integrate the checkmark and the checkbox, you can convert the checkbox object to a path, the checkmark stroke to a path and then create a union of the two. I'll leave that to you if you're interested.&lt;/p&gt;

&lt;h5&gt;Apply the gloss effect and round corners&lt;/h5&gt;

&lt;p&gt;Select the green gradient background, the starburst, the checkbox and the checkmark and group them all together (Control-G or menu "Object"&amp;rarr;"Group"). This will let you select them all in one go (ungroup with Control-Shift-G or double-click the group to select objects within the group without ungrouping).&lt;/p&gt;

&lt;p&gt;With the group selected, from the Edit menu select "Clone"&amp;rarr;"Create Clone". This will create a copy that continues to update when the original updates. Move the clone to X,Y=(-115.7,-15.7) (this coordinate include extra padding of approximately 2.74 times the starburst's blur standard deviation of 0.25 which is the amount that a blur will expand an object's boundary).&lt;/p&gt;

&lt;p&gt;Now we need the red glossy round rectangle. If you saved them in a different document, copy them into this document now. Select the red background and gloss (drag a rectangle around both using the Selection Tool) and set the X,Y coordinates of the two of them to (100,0). This may make the two objects hidden behind the cloned group objects so press the "Home" key (or select Raise to Top from the Object menu).&lt;/p&gt;

&lt;p&gt;Drag the gloss and the red rectangle off of the objects they are covering (it doesn't matter where you put them). Select the cloned group and the red round rectangle but not the gloss gradient. Undo the two object moves. This should leave the cloned objects and the red round rectangle selected but all of the objects on top of each other. From the Object menu, select "Clip"&amp;rarr;"Set". This should clip the cloned group to the boundary of the red round rectangle, and make the red round rectangle disappear.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Clipping&lt;/strong&gt;: when clipping in Inkscape, the topmost object is always used as the clipping boundary and all other selected objects are clipped to its boundary.&lt;/blockquote&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SvAqLLOREPI/AAAAAAAAAec/p4AYpJ_w6wU/side-by-side.png?imgmax=800" alt="side-by-side.png" border="0" width="444" height="223" /&gt;

&lt;h4&gt;Export the bitmap&lt;/h4&gt;

&lt;p&gt;Congratulations, your iPhone icon is complete.&lt;/p&gt;

&lt;p&gt;You can export the prerendered (cloned, glossed and rounded) version to a PNG by selecting the gloss gradient that's over the clipped shape and selecting "Export Bitmap" from the "File" menu. Make sure that "Selection" is highlighted in the window that appears and set the width and height of the exported image to whatever size you want. Use the Browse button to select a location then hit the export button.&lt;/p&gt;

&lt;p&gt;If you want to send the non-prerendered version to Apple, then select the uncloned group and export from that. 57x57 for the application icon and 512x512 for the high resolution version in your App Store submission.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Resampling&lt;/strong&gt;: You may get a better effect on the small icon if you export at a larger size and use another program (Preview, GIMP, etc) to scale it down. This may give better anti-aliasing performance &amp;mdash; particularly if your resizing program uses Lanczos resampling.&lt;/blockquote&gt;

&lt;p&gt;If you'd like your icon as a PDF, SVG or a number of other vector graphics types, you can choose "Save As..." and save to the format of your choice.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can &lt;a href="http://projectswithlove.com/projects/cocoawithlove-inkscape-icons-part1.svg"&gt;download an Inkscape SVG file containing the final icon&lt;/a&gt; (122kb). Note: Safari and other programs will open SVG files but the effects (shadows, blurs, etc) will only appear if the SVG is opened in Inkscape.&lt;/blockquote&gt;

&lt;p&gt;In the second part, I will go through the steps for other icons, showing different stylistic options and explaining more of the effects and graphical elements you can use to create your icons. I'll look closer at filter effects in Inkscape, creating more sophisticated line paths, using gradients in multiple directions to achieve softer effects and creating simple textures to fill blank areas.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-8239862947234112962?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8239862947234112962?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8239862947234112962?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/11/creating-iphone-and-mac-icons-using.html" title="Creating iPhone and Mac icons using Inkscape (Part 1 of 2)" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;CkQBQ3o7fCp7ImA9WxNVFU4.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-7079014197513352171</id><published>2009-10-25T04:26:00.001-07:00</published><updated>2009-10-25T21:12:32.404-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-25T21:12:32.404-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="fun hacks" /><title>Memory and thread-safe custom property methods</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Objective-2.0 property methods are a nice convenience but if you need to override a property implementation &amp;mdash; particularly an atomic, retained or copied object setter property &amp;mdash; there are some potential bugs you can create if you don't follow the rules carefully. I'll show you the pitfalls and the correct way to implement a property accessor. I'll also show a way to directly invoke hidden runtime functions to let Objective-C perform atomic getting and setting safely for you.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Custom getter and setter methods for implicitly atomic types&lt;/h4&gt;

&lt;p&gt;For implicitly atomic types or for types where memory management doesn't apply, custom getter and setter methods in Objective-C are easy. These "easy" situations include:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Basic value types (&lt;code&gt;char&lt;/code&gt;, &lt;code&gt;short&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt;, &lt;code&gt;long&lt;/code&gt;, &lt;code&gt;double&lt;/code&gt;, etc).&lt;/li&gt;
&lt;li&gt;Objective-C objects in a garbage collected environment&lt;/li&gt;
&lt;li&gt;Assigned (non-retained) pointers&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;For these types, it is pretty hard to get a custom getter or setter method wrong. For the following property declaration:&lt;/p&gt;

&lt;pre&gt;@property SomeAtomicType somePropertyVariable;&lt;/pre&gt;

&lt;p&gt;the custom getter and setter simply look like this:&lt;/p&gt;

&lt;pre&gt;- (SomeAtomicType)somePropertyVariable
{
    return somePropertyVariable;
}
- (void)setSomePropertyVariable:(SomeAtomicType)aValue
{
    somePropertyVariable = aValue;
}&lt;/pre&gt;

&lt;h4&gt;Common mistakes in accessor methods for non-atomic types&lt;/h4&gt;

&lt;p&gt;Non-atomic types require greater care. These types include:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Objective-C objects in a manually managed memory environment&lt;/li&gt;
&lt;li&gt;&lt;code&gt;struct&lt;/code&gt;s and other compound types&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Given how simple custom getter and setter methods are for atomic types, it is easy to be complacent about implementing methods for these types. However, following the wrong approach can lead to memory crash bugs and lack of proper thread safety.&lt;/p&gt;

&lt;p&gt;To illustrate how simple it can be to introduce bugs while implementing a custom setter method, consider the following declared property:&lt;/p&gt;

&lt;pre&gt;@property NSString (copy) someString;&lt;/pre&gt;

&lt;p&gt;A hasty implementation of the setter might be:&lt;/p&gt;

&lt;pre&gt;- (void)setSomeString:(NSString *)aString
{
    [someString release];
    someString = [aString copy];
}&lt;/pre&gt;

&lt;p&gt;This implementation actually contains two bugs:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;&lt;strong&gt;This method is not atomic.&lt;/strong&gt;&lt;br/&gt;The &lt;code&gt;someString&lt;/code&gt; object changes twice: once on &lt;code&gt;release&lt;/code&gt; and again when it is assigned the copied object's address. This method is &lt;em&gt;not&lt;/em&gt; atomic and therefore violates the declaration (which omits the &lt;code&gt;nonatomic&lt;/code&gt; keyword and therefore requires atomicity).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The assignment contains a potential memory deallocation bug.&lt;/strong&gt;&lt;br/&gt;If &lt;code&gt;someString&lt;/code&gt; is ever assigned its own value, it will &lt;code&gt;release&lt;/code&gt; it before &lt;code&gt;copy&lt;/code&gt;ing it, causing potential use of a &lt;code&gt;release&lt;/code&gt;d variable. The code: &lt;code&gt;self.someString = someString;&lt;/code&gt; is an example of this potential issue.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Don't feel too bad if you've ever made these mistakes. I spent some time looking at &lt;a href="http://clang.llvm.org/"&gt;clang's&lt;/a&gt; synthesized method implementations when I was researching this post and I noticed that &lt;a href="http://llvm.org/svn/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp"&gt;they've forgotten to handle struct accessor methods in an atomic manner&lt;/a&gt; when required.&lt;/p&gt;

&lt;h4&gt;Safe implementations of custom accessor methods for non-atomic types&lt;/h4&gt;

&lt;p&gt;To address this second issue, &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html"&gt;Apple's Declared Properties documentation&lt;/a&gt; suggests that your setter methods should look like this:&lt;/p&gt;

&lt;pre&gt;- (void)setSomeString:(NSString *)aString
{
    if (someString != aString)
    {
        [someString release];
        someString = [aString copy];
    }
}&lt;/pre&gt;

&lt;p&gt;This only fixes the memory issue, it doesn't fix the atomicity issue. To handle that, the only simple solution is to used a &lt;code&gt;@synchronized&lt;/code&gt; section:&lt;/p&gt;

&lt;pre&gt;- (void)setSomeString:(NSString *)aString
{
    @synchronized(self)
    {
        if (someString != aString)
        {
            [someString release];
            someString = [aString copy];
        }
    }
}&lt;/pre&gt;

&lt;p&gt;This approach will also work for &lt;code&gt;retain&lt;/code&gt; properties as well (simply replace the &lt;code&gt;copy&lt;/code&gt; method with a &lt;code&gt;retain&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To maintain atomicity, you also need a &lt;code&gt;retain/autorelease&lt;/code&gt; pattern and lock on any getter methods too:&lt;/p&gt;

&lt;pre&gt;- (NSString *)someString
{
    @synchronized(self)
    {
        id result = [someString retain];
    }
    return [result autorelease];
}&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;@synchronized&lt;/code&gt; section is only required around the &lt;code&gt;retain&lt;/code&gt; since that will prevent a setter releasing the value before we can return it (the &lt;code&gt;autorelease&lt;/code&gt; is then safely done outside the section).&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;struct&lt;/code&gt; and other compound data types, we don't need to &lt;code&gt;retain&lt;/code&gt; or &lt;code&gt;copy&lt;/code&gt;, so only the &lt;code&gt;@synchronized&lt;/code&gt; section is required:&lt;/p&gt;

&lt;pre&gt;- (NSRect)someRect
{
    @synchronized(self)
    {
        return someRect;
    }
}
- (void)setSomeRect:(NSRect)aRect
{
    @synchronized(self)
    {
        someRect = aRect;
    }
}&lt;/pre&gt;

&lt;h4&gt;A faster, shorter way to implement custom accessors&lt;/h4&gt;

&lt;p&gt;There are two negative points to the custom accessor methods listed above:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;They need to be coded exactly to avoid bugs.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;@synchronized&lt;/code&gt; section on &lt;code&gt;self&lt;/code&gt; is coarse-grained and slow.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;There is another way to implement these methods that doesn't require as much careful coding and uses much more efficient locking: use the same functions that the &lt;code&gt;synthesized&lt;/code&gt; methods use.&lt;/p&gt;

&lt;p&gt;The following functions are implemented in the Objective-C runtime:&lt;/p&gt;

&lt;pre&gt;id &lt;strong&gt;objc_getProperty&lt;/strong&gt;(id self, SEL _cmd, ptrdiff_t offset, BOOL atomic);
void &lt;strong&gt;objc_setProperty&lt;/strong&gt;(id self, SEL _cmd, ptrdiff_t offset, id newValue, BOOL atomic,
    BOOL shouldCopy);
void &lt;strong&gt;objc_copyStruct&lt;/strong&gt;(void *dest, const void *src, ptrdiff_t size, BOOL atomic,
    BOOL hasStrong);&lt;/pre&gt;

&lt;p&gt;While these functions are implemented in the runtime, they are not declared, so if you want to use them, you must declare them yourself (the compiler will then find their definitions when you compile).&lt;/p&gt;

&lt;p&gt;These methods are much faster than using a &lt;code&gt;@synchronized&lt;/code&gt; section on the whole object because (as shown in their &lt;a href="http://www.opensource.apple.com/source/objc4/objc4-371.2/runtime/Accessors.subproj/objc-accessors.m"&gt;Apple opensource implementation&lt;/a&gt;) they use a finely grained, instance variable only spin lock for concurrent access (although the copy struct function uses two locks following an interface design mixup).&lt;/p&gt;

&lt;p&gt;When you declare these functions, you can also declare the following convenience macros:&lt;/p&gt;

&lt;pre&gt;#define &lt;strong&gt;AtomicRetainedSetToFrom&lt;/strong&gt;(dest, source) \
    objc_setProperty(self, _cmd, (ptrdiff_t)(&amp;dest) - (ptrdiff_t)(self), source, YES, NO)
#define &lt;strong&gt;AtomicCopiedSetToFrom&lt;/strong&gt;(dest, source) \
    objc_setProperty(self, _cmd, (ptrdiff_t)(&amp;dest) - (ptrdiff_t)(self), source, YES, YES)
#define &lt;strong&gt;AtomicAutoreleasedGet&lt;/strong&gt;(source) \
    objc_getProperty(self, _cmd, (ptrdiff_t)(&amp;source) - (ptrdiff_t)(self), YES)
#define &lt;strong&gt;AtomicStructToFrom&lt;/strong&gt;(dest, source) \
    objc_copyStruct(&amp;dest, &amp;source, sizeof(__typeof__(source)), YES, NO)&lt;/pre&gt;

&lt;p&gt;I like to include the "To/From" words so I can remember the ordering of the source and destination parameters. You can remove them if they bother you.&lt;/p&gt;

&lt;p&gt;With these macros, the &lt;code&gt;someString&lt;/code&gt; "copy" getter and setter methods above would become:&lt;/p&gt;

&lt;pre&gt;- (NSString *)someString
{
    return AtomicAutoreleasedGet(someString);
}
- (void)setSomeString:(NSString *)aString
{
    AtomicCopiedSetToFrom(someString, aString);
}&lt;/pre&gt;

&lt;p&gt;and the someRect accessor methods shown above would become:&lt;/p&gt;

&lt;pre&gt;- (NSRect)someRect
{
    NSRect result;
    AtomicStructToFrom(result, someRect);
    return result;
}
- (void)setSomeRect:(NSRect)aRect
{
    AtomicStructToFrom(someRect, aRect);
}&lt;/pre&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Most of the accessor methods I've shown here are atomic but in reality, most Objective-C object accessors are declared &lt;code&gt;nonatomic&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Even if your properties are declared &lt;code&gt;nonatomic&lt;/code&gt;, the memory management rules still apply. These rules are important to follow since they can lead to some very obscure and hard to track down memory bugs.&lt;/p&gt;

&lt;p&gt;The macros I've provided are all for atomic properties. For non-atomic properties the boilerplate assignment code is probably simple enough to remember. If not, you could also use a macro:&lt;/p&gt; &lt;pre&gt;#define &lt;strong&gt;NonatomicRetainedSetToFrom&lt;/strong&gt;(a, b) do{if(a!=b){[a release];a=[b retain];}}while(0)
#define &lt;strong&gt;NonatomicCopySetToFrom&lt;/strong&gt;(a, b) do{if(a!=b){[a release];a=[b copy];}}while(0)&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; following comments below, I realize I omitted to qualify the situations in which these accessors are thread-safe. Specifically:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;These setter methods are only thread-safe if the parameters passed to them are immutable. For mutable parameters, you may need to ensure thread safety between mutations on the parameter and the assignment of the property.&lt;/li&gt;
&lt;li&gt;Atomic accessors only provide thread safety to an instance variable if they are the sole way you access the instance variable. If non-property access is required, you must ensure shared thread safety between property accessor methods and the non-property access.&lt;/li&gt;
&lt;li&gt;Atomic assignment for the "implicitly atomic" types I listed does not mean that all CPUs/cores see the same thing (since each CPU/core could have its own cache of the value) &amp;mdash; it only ensures that value is wholly set without possibility of interruption. If you require all CPUs/core to be synchronized and see the same value at a given moment, then even the "implicitly atomic" types may require &lt;code&gt;volatile&lt;/code&gt; qualifiers or a &lt;code&gt;@synchronized&lt;/code&gt; section around the assignment to flush caches.&lt;/li&gt;
&lt;/ol&gt;


&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-7079014197513352171?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/7079014197513352171?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/7079014197513352171?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/10/memory-and-thread-safe-custom-property.html" title="Memory and thread-safe custom property methods" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;CE8BSH49cSp7ImA9WxNWGUw.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-2347122604201755491</id><published>2009-10-18T02:12:00.001-07:00</published><updated>2009-10-18T17:40:59.069-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-18T17:40:59.069-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Snow Leopard" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="Foundation" /><category scheme="http://www.blogger.com/atom/ns#" term="C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Standard C" /><title>How blocks are implemented (and the consequences)</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;

&lt;p&gt;This post is a look at how clang implements blocks and how this implementation leads to a number of strange behaviors including local variables that end up global, Objective-C objects allocated on the stack instead of the heap, C variables that behave like C++ references, Objective-C objects in non-Objective-C languages, copy methods that don't copy and retain methods that don't retain.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;What blocks are to the compiler&lt;/h4&gt;

&lt;p&gt;Blocks are addressable sections of code implemented inline (inside other functions). The inline-edness can be convenient but the real reason why blocks are different to regular functions and function pointers is that they can reference local variables from the scope of the function surrounding their implementation without the invoker of the block needing to know of the surrounding scope variables' existence.&lt;/p&gt;

&lt;p&gt;A block is implemented internally using two pieces:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;compiled code in the &lt;code&gt;.text&lt;/code&gt; segment of the executable&lt;/li&gt;
&lt;li&gt;a data structure that predominantly contains the values of the variables that the block uses from its surrounding scope&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The compiled code lives in its own separate location and does not actually reside inside inside the code of its surrounding scope. In implementation, the code is a function like any other. If you run:&lt;/p&gt;

&lt;pre&gt;otool -tV MyCompiledExecutable&lt;/pre&gt;

&lt;p&gt;then you'll see your blocks appearing immediately after their surrounding functions with names like &lt;code&gt;___surroundingFunction_block_invoke_21&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So it is not the code which makes blocks special, it is the separate data structure. It is this data structure that I will focus on for the remainder of this post.&lt;/p&gt;

&lt;h4&gt;The block data structure&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://clang.llvm.org/docs/BlockImplementation.txt"&gt;Clang's basic documentation on block implementations&lt;/a&gt; indicates that the data structure describing the block looks something like this:&lt;/p&gt;

&lt;pre&gt;struct Block_literal {
    void *isa;

    int flags;
    int reserved; // is actually the retain count of heap allocated blocks

    void (*invoke)(void *, ...); // a pointer to the block's compiled code

    struct Block_descriptor {
        unsigned long int reserved; // always nil
        unsigned long int size; // size of the entire Block_literal
        
        // functions used to copy and dispose of the block (if needed)
        void (*copy_helper)(void *dst, void *src);
        void (*dispose_helper)(void *src); 
    } *descriptor;

    // Here the struct contains one entry for every surrounding scope variable.
    // For non-pointers, these entries are the actual const values of the variables.
    // For pointers, there are a range of possibilities (__block pointer,
    // object pointer, weak pointer, ordinary pointer)
};&lt;/pre&gt;

&lt;p&gt;Of course, the reality is that this structure is never explicitly declared like this in clang. Clang is a compiler &amp;mdash; a code generator &amp;mdash; and the format of this structure is &lt;em&gt;generated&lt;/em&gt; programmatically from the &lt;a href="http://clang.llvm.org/doxygen/CGBlocks_8cpp-source.html#l00103"&gt;CodeGenFunction::BuildBlockLiteralTmp&lt;/a&gt; method.&lt;/p&gt;

&lt;h4&gt;Stack blocks and global blocks&lt;/h4&gt;

&lt;p&gt;Since the biggest difference between a function pointer and a block is the ability to use variables from the surrounding scope, it is interesting to look at what happens when a block does not reference anything in the surrounding scope.&lt;/p&gt;

&lt;p&gt;Normally, the &lt;code&gt;Block_literal&lt;/code&gt; data appears on the stack (like a regular &lt;code&gt;struct&lt;/code&gt; would in its surrounding function). With no references to the surrounding scope, clang configures the &lt;code&gt;Block_literal&lt;/code&gt; as a &lt;em&gt;global&lt;/em&gt; block instead. This causes the block to appear in a fixed global location instead of on the stack (the &lt;code&gt;flags&lt;/code&gt; value has the &lt;code&gt;BLOCK_IS_GLOBAL&lt;/code&gt; flag set to indicate this at runtime but it's not immediately clear to me if this is ever used).&lt;/p&gt;

&lt;p&gt;The implication of this is that global blocks are never actually copied or disposed, even if you invoke the functions to do so. This optimisation is possible because without any references to the surrounding scope, no part of the block (neither its code nor its &lt;code&gt;Block_literal&lt;/code&gt;) will ever change &amp;mdash; it becomes a shared constant value.&lt;/p&gt;

&lt;h4&gt;Blocks are always objects&lt;/h4&gt;

&lt;p&gt;If you're familiar with how Objective-C objects are declared, the &lt;code&gt;isa&lt;/code&gt; field in the &lt;code&gt;Block_literal&lt;/code&gt; above should be familiar &amp;mdash; blocks are Objective-C objects. This may not seem strange in Objective-C but the reality is that even in pure C or C++, blocks are still Objective-C objects and the runtime support for blocks handles the &lt;code&gt;retain&lt;/code&gt;/&lt;code&gt;release&lt;/code&gt;/&lt;code&gt;copy&lt;/code&gt; behaviors for the block in an Objective-C messaging manner.&lt;/p&gt;

&lt;p&gt;Clang uses the class names &lt;code&gt;_NSConcreteStackBlock&lt;/code&gt; and &lt;code&gt;_NSConcreteGlobalBlock&lt;/code&gt; to refer to the classes for block literals but in CoreFoundation projects, this will map onto &lt;code&gt;NSStackBlock&lt;/code&gt; and &lt;code&gt;NSGlobalBlock&lt;/code&gt;. If you copy an &lt;code&gt;NSStackBlock&lt;/code&gt;, it will return an &lt;code&gt;NSMallocBlock&lt;/code&gt; (indicating its changed allocation location).&lt;/p&gt;

&lt;h4&gt;Blocks are slightly weird objects&lt;/h4&gt;

&lt;p&gt;The interesting point to note about &lt;code&gt;NSStackBlock&lt;/code&gt; is that it is a stack allocated Objective-C object. If you have ever tried to allocate an Objective-C object on the stack (not as a pointer but statically allocated) you'll know that the compiler normally forbids this.&lt;/p&gt;

&lt;p&gt;The reason why blocks are placed on the stack by default is speed. In the common case where the lifetime of the block is less than that of the stack function that contains it, this is a very good optimisation.&lt;/p&gt;

&lt;p&gt;The implication of stack blocks being allocated on the stack, is that a stack block cannot simply be &lt;code&gt;retain&lt;/code&gt;ed &amp;mdash; it will become invalid once the function that contains it is popped from the stack. If you invoke &lt;code&gt;retain&lt;/code&gt; on a stack block, it will have no effect (the retain count of the block will remain at 1).&lt;/p&gt;

&lt;p&gt;For this reason, if you need to return a block from a function or method, you must &lt;code&gt;[[block copy] autorelease]&lt;/code&gt; it, not simply &lt;code&gt;[[block retain] autorelease]&lt;/code&gt; it.&lt;/p&gt;

&lt;h4&gt;__block values can move magically&lt;/h4&gt;

&lt;p&gt;Scope variables used in a block are normally passed to the block by &lt;code&gt;const&lt;/code&gt; value (the compiler won't let you change the value but even if it did, the change wouldn't affect the value of the variable outside the block).&lt;/p&gt;

&lt;p&gt;To alter this behavior, the type specifier &lt;code&gt;__block&lt;/code&gt; was added. Any variable declared &lt;code&gt;__block&lt;/code&gt; is passed by reference into the block (value on the outside will be changed after the block is invoked).&lt;/p&gt;

&lt;p&gt;In the implementation, &lt;code&gt;__block&lt;/code&gt; variables are initially allocated on the stack but if any block which references them is copied, they are moved onto the heap (&lt;code&gt;malloc&lt;/code&gt;ed). This leads to the following strange situation...&lt;/p&gt;

&lt;pre&gt;int (^function())()
{
    __block int x = 0;
    
    int (^block)() = ^{
        x += 1;
        return x;
    };
    
    NSLog(@"x's location is on the stack: %p", &amp;x);
    block = [[block copy] autorelease];
    NSLog(@"x's location is now on the heap: %p", &amp;x);
    
    return block;
}&lt;/pre&gt;

&lt;p&gt;In this example, x's address changes when the copy is invoked. This is because when we declare a &lt;code&gt;__block&lt;/code&gt; variable, a pointer to the real variable is created and any attempt to use the variable dereferences it. When &lt;code&gt;copy&lt;/code&gt; is invoked, the location pointed to by the pointer changes to the new heap location, so any use of &lt;code&gt;x&lt;/code&gt; causes a dereference to this new location.&lt;/p&gt;

&lt;p&gt;This makes &lt;code&gt;__block&lt;/code&gt; similar to to a reference parameter in C++ since C++ references are also transparently dereferenced pointers.&lt;/p&gt;

&lt;h4&gt;NSMallocBlock never actually copies&lt;/h4&gt;

&lt;p&gt;Copying a block doesn't really give you a copy of the block &amp;mdash; if the block is already an &lt;code&gt;NSMallocBlock&lt;/code&gt;, a &lt;code&gt;copy&lt;/code&gt; simply increases the retain count of the block (this retain count is an internal &lt;code&gt;reserved&lt;/code&gt; field &amp;mdash; the &lt;code&gt;retainCount&lt;/code&gt; returned from the object will remain at 1). This is perfectly appropriate since the scope of the block cannot change after it is created (therefore the block is constant) but it does mean that invoking &lt;code&gt;copy&lt;/code&gt; on a block is not the same thing as recreating it.&lt;/p&gt;

&lt;p&gt;Assume the following code is in the same program as the previous example.&lt;/p&gt;

&lt;pre&gt;int (^someBlock)() = counterBlock();
int (^someBlockCopy)() = [[someBlock copy] autorelease];
int (^anotherBlock)() = counterBlock();&lt;/pre&gt;

&lt;p&gt;The block returned from &lt;code&gt;counterBlock()&lt;/code&gt; counts the number of times that it is invoked by saving the count in the &lt;code&gt;__block&lt;/code&gt; variable &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In this example though, &lt;code&gt;someBlock&lt;/code&gt; and &lt;code&gt;someBlockCopy&lt;/code&gt; share the same &lt;code&gt;x&lt;/code&gt; variable &amp;mdash; they are not actually separate copies. However, &lt;code&gt;anotherBlock&lt;/code&gt; does have its own separate &lt;code&gt;x&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;If you need a genuinely separate copy, recreate the block, don't copy it.&lt;/p&gt;

&lt;h4&gt;Blocks retain their NSObject scope variables&lt;/h4&gt;

&lt;p&gt;Blocks will &lt;code&gt;retain&lt;/code&gt; any &lt;code&gt;NSObject&lt;/code&gt; that they use from their enclosing scope when they are copied.&lt;/p&gt;

&lt;p&gt;The biggest implication of this is that you must remember to &lt;a href="http://cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html"&gt;avoid retain cycles&lt;/a&gt; if the block will be held beyond a simple stack lifetime.&lt;/p&gt;

&lt;p&gt;A &lt;a href="http://www.mikeash.com/?page=pyblog/friday-qa-2009-08-14-practical-blocks.html"&gt;pointed out elsewhere&lt;/a&gt;, you can suppress this retain of &lt;code&gt;NSObject&lt;/code&gt;s by assigning the object to a &lt;code&gt;__block&lt;/code&gt; variable outside the block and only ever using the &lt;code&gt;__block&lt;/code&gt; variable inside the block.&lt;/p&gt;

&lt;p&gt;You can also do the reverse of this and force a pointer that isn't an &lt;code&gt;NSObject&lt;/code&gt; derived class to be retained when copied. Do this by declaring the pointer with &lt;code&gt;__attribute__((NSObject))&lt;/code&gt;. Of course, the situations where you'd want to do this are exceedingly rare.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Blocks are very simple to use in the case where you declare one inline and immediately pass into another function but once you need to copy or hold onto a block for a while, there are a number of quirks, some of which I've covered in this post.&lt;/p&gt;

&lt;p&gt;Sadly at this time, &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Blocks/Articles/00_Introduction.html"&gt;Apple's documentation on blocks&lt;/a&gt; is fairly basic and lacking in detail. This is what led me to start looking at clang's source code.&lt;/p&gt;

&lt;p&gt;Of course, you don't need to stare at someone else's C++ code to learn about blocks. There are other sources of lighter, more approachable documentation on the topic. In addition to sources that I've already linked, there's also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mike Ash's colorfully titled "&lt;a href="http://www.mikeash.com/?page=pyblog/friday-qa-2008-12-26.html"&gt;Friday Q&amp;A 2008-12-26&lt;/a&gt;" &amp;mdash; an excellent run-down of potential use-cases for blocks in Objective-C.&lt;/li&gt;
&lt;li&gt;Joachim Bengtsson's &lt;a href="http://thirdcog.eu/pwcblocks/"&gt;Programming with C Blocks&lt;/a&gt; &amp;mdash; a good general summary of most aspects of blocks&lt;/li&gt;
&lt;li&gt;Jim Dovey's Blocks &lt;a href="http://alanquatermain.net/post/138827791/blocks-episode-2-life-cycles"&gt;Episode 2: Life Cycles&lt;/a&gt; &amp;mdash; a look at stack and heap allocation of blocks with diagrams&lt;/li&gt;
&lt;li&gt;clang's &lt;a href="http://clang.llvm.org/docs/BlockLanguageSpec.txt"&gt;BlockLanguageSpec&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-2347122604201755491?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/2347122604201755491?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/2347122604201755491?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html" title="How blocks are implemented (and the consequences)" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;DEcMRXc8fip7ImA9WxNWFE4.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-565887544693158621</id><published>2009-10-12T01:47:00.001-07:00</published><updated>2009-10-13T05:14:44.976-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-13T05:14:44.976-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Standard C" /><title>Objective-C's niche: why it survives in a world of alternatives</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Objective-C remains an impediment for many programmers coming to the Mac or iPhone platforms &amp;mdash; few programmers have ever experienced it before learning Cocoa, forcing two learning curves at once for new Cocoa developers. How did Apple end up with such a weird language? And for a company known to replace CPU architectures and their entire operating system, why does Apple persist with Objective-C? The answer lies in the methods.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Virtual methods&lt;/h4&gt;

&lt;p&gt;Most compiled, object-oriented languages (like C++, Java and C&amp;#9839;) adhere closely to the object-oriented approaches first introduced in &lt;a href="http://en.wikipedia.org/wiki/Simula"&gt;Simula 67&lt;/a&gt; &amp;mdash; in particular the concept of &lt;a href="http://en.wikipedia.org/wiki/Virtual_function"&gt;virtual methods&lt;/a&gt; and how they enable methods to be overridden.&lt;/p&gt;

&lt;blockquote style="width:40%;float:right;font-size:12px;margin-left:10px;"&gt;&lt;strong&gt;Origins in Algol:&lt;/strong&gt; In much the same way that Objective-C is often called a "pure superset" of C, Simula 67 was a "pure superset" of &lt;a href="http://en.wikipedia.org/wiki/ALGOL"&gt;Algol 60&lt;/a&gt;. While &lt;a href="http://en.wikipedia.org/wiki/Fortran"&gt;Fortran&lt;/a&gt; is sometimes remembered as the first high-level language to gain popularity (and disdain), Algol 60 was the first programming language to actually resemble a modern language as it contained the &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;if&lt;/code&gt;/&lt;code&gt;else&lt;/code&gt;, &lt;code&gt;while,&lt;/code&gt; &lt;code&gt;return&lt;/code&gt; and other procedural contructs that are expected now in programming languages. While Algol was rarely used past the 1970's, &lt;a href="http://en.wikipedia.org/wiki/Pascal_(programming_language)"&gt;Pascal&lt;/a&gt; and its descendants closely resemble Algol in syntax.&lt;/blockquote&gt;

&lt;p&gt;In a compiled language, a &lt;a href="http://en.wikipedia.org/wiki/Subroutine"&gt;regular function&lt;/a&gt; (non-overrideable) ends up as a basic memory address. When the function is invoked, the CPU jumps to the memory address.&lt;/p&gt;

&lt;p&gt;Simula 67 introduced &lt;a href="http://en.wikipedia.org/wiki/Virtual_table"&gt;virtual method tables&lt;/a&gt; to adapt this for object-orientation. Instead of basic memory addresses, methods are compiled to row numbers in a table. To get the memory address, the method table is retrieved from the class of the object and the CPU jumps to the address at the specified row.&lt;/p&gt;

&lt;p&gt;Since different objects have different classes, they will have different addresses in their method tables, hereby allowing sublcasses to have different implementations of methods (&lt;a href="http://en.wikipedia.org/wiki/Method_overriding"&gt;method overrides&lt;/a&gt;) to their base classes.&lt;/p&gt;

&lt;h4&gt;Message passing&lt;/h4&gt;

&lt;p&gt;While virtual method tables do introduce a level of indirection that allows method behavior to change from object to object, the offsets into the table and hence the tables themselves all need to be created at compile-time.&lt;/p&gt;

&lt;blockquote style="width:40%;float:right;font-size:12px;margin-left:10px;"&gt;&lt;strong&gt;History of message passing:&lt;/strong&gt; As with object-orientation itself, message passing was inspired by Simula 67 but Simula's message passing (called "Simulation") wasn't for method invocations &amp;mdash; it was instead used for discrete event simulation (mostly queueing and list processing). &lt;a href="http://en.wikipedia.org/wiki/Smalltalk"&gt;Smalltalk&lt;/a&gt; expanded upon this idea by using message passing for method invocation. Smalltalk subsequently inspired the &lt;a href="http://en.wikipedia.org/wiki/Actor_model"&gt;Actor Model&lt;/a&gt; (used in distributed processing) and &lt;a href="http://en.wikipedia.org/wiki/Remote_procedure_call"&gt;remote procedure calls&lt;/a&gt; (RPC). Originally, Smalltalk messages were conceived to have a large amount of metadata (more like the full headers on an email) but eventually, this was simplified down to an approach syntactically similar to Objective-C's current implementation (minus square brackets).&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Message_passing"&gt;Message passing&lt;/a&gt; presents an alternative way of solving the &lt;a href="http://en.wikipedia.org/wiki/Dynamic_dispatch"&gt;method dispatch problem&lt;/a&gt;. Instead of the virtual method's compile-time offsets and tables which don't consult the object (except for its type), message passing sends a unique message identifier to the object itself and the object determines at runtime what action to take.&lt;/p&gt;

&lt;p&gt;There are two important differences here:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Runtime resolution &amp;mdash; so the connection between message identifier and action can be changed at runtime.&lt;/li&gt;
&lt;li&gt;Involvement of the object itself, not just its class.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;On a technical level, the difference between a virtual method table and passing a message identifier is relatively minor (since both are really table lookups and both are actually performed at runtime). The difference ends up being conceptual:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Virtual method table languages generally make it hard or impossible to change the virtual method table contents or pointers at runtime.&lt;/li&gt;
&lt;li&gt;Type safety is essential in a virtual method table language since the compiler may alter table lookups based on type, particularly in cases of multiple inheritance. In message passing systems, type safety is irrelevant to method invocation.&lt;/li&gt;&lt;/ul&gt;

&lt;h4&gt;Why this matters&lt;/h4&gt;

&lt;p&gt;The short answer is that this dynamic message handling in Objective-C makes it much easier to work within a large framework that you didn't create because you can examine, patch and modify elements of that framework on the fly. The most common situation where this is likely to occur is when dealing with an &lt;a href="http://en.wikipedia.org/wiki/Application_framework"&gt;application framework&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The biggest reason for this is that you can add or change methods on existing objects, without needing to subclass them, while they are running. Approaches for this include &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocCategories.html#//apple_ref/doc/uid/TP30001163-CH20-TPXREF141"&gt;categories&lt;/a&gt;, &lt;a href="http://cocoawithlove.com/2008/03/supersequent-implementation.html"&gt;method swizzling&lt;/a&gt; and isa-swizzling.&lt;/p&gt;

&lt;p&gt;This makes the following situations possible:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;You want to add a convenience method to someone else's object (a quick search of my own posts reveals that about a dozens of my own posts involve adding convenience methods to Cocoa classes, e.g. &lt;a href="http://cocoawithlove.com/2008/08/safely-fetching-nsmanagedobject-by-uri.html"&gt;Safely fetching an NSManagedObject by URI&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;You want to change the behavior of a class you didn't (and can't) allocate because it is created by someone else (this is how &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/KeyValueObserving/Concepts/KVOImplementation.html"&gt;Key-Value Observing is implemented in Cocoa&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;You want to treat objects generically and handle potential differences with runtime introspection.&lt;/li&gt;
&lt;li&gt;You want to substitute an object of a completely different class to the expected class (this is used in Cocoa by &lt;a href="http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSProxy_Class/Reference/Reference.html"&gt;NSProxy&lt;/a&gt; to turn a regular object into a distributed object).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These points may seem somewhat mild but they are central to maximizing code reuse when working within someone else's framework: if you need existing code to work differently, you don't need to reimplement the whole class and you don't need to change how it is allocated.&lt;/p&gt;

&lt;p&gt;Languages using virtual method tables can adopt some of these ideas (like the &lt;a href="http://www.boost.org/doc/libs/1_40_0/doc/html/boost/any.html"&gt;boost::any&lt;/a&gt; class or &lt;a href="http://en.wikipedia.org/wiki/C_Sharp_4.0"&gt;C&amp;#9839; 4.0's dynamic member lookup&lt;/a&gt;) but these features have additional restrictions and don't apply to all objects, meaning that they can't be used on purely arbitrary objects (such as those you don't control or didn't create) and so don't help when interacting with someone else's framework.&lt;/p&gt;

&lt;p&gt;Simply put: dynamic message passing instead of virtual method invocations makes Objective-C a much better language for working with a large library or framework that someone has written.&lt;/p&gt;

&lt;h4&gt;The tradeoff&lt;/h4&gt;

&lt;p&gt;The downside to dynamic message invocation is that it is only as fast as virtual method invocation when the message lookup is cached, otherwise it is invariably slower.&lt;/p&gt;

&lt;p&gt;Also, in keeping with the philosophy of a purely dynamic messaging system, Objective-C does not use templates or template metaprogramming and does not have non-dynamic (i.e. non-virtual) methods. This means that Objective-C methods will miss out on the compiler optimizations possible when employing these techniques. Also, since modern programming in C++ is substantially focussed on these features, it can difficult to adapt programs using these ideas to Objective-C.&lt;/p&gt;

&lt;p&gt;Theoretically, Objective-C could implement these features but they are in opposition to the underlying concepts of flexibility and dynamic behavior in Objective-C &amp;mdash; and would shut-down all advantages from the previous section if they were used.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;It's not a coincidence that I write an Objective-C/Cocoa blog, I'm obviously an advocate of the two. In my opinion, Objective-C is the best language for programming situations where you must make extensive use of a framework written by someone else (particularly an application framework). The success of Objective-C in this situation is due to the combination of:&lt;/p&gt;
&lt;ul&gt;&lt;li&gt;speed and precision (from its compiled C roots)&lt;/li&gt;
&lt;li&gt;dynamic flexibility (due to using message passing for method invocations)&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;To frame this conclusion, I'll state that I've written major projects using C/WIN32, C++/PowerPlant, C++/MFC, and Java/Swing/AWT. I've also dabbled in smaller projects using C&amp;#9839;/.Net. In all of these cases I have found the application frameworks to be less flexible and less reusable because they lack the dynamic modifiability of Objective-C.&lt;/p&gt;

&lt;p&gt;As I've stated, I do view Objective-C's strength in the area of application frameworks as a niche (albeit a very large niche). If I were writing a compiler, OS kernel, or a low-level/high-performance library, then I would use C++ (I wouldn't use pure C because I'd miss my abstractions) &amp;mdash; but these are situations where metaprogramming, greater inlining and faster method invocations would trump flexibility concerns. Of course, if you have a project that needs to satisfy all these criteria: then there's always Objective-C++.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-565887544693158621?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/565887544693158621?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/565887544693158621?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/10/objective-c-niche-why-it-survives-in.html" title="Objective-C&amp;#39;s niche: why it survives in a world of alternatives" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;AkIFRH8-fip7ImA9WxNXGEU.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-5233290619796143454</id><published>2009-10-05T20:20:00.001-07:00</published><updated>2009-10-06T21:08:35.156-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-06T21:08:35.156-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Snow Leopard" /><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><category scheme="http://www.blogger.com/atom/ns#" term="C++" /><category scheme="http://www.blogger.com/atom/ns#" term="Standard C" /><title>The ugly side of blocks: explicit declarations and casting.</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Blocks are a welcome addition to C/Objective-C/C++/Objective-C++ with Snow Leopard but they carry with them the worst aspect of Standard C: function pointer declaration and casting syntax. In this post, I'll show you how to understand declarations and casting syntax for blocks and function pointers, even in the worst of scenarios.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Simple block declarations and casting&lt;/h4&gt;

&lt;p&gt;Used as intended (simple inline code implementations) blocks are fairly elegant. This is due to one advantage they offer: in simple cases, you do not need to specify the return type &amp;mdash; it can be inferred from the return statement in the block itself.&lt;/p&gt;

&lt;p&gt;So declaring a block that returns an &lt;code&gt;int&lt;/code&gt; can be as simple as:&lt;/p&gt;

&lt;pre&gt;int (^alwaysReturnIntZero)() = ^{ return 0; };&lt;/pre&gt;

&lt;p&gt;In this case though, an unqualified integral value is correctly assumed to be an &lt;code&gt;int&lt;/code&gt;. If we want the block to return an &lt;code&gt;NSInteger&lt;/code&gt;, we need to either cast the return type or not rely on type inference and declare the return fully:&lt;/p&gt;

&lt;pre&gt;NSInteger (^alwaysReturnNSIntegerZero)() = ^ NSInteger (){ return 0; };&lt;/pre&gt;

&lt;p&gt;Notice that the &lt;em&gt;block literal&lt;/em&gt; (righthand side) does not follow the structure as the &lt;em&gt;block declaration&lt;/em&gt; (lefthand side). The block literal uses a straightforward "caret, return type, parameter list" order but the block declaration uses the C function pointer declaration syntax, which can grow more complex (as I'll show later). At this point though, the two are of similar complexity.&lt;/p&gt;

&lt;p&gt;Casting a block looks much like declaring a block, minus the name of the variable from the declaration.&lt;/p&gt;

&lt;pre&gt;long long (^alwaysReturnLongLongZero)() = (long long (^)())alwaysReturnNSIntegerZero;&lt;/pre&gt;

&lt;p&gt;If you look at what is done here, all that is needed to create a cast for a value to the variable type, is to copy the variable's declaration, put parentheses around the copied declaration and remove the variable name.&lt;/p&gt;

&lt;h5&gt;Function pointers&lt;/h5&gt;

&lt;p&gt;Blocks borrow their syntax from standard C function pointers. In almost all cases, the only difference between a block declaration or cast and a function pointer declaration or cast is the "&lt;code&gt;^&lt;/code&gt;" character is used for the block and the "&lt;code&gt;*&lt;/code&gt;" character is used for the function pointer. e.g.:&lt;/p&gt;

&lt;pre&gt;long long (*fnAlwaysReturnLongLongZero)() = (long long (*)())fnAlwaysReturnNSIntegerZero;&lt;/pre&gt;

&lt;p&gt;Of course, functions cannot be declared inline, so you cannot have function literals in the same way as you can have block literals. However, all other syntactic traits remain the same.&lt;/p&gt;

&lt;h4&gt;Reading declarations correctly&lt;/h4&gt;

&lt;p&gt;Unfortunately, blocks follow the typical C declaration rules which become outright confusing when you try to return something. Before it all gets complicated, I'm going to explain something simple about C declarations.&lt;/p&gt;

&lt;p&gt;Consider how a pointer is declared:&lt;/p&gt;

&lt;pre&gt;int *myVariable;&lt;/pre&gt;

&lt;p&gt;If you're reading this blog at all, you should know that this statement creates a pointer named &lt;code&gt;myVariable&lt;/code&gt; which points to an &lt;code&gt;int&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But the operator used here is a "dereference", it is not the "make a pointer" (address of) operator. The correct way to read this line is:

&lt;ol&gt;
&lt;li&gt;Declare a variable:&lt;br/&gt;
	&lt;code&gt;myVariable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;It can be dereferenced (and by &lt;em&gt;implication&lt;/em&gt; is therefore a pointer)&lt;br/&gt;
	&lt;code&gt;*myVariable&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;If it is deferenced, then the value yielded from the dereference should be treated as an &lt;code&gt;int&lt;/code&gt;:&lt;br/&gt;
	&lt;code&gt;int *myVariable;&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's look at the &lt;code&gt;alwaysReturnIntZero&lt;/code&gt; declaration from above again and we'll apply this same reading to it.&lt;/p&gt;

&lt;pre&gt;int (^alwaysReturnIntZero)() = ^{ return 0; };&lt;/pre&gt;

&lt;ol&gt;
&lt;li&gt;Declare a variable:&lt;br/&gt;
	&lt;code&gt;alwaysReturnIntZero&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;It can be dereferenced to yield block information (and by &lt;em&gt;implication&lt;/em&gt; is therefore a block pointer):&lt;br/&gt;
	&lt;code&gt;^alwaysReturnIntZero&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Its block implementation takes no parameters and returns an &lt;code&gt;int&lt;/code&gt;:&lt;br/&gt;
	&lt;code&gt;int (^alwaysReturnIntZero)()&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach to reading a declaration is quite simple but you'll need to it to follow the next section.&lt;/p&gt;

&lt;h4&gt;Declaring a block that returns a block&lt;/h4&gt;

&lt;p&gt;Imagine you wanted to use a block to compare a &lt;code&gt;double&lt;/code&gt; to an &lt;code&gt;int&lt;/code&gt; and return &lt;code&gt;true&lt;/code&gt; if the &lt;code&gt;double&lt;/code&gt; is greater than the &lt;code&gt;int&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; if the double is equal or smaller. In the simple case, that might look like this:&lt;/p&gt;

&lt;pre&gt;bool (^compareDoubleToInt)(int i, double j) = ^{ return j &gt; i; };&lt;/pre&gt;

&lt;p&gt;Easy enough but imagine now that you want to break this into two pieces:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;A first block which takes only the &lt;code&gt;int&lt;/code&gt; and returns a second block, pre-configured to use this &lt;code&gt;int&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The second block then takes the &lt;code&gt;double&lt;/code&gt;, compares it to its pre-configured &lt;code&gt;int&lt;/code&gt; and returns the result.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;The first block is then a &lt;em&gt;factory block&lt;/em&gt; which creates instances of the second block that operate like the &lt;code&gt;compareDoubleToInt&lt;/code&gt; shown above for a single, pre-configured value of &lt;code&gt;i&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The complete implemention of this would be:&lt;/p&gt;

&lt;pre&gt;bool (^(^newDoubleToIntComparison)(int))(double) =
    ^(int i)
    {
        return Block_copy(^ (double j)
        {
            return j &gt; i;
        });
    };&lt;/pre&gt;

&lt;blockquote&gt;Pay careful attention to the "new" in the name &amp;mdash; this serves to notify that you must use &lt;code&gt;Block_destroy&lt;/code&gt; on any blocks created in this fashion when you're done.&lt;/blockquote&gt;

&lt;p&gt;If everything about the syntax on that first line (the declaration) makes immediate sense to you, then you may consider yourself skilled at syntactic recursion.&lt;/p&gt;

&lt;p&gt;The reason most people find this hard to read is that verbally, we would describe this scenario in a very different order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Declare a variable:&lt;br/&gt;&lt;code&gt;newDoubleToIntComparison&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;It can be dereferenced to yield block information (and by &lt;em&gt;implication&lt;/em&gt; is therefore a block pointer):&lt;br/&gt;
&lt;code&gt;^newDoubleToIntComparison&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The block takes an &lt;code&gt;int&lt;/code&gt; parameter:&lt;br/&gt;&lt;code&gt;(^newDoubleToIntComparison)(int)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Its return value can be dereferenced to yield block information (and by &lt;em&gt;implication&lt;/em&gt; the return value is therefore a block pointer):&lt;br/&gt;
&lt;code&gt;(^(^newDoubleToIntComparison)(int))&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;This returned block takes a &lt;code&gt;double&lt;/code&gt; parameter&lt;br/&gt;&lt;code&gt;(^(^newDoubleToIntComparison)(int))(double)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;And the returned block returns a &lt;code&gt;bool&lt;/code&gt;&lt;br/&gt;&lt;code&gt;bool (^(^newDoubleToIntComparison)(int))(double);&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;If C declarations read from left-to-right, it would be far less confusing. Instead, we have a situation where blocks that return blocks are recursively nested inside each other.&lt;/p&gt;

&lt;p&gt;Of course, most people mitigate this by &lt;code&gt;typedef&lt;/code&gt;'ing absolutely function pointer they ever use. Doing this for the previous block declaration changes it to:&lt;/p&gt;

&lt;pre&gt;typedef bool (^IsDoubleBiggerBlock)(double);
IsDoubleBiggerBlock (^newDoubleToIntComparison)(int);&lt;/pre&gt;

&lt;h4&gt;Functions or methods that return blocks&lt;/h4&gt;

&lt;p&gt;It may also be helpful to see the subtle difference between declaring a block that returns a block and the definition of of a function returns a block.&lt;/p&gt;

&lt;p&gt;Replacing the &lt;em&gt;factory block&lt;/em&gt; with a &lt;em&gt;factory function&lt;/em&gt; in the previous example would lead to:&lt;/p&gt;

&lt;pre&gt;bool (^NewDoubleToIntComparisonFunction(int i))(double)
{
    return (bool (^)(double))Block_copy(^ (double j)
    {
        return j &gt; i;
    });
};&lt;/pre&gt;

&lt;p&gt;This function takes a single &lt;code&gt;int&lt;/code&gt; as its parameter and yet the last component on the function prototype line is &lt;code&gt;(double)&lt;/code&gt;. The &lt;code&gt;int&lt;/code&gt; parameter that the function actually takes and the name of the function are nested inside of the return type (the return type comprises the &lt;code&gt;double&lt;/code&gt; parameter to the right, the caret character and the &lt;code&gt;bool&lt;/code&gt; return value to the left).&lt;/p&gt;

&lt;p&gt;Also notice that you need to cast the output of &lt;code&gt;Block_copy&lt;/code&gt; to have it recognized as the correct return type.&lt;/p&gt;

&lt;p&gt;As with the variable declarations, this nested behaviour is normally considered too annoying, so typedefs are employed to simplify:&lt;/p&gt;

&lt;pre&gt;typedef bool (^IsDoubleBiggerBlock)(double);
IsDoubleBiggerBlock NewDoubleToIntComparisonFunction(int i)
{
    return (IsDoubleBiggerBlock)Block_copy(^ (double j)
    {
        return j &gt; i;
    });
};&lt;/pre&gt;

&lt;p&gt;This has the huge advantage that it puts the function's parameter back where it belongs &amp;mdash; as the last component on the function prototype line.&lt;/p&gt;

&lt;p&gt;An Objective-C method that returns a block is a much simpler situation since the method does not become nested within the return type in the same way. Instead, the return type looks identical to the cast of the returned copied block and the rest of the method remains distinct.&lt;/p&gt;

&lt;pre&gt;- (bool (^)(double))newDoubleToIntComparison:(int)i
{
    return (bool (^)(double))Block_copy(^ (double j)
    {
        return j &gt; i;
    });
}&lt;/pre&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;The declaration of C function pointers is widely regarded as the worst syntax in the language. There is a good reason for this: the information in a function pointer's declaration flows from the most significant components which are nestled on the inside of the declaration to the least significant components which encircle the outside. They could flow left-to-right like a sentence but instead they flow outwards from an identifier somewhere in the middle.&lt;/p&gt;

&lt;p&gt;Sadly, blocks follow in this tradition. All you can do to mitigate the torment is use &lt;code&gt;typedef&lt;/code&gt;'d declarations judiciously and try to keep your blocks simple. They're not really intended for large numbers of parameters and complex return values, anyway.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-5233290619796143454?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/5233290619796143454?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/5233290619796143454?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/10/ugly-side-of-blocks-explicit.html" title="The ugly side of blocks: explicit declarations and casting." /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;CkQBQHgzeyp7ImA9WxNXF0k.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-8219069459936566510</id><published>2009-10-05T03:59:00.001-07:00</published><updated>2009-10-05T03:59:11.683-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-05T03:59:11.683-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Xcode" /><category scheme="http://www.blogger.com/atom/ns#" term="UIKit" /><title>Apologies for Atom/RSS feed issues. Here are the real articles...</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Last week, I updated a large number of old articles (to ensure the code still builds). During the course of these updates, I accidentally duplicated two old articles. Once I noticed, I deleted the duplicates but unfortunately, the duplicates appeared as new posts in many Atom/RSS feeds with a broken/missing link to the actual post.&lt;/p&gt;
&lt;p&gt;If you're looking for the actual location of these articles, you can find them here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://cocoawithlove.com/2008/12/heterogeneous-cells-in.html"&gt;Heterogeneous cells in a UITableViewController&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://cocoawithlove.com/2008/12/instance-variable-to-synthesized.html"&gt;Instance variable to synthesized property (an Xcode user script)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;p&gt;&lt;/p&gt;
&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-8219069459936566510?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8219069459936566510?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8219069459936566510?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/10/apologies-for-atomrss-feed-issues-here.html" title="Apologies for Atom/RSS feed issues. Here are the real articles..." /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;CkYGSXY8eyp7ImA9WxNXEkw.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-7513338720496225171</id><published>2009-09-28T18:51:00.001-07:00</published><updated>2009-09-29T00:42:08.873-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-29T00:42:08.873-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cocoa Touch" /><category scheme="http://www.blogger.com/atom/ns#" term="Foundation" /><title>Optimizing the loading of a very large table on the iPhone</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;In this post, I look at a &lt;code&gt;UITableView&lt;/code&gt; on the iPhone which loads its data from a server and look at how its performance scales from single rows to tens of thousands of rows. I'll examine which aspects of the iPhone scale well and which become a burden as a displayed dataset moves from trivially sized to large sizes.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Last week, I received an email asking if &lt;a href="http://projectswithlove.com/streamtome"&gt;StreamToMe&lt;/a&gt;  would be able to handle 20,000 files in a media collection. This person probably meant "20,000 files categorized into subfolders" but the performance geek in me immediately thought that 20,000 files in a single directory was a far more interesting question.&lt;/p&gt;

&lt;p&gt;It's easy to find programs on the iPhone that become slower and less responsive when dealing with tables that only contain a few hundred rows. In my own experience, I've rarely tested with more than a couple hundred items in a &lt;code&gt;UITableView&lt;/code&gt;. I had no idea what a &lt;code&gt;UITableView&lt;/code&gt; would do with 20,000 items.&lt;/p&gt;

&lt;p&gt;Purely looking at data sizes, it seems like it should work: the 128MB versions of the iPhone (all devices prior to the 3Gs) allow applications to use between 24MB and 64MB of RAM before they are killed for excess memory use. This should allow for between 1-3kB per row within available memory &amp;mdash; far more than I need.&lt;/p&gt;

&lt;p&gt;Of course, this won't be a synthetic test with efficient but trivial rows: this is a program with real data, transferred from a server, parsed, constructed and displayed, which must remain capable of media playback after everything else is loaded into memory.&lt;/p&gt;

&lt;h4&gt;Generating test data&lt;/h4&gt;

&lt;p&gt;I wanted real test data so I decided to replicate a small MP3 file on the server. I used a 1 kilobyte file containing a single tone that plays for 4 seconds. I used UUID strings appended with ".mp3" for filenames so that file sorting algorithms would still have some real work to do.&lt;/p&gt;

&lt;pre&gt;for (NSInteger i = 0; i &lt; MAX_FILES; i++)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
    CFUUIDRef uuid = CFUUIDCreate(NULL);
    NSString *uuidString = (NSString *)CFUUIDCreateString(NULL, uuid);
    CFRelease(uuid);
    [uuidString autorelease];

    NSString *filePath =
        [directoryPath stringByAppendingPathComponent:
            [NSString stringWithFormat:@"%@.mp3", uuidString]];
    [[NSFileManager defaultManager]
        createFileAtPath:filePath
        contents:mp3Data
        attributes:nil];
    
    if ((i % 1000) == 0)
    {
        NSLog(@"%ld files remaining.", MAX_FILES - i);
    }
    
    [pool drain];
}&lt;/pre&gt;

&lt;p&gt;Using this code, I created directories with 1, 10, 100, 1000, 10,000, 20,000, 100,000 and 1,000,000 files to see how far I would get with the application.&lt;/p&gt;

&lt;p&gt;A few interesting points came out of this work, unrelated to the iPhone itself:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Yes, you can now create more than 65536 files in a directory. I remember when Macs couldn't create more than 65536 files on the entire disk.&lt;/li&gt;
&lt;li&gt;Curiously, when you select files and use the "Copy" menu item in the Finder, the maximum number of items is still 65536.&lt;/li&gt;
&lt;li&gt;Don't try to drag 10,000 (or more) items from one window to another &amp;mdash; I gave up watching the beachball on this action and hard-booted.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-[NSFileManager createFileAtPath:contents:attributes:]&lt;/code&gt; is a little slower than other approaches because it creates the file in a temporary location and moves it to the target location (a single create at the target location would have been faster).&lt;/li&gt;
&lt;li&gt;if you try to create a million MP3s on your computer, be prepared to wait 3 hours while it churns away and then have the Spotlight metadata indexer slow your computer down for a further few hours.&lt;/li&gt;&lt;/ul&gt;

&lt;h4&gt;Initial results&lt;/h4&gt;

&lt;p&gt;Which data sets will load and how long will they take? With no preparation of StreamToMe in anticipation of this test, I immediately pointed it at the test directories.&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;&lt;tr&gt;&lt;td&gt;Number of files&lt;/td&gt;&lt;td&gt;Total time from touch event to display of directory&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;131ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;128ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;100&lt;/td&gt;&lt;td&gt;424ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1,000&lt;/td&gt;&lt;td&gt;3,108ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;10,000&lt;/td&gt;&lt;td&gt;30,587ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;20,000&lt;/td&gt;&lt;td&gt;64,191ms&lt;strong&gt;*&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;100,000&lt;/td&gt;&lt;td&gt;N/A&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1,000,000&lt;/td&gt;&lt;td&gt;N/A&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;&lt;em&gt;The asterisk here indicates that the 20,000 row run was not able to reliably play the audio files after loading (it would sometimes quit due to low memory). The one hundred thousand and million row tests both failed to load at all.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;All tests performed on an iPhone 3G connected via 802.11g to a Mac Pro Quad 2.66Ghz (the iPhone was also connected to the Mac Pro via USB for logging purposes). Times are taken from a single cold run.&lt;/blockquote&gt;

&lt;h4&gt;Initial analysis&lt;/h4&gt;

&lt;h5&gt;Scaling&lt;/h5&gt;

&lt;p&gt;Looking first at the way the results scale, this table shows the expected behavior with the iPhone's memory arrangement:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;The iPhone has a 16k data cache so tests that operate within this limit (fewer than a couple hundred rows) are more bound by the network latency and fixed-duration setup costs than any row-specific work performed. This leads to better than linear (less than O(n)) scaling for the 1, 10 and 100 tests.&lt;/li&gt;
&lt;li&gt;Tests that exceed the 16k data limit (one thousand through twenty thousand) scale almost perfectly linearly as they push a consistent amount of data through main memory.&lt;/li&gt;
&lt;li&gt;There is no virtual memory on the iPhone, so you don't see a greater than linear increase in time as memory runs out (thrashing) &amp;mdash; instead, there's an abrupt point at which things simply fail. More memory will not make a iPhone faster in the same way that it will make a memory constrained Mac faster.&lt;/li&gt;&lt;/ol&gt;

&lt;h5&gt;Speed&lt;/h5&gt;

&lt;p&gt;Looking at performance, it's a little disappointing &amp;mdash; no one would want to wait over a minute for their file list to load. Where is that time taken? Looking at timing results for the 20,000 row test:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;6,563ms on the server, loading the directory listing and formatting the response.&lt;/li&gt;
&lt;li&gt;3,111ms transferring data.&lt;/li&gt;
&lt;li&gt;12,771ms on the client parsing the response from the server.&lt;/li&gt;
&lt;li&gt;32,098ms on the client converting the parsed response into row-ready classes&lt;/li&gt;
&lt;li&gt;9,453ms in autorelease pool cleanup&lt;/li&gt;&lt;/ul&gt;

&lt;h5&gt;Memory use&lt;/h5&gt;

&lt;p&gt;The memory footprint with 20,000 files loaded is around 6.8MB with peak memory use of 38.2MB. This leads to two questions:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;With final memory so low, why is the program behaving as though its memory is constrained?&lt;/li&gt;
&lt;li&gt;What is causing the peak memory to be so high? If it were much lower, 100,000 rows might be possible.&lt;/li&gt;&lt;/ol&gt;

&lt;h4&gt;Code changes and improvements&lt;/h4&gt;

&lt;h5&gt;stat is the biggest constraint on filesystem lookups&lt;/h5&gt;

&lt;p&gt;The first change I made was on the server. 6.5 seconds to load 20,000 files is too slow. The key constraining factor here is reading the basic metadata for tens of thousands of small files. The low level file function &lt;code&gt;stat&lt;/code&gt; (or in this case, &lt;code&gt;lstat&lt;/code&gt;) is the limiting factor.&lt;/p&gt;

&lt;p&gt;Technically, I wasn't using &lt;code&gt;lstat&lt;/code&gt; but &lt;code&gt;-[NSFileManager contentsOfDirectoryAtPath:error:]&lt;/code&gt; was invoking it for every file and then &lt;code&gt;-[NSFileManager fileExistsAtPath:isDirectory:]&lt;/code&gt; was invoking it again to see if each file was a directory.&lt;/p&gt;

&lt;p&gt;In 10.6, you can replace &lt;code&gt;-[NSFileManager contentsOfDirectoryAtPath:error:]&lt;/code&gt; with &lt;code&gt;-[NSFileManager contentsOfDirectoryAtURL:includingPropertiesForKeys:options:error:]&lt;/code&gt; so that these two commands can be rolled into one (halving the number of calls to &lt;code&gt;lstat&lt;/code&gt;). I want to keep 10.5 compatibility, so instead, I wrote my own traversal using &lt;code&gt;readdir&lt;/code&gt; and &lt;code&gt;lstat&lt;/code&gt; directly.&lt;/p&gt;

&lt;p&gt;This change doubled the directory reading speed of the server.&lt;/p&gt;

&lt;h5&gt;Lowering memory footprint&lt;/h5&gt;

&lt;p&gt;In Cocoa, peak memory is often caused by autoreleased memory that accumulates during loops. You can address this by inserting &lt;code&gt;NSAutoreleasePool&lt;/code&gt; allocations and drains into your loops but this is slow. The best approach is to eliminate autoreleased memory in memory constrained areas. I did this throughout the parsing and conversion code on the iPhone.&lt;/p&gt;

&lt;p&gt;There was also some unnecessary copying of memory (from the network data buffer to an NSString and back to a UTF8 string) that I removed (by passing the network data buffer directly as the UTF8 string).&lt;/p&gt;

&lt;p&gt;More than simply lowering the memory footprint, these changed almost doubled the speed of parsing on the iPhone.&lt;/p&gt;

&lt;h5&gt;Memory fragmentation&lt;/h5&gt;

&lt;p&gt;Even after lowering peak memory usage, I still encountered out of memory errors when trying to allocate larger objects, even though my memory usage was only 16MB.&lt;/p&gt;

&lt;p&gt;After some investigation, I realized that my parser was fragmenting memory by allocating smaller and larger string fragments in a leapfrogging effect so that consecutive strings in the final data structure were not actually adjacent in memory. Even though memory usage was only around 50%, there was not a single, contiguous 2MB space within this for media loading and playback due to the scattered pattern of string, array and dictionary allocations following parsing.&lt;/p&gt;

&lt;p&gt;The simplest solution (one that didn't involve rewriting the parser) was to copy the parsed data every few rows into properly contiguous locations, releasing the old non-contiguous locations. After this, memory allocation issues went away.&lt;/p&gt;

&lt;p&gt;Of course, this did result in a minor increase in parsing time but the improved memory performance was worth the minor performance cost.&lt;/p&gt;

&lt;h5&gt;Moving work out of critical loops&lt;/h5&gt;

&lt;p&gt;Finally, I looked at the conversion of parsed data into classes representing each row. This work was primarily assigning strings to properties of an object and couldn't be easily avoided.&lt;/p&gt;

&lt;blockquote&gt;Of course, in an ideal case, parsing and object construction would be an integrated process but since the parser is generic and wasn't written for this program, it doesn't produce data in the best format, requiring this extra "converting" pass through the data. For development time constraints, I didn't consider integrating these two components although this is certainly a point where further speed improvements could be gained.&lt;/blockquote&gt;

&lt;p&gt;During this process, I also created an &lt;code&gt;NSInvocation&lt;/code&gt; for each object to handle its user-interface action when tapped in the table (media rows play the file, folder rows open the folder) and assigned a named &lt;code&gt;UIImage&lt;/code&gt; (either the file or the folder icon) to the object.&lt;/p&gt;

&lt;p&gt;Since there are only two images and two possible actions, these objects could be created outside the loop and either minimally modified for each row (with different parameters in the case of the &lt;code&gt;NSInvocation&lt;/code&gt;) or assigned as-is (in the case of the &lt;code&gt;UIImage&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;These seemingly tiny changes (in addition to the memory changes mentioned above) resulted in a better than tenfold performance increase for the converting stage (which had been the most time consuming stage).&lt;/p&gt;

&lt;h4&gt;Results revisited&lt;/h4&gt;

&lt;p&gt;With these changes, the results became.&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;&lt;tr&gt;&lt;td&gt;Number of files&lt;/td&gt;&lt;td&gt;New time taken&lt;/td&gt;&lt;td&gt;Old time taken&lt;/td&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;135ms&lt;/td&gt;&lt;td&gt;131ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;137ms&lt;/td&gt;&lt;td&gt;128ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;100&lt;/td&gt;&lt;td&gt;250ms&lt;/td&gt;&lt;td&gt;424ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1,000&lt;/td&gt;&lt;td&gt;845ms&lt;/td&gt;&lt;td&gt;3,108ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;10,000&lt;/td&gt;&lt;td&gt;7,998ms&lt;/td&gt;&lt;td&gt;30,587ms&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;20,000&lt;/td&gt;&lt;td&gt;14,606ms&lt;/td&gt;&lt;td&gt;64,191ms&lt;strong&gt;*&lt;/strong&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;100,000&lt;/td&gt;&lt;td&gt;84,594ms&lt;/td&gt;&lt;td&gt;N/A&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;1,000,000&lt;/td&gt;&lt;td&gt;N/A&lt;/td&gt;&lt;td&gt;N/A&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;The 20,000 row test case now runs more than 4 times faster and the 100,000 test case completes successfully and can play the audio files once loaded.&lt;/p&gt;

&lt;h4&gt;Running one million rows in the simulator&lt;/h4&gt;

&lt;p&gt;The million row test set involved 121MB of data sent over the network &amp;mdash; it was never going to work on a 128MB iPhone.&lt;/p&gt;

&lt;p&gt;Without the memory constraints of the iPhone, I ran a million rows in the simulator. It took 7.5 minutes to load (almost entirely bound by &lt;code&gt;lstat&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;After around 800,000 rows (40 pixels high each), &lt;code&gt;UITableView&lt;/code&gt; can no longer address each pixel accurately with single precision &lt;code&gt;CGFloat&lt;/code&gt;s used on the iPhone, so every second row was misplaced by 16 pixels or so making the result almost unreadable beyond that point. In short: &lt;code&gt;UITableView&lt;/code&gt; isn't really meant to handle a million rows.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;The iPhone &lt;em&gt;can&lt;/em&gt; handle tables with 100,000 rows &amp;mdash; and it continues to scroll as smoothly as though it were only 100 rows.&lt;/p&gt;

&lt;p&gt;Optimization doesn't mean writing assembly code and bleeding from your fingernails. A couple hours work resulted in a 4 times performance increase and dramatically better memory usage from very simple code rearrangement.&lt;/p&gt;

&lt;p&gt;The biggest improvements to the performance came from three points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;replacing autoreleased objects with tight alloc and release pairs in just two loops (in some cases removing the allocation entirely)&lt;/li&gt;
&lt;li&gt;removing the &lt;code&gt;NSInvocation&lt;/code&gt; generation and &lt;code&gt;UIImage&lt;/code&gt; lookup work from the key construction loop&lt;/li&gt;
&lt;li&gt;reducing the calls to lstat on the server (although this wasn't part of iPhone &lt;code&gt;UITableView&lt;/code&gt; optimization per se)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And increasing available productive memory actually involved performing &lt;em&gt;more&lt;/em&gt; allocations &amp;mdash; reallocating discontiguous collections of objects to contiguous memory locations. There was also the typical elimination of unnecessary copying.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-7513338720496225171?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/7513338720496225171?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/7513338720496225171?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/09/optimizing-loading-of-very-large-table.html" title="Optimizing the loading of a very large table on the iPhone" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;DUINRH49eip7ImA9WxNQFks.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-8675602142342917179</id><published>2009-09-22T17:59:00.001-07:00</published><updated>2009-09-22T17:59:55.062-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-22T17:59:55.062-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="self promotion" /><title>StreamToMe Version 1.1 available</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;The latest version of &lt;a href="http://projectswithlove.com/streamtome/index.html"&gt;StreamToMe&lt;/a&gt; &amp;mdash; for streaming audio and video from your Mac to your iPhone/iPod Touch &amp;mdash; is &lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=325327899&amp;mt=8"&gt;now available on the App Store&lt;/a&gt;. It has only been one month &lt;a href="http://cocoawithlove.com/2009/08/streamtome-iphone-app-released.html"&gt;since I released version 1.0&lt;/a&gt; but I have lots of new changes to share.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;New Features&lt;/h4&gt;

&lt;blockquote&gt;You will need to &lt;a href="http://projectswithlove.com/streamtome/servetome.html"&gt;download the latest version of ServeToMe&lt;/a&gt; to take advantage of these new features.&lt;/blockquote&gt;

&lt;h5&gt;The "Seek to anywhere" update&lt;/h5&gt;
&lt;p&gt;StreamToMe version 1.1 adds a number of requested features, most prominent of which is "seek to anywhere". You no longer need to wait for the end of the file to be encoded  before you jump ahead &amp;mdash; you can seek to anywhere at anytime and it will "just work".&lt;/p&gt;

&lt;h5&gt;Remote WiFi and 3G access&lt;/h5&gt;

&lt;p&gt;StreamToMe now supports connections via 3G and from non-local WiFi locations. Bitrates between 96k and 1600k are chosen by the iPhone based on the available data rate. These lower bitrates are also available on local WiFi connections for situations where interference means a lower bitrate is required.&lt;/p&gt;

&lt;p&gt;A remote connection requires that you have configured your Mac's network to make ServeToMe's port accessible remotely. This configuration is left to you since it is dependent on how you are connected to the internet, your modem/router and firewalls.&lt;/p&gt;

&lt;h5&gt;Password protection&lt;/h5&gt;

&lt;p&gt;To protect access to your files (especially when made available over the internet) you can now password protect the server.&lt;/p&gt;

&lt;h4&gt;Minor changes and fixes&lt;/h4&gt;

&lt;p&gt;Of course, there are numerous little fixes and changes too:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fixed playback of many common MOV codecs, so many more Quicktime MOV files will be supported.&lt;/li&gt;
&lt;li&gt;The server now only encodes video as needed, resulting in much lower average CPU usage.&lt;/li&gt;
&lt;li&gt;Fixes for occasional broken socket (network dropout) problems on Snow Leopard.&lt;/li&gt;
&lt;li&gt;Fixes for session ID problems that caused "The requested file couldn't be converted for streaming" to be incorrectly sent for supported files.&lt;/li&gt;
&lt;li&gt;Scroll indexes now used for large directories.&lt;/li&gt;
&lt;li&gt;Shinier file and folder icons.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Still coming...&lt;/h4&gt;

&lt;p&gt;I can't deliver everything all at once but the following frequently requested features are still planned for a future version:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows support for ServeToMe&lt;/li&gt;
&lt;li&gt;Alternate audio tracks&lt;/li&gt;
&lt;li&gt;Subtitles&lt;/li&gt;
&lt;li&gt;Thumbnail previews&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Screenshots&lt;/h4&gt;

&lt;p&gt;Here are some screenshots of the updated application in action:&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/SrlxR7MQ8BI/AAAAAAAAAaQ/fbFO4JG4Zks/screenshot3.png?imgmax=800" alt="screenshot3.png" border="0" width="160px" height="240px" style="display:inline;" /&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/SrlxU2QUiiI/AAAAAAAAAaU/Q7v2DwGq7Ng/screenshot1.png?imgmax=800" alt="screenshot1.png" border="0" width="160px" height="240px" style="display:inline;" /&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SrlxcJa1s4I/AAAAAAAAAaY/3AhX_TP2o5w/screenshot5.png?imgmax=800" alt="screenshot5.png" border="0" width="240px" height="160px" style="display:inline;" /&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-8675602142342917179?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8675602142342917179?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8675602142342917179?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/09/streamtome-version-11-available.html" title="StreamToMe Version 1.1 available" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;CkEBRHg5cSp7ImA9WxNQFUo.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-8806801813903010920</id><published>2009-09-21T06:08:00.001-07:00</published><updated>2009-09-21T15:04:15.629-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-21T15:04:15.629-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Snow Leopard" /><category scheme="http://www.blogger.com/atom/ns#" term="WebKit" /><category scheme="http://www.blogger.com/atom/ns#" term="AppKit" /><title>WhereIsMyMac, a Snow Leopard CoreLocation project</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;In Snow Leopard, you can ask for the computer's location. Without a GPS, how accurate could that be? The answer in my case is: very accurate. In this post, I'll show you how to write a CoreLocation app for the Mac that shows the current location in Google Maps, so you can see exactly where your computer thinks it is.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Where Is My Mac?&lt;/h4&gt;
&lt;p&gt;In this post, I present the following sample project:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/SrdpBa7eVbI/AAAAAAAAAZ8/uHhMk6yR0iQ/whereismymac.png?imgmax=800" alt="whereismymac.png" border="0" width="405" height="476" /&gt;

&lt;blockquote&gt;You can download the Xcode 3.2 project here: &lt;a href="http://projectswithlove.com/projects/WhereIsMyMac.zip"&gt;WhereIsMyMac.zip&lt;/a&gt; (33kB). Mac OS X 10.6 is required.&lt;/blockquote&gt;

&lt;p&gt;The program shows your current location, centered in the map. The zoom level is set so that the accuracy radius reported by CoreLocation is exactly half the width of the window.&lt;/p&gt;

&lt;p&gt;So how accurate is it? For me, my actual location was within about 50 meters of the detected location.&lt;/p&gt;

&lt;p&gt;First, I'll talk about the extremely simple code involved. Afterwards, I'll discuss how CoreLocation gets this information.&lt;/p&gt;

&lt;h4&gt;Implementation&lt;/h4&gt;

&lt;p&gt;If you haven't already used CoreLocation on the iPhone, it's really simple: just turn it on and let it update you when it has location information.&lt;/p&gt;

&lt;pre&gt;- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    &lt;strong&gt;// Turn on CoreLocation&lt;/strong&gt;
    locationManager = [[CLLocationManager alloc] init];
    locationManager.delegate = self;
    [locationManager startUpdatingLocation];
}&lt;/pre&gt;

&lt;p&gt;Then all you need to do is receive the location updates and load the map at the new location when received. We do this in the &lt;code&gt;CLLocationManagerDelegate&lt;/code&gt; methods.&lt;/p&gt;

&lt;pre&gt;- (void)locationManager:(CLLocationManager *)manager
    didUpdateToLocation:(CLLocation *)newLocation
    fromLocation:(CLLocation *)oldLocation
{
    &lt;strong&gt;// Ignore updates where nothing we care about changed&lt;/strong&gt;
    if (newLocation.coordinate.longitude == oldLocation.coordinate.longitude &amp;&amp;
        newLocation.coordinate.latitude == oldLocation.coordinate.latitude &amp;&amp;
        newLocation.horizontalAccuracy == oldLocation.horizontalAccuracy)
    {
        return;
    }

    &lt;strong&gt;// Load the HTML for displaying the Google map from a file and replace the
    // format placeholders with our location data&lt;/strong&gt;
    NSString *htmlString = [NSString stringWithFormat:
        [NSString 
            stringWithContentsOfFile:
                [[NSBundle mainBundle]
                    pathForResource:@"HTMLFormatString" ofType:@"html"]
            encoding:NSUTF8StringEncoding
            error:NULL],
        newLocation.coordinate.latitude,
        newLocation.coordinate.longitude,
        [WhereIsMyMacAppDelegate latitudeRangeForLocation:newLocation],
        [WhereIsMyMacAppDelegate longitudeRangeForLocation:newLocation]];
    
    &lt;strong&gt;// Load the HTML in the WebView and set the labels&lt;/strong&gt;
    [[webView mainFrame] loadHTMLString:htmlString baseURL:nil];
    [locationLabel setStringValue:[NSString stringWithFormat:@"%f, %f",
        newLocation.coordinate.latitude, newLocation.coordinate.longitude]];
    [accuracyLabel setStringValue:[NSString stringWithFormat:@"%f",
        newLocation.horizontalAccuracy]];
}&lt;/pre&gt;

&lt;p&gt;Notice here that I load the HTML from a file, then use it as a format string, replacing the % sequences. This means that I need to escape the two percent characters in the file that need to remain percents (this is done by turning them into double percents).&lt;/p&gt;

&lt;p&gt;The only other relevant code is the code to convert from meters (the unit for accuracy in CoreLocation) to Longitude and Latitude (used to specify the zoom factor to Google Maps).&lt;/p&gt;

&lt;p&gt;This too is pretty simple: it's just a scale factor for the latitude and a scale plus a trigonometric function for the longitude:&lt;/p&gt;

&lt;pre&gt;+ (double)latitudeRangeForLocation:(CLLocation *)aLocation
{
    const double M = 6367000.0; &lt;strong&gt;// mean meridional radius of curvature of Earth&lt;/strong&gt;
    const double metersToLatitude = 1.0 / ((M_PI / 180.0) * M);
    const double accuracyToWindowScale = 2.0;
    
    return aLocation.horizontalAccuracy * metersToLatitude * accuracyToWindowScale;
}

+ (double)longitudeRangeForLocation:(CLLocation *)aLocation
{
    double latitudeRange =
        [WhereIsMyMacAppDelegate latitudeRangeForLocation:aLocation];
    
    return latitudeRange * cos(aLocation.coordinate.latitude * M_PI / 180.0);
}&lt;/pre&gt;

&lt;p&gt;People who are extremely fussy about distance to latitude conversions don't use a constant meridional radius of curvature for Earth (since Earth is an oblate ellipsoid, this value varies from around 6,330,000 to almost 6,400,000) but a constant value is sufficient for most purposes.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;accuracyToWindowScale&lt;/code&gt; value is used so that the accuracy range reported by CoreLocation ends up as half the window width (instead of 100% of the window width).&lt;/p&gt;

&lt;h4&gt;Where does CoreLocation get this information?&lt;/h4&gt;

&lt;p&gt;The documentation is somewhat vague on where CoreLocation gets this information. Apple imply that there are a few different sources of information that may be used, depending on what is available.&lt;/p&gt;

&lt;p&gt;My first thought was: maybe it is using my IP address to determine my location.&lt;/p&gt;

&lt;p&gt;Looking up my IP address using two different online IP geocoding services revealed the exact center of Australia as my location from my IP address &amp;mdash; almost 2000 kilometers from where I actually am.&lt;/p&gt;

&lt;p&gt;My second thought was maybe it is geocoding my address in Address Book. That's not the answer either, since that address is out-of-date and is at least 5 kilometers away.&lt;/p&gt;

&lt;p&gt;The answer is that I have WiFi on my Mac. Apple uses the WiFi networks you can see from your current location and correlates that against a database of known locations of WiFi networks (yes, companies drive down streets and record the approximate street addresses of WiFi networks).&lt;/p&gt;

&lt;p&gt;So my neighbouring networks: "SweetCheeks", "TheSherriff", "MrBojangles" and "Netgear5" are revealing my location (although I doubt the names are important &amp;mdash; its probably the WiFi MAC addresses that are tracked).&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can download the Xcode 3.2 project here: &lt;a href="http://projectswithlove.com/projects/WhereIsMyMac.zip"&gt;WhereIsMyMac.zip&lt;/a&gt; (33kB). Mac OS X 10.6 is required&lt;/blockquote&gt;

&lt;p&gt;The only use I've seen for CoreLocation in Snow Leopard so far is setting the Time Zone automatically in the Date &amp; Time System Preferences panel. This doesn't require a great deal of accuracy but it turns out that CoreLocation is capable of much more.&lt;/p&gt;

&lt;p&gt;Of course, I'm only reporting on the accuracy that I see, which is anecdotal evidence only. I'd be interested to know how accurate (or inaccurate) this is for other people.&lt;/p&gt;

&lt;p&gt;As you can see in this sample application, the code involved is very simple. Even if it isn't accurate for everyone, it would make a good option in many applications.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-8806801813903010920?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8806801813903010920?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8806801813903010920?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/09/whereismymac-snow-leopard-corelocation.html" title="WhereIsMyMac, a Snow Leopard CoreLocation project" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;AkIARXszfCp7ImA9WxNQFU4.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-8590142962362034735</id><published>2009-09-16T03:10:00.001-07:00</published><updated>2009-09-21T06:09:04.584-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-21T06:09:04.584-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Snow Leopard" /><category scheme="http://www.blogger.com/atom/ns#" term="Cocoa Touch" /><category scheme="http://www.blogger.com/atom/ns#" term="Xcode" /><category scheme="http://www.blogger.com/atom/ns#" term="Standard C" /><category scheme="http://www.blogger.com/atom/ns#" term="AppKit" /><title>Building for earlier OS versions from Snow Leopard</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;It is very easy, when developing on a new operating system, to create projects that won't run on any previous OS version. To ensure backwards compatibility, there are Xcode and gcc options that allow you to build while maintaining support for earlier OS versions. In this post, I'll look at the ways in which this compatibility is controlled and some of the new ways it can go wrong on Snow Leopard.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;The cost of backwards compatibility&lt;/h4&gt;

&lt;p&gt;Customers are regularly unhappy at programmers for dropping support for older operating systems as soon as possible. As with most decisions like this, the reason tends to be a little bit feature-driven and a little bit economic: development support costs increase for every supported version of the OS older than the most recent supported version.&lt;/p&gt;

&lt;p&gt;Supporting older operating systems requires:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When creating a build on a newer OS, you must be careful to write the entire program relying only on behaviors that existing on your earliest targetted OS.&lt;/li&gt;
&lt;li&gt;A test system running an earlier version of the OS to verify that point 1 succeeded.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Point 1 tends to be where most programmers rule out support for earlier systems. I know that as much as 20% of the Mac user-base are still running Mac OS X 10.3.9 and 10.4.11 but I'm unlikely to ever support these operating systems again in one of my releases because these markets aren't big enough to warrant giving up features like Obj-C 2.0's fast iteration, &lt;code&gt;NSOperationQueue&lt;/code&gt; or CoreAnimation which have changed how I write programs.&lt;/p&gt;

&lt;p&gt;Point 2 can also be a serious impediment for small developers who simply don't maintain a series of test machines for their software. Larger developers can simply buy extra machines or buy time in Apple's &lt;a href="https://developer.apple.com/labs/"&gt;Compatibility Labs&lt;/a&gt; but even large companies need to weigh this cost against the potential return.&lt;/p&gt;

&lt;h4&gt;Easy part: building against earlier SDKs in Xcode&lt;/h4&gt;

&lt;p&gt;With Snow Leopard now installed on my main development machine though, I'm forced to go through the backwards compatibility rigamarole just to ensure Leopard compatibility. As fast as the uptake of Snow Leopard was, it still isn't the dominant Mac OS X version &amp;mdash; it is far too soon for me to demand users upgrade (although Gus Mueller has already ripped that band-aid off with the 10.6-only release of &lt;a href="http://flyingmeat.com/acorn/"&gt;Acorn 2&lt;/a&gt;).&lt;/p&gt;

&lt;blockquote&gt;While I'm talking about Mac OS X here, these settings are the same when building for different iPhone OS versions.&lt;/blockquote&gt;

&lt;p&gt;Building against earlier SDKs in Xcode is the easy part. There are two settings involved:

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Base SDK&lt;/strong&gt; (the OS version whose headers you'll use and the newest OS version from which you'll use optional features)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mac OS X Deployment Target&lt;/strong&gt; (the oldest OS version supported)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Base SDK controls what SDK you actually link against and the Mac OS X Deployment Target controls the minimum OS version allowed. In simple cases, just set both of these to the same value.&lt;/p&gt;

&lt;p&gt;You set the Base SDK in the Project settings:&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SrCKzOvjgVI/AAAAAAAAAZs/G1_z5CTYTr8/xcodesdksetting.png?imgmax=800" alt="xcodesdksetting.png" border="0" width="570" height="285" /&gt;

&lt;p&gt;and further down the settings list, the Mac OS X Deployment Target:&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SrCLrkN1JLI/AAAAAAAAAZ0/JHR_8dL7GnI/xcodedeploymentsetting.png?imgmax=800" alt="xcodedeploymentsetting.png" border="0" width="570" height="160" /&gt;

&lt;h4&gt;Weak linking (using newer features if they are available)&lt;/h4&gt;

&lt;p&gt;Weak linking allows you to link against a newer SDK but deploy on an older operating system.&lt;/p&gt;

&lt;p&gt;You should use weak linking in cases where you:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;want the program to run on a earlier version of the operating system&lt;/li&gt;
&lt;li&gt;want to use a feature from a newer OS version if it is available&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Set the Base SDK to the newer OS version that contains the newer features you will use if available and set the Mac OS X Deployment Target to the older version.&lt;/p&gt;

&lt;p&gt;This causes everything newer than the Mac OS X Deployment Target to be &lt;strong&gt;weak linked&lt;/strong&gt; &amp;mdash; meaning that you will try to link against the newer features if available but can live without them if they are not available.&lt;/p&gt;

&lt;p&gt;If a program is run on an older OS than the Base SDK:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unavailable weak linked functions will have &lt;code&gt;NULL&lt;/code&gt; function pointers&lt;/li&gt;
&lt;li&gt;unavailable weak linked class names will return &lt;code&gt;nil&lt;/code&gt; from &lt;code&gt;NSClassFromString&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;unavailable weak linked methods will return NO from the containing objects' &lt;code&gt;respondsToSelector:&lt;/code&gt; method.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;The important point to remember is that anything weak-linked should be checked to ensure it is non-zero before use.&lt;/p&gt;

&lt;p&gt;For example, suppose to wanted to set the Dock to autohide on Mac OS X 10.6 (using the new Snow Leopard &lt;code&gt;-[NSApplication setPresentationOptions:]&lt;/code&gt; method) but you want your application to also run on Mac OS X 10.5 and leave the Dock as-is, you could set the Base SDK to Mac OS X 10.6, the Deployment Target to Mac OS X 10.5 and run the following code:&lt;/p&gt;

&lt;pre&gt;if ([[NSApplication sharedApplication]
    respondsToSelector:@selector(setPresentationOptions:)])
{
    [[NSApplication sharedApplication]
        setPresentationOptions:NSApplicationPresentationAutoHideDock];
}&lt;/pre&gt;

&lt;h4&gt;Command-line building for earlier OS versions&lt;/h4&gt;

&lt;p&gt;You might think POSIX/Open Source libraries that are written to be cross-platform and don't link directly against an Mac OS X specific libraries shouldn't need to change from OS version to OS version.&lt;/p&gt;

&lt;p&gt;However, most C/C++ libraries do link against libc (which is a part of libSystem on Mac OS X). Since libSystem is a dynamic library and changes between OS versions, this means that you must be mindful of exactly what version of libSystem you build against.&lt;/p&gt;

&lt;p&gt;A common example of getting this wrong is the following linker error:&lt;/p&gt;

&lt;pre&gt;Undefined symbols:
  "_fopen$UNIX2003", referenced from:
      _some_function in somefile.o
&lt;/pre&gt;

&lt;p&gt;You will get this and similar errors when trying to link two different components which are themselves linked against different versions of libSystem. In this case, the application was linked against Base SDK Mac OS X 10.5 but the static library was linked against the current libSystem.B.dylib in Mac OS X 10.6.&lt;/p&gt;

&lt;p&gt;Obviously, &lt;code&gt;fopen&lt;/code&gt; is a Standard C function and it is in every version of libSystem but different versions of libSystem have subtly different versions of the function. To fix the bug, you must ensure that all components you link together themselves link against the same versions of the standard libraries.&lt;/p&gt;

&lt;p&gt;In the example above, the solution is to rebuild the static library from the source using the following gcc link-line options:&lt;/p&gt;

&lt;pre&gt;-isysroot /Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5&lt;/pre&gt;

&lt;p&gt;That's right, it's the same settings as in Xcode but on the command line &amp;mdash; the Base SDK (&lt;code&gt;isysroot&lt;/code&gt;) and the Mac OS X Deployment Target (&lt;code&gt;mmacosx-version-min&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Once you've built an executable or a dynamic library, you can use otool to check that they're not linking against any unexpected dynamic libraries (which may not be present on older OS versions) with the following command:&lt;/p&gt;

&lt;pre&gt;otool -L myAppExecutable&lt;/pre&gt;

&lt;p&gt;This reports the required dynamic libraries and their version numbers.&lt;/p&gt;

&lt;p&gt;Run the same command on the dynamic libraries in your targetted SDK directory to check their version numbers against the library numbers required by your executable.&lt;/p&gt;

&lt;h4&gt;Be wary of changed gcc&lt;/h4&gt;

&lt;p&gt;In Mac OS X 10.5, if you didn't specify an architecture, gcc would build a 32-bit binary. In Snow Leopard, this has changed: if no architecture is specified, a 64-bit binary will be built.&lt;/p&gt;

&lt;p&gt;You'll need to pay attention to this, particularly for auto-configured builds which may need to coaxing now to build 32-bit binaries.&lt;/p&gt;

&lt;p&gt;Of course, this is an easy thing to do: just specify "-arch i386" or "-arch x86_64" or both on the gcc compile command line &amp;mdash; but you will need to remember.&lt;/p&gt;

&lt;p&gt;This problem can manifest in an annoying way: a file not found error when linking, even when there is a file of the desired name in the search path. If this occurs, be sure to check that the file in the search path contains the right architecture for your build.&lt;/p&gt;

&lt;p&gt;Check an architecture with the following:&lt;/p&gt;

&lt;pre&gt;file libSomeLibrary.dylib&lt;/pre&gt;

&lt;p&gt;If you're trying to build a 32-bit binary and you only see:&lt;/p&gt;

&lt;pre&gt;libSomeLibrary.dylib (for architecture x86_64):	Mach-O 64-bit executable x86_64&lt;/pre&gt;

&lt;p&gt;Then you need to rebuild libSomeLibrary.dylib or find a 32-bit version.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Programmers don't like supporting earlier OS versions because it means more work and fewer cool features to play with. Despite this, there are often economic reasons to put in the effort and forgo the more modern features to support earlier OS versions.&lt;/p&gt;

&lt;p&gt;You will want to choose an OS version when you start a project, since removing OS-specific features can be hugely time consuming &amp;mdash; it is always easier to drop support later rather than gain support.&lt;/p&gt;

&lt;p&gt;Set the Base SDK, set the Deployment Target and make certain all your components remain in-sync on these points. Remember to double check the build target and architecture for all components you build for yourself and always be wary of dynamic libraries.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-8590142962362034735?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8590142962362034735?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/8590142962362034735?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/09/building-for-earlier-os-versions-in.html" title="Building for earlier OS versions from Snow Leopard" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;CUEGRns4eip7ImA9WxNRFkg.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-2267544611356175271</id><published>2009-09-09T05:02:00.001-07:00</published><updated>2009-09-11T00:20:27.532-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-11T00:20:27.532-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="UIKit" /><category scheme="http://www.blogger.com/atom/ns#" term="CoreGraphics" /><category scheme="http://www.blogger.com/atom/ns#" term="AppKit" /><title>Creating alpha masks from text on the iPhone and Mac</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Alpha masks are a powerful way to create graphical effects in your program. In this post, I'll show you how to create an alpha mask from a text string and use that mask to create text-based effects with an image. I'll also show you how to do this on the iPhone and the Mac, so you can see the differences between these platforms in this area.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In this post I will present the following sample application:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Sqc2tg_BfaI/AAAAAAAAAZk/DJCiT0mByZg/textmasking.png?imgmax=800" alt="textmasking.png" border="0" width="240" height="361" /&gt;

&lt;p&gt;The program shows the current time, updating every second, on the Mac or iPhone. Within the bounds of the text, the image of the space shuttle is displayed at 100% opacity. Everywhere else, it displays at 30% opacity.&lt;/p&gt;

&lt;p&gt;This is done by drawing the image of the shuttle over a white background using an alpha mask &amp;mdash; where the mask is white (100% opaque) for the text and dark gray (30% opaque) for the background.&lt;/p&gt;

&lt;blockquote&gt;Download the &lt;a href="http://projectswithlove.com/projects/TextMasking-iPhone.zip"&gt;TextMasking-iPhone.zip&lt;/a&gt; (37kB) and the &lt;a href="http://projectswithlove.com/projects/TextMasking-Mac.zip"&gt;TextMasking-Mac.zip&lt;/a&gt; (42kB) projects.&lt;/blockquote&gt;

&lt;h4&gt;Clipping regions in Core Graphics&lt;/h4&gt;

&lt;p&gt;Clipping and masking are the two key ways of limiting the effect that drawing has in CoreGraphics.&lt;/p&gt;

&lt;p&gt;With a clipping region, we create a hard boundary. When a clipping region is used, every pixel drawn inside the region is fully shown (completely opaque), and no pixels outside the region are affected (completely transparent). For example, the following code:&lt;/p&gt;

&lt;pre&gt;CGContextBeginPath(context);
CGContextAddRect(context, CGRectMake(10, 10, 80, 80));
CGContextAddRect(context, CGRectMake(20, 20, 40, 40));
CGContextEOClip(context);&lt;/pre&gt;

&lt;p&gt;will ensure that subsequent drawing only has an effect if it is inside the rectangle (x=10, y=10, width=80, height=80) but outside the rectangle (x=20, y=20, width=10, height=10).&lt;/p&gt;

&lt;blockquote&gt;The "EO" in &lt;code&gt;CGContextEOClip&lt;/code&gt; stands for "Even-Odd". When you use this function instead of &lt;code&gt;CGContextClip&lt;/code&gt;, subsequent nested regions (an even or an odd number of nestings) continue to toggle clipping on and off. That is why the second &lt;code&gt;CGContextAddRect&lt;/code&gt; is excluded from the clipping region. If I had used &lt;code&gt;CGContextClip&lt;/code&gt;, the nested rectangle would have no effect (it is &lt;em&gt;already&lt;/em&gt; inside the clipping region).&lt;/blockquote&gt;

&lt;h4&gt;Clipping with image masks in Core Graphics&lt;/h4&gt;

&lt;p&gt;A mask affects the opacity/transparency of drawn pixels like a clipping region but the affected areas are specified by the color values in an image, not from a region. This is the approach used in the sample applications. A mask is used instead of a clipping region for two reasons:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;A mask allows varying levels of transparency, not just on or off (for the partially transparent regions in the image).&lt;/li&gt;
&lt;li&gt;On the iPhone, it's very difficult to get the region outline of text characters (on the Mac you can use &lt;code&gt;appendBezierPathWithGlyph:inFont:&lt;/code&gt;), making a clipping region from a text boundary impractical.&lt;/li&gt;&lt;/ul&gt;

&lt;h4&gt;Creating a mask&lt;/h4&gt;

&lt;p&gt;The Mac and the iPhone differ significantly on how the mask image must be created.&lt;/p&gt;

&lt;p&gt;On the iPhone, it is possible to copy the current graphics context to an image before it is drawn to screen and use that as the mask.&lt;/p&gt;

&lt;p&gt;On the Mac this doesn't work. The Mac requires that masking images be grayscale without an alpha channel &amp;mdash; you could copy the current graphics context in the same way but it can't be used as a mask image. We'll need to create a context that meets these specific requirements.&lt;/p&gt;

&lt;h5&gt;On the iPhone:&lt;/h5&gt;

&lt;p&gt;Drawing the text to the current graphics context and copying that to an image on the iPhone:&lt;/p&gt;

&lt;pre&gt;CGContextRef context = UIGraphicsGetCurrentContext();

&lt;strong&gt;// Draw a dark gray background&lt;/strong&gt;
[[UIColor darkGrayColor] setFill];
CGContextFillRect(context, rect);

&lt;strong&gt;// Draw the text upside-down&lt;/strong&gt;
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0, rect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
[[UIColor whiteColor] setFill];
[text drawInRect:rect withFont:[UIFont fontWithName:@"HelveticaNeue-Bold" size:124]];
CGContextRestoreGState(context);

&lt;strong&gt;// Create an image mask from what we've drawn so far&lt;/strong&gt;
CGImageRef alphaMask = CGBitmapContextCreateImage(context);&lt;/pre&gt;

&lt;p&gt;The only tricky part here is that the image will be flipped when we draw it back again, so we need to draw the text upside-down &amp;mdash; other than that, the iPhone has it easy here.&lt;/p&gt;

&lt;h5&gt;On the Mac&lt;/h5&gt;

&lt;p&gt;Since the Mac must have the bitmap image as a &lt;code&gt;CGColorSpaceCreateDeviceGray();&lt;/code&gt; image without an alpha channel, we can't just copy a screen context to use as our mask. Instead, we need to create a new context with the settings we require and perform all drawing there.&lt;/p&gt;

&lt;p&gt;This has one advantage: we can set the context to &lt;code&gt;flipped:NO&lt;/code&gt; so that we don't need to draw upside-down to have it render correctly.&lt;/p&gt;

&lt;pre&gt;&lt;strong&gt;// Create a grayscale context for the mask&lt;/strong&gt;
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceGray();
CGContextRef maskContext =
CGBitmapContextCreate(
    NULL,
    self.bounds.size.width,
    self.bounds.size.height,
    8,
    self.bounds.size.width,
    colorspace,
    0);
CGColorSpaceRelease(colorspace);

&lt;strong&gt;// Switch to the context for drawing&lt;/strong&gt;
NSGraphicsContext *maskGraphicsContext =
    [NSGraphicsContext
        graphicsContextWithGraphicsPort:maskContext
        flipped:NO];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:maskGraphicsContext];

&lt;strong&gt;// Draw a black background&lt;/strong&gt;
[[NSColor darkGrayColor] setFill];
CGContextFillRect(maskContext, rect);

&lt;strong&gt;// Draw the text right-way-up (non-flipped context)&lt;/strong&gt;
[text
    drawInRect:rect
    withAttributes:
        [NSDictionary dictionaryWithObjectsAndKeys:
            [NSFont fontWithName:@"HelveticaNeue-Bold" size:124], NSFontAttributeName,
            [NSColor whiteColor], NSForegroundColorAttributeName,
        nil]];

&lt;strong&gt;// Switch back to the window's context&lt;/strong&gt;
[NSGraphicsContext restoreGraphicsState];

&lt;strong&gt;// Create an image mask from what we've drawn so far&lt;/strong&gt;
CGImageRef alphaMask = CGBitmapContextCreateImage(maskContext);&lt;/pre&gt;

&lt;h4&gt;Using the mask&lt;/h4&gt;

&lt;p&gt;Using the mask is much easier than creating it:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Save the state of the current context (so that we can go back to a non-masked state when we're done).&lt;/li&gt;
&lt;li&gt;Apply the mask using &lt;code&gt;CGContextClipToMask&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Perform whatever drawing we want masked.&lt;/li&gt;
&lt;li&gt;Restore the saved context state to remove the mask again.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;The iPhone version is:&lt;/p&gt;

&lt;pre&gt;&lt;strong&gt;// Draw a white background (clear the window)&lt;/strong&gt;
[[UIColor whiteColor] setFill];
CGContextFillRect(context, rect);

&lt;strong&gt;// Draw the image, clipped by the mask&lt;/strong&gt;
CGContextSaveGState(context);
CGContextClipToMask(context, rect, alphaMask);
[[UIImage imageNamed:@"shuttle.jpg"] drawInRect:rect];
CGContextRestoreGState(context);
CGImageRelease(alphaMask);&lt;/pre&gt;

&lt;p&gt;The Mac version substitutes &lt;code&gt;NSColor&lt;/code&gt; and &lt;code&gt;NSImage&lt;/code&gt; for &lt;code&gt;UIColor&lt;/code&gt; and &lt;code&gt;UIImage&lt;/code&gt; but is otherwise the same.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;Download the &lt;a href="http://projectswithlove.com/projects/TextMasking-iPhone.zip"&gt;TextMasking-iPhone.zip&lt;/a&gt; (37kB) and the &lt;a href="http://projectswithlove.com/projects/TextMasking-Mac.zip"&gt;TextMasking-Mac.zip&lt;/a&gt; (42kB) projects.&lt;/blockquote&gt;

&lt;p&gt;Clipping and masking are two of the most powerful operations available when drawing in code but as highly abstract concepts they can be difficult to use for the first time since a mistake normally results in nothing happening (a difficult scenario from which to learn).&lt;/p&gt;

&lt;p&gt;I have only briefly shown region-based clipping. If you don't need the partial transparency offered by masks and can draw your shapes as a region then it is faster than a mask (since it doesn't need to allocate or load the mask image). Obviously, the option you choose should be based on the output you require.&lt;/p&gt;

&lt;p&gt;The examples shown here don't cache anything &amp;mdash; they allocate and dispose of all data structures every time the &lt;code&gt;drawRect:&lt;/code&gt; method is called. In a proper program, you should not allocate the mask image every time you draw. You can allocate the mask once and simply set the context back to it to update it.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-2267544611356175271?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/2267544611356175271?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/2267544611356175271?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/09/creating-alpha-masks-from-text-on.html" title="Creating alpha masks from text on the iPhone and Mac" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;DkIDQHc4fip7ImA9WxNSGEs.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-2547147530733225556</id><published>2009-09-01T21:09:00.001-07:00</published><updated>2009-09-01T21:09:31.936-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-01T21:09:31.936-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="AppKit" /><title>An NSSplitView delegate for priority based resizing</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;The default resizing mechanism in &lt;code&gt;NSSplitView&lt;/code&gt; is proportional resizing &amp;mdash; if the &lt;code&gt;NSSplitView&lt;/code&gt; changes size, each column resizes by an equal percent. This works badly in the common case where the columns in a split view are used to separate a side panels from a main view area (for example the "source list" in iTunes or the file tree in Xcode). In this post, I'll show you a delegate class that configures a split view for this side panel and main view behavior &amp;mdash; resizing the views in a split view based on a priority list.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Snow Leopard?&lt;/h4&gt;

&lt;p&gt;Every Mac programming blog that I read is overflowing this week with Snow Leopard information. To celebrate this exciting event, I proudly ignore the trend and present code that (aside from a little Objective-C 2.0 syntax) would run on Mac OS 10.0.&lt;/p&gt;

&lt;h4&gt;Proportional versus priority-based resizing&lt;/h4&gt;

&lt;p&gt;For a three section &lt;code&gt;NSSplitView&lt;/code&gt;, the default proportional resizing behaves like this:&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Sp3dIglhG0I/AAAAAAAAAZI/F9zwuapbQHU/proportionalsmall.png?imgmax=800" alt="proportionalsmall.png" border="0" width="370" height="124" /&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Sp3dQ-iOb0I/AAAAAAAAAZM/5pumyxzJaNA/proportionallarge.png?imgmax=800" alt="proportionallarge.png" border="0" width="563" height="124" /&gt;

&lt;p&gt;In proportional resizing, as the window grows, each column grows by the same percentage.&lt;/p&gt;

&lt;p&gt;By comparison, priority-based resizing works like this:&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/Sp3eDSQrRgI/AAAAAAAAAZQ/akzGUNmmMmM/prioritysmall.png?imgmax=800" alt="prioritysmall.png" border="0" width="427" height="124" /&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/Sp3eh96zDZI/AAAAAAAAAZY/ZuAiy8VpDfY/prioritylarge.png?imgmax=800" alt="prioritylarge.png" border="0" width="550" height="124" /&gt;

&lt;p&gt;Priority-based resizing nominates 1 view as the most important. This is normally the window's "main" view. This highest priority view is the only view that grows in size as the window grows.&lt;/p&gt;

&lt;blockquote&gt;You can download the sample project &lt;a href="http://projectswithlove.com/projects/ColumSplitView.zip"&gt;ColumSplitView.zip&lt;/a&gt; (60kb) to see the priority resizing at work.&lt;/blockquote&gt;

&lt;h4&gt;Proportional resizing in reverse&lt;/h4&gt;

&lt;p&gt;The flip side to priority resizing is that the highest priority view is also the first to compress to zero. For this reason, the priority-based resizing should also implement minimum sizes so that the main view never actually reaches zero size.&lt;/p&gt;

&lt;p&gt;Once the highest priority view reaches minimum, remaining views are collapsed by priority until all views are at their minimum size. The window or enclosing scroll view's minimum size should be constrained so that the split view is never forced past the point where columns are all at minimum size.&lt;/p&gt;

&lt;h4&gt;Controlling an NSSplitView&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;NSSplitView&lt;/code&gt; takes a delegate. The delegate methods are where we control the minimum sizes of sections and which views expand or collapse by what amount.&lt;/p&gt;

&lt;p&gt;The class I'll present will be a dedicated delegate class named &lt;code&gt;PrioritySplitViewDelegate&lt;/code&gt; that allows you to configure priorities and minimum sizes for the &lt;code&gt;NSSplitView&lt;/code&gt;'s subviews. This generic delegate can then be constructed, configured and attached to the &lt;code&gt;NSSplitView&lt;/code&gt; in your controller code.&lt;/p&gt;

&lt;pre&gt;@interface PrioritySplitViewDelegate : NSObject
{
    NSMutableDictionary *lengthsByViewIndex;
    NSMutableDictionary *viewIndicesByPriority;
}

- (void)setMinimumLength:(CGFloat)minLength
    forViewAtIndex:(NSInteger)viewIndex;
- (void)setPriority:(NSInteger)priorityIndex
    forViewAtIndex:(NSInteger)viewIndex;

@end&lt;/pre&gt;

&lt;p&gt;Some usage cautions about this design: the delegate does not know in advance how many sections the split view will have, so it will let you specify priorities or minimum sizes for views that don't exist.&lt;/p&gt;

&lt;p&gt;Specifying a priority for every view is mandatory so if you forget to specify a priority for a view, an exception will be thrown when the &lt;code&gt;NSSplitView&lt;/code&gt; is resized. Minimum sizes are optional but will be zero if not specified. Keep these points in mind when using this class.&lt;/p&gt;

&lt;h4&gt;Implementation&lt;/h4&gt;

&lt;p&gt;Constraining the coordinates in the &lt;code&gt;splitView:constrainMinCoordinate:ofSubviewAt:&lt;/code&gt; and &lt;code&gt;splitView:constrainMaxCoordinate:ofSubviewAt:&lt;/code&gt; happens when the user drags the boundary between two split view sections. In these methods, we need to ensure that the view which is getting smaller does not exceed its minimum size.&lt;/p&gt;

&lt;p&gt;When dragging the boundary between two columns to the left, this means that the minimum coordinate is that which would collapse the left view to its minimum size.&lt;/p&gt;

&lt;pre&gt;- (CGFloat)splitView:(NSSplitView *)sender
    constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)offset
{
    NSView *subview = [[sender subviews] objectAtIndex:offset];
    NSRect subviewFrame = subview.frame;
    CGFloat frameOrigin;
    if ([sender isVertical])
    {
        frameOrigin = subviewFrame.origin.x;
    }
    else
    {
        frameOrigin = subviewFrame.origin.y;
    }
    
    CGFloat minimumSize =
        [[lengthsByViewIndex objectForKey:[NSNumber numberWithInteger:offset]]
            doubleValue];
    
    return frameOrigin + minimumSize;
}&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;splitView:constrainMaxCoordinate:ofSubviewAt:&lt;/code&gt; is similar. You can download the sample project to see the implementation of this method.&lt;/p&gt;

&lt;p&gt;Finally, we need to handle the priority resizing itself. This happens in the implementation of the delegate method &lt;code&gt;splitView:resizeSubviewsWithOldSize:&lt;/code&gt;. This method is invoked when the split view is resized (normally because the enclosing window has resized).&lt;/p&gt;

&lt;p&gt;A brief description of the work involved is:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Iterate over the list of views, sorted by priority.&lt;/li&gt;
&lt;li&gt;As each view is reached, attempt to apply the entire size change to this view.&lt;/li&gt;
&lt;li&gt;If applying the size to the view would cause it to become smaller than its minimum size, apply as much as possible and proceed to the next view by priority.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;The size change for the split view is named &lt;code&gt;delta&lt;/code&gt; in the following code taken from the &lt;code&gt;splitView:resizeSubviewsWithOldSize:&lt;/code&gt; method.&lt;/p&gt;

&lt;pre&gt;for (NSNumber *priorityIndex in
    [[viewIndicesByPriority allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
    NSNumber *viewIndex = [viewIndicesByPriority objectForKey:priorityIndex];
    NSInteger viewIndexValue = [viewIndex integerValue];
    if (viewIndexValue &gt;= subviewsCount)
    {
        continue;
    }
    
    NSView *view = [subviews objectAtIndex:viewIndexValue];
    
    NSSize frameSize = [view frame].size;
    NSNumber *minLength = [lengthsByViewIndex objectForKey:viewIndex];
    CGFloat minLengthValue = [minLength doubleValue];
    
    if (isVertical)
    {
        frameSize.height = sender.bounds.size.height;
        if (delta &gt; 0 ||
            frameSize.width + delta &gt;= minLengthValue)
        {
            frameSize.width += delta;
            delta = 0;
        }
        else if (delta &lt; 0)
        {
            delta += frameSize.width - minLengthValue;
            frameSize.width = minLengthValue;
        }
    }
    else
    {
        frameSize.width = sender.bounds.size.width;
        if (delta &gt; 0 ||
            frameSize.height + delta &gt;= minLengthValue)
        {
            frameSize.height += delta;
            delta = 0;
        }
        else if (delta &lt; 0)
        {
            delta += frameSize.height - minLengthValue;
            frameSize.height = minLengthValue;
        }
    }
    
    [view setFrameSize:frameSize];
    viewCountCheck++;
}&lt;/pre&gt;

&lt;p&gt;The "&lt;code&gt;continue&lt;/code&gt;" skips invalid priorities. You might replace this in your own code with an &lt;code&gt;NSAssert&lt;/code&gt; instead, depending on how you like to handle minor errors.&lt;/p&gt;

&lt;p&gt;The other point to notice is that we don't break out of the loop once the &lt;code&gt;delta&lt;/code&gt; is fully applied &amp;mdash; we still need to run &lt;code&gt;setFrameSize:&lt;/code&gt; on each view to apply any size change in the perpendicular direction (vertically for columns or horizontally for rows).&lt;/p&gt;

&lt;p&gt;This fragment doesn't show it but the code includes a second iteration over all the views, in order, which sets the origins of each view following the resize so they are all positioned correctly for their new sizes.&lt;/p&gt;

&lt;h4&gt;Hitting the minimum size&lt;/h4&gt;

&lt;p&gt;If all views are at their minimum and the split view cannot contract any further, the current implementation throws an exception giving the minimum size. This is so that you can configure the containing view (often a window) to respect this minimum and never try to make the &lt;code&gt;NSSplitView&lt;/code&gt; smaller than this. If you don't like this behavior, you can remove the &lt;code&gt;NSAssert3&lt;/code&gt; statement in the  &lt;code&gt;setMinimumLength:forViewAtIndex:&lt;/code&gt; method.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can download the sample project &lt;a href="http://projectswithlove.com/projects/ColumSplitView.zip"&gt;ColumSplitView.zip&lt;/a&gt; (60kb) to see the full &lt;code&gt;PrioritySplitViewDelegate&lt;/code&gt; class.&lt;/blockquote&gt;

&lt;p&gt;The advantage to the &lt;code&gt;PrioritySplitViewDelegate&lt;/code&gt; class is that it is generic: you don't need to write this code each time and it handles the common case of using an &lt;code&gt;NSSplitView&lt;/code&gt; to contain columns and a main view. It offers an easy plug in solution for managing a split view in this arrangement.&lt;/p&gt;

&lt;p&gt;It could probably be improved by changing the &lt;code&gt;setMinimumLength:forViewAtIndex:&lt;/code&gt; and &lt;code&gt;setPriority:forViewAtIndex:&lt;/code&gt; methods to something that prevents you from providing the wrong values for indices or number of lengths or priorities but the &lt;code&gt;NSAssert&lt;/code&gt;s in the &lt;code&gt;splitView:resizeSubviewsWithOldSize:&lt;/code&gt; method will pick up the most critical errors you might make.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-2547147530733225556?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/2547147530733225556?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/2547147530733225556?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/09/nssplitview-delegate-for-priority-based.html" title="An NSSplitView delegate for priority based resizing" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;DUIMQ3g8eip7ImA9WxNQFks.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-6719294933409122006</id><published>2009-08-21T08:04:00.001-07:00</published><updated>2009-09-22T17:59:42.672-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-22T17:59:42.672-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="self promotion" /><title>StreamToMe iPhone App Released</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;&lt;a href="http://projectswithlove.com/streamtome/index.html"&gt;StreamToMe&lt;/a&gt; is an iPhone app I've written that streams video in most common formats from your Mac to the iPhone/iPod Touch &amp;mdash; without prior conversion or copying. It supports the TV out cable for the iPhone, turning your iPhone+Mac into a wireless media center. I'm excited that &lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=325327899&amp;mt=8"&gt;it's finally on the App Store&lt;/a&gt; because I've been using it non-stop during development and I'm really happy with it.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Use your Mac to stream it&lt;/h4&gt;

&lt;p&gt;Your Mac can store hundreds of gigabytes and play almost any video format (Xvid, Flash Video, WMV, MPG, MP4 and more), in almost any size (from QCIF to 1080p), but your iPhone cannot. Take advantage of this power; run the free ServeToMe app on your Mac and make it do all the hard work by live-transcoding video to your iPhone.&lt;/p&gt;

&lt;p&gt;Then to watch video all you need to do is open the StreamToMe app on your iPhone or iPod Touch, select the video and 5 seconds later it's playing. No prior conversion, no archive of iPhone-encodes, no waiting, no copying, no syncing.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=325327899&amp;mt=8"&gt; Download StreamToMe from the iTunes App Store&lt;/a&gt; and enjoy!&lt;/p&gt;

&lt;p&gt;For more information, see the &lt;a href="http://projectswithlove.com/streamtome/index.html"&gt;StreamToMe product page&lt;/a&gt; or the &lt;a href="http://projectswithlove.com/streamtome/faq.html"&gt;StreamToMe FAQ&lt;/a&gt;.&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SrlwsUlxyKI/AAAAAAAAAaE/T-FERr_nLi0/screenshot1.png?imgmax=800" alt="screenshot1.png" border="0" width="160px" height="240px" style="display:inline;" /&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SrlwzzAtrBI/AAAAAAAAAaI/xV-ex5LHJB4/screenshot5.png?imgmax=800" alt="screenshot5.png" border="0" width="160px" height="240px" style="display:inline;" /&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Srlw6Ae93cI/AAAAAAAAAaM/KN6J5L8P_6c/screenshot7.png?imgmax=800" alt="screenshot7.png" border="0" width="240px" height="160px" style="display:inline;" /&gt;


&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-6719294933409122006?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/6719294933409122006?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/6719294933409122006?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/08/streamtome-iphone-app-released.html" title="StreamToMe iPhone App Released" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;DUIHR3g-fip7ImA9WxNSEEs.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-450107741252258283</id><published>2009-08-21T02:59:00.001-07:00</published><updated>2009-08-23T15:45:36.656-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-23T15:45:36.656-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cocoa Touch" /><category scheme="http://www.blogger.com/atom/ns#" term="UIKit" /><title>Adding shadow effects to UITableView using CAGradientLayer</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Shadows can be a useful effect, drawing attention to the content of your view by separating the view from the background. They also look cool. In this post, I'll show you how to add shadows to a UITableView using three CAGradientLayers &amp;mdash; one above the first row, one after the last row and one for under the navigation bar.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;ShadowedTableView app&lt;/h4&gt;

&lt;p&gt;In this post, I'll present the following sample app:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/So5US7FNQPI/AAAAAAAAAZA/ERaSTx9XtJ4/shadowedtableview.png?imgmax=800" alt="shadowedtableview.png" border="0" width="275" height="350" /&gt;

&lt;p&gt;In this screenshot, the rows are dragged downwards to reveal the three different shadows: under the navigation bar, above the first row and under the last row.&lt;/p&gt;

&lt;blockquote&gt;Download the sample project &lt;a href="http://projectswithlove.com/projects/ShadowedTableView.zip"&gt;ShadowedTableView.zip&lt;/a&gt; (26kB). Last updated 2009-08-23.&lt;/blockquote&gt;

&lt;h4&gt;CAGradientLayer&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;CAGradientLayer&lt;/code&gt; was a handy addition in iPhone SDK 3.0 &amp;mdash; it allows you to create an efficient, linear gradient in just a couple lines. In this sample app, is it used to draw the opaque gradients on the table rows as well as the transparent gradients of the shadows.&lt;/p&gt;

&lt;p&gt;While not as flexible as &lt;code&gt;CGContextSetShadow&lt;/code&gt; (which can draw shadows around multiple shapes simultaneously or curved edges), &lt;code&gt;CAGradientLayer&lt;/code&gt; is very fast, so it shouldn't have a noticeable effect on the speed of your application.&lt;/p&gt;

&lt;p&gt;Since &lt;code&gt;CAGradientLayer&lt;/code&gt; requires iPhone SDK 3.0, if you need a similar effect on earlier versions of iPhone OS, you'll need to use &lt;code&gt;CGGradientCreateWithColorComponents&lt;/code&gt; to draw the contents of a &lt;code&gt;CALayer&lt;/code&gt; yourself or perhaps use a &lt;code&gt;UIImageView&lt;/code&gt; (an image view is another alternative if you need non-straight edges).&lt;/p&gt;

&lt;h4&gt;Required steps&lt;/h4&gt;

&lt;p&gt;Adding the shadows can be done using a &lt;code&gt;UITableView&lt;/code&gt; subclass. In this subclass, we need to perform the following steps:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Create the three &lt;code&gt;CAGradientLayer&lt;/code&gt;s&lt;/li&gt;
&lt;li&gt;Place them and make sure they stay underneath the table's rows&lt;/li&gt;
&lt;li&gt;Update the positions of the gradients when the table scrolls or grows&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;We can perform all these steps by overriding the &lt;code&gt;layoutSubviews&lt;/code&gt; method.&lt;/p&gt;

&lt;h4&gt;Constructing the gradients&lt;/h4&gt;

&lt;p&gt;The construction of the &lt;code&gt;CAGradientLayer&lt;/code&gt;s is done lazily (i.e. as needed) in &lt;code&gt;layoutSubviews&lt;/code&gt; (removing the need to override any constructors.&lt;/p&gt;

&lt;p&gt;The three gradients are all constructed using the following method. The &lt;code&gt;inverse&lt;/code&gt; parameter is used to generate the smaller gradient that fades-out upwards (for the shadow above the first table row).&lt;/p&gt;

&lt;pre&gt;- (CAGradientLayer *)shadowAsInverse:(BOOL)inverse
{
    CAGradientLayer *newShadow = [[[CAGradientLayer alloc] init] autorelease];
    CGRect newShadowFrame =
        CGRectMake(0, 0, self.frame.size.width,
            inverse ? SHADOW_INVERSE_HEIGHT : SHADOW_HEIGHT);
    newShadow.frame = newShadowFrame;
    CGColorRef darkColor =
        [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:
            inverse ? (SHADOW_INVERSE_HEIGHT / SHADOW_HEIGHT) * 0.5 : 0.5].CGColor;
    CGColorRef lightColor =
        [self.backgroundColor colorWithAlphaComponent:0.0].CGColor;
    newShadow.colors =
        [NSArray arrayWithObjects:
            (id)(inverse ? lightColor : darkColor),
            (id)(inverse ? darkColor : lightColor),
        nil];
    return newShadow;
}&lt;/pre&gt;

&lt;p&gt;Notice that the gradient goes from 50% black to 0% of the table's background color. It is important to use the table's actual background color, even though it may seem as though the 0% opacity on it would make it invisible. The mathematics of the gradient will cause the middle color to be 12.5% black +  12.5% background color, so the background color does have an effect on the gradient.&lt;/p&gt;

&lt;h4&gt;Placing the gradients&lt;/h4&gt;

&lt;p&gt;The simplest gradient to place is the one under the navigation bar &amp;mdash; we just put it at the top of the &lt;code&gt;UITableView&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The only tricky part is that the view, as a child of the &lt;code&gt;UITableView&lt;/code&gt; will scroll downwards when the view scrolls (we want it to stay still and not scroll). To fix this issue, we'll offset the view by the same amount as the scroll offset (to keep it in place) and perform this frame adjustment inside a &lt;code&gt;CATransaction&lt;/code&gt; with animation disabled (so that these offsets are not visible).&lt;/p&gt;

&lt;pre&gt;[CATransaction begin];
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];

//
// Stretch and place the origin shadow
//
CGRect originShadowFrame = originShadow.frame;
originShadowFrame.size.width = self.frame.size.width;
originShadowFrame.origin.y = self.contentOffset.y;
originShadow.frame = originShadowFrame;

[CATransaction commit];&lt;/pre&gt;

&lt;p&gt;The gradients on the rows are a little trickier. First, we only want to add them if the rows are visible. Second, we want to make them child layers of their respective rows so that if the rows animate, the shadows will follow them.&lt;/pre&gt;

&lt;blockquote&gt;&lt;strong&gt;Update 2009-08-23&lt;/strong&gt;: adding the shadows as children of the cells themselves is a new addition to improve performance during animation from the original post (which arranged the rows directly in the &lt;code&gt;UITableView&lt;/code&gt;.&lt;/blockquote&gt;

&lt;pre&gt;NSIndexPath *firstRow = [indexPathsForVisibleRows objectAtIndex:0];
if ([firstRow section] == 0 &amp;&amp; [firstRow row] == 0)
{
    UIView *cell = [self cellForRowAtIndexPath:firstRow];
    if (!topShadow)
    {
        topShadow = [[self shadowAsInverse:YES] retain];
        [cell.layer insertSublayer:topShadow atIndex:0];
    }
    else if ([cell.layer.sublayers indexOfObjectIdenticalTo:topShadow] != 0)
    {
        [cell.layer insertSublayer:topShadow atIndex:0];
    }

    CGRect shadowFrame = topShadow.frame;
    shadowFrame.size.width = cell.frame.size.width;
    shadowFrame.origin.y = -SHADOW_INVERSE_HEIGHT;
    topShadow.frame = shadowFrame;
}
else
{
    // Remove the shadow if it isn't visible
    [topShadow removeFromSuperlayer];
    [topShadow release];
    topShadow = nil;
}
&lt;/pre&gt;

&lt;p&gt;This is the placement of the top shadow (the one above the first row). We only attend to it if the first row is visible and when we do, we always ensure that it is the 0-th sublayer of the appropriate cell.&lt;/p&gt;

&lt;h4&gt;Other tidbits&lt;/h4&gt;

&lt;p&gt;The sample project also contains the &lt;code&gt;GradientView&lt;/code&gt; class which is a very simple subclass of &lt;code&gt;UIView&lt;/code&gt; that sets the &lt;code&gt;UIView&lt;/code&gt;'s &lt;code&gt;layerClass&lt;/code&gt; to &lt;code&gt;CAGradientLayer&lt;/code&gt; and uses that to draw a gradient across the view. This is the view that is set as the &lt;code&gt;UITableViewCell&lt;/code&gt;'s &lt;code&gt;backgroundView&lt;/code&gt; to draw the views in this sample project.&lt;/p&gt;

&lt;p&gt;The project also contains the &lt;code&gt;ClearLabelsCellView&lt;/code&gt; which is a &lt;code&gt;UITableViewCell&lt;/code&gt; subclass that overrides &lt;code&gt;setSelected:animate:&lt;/code&gt; to fix the fact that this method always sets the default &lt;code&gt;textLabel&lt;/code&gt; and &lt;code&gt;detailTextLabel&lt;/code&gt; &lt;code&gt;backgroundColor&lt;/code&gt; to white &amp;mdash; instead setting it to &lt;code&gt;clearColor&lt;/code&gt; so you can combine the default text labels with non-white cell backgrounds.&lt;/p&gt;

&lt;pre&gt;- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];

    self.textLabel.backgroundColor = [UIColor clearColor];
    self.detailTextLabel.backgroundColor = [UIColor clearColor];
}&lt;/pre&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;Download the sample project &lt;a href="http://projectswithlove.com/projects/ShadowedTableView.zip"&gt;ShadowedTableView.zip&lt;/a&gt; (26kB). Last updated 2009-08-23.&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;ShadowedTableView&lt;/code&gt; is self-contained so you can drop it easily into a project.&lt;/p&gt;

&lt;p&gt;In its current form, it only works well for full-width, rectangular, contiguous tables &amp;mdash; so it works well for "plain" tables but is not suited to "grouped" tables. It also looks best if the table row separator is set to "none".&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-450107741252258283?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/450107741252258283?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/450107741252258283?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/08/adding-shadow-effects-to-uitableview.html" title="Adding shadow effects to UITableView using CAGradientLayer" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;D0EDQ3gycSp7ImA9WxNQFE8.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-3877884665805423613</id><published>2009-08-14T06:47:00.001-07:00</published><updated>2009-09-19T22:47:52.699-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-19T22:47:52.699-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="AppKit" /><title>Animating a window to fullscreen on the Mac</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Many Mac OS X applications animate their regular application windows to fullscreen but since there's no dedicated method for the task, there's no standard Apple documentation that covers the operation. If you look for examples on the web, you'll find numerous examples that perform this operation using old APIs or methods intended for permanently fullscreen games (the wrong approach for an application window). In this post I'll show you my preferred approach for making an application window fullscreen, with continuous display and smooth animation.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;The sample app for this post has one window:&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/SoVUcqE4C8I/AAAAAAAAAY0/SNIr7Ya7zD0/fullscreenwindow.png?imgmax=800" alt="fullscreenwindow.png" border="0" width="364" height="276" /&gt;

&lt;p&gt;When you choose the "Toggle Fullscreen" menu item, the content area of the window (not the window's frame) will animate to fill the entire screen (the Dock and menubar will hide).&lt;/p&gt;

&lt;blockquote&gt;You can download the Xcode 3.1 project here: &lt;a href="http://projectswithlove.com/projects/FullscreenImage.zip"&gt;FullscreenImage.zip (277kB)&lt;/a&gt;.&lt;/blockquote&gt;

&lt;h4&gt;Fullscreen windows&lt;/h4&gt;

&lt;p&gt;There are two basic types of fullscreen on the Mac:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Screen takeover &amp;mdash; where one view gains exclusive control of the screen.&lt;/li&gt;
&lt;li&gt;Basic fullscreen window &amp;mdash; where a regular window occupies the whole screen without occlusions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first is normally recommended for games where you never want the window to be interrupted. For an example of this type of window, see my earlier post &lt;a href="http://cocoawithlove.com/2009/02/asteroids-style-game-in-coreanimation.html"&gt;An Asteroids-Style Game in Core Animation: Part 1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The second option has the advantage that it &lt;em&gt;can&lt;/em&gt; be interrupted by other windows. For example: Expos&amp;eacute;, Command-Tab and notification windows will continue to function. This is the approach that I will detail in this post.&lt;/p&gt;

&lt;h4&gt;Animating a window to fullscreen&lt;/h4&gt;

&lt;p&gt;Zooming a window to the full size of the screen can be done using the &lt;code&gt;setFrame:display:animate:&lt;/code&gt; method:&lt;/p&gt;

&lt;pre&gt;[mainWindow
    setFrame:[mainWindow frameRectForContentRect:[[mainWindow screen] frame]]
    display:YES
    animate:YES];&lt;/pre&gt;

&lt;p&gt;This will smoothly zoom a window to fill the available screen area.&lt;/p&gt;

&lt;p&gt;On its own though, it has a few limitations:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;It doesn't hide the menubar or Dock &amp;mdash; so it doesn't actually &lt;em&gt;fill&lt;/em&gt; the screen.&lt;/li&gt;
&lt;li&gt;It doesn't hide the frame of the window, so the frame remains visible around the outside.&lt;/li&gt;
&lt;li&gt;It doesn't change the window's level so panels and other window may still overlap the expanded window.&lt;/li&gt;&lt;/ul&gt;

&lt;h4&gt;Hiding the menubar and Dock&lt;/h4&gt;

&lt;p&gt;There are two different ways to hide the menubar and the Dock. They are:&lt;/p&gt;

&lt;pre&gt;SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);&lt;/pre&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;pre&gt;[NSMenu setMenuBarVisible:NO];&lt;/pre&gt;

&lt;p&gt;Despite the wording of the &lt;code&gt;NSMenu&lt;/code&gt; method, it does also hide the Dock.&lt;/p&gt;

&lt;p&gt;The first method has more options &amp;mdash; the biggest of which is the &lt;code&gt;kUIOptionAutoShowMenuBar&lt;/code&gt; which will reshow the menubar if you move the mouse to the top of the screen &amp;mdash; but unfortunately, this method is Carbon, not Cocoa, so it requires you to link against the Carbon frameworks.&lt;/p&gt;

&lt;p&gt;I prefer the &lt;code&gt;NSMenu&lt;/code&gt; method for its simplicity and Cocoa linkage. This does mean that if you want to show the menubar, you'd need to create an &lt;code&gt;NSTrackingArea&lt;/code&gt; or something similar to detect when the mouse is over the menubar and show it again.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Update 2009-09-20&lt;/strong&gt;: In Snow Leopard, you can use the &lt;code&gt;-[NSApplication setPresentationOptions:]&lt;/code&gt; method to handle all that &lt;code&gt;SetSystemUIMode&lt;/code&gt; could do and more, all with standard Cocoa linkage.&lt;/blockquote&gt;

&lt;p&gt;The other consideration with hiding the menubar is that you should only do it if the window you are resizing is actually on the &lt;code&gt;[[NSScreen screens] objectAtIndex:0]&lt;/code&gt; (the screen that shows the menubar). i.e.:&lt;/p&gt;

&lt;pre&gt;if ([[mainWindow screen] isEqual:[[NSScreen screens] objectAtIndex:0]])
{
    [NSMenu setMenuBarVisible:NO];
}&lt;/pre&gt;

&lt;h4&gt;Hiding the window frame&lt;/h4&gt;

&lt;p&gt;The next issue to address is the window frame: we need to hide it. The problem is that you &lt;em&gt;can't&lt;/em&gt; hide the frame of an existing window.&lt;/p&gt;

&lt;p&gt;Instead, what we do is create a new, borderless window and swap the &lt;code&gt;contentView&lt;/code&gt; from the old window into the new window.&lt;/p&gt;

&lt;pre&gt;fullscreenWindow = [[FullscreenWindow alloc]
    initWithContentRect:[mainWindow contentRectForFrameRect:[mainWindow frame]]
    styleMask:NSBorderlessWindowMask
    backing:NSBackingStoreBuffered
    defer:YES
    screen:[mainWindow screen]];
[fullscreenWindow setLevel:NSFloatingWindowLevel];
[fullscreenWindow setContentView:[mainWindow contentView]];
[fullscreenWindow setTitle:[mainWindow title]];
[fullscreenWindow makeKeyAndOrderFront:nil];&lt;/pre&gt;

&lt;p&gt;There are three other points to notice in this code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The window level is &lt;code&gt;NSFloatingWindowLevel&lt;/code&gt; (so that the window will appear above &lt;code&gt;NSPanel&lt;/code&gt;s and similar windows).&lt;/li&gt;
&lt;li&gt;The window title is set to match the old window (so that the new window will appear the same in Expos&amp;eacute;). &lt;/li&gt;
&lt;li&gt;The window is actually a subclass so we can override the method &lt;code&gt;canBecomeKeyWindow&lt;/code&gt; to return &lt;code&gt;YES&lt;/code&gt; (since it returns &lt;code&gt;NO&lt;/code&gt; by default for &lt;code&gt;NSBorderlessWindowMask&lt;/code&gt; windows).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;Other minor points&lt;/h4&gt;

&lt;p&gt;When swapping the &lt;code&gt;contentView&lt;/code&gt; between windows, the destination window should not be onscreen (&lt;code&gt;orderedOut:&lt;/code&gt;) otherwise flicker can occur.&lt;/p&gt;

&lt;p&gt;If you run the whole process while the window is miniaturized in the Dock, numerous screen glitches will occur. It's best to deminiaturize before you start (this must happen before you hide the Dock).&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can download the Xcode 3.1 project here:&lt;a href="http://projectswithlove.com/projects/FullscreenImage.zip"&gt; FullscreenImage.zip (277kB)&lt;/a&gt;.&lt;/blockquote&gt;

&lt;p&gt;The whole code is one method in the sample app &amp;mdash; an easy copy and paste into any application.&lt;/p&gt; 

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-3877884665805423613?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/3877884665805423613?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/3877884665805423613?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/08/animating-window-to-fullscreen-on-mac.html" title="Animating a window to fullscreen on the Mac" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;Ck8NSHozcSp7ImA9WxJaGE8.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-4608892811238634473</id><published>2009-08-09T00:36:00.001-07:00</published><updated>2009-08-09T05:28:19.489-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-09T05:28:19.489-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Foundation" /><title>Safe, threaded design and inter-thread communication</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;The Foundation framework provides all the tools you need for inter-thread communication &amp;mdash; without needing to handling locks and synchronization yourself. I'll show you Cocoa's tools for inter-thread communication, notifications and easy synchronization &amp;mdash; including far simpler code for posting NSNotifications on the main thread than the Cocoa documentation suggests.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Multi-threaded code has a reputation for being difficult to write and prone to deadlocks, race conditions and unpredictable behaviors.&lt;/p&gt;

&lt;p&gt;While this remains true if you are forced to handle locking yourself, Foundation provides all the tools you require to manage typical multi-threaded situations so that you can avoid the risks of locks entirely.&lt;/p&gt;

&lt;p&gt;This post comes from my shock at Apple's suggestion (in their &lt;a href="http://developer.apple.com/documentation/Cocoa/Conceptual/Notifications/Articles/Threading.html"&gt;Delivering Notifications To Particular Threads&lt;/a&gt;) that something as simple as sending an &lt;code&gt;NSNotification&lt;/code&gt; from one thread to another should take dozens of lines of code and a dedicated class for the purpose.&lt;/p&gt;

&lt;p&gt;It isn't that difficult. Sending data between threads (including notifications) is a one line job.&lt;/p&gt;

&lt;h4&gt;Rules for safe simple threading&lt;/h4&gt;

&lt;p&gt;Simple thread safety in Cocoa requires just two rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Every variable or object must nominally belong to a thread (although may be completely handed over to a different thread) and must not be used in multiple threads without handover (unless it is on the &lt;a href="http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html"&gt;list of explicity thread-safe classes&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;All communication between threads (after thread startup) should use &lt;code&gt;performSelector:onThread:withObject:waitUntilDone:&lt;/code&gt; and both the receiver and the "object" should belong (or be handed over) to the target thread.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The only limitation with this approach is that any thread that &lt;em&gt;receives&lt;/em&gt; communication must be running an &lt;code&gt;NSRunLoop&lt;/code&gt;. Since communication after construction is normally one-way (from worker thread back to the main thread) this is rarely a significant limitation. Other threads can invoke the &lt;code&gt;[NSRunLoop currentRunLoop]&lt;/code&gt;'s &lt;code&gt;runMode:beforeDate&lt;/code&gt; to process the run loop and receive messages.&lt;/p&gt;

&lt;p&gt;A lot of multi-threaded code does not follow these rules. A lot of multi-threaded code uses a careful system of locks, synchronized sections, volatile variables and atomic operations to allow single objects to be accessed simultaneously from multiple threads. This does work but generally speaking: you don't want to design code this way. It's tricky, confusing and prone to errors. To illustrate, you can have a look at how many changes I had to make to my AudioStreamer code between the &lt;a href="http://cocoawithlove.com/2008/09/streaming-and-playing-live-mp3-stream.html"&gt;first&lt;/a&gt; and &lt;a href="http://cocoawithlove.com/2009/06/revisiting-old-post-streaming-and.html"&gt;second&lt;/a&gt; versions &amp;mdash; rock-solid, manually-locked code is annoying and difficult to write.&lt;/p&gt;

&lt;p&gt;Instead, as much as possible, you should write your code to keep all objects compartmentalized to individual threads and to restrict communication between threads to method invocations using &lt;code&gt;performSelector:onThread:withObject:waitUntilDone:&lt;/code&gt;. To explain how this works, I'll show a simple example of something running in a separate thread and show how it can perform all its inter-thread communication using existing Foundation methods to automatically handle all thread safety issues.&lt;/p&gt;

&lt;h4&gt;Scenario: writing to a network NSFileHandle in a worker thread&lt;/h4&gt;

&lt;p&gt;One of the simplest situations where you may want multithreading is writing to a network socket's &lt;code&gt;NSFileHandle&lt;/code&gt;. This is a synchronous operation (blocks until complete) so it is a good idea to perform this in a worker thread so that the main thread of your program can remain responsive.&lt;/p&gt;

&lt;p&gt;The following class is an &lt;code&gt;NSOperation&lt;/code&gt; subclass. If you don't know about &lt;code&gt;NSOperation&lt;/code&gt;, it's an object that you can add to an &lt;code&gt;NSOperationQueue&lt;/code&gt; to have the object's &lt;code&gt;main&lt;/code&gt; method run in a separate thread (see &lt;a href="http://developer.apple.com/documentation/Cocoa/Conceptual/Multithreading/OperationObjects/OperationObjects.html"&gt;Apple's Threading Programming Guide&lt;/a&gt;). While &lt;code&gt;NSThread&lt;/code&gt;'s &lt;code&gt;detachNewThreadSelector:toTarget:withObject:&lt;/code&gt; is the best way to launch a single worker thread, &lt;code&gt;NSOperation&lt;/code&gt;s are the best way to run a series threaded tasks (or has been since &lt;a href="http://www.mikeash.com/?page=pyblog/use-nsoperationqueue.html"&gt;serious bugs in it were fixed in 10.5.7&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;This class' init method takes an &lt;code&gt;NSFileHandle&lt;/code&gt; and an &lt;code&gt;NSData&lt;/code&gt; object on construction and writes the data to the file handle in its &lt;code&gt;main&lt;/code&gt; method.&lt;/p&gt;

&lt;pre&gt;@interface FileWriteOperation : NSOperation
{
    NSFileHandle *fileHandle;
    NSData *data;
}
@end

@implementation FileWriteOperation

- (id)initWithFileHandle:(NSFileHandle *)aFileHandle data:(NSData *)aData
{
    self = [super init];
    if (self != nil)
    {
        fileHandle = [aFileHandle retain];
        data = [aData retain];
    }
    return self;
}

- (void)main
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    @try
    {
        [fileHandle writeData:data];
        // At this point, the write has succeeded
    }
    @catch (NSException *e)
    {
        // At this point, the write has failed
    }
    @finally
    {
        [pool drain];
    }
}

- (void)dealloc
{
    [fileHandle closeFile];
    [fileHandle release];
    [data release];
    [super dealloc];
}

@end&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;NSOperation&lt;/code&gt; is created and its thread is launched as follows:&lt;/p&gt;

&lt;pre&gt;// Assume the operationQueue, fileHandle and fileData already exist
[operationQueue
    addOperation:
        [[[FileWriteOperation alloc]
            initWithFileHandle:fileHandle
            data:fileData]
        autorelease]];&lt;/pre&gt;


&lt;p&gt;To follow the first rule of thread-safety, after the &lt;code&gt;FileWriteOperation&lt;/code&gt; is constructed, the &lt;code&gt;fileHandle&lt;/code&gt; value passed into its &lt;code&gt;initWithFileHandle:data:&lt;/code&gt; method cannot be used again outside the &lt;code&gt;NSOperationQueue&lt;/code&gt;'s worker thread.&lt;/p&gt;

&lt;h4&gt;Communicating success or failure&lt;/h4&gt;

&lt;p&gt;The above class works but doesn't have any way of communicating the result. What would be good is if we could send a &lt;code&gt;writeFinishedWithSuccess:YES&lt;/code&gt; at the "&lt;code&gt;write has succeeded&lt;/code&gt;" line and a &lt;code&gt;writeFinishedWithSuccess:NO&lt;/code&gt; at the "&lt;code&gt;write has failed&lt;/code&gt;" line.&lt;/p&gt;

&lt;p&gt;The unsafe way of doing this is to invoke a method on another object sending the result:&lt;/p&gt;

&lt;pre&gt;    [responseHandler writeFinishedWithSuccess:YES]; // BAD!!&lt;/pre&gt;

&lt;p&gt;If &lt;code&gt;responseHandle&lt;/code&gt; belongs to another thread, then this method could cause any number of race conditions and other multi-threading issues.&lt;/p&gt;

&lt;p&gt;The solution though is exceptionally simple:&lt;/p&gt;

&lt;pre&gt;    [responseHandler
        performSelectorOnMainThread:@selector(writeFinishedWithSuccess:)
        withObject:[NSNumber numberWithBool:YES]
        waitUntilDone:NO];&lt;/pre&gt;

&lt;p&gt;This assumes that &lt;code&gt;responseHandler&lt;/code&gt; is a nominally "main thread" object. You can use the &lt;code&gt;performSelector:onThread:withObject:waitUntilDone:&lt;/code&gt; method and specify a different thread if you need to send the response elsewhere.&lt;/p&gt;

&lt;p&gt;You'll notice that the parameter has to be an object in this case (&lt;code&gt;[NSNumber numberWithBool:YES]&lt;/code&gt; instead of simply &lt;code&gt;YES&lt;/code&gt;) and any parameter that you pass to another thread should not be used again in the current thread.&lt;/p&gt;

&lt;h4&gt;Delivering Notifications To Particular Threads&lt;/h4&gt;

&lt;p&gt;Of course, the &lt;code&gt;FileWriteOperation&lt;/code&gt; class shown above doesn't have a &lt;code&gt;responseHandle&lt;/code&gt; object that it can notify when it is done, so I'd rather use an &lt;code&gt;NSNotification&lt;/code&gt; sent to the &lt;code&gt;NSNotificationCenter&lt;/code&gt; and if any object wants to receive the notification, it can.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;NSNotificationCenter&lt;/code&gt; itself is thread-safe but it delivers the notifications on the thread in which you invoke &lt;code&gt;postNotification:&lt;/code&gt; so if you expect the observers of that notification to belong to a different thread, you've just broken those objects' thread safety.&lt;/p&gt;

&lt;p&gt;Normally it is a good idea to deliver all notifications on the main thread. We can do this as follows:&lt;/p&gt;

&lt;pre&gt;    [[NSNotificationCenter defaultCenter]
        performSelectorOnMainThread:@selector(postNotification:)
        withObject:
            [NSNotification
                notificationWithName:@"FileWriteOperationSucceeded"
                object:self]];&lt;/pre&gt;

&lt;p&gt;Some classes follow a different behavior of delivering notifications to the thread on which they were constructed (not necessarily the main thread). To follow this behavior, simply save the &lt;code&gt;[NSThread currentThread]&lt;/code&gt; on construction and perform the &lt;code&gt;postNotification:&lt;/code&gt; selector on that thread.&lt;/p&gt;

&lt;p&gt;You may have noticed that the notification is passing "&lt;code&gt;self&lt;/code&gt;" from one thread to another &amp;mdash; breaking the thread ownership of "&lt;code&gt;self&lt;/code&gt;". This is only really safe in one of the following cases:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Handover&lt;/strong&gt; &amp;mdash; the parameter will never be used on this thread again.&lt;br/&gt;In this case, if "&lt;code&gt;self&lt;/code&gt;" is complete on the worker thread (for example at the bottom of the &lt;code&gt;main&lt;/code&gt; method shown above). In this case, the object is passing itself back to the other thread.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Thread-safe&lt;/strong&gt; &amp;mdash; if the class or specific methods are guaranteed to be thread-safe.&lt;br/&gt;In this case, if the only methods invoked on &lt;code&gt;self&lt;/code&gt; are &lt;code&gt;retain&lt;/code&gt;, &lt;code&gt;release&lt;/code&gt; and the default pointer comparison &lt;code&gt;isEqual:&lt;/code&gt; method (these are the methods invoked when removing from an &lt;code&gt;NSMutableArray&lt;/code&gt;). These are guaranteed thread-safe methods.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;If neither of these are true then you can't pass &lt;code&gt;self&lt;/code&gt; (or any other parameter) safely between threads.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;The purpose of this article is to communicate two ideas:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Carefully locking and synchronizing makes programming hard but if you design your objects to be used on only one thread at a time, then they are thread-safe without the need for locks or synchronzation (if needed, split your objects into components for separate threads).&lt;/li&gt;
&lt;li&gt;Use inter-thread communication to keep objects in separate threads up-to-date with each other. In Cocoa, this is very simple but you do need to ensure that all parameters you pass are either thread-safe objects or handover objects.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;Frankly, Apple has made of meal of the &lt;a href="http://developer.apple.com/documentation/Cocoa/Conceptual/Notifications/Articles/Threading.html"&gt;Delivering Notifications To Particular Threads&lt;/a&gt; code. I would be happy to see it completely changed &amp;mdash; you should never need something so complex just to deliver notifications to another thread.&lt;/p&gt;

&lt;p&gt;Of couse, there are always situations where you can't run an &lt;code&gt;NSRunLoop&lt;/code&gt; to process &lt;code&gt;performSelector:onThread:withObject:waitUntilDone:&lt;/code&gt; messages. There are also situations where you feel that one of your object
s must be multi-threaded (rather than single thread exclusive). Either of these cases requires will require a synchronized or locked solution but my recommendation is to try to find an &lt;code&gt;NSRunLoop&lt;/code&gt; and thread exclusive solution first as these are significantly easier to manage and prone to fewer potential problems.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-4608892811238634473?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/4608892811238634473?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/4608892811238634473?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/08/safe-threaded-design-and-inter-thread.html" title="Safe, threaded design and inter-thread communication" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;A0UHRH4yfip7ImA9WxJaE0s.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-3496925401029784195</id><published>2009-08-03T23:36:00.001-07:00</published><updated>2009-08-04T00:00:35.096-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-04T00:00:35.096-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="UIKit" /><category scheme="http://www.blogger.com/atom/ns#" term="AppKit" /><title>Control and configuration of applications through Info.plist</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;The Info.plist file is home to the metadata about your application used by the operating system. Most Cocoa programmers know that it stores the bundle identifier, icon name and version number of an application but the Info.plist can also control access to essential iPhone hardware resources and can change the very nature of your Mac OS X applications. In this post, I'll cover basic Info.plist usage and also explain some of the rarer settings.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;The default fields: identifiers, icons and version numbers&lt;/h4&gt;

&lt;p&gt;The Info.plist is the main source of metadata that the operating system has to learn information about your application. Everything that the operating system may need to know (names, icons, supported file types, URL types, &lt;code&gt;NSApplication&lt;/code&gt; subclasses) may all be specified in the Info.plist.&lt;/p&gt;

&lt;p&gt;The file itself is familiar to almost all Cocoa programmers since Xcode inserts one automatically into every project created from an application template.&lt;/p&gt;

&lt;p&gt;Probably the most common settings are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CFBundleIdentifier&lt;/code&gt; &amp;mdash; the identifier for your application, normally in the form "com.[company].[application]". The iPhone tries to fill in the application name from the Project's product name but will fail if you ever try to build for a device if there are spaces or differences in capitalization so you may just want to set this manually.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CFBundleIconFile&lt;/code&gt; &amp;mdash; almost every application I ship names its icon "Icon.[png/icns]". Why Apple can't put a default value here, I don't know.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CFBundleVersion&lt;/code&gt; &amp;mdash; this isn't the only version number since you can embed a different version in the Project Settings. If you don't have a formal build system in place though, you'll need to make certain that this number is always different every time you give a build to someone to test (a crash log is useless if you can't guarantee which version it came from).&lt;/li&gt;&lt;/ul&gt;

&lt;h4&gt;How Xcode builds the Info.plist&lt;/h4&gt;

&lt;p&gt;Most of the other settings that are in the Info.plist by default have either good initial values (like the &lt;code&gt;NSMainNibFile&lt;/code&gt; value which is automatically set to the name of the Nib file that the template itself includes), are largely pointless (like the &lt;code&gt;CFBundleSignature&lt;/code&gt; which is a campy Mac OS 9 throwback) or are generated from values defined in the Project settings (like the &lt;code&gt;CFBundleName&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The reason why the fields in the Info.plist can be generated from "Project settings" fields is that their values are filled in when the Info.plist file is "built" by Xcode.&lt;/p&gt;

&lt;p&gt;Building the Info.plist file is actually the first stage in building for an application &amp;mdash; the file is build immediately after creating the directory structure for the bundle. You can control the Info.plist's build settings in the "Packaging" section of the Target settings &amp;mdash; including setting a different Info.plist for each target if needed.&lt;/p&gt;

&lt;p&gt;While most stages of a build are handled by an external process (like gcc or ibtool), if you look through the Build Results window log, you'll notice that the Info.plist is built by a tool that identifies itself as &lt;code&gt;&amp;lt;com.apple.tools.info-plist-utility&amp;gt;&lt;/code&gt;. This isn't actually a separate tool &amp;mdash; it is described as "abstract" by the "Built-in compilers.pbcompspec" in the DevToolCore.framework and is implemented internally by the &lt;code&gt;XCInfoPlistUtilityCommandInvocation&lt;/code&gt; class in the DevToolCore.framework. Xcode passes the arguments into this class (like it would for any other build stage) and the class parses the arguments and handles all the work itself.&lt;/p&gt;

&lt;h4&gt;Reading from the Info.plist in your program&lt;/h4&gt;

&lt;p&gt;While the Info.plist is primary metadata that your program advertises to the operating system and external programs, your program can easily read any of the fields in the Info.plist for its own purposes using the &lt;code&gt;NSBundle&lt;/code&gt;'s &lt;code&gt;infoDictionary&lt;/code&gt;. For example, the URL to an iPhone app's own page on the iTunes App Store would be:&lt;/p&gt;

&lt;pre&gt;NSURL *appURL =
    [NSURL URLWithString:[NSString stringWithFormat:@"http://www.itunes.com/app/%@",
        [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]
            stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];&lt;/pre&gt;

&lt;p&gt;Technically, you can store anything you want in the Info.plist file but generally your own data would be better put in a separate file so you don't slow the operating system down when it needs to open and parse the Info.plist file to extract the data it needs.&lt;/p&gt;

&lt;h4&gt;Essential iPhone Info.plist entries&lt;/h4&gt;

&lt;h5&gt;Aesthetic settings&lt;/h5&gt;

&lt;p&gt;A number of fields are required in the Info.plist to control aesthetic options for an iPhone application. These include:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;code&gt;UIPrerenderedIcon&lt;/code&gt; &amp;mdash; set this to disable the gloss highlight that the Springboard applies to your application's icon.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UIInterfaceOrientation&lt;/code&gt; &amp;mdash; use this to start your application in a non-portrait orientation.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UIStatusBarStyle&lt;/code&gt; &amp;mdash; use this to enable black or transparent status bars.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Avoiding WiFi disconnections&lt;/h5&gt;

&lt;p&gt;Any iPhone application that requires a WiFi connection must set &lt;code&gt;UIRequiresPersistentWiFi&lt;/code&gt; to &lt;code&gt;&amp;lt;true/&amp;gt;&lt;/code&gt;, otherwise the iPhone will abruptly disconnect the WiFi connection after 30 minutes of use. No warning, no error: 30 minutes and you'll lose WiFi without this flag.&lt;/p&gt;

&lt;h5&gt;Invoking your iPhone application by URL&lt;/h5&gt;

&lt;p&gt;The &lt;code&gt;CFBundleURLTypes&lt;/code&gt; key allows you to specify URL schemes that will cause the iPhone to switch to your application. No, you can't override the schemes for the built-in applications.&lt;/p&gt;

&lt;p&gt;If your application is launched using a URL type named &lt;em&gt;scheme&lt;/em&gt;, then you can also provide a different startup image "Default-&lt;em&gt;scheme&lt;/em&gt;.png" instead of the regular "Default.png".&lt;/p&gt;

&lt;h4&gt;Essential Mac OS X Info.plist entries&lt;/h4&gt;

&lt;h5&gt;Changing the application type&lt;/h5&gt;

&lt;p&gt;You can create an application with no UI &amp;mdash; no appearance in the Dock, no menubar and can't be the frontmost application &amp;mdash; by setting the &lt;code&gt;LSBackgroundOnly&lt;/code&gt; flag in the Info.plist.&lt;/p&gt;

&lt;p&gt;Realistically though, you're more likely to make your application &lt;code&gt;LSUIElement&lt;/code&gt;. The reason why this flag is better, is that your application &lt;em&gt;can&lt;/em&gt; be frontmost if you open a window but the other traits of &lt;code&gt;LSBackgroundOnly&lt;/code&gt; remain (no appearance in the Dock and no menubar).&lt;/p&gt;

&lt;p&gt;Why would you want an application with no appearance in the Dock? If you're making an &lt;code&gt;NSStatusBar&lt;/code&gt; application (little applications that run as icons in the right of the menubar).&lt;/p&gt;

&lt;p&gt;The following code adds an entry to the status bar when the application starts:&lt;/p&gt;

&lt;pre&gt;- (void)applicationDidFinishLaunching:(NSNotification *)notification
{
    statusItem = [[[NSStatusBar systemStatusBar]
        statusItemWithLength:NSSquareStatusItemLength] retain];
    
    [statusItem setMenu:statusMenu];
    [statusItem setHighlightMode:YES];
    [statusItem setToolTip:@"My Status Bar App"];
    [statusItem setTitle:nil];
    [statusItem setImage:[NSImage imageNamed:@"StatusBarIcon"]];
}&lt;/pre&gt;

&lt;h5&gt;Accepted document types&lt;/h5&gt;

&lt;p&gt;Document types accepted by an application can be set by editing the Info.plist file (the &lt;code&gt;CFBundleDocumentTypes&lt;/code&gt; dictionary) although this is easier to do on the Properties tab of the Target settings.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Looking back over the range of topics that I've covered, you can see that the Info.plist controls a very diverse range of application settings and capabilities. There are many more options that I haven't listed here so if you're trying to specify default localizations, change the &lt;code&gt;NSApplication&lt;/code&gt; subclass, set environment variables for your application, specify a minimum OS versions and more, have a look at &lt;a href="http://developer.apple.com/documentation/MacOSX/Conceptual/BPRuntimeConfig/Articles/PListKeys.html"&gt;Runtime Configuration Guidelines: Property List Key Reference&lt;/a&gt; for other fields.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-3496925401029784195?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/3496925401029784195?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/3496925401029784195?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/08/control-and-configuration-of.html" title="Control and configuration of applications through Info.plist" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;D08DRXw-fCp7ImA9WxJbGE8.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-6818401115770833673</id><published>2009-07-27T17:20:00.001-07:00</published><updated>2009-07-28T17:04:34.254-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-28T17:04:34.254-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Objective-C" /><title>Rules to avoid retain cycles</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Normally in Objective-C, if you follow the basic rule of maintaining a positive retain count for everything you need to hold onto and releasing when you're done, memory management will "just work" &amp;mdash; until you create a retain cycle and suddenly no objects in the cycle will ever be freed. In this post, I'll explain retain cycles, common cases where they occur and the solutions to these problems.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Memory Management&lt;/h4&gt;

&lt;p&gt;All memory in a computer program must be allocated before it can be used and if you want to reuse that memory later for another purpose, it must be deallocated when you are done with it.&lt;/p&gt;

&lt;p&gt;In garbage collected environments, programmers don't need to handle the allocation and deallocation themselves; the allocation, retaining, releasing and deallocation are handled automatically &amp;mdash; but these steps still occur. Unfortunately, this automatic work is CPU and memory hungry; garbage collection is slower and takes more memory than manual memory management.&lt;/p&gt;

&lt;p&gt;So, on the iPhone and in performance critical Mac OS X applications, we still have to handle memory management ourselves and that means methodically following the rules of Objective-C memory management:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;If you want to "own" an object, you must alloc, copy or retain it.&lt;/li&gt;
&lt;li&gt;Always release or autorelease when you are done with an object.&lt;/li&gt;&lt;/ol&gt;

&lt;p&gt;Unfortunately, if a retain cycle occurs, these rules are not enough to guarantee memory is freed correctly.&lt;/p&gt;

&lt;h4&gt;Object hierarchies and retain cycles&lt;/h4&gt;

&lt;p&gt;A quick explanation of retain cycles requires that I quickly summarize how hierarchies of objects are tied together. Specifically: objects in a hierarchy are created, owned and freed in a chain along the hierarchy.&lt;/p&gt;

&lt;img src="http://lh4.ggpht.com/_gfktUGS0ov0/Sm1ETh2EknI/AAAAAAAAAYQ/_SUQ2BfEvls/retaincycle1.png?imgmax=800" alt="retaincycle1.png" border="0" width="412" height="193" /&gt;

&lt;p&gt;In this example, "Some Object" owns Parent which in turn owns the Child.&lt;/p&gt;

&lt;p&gt;When the hierarchy is no longer needed, "Some Object" sends a &lt;code&gt;release&lt;/code&gt; to the Parent. The Parent's &lt;code&gt;retainCount&lt;/code&gt; hits zero, causing its &lt;code&gt;dealloc&lt;/code&gt; method to run. In its &lt;code&gt;dealloc&lt;/code&gt; method, it sends a &lt;code&gt;release&lt;/code&gt; to the Child, successfully freeing the chain. This is the &lt;em&gt;correct&lt;/em&gt; behavior.&lt;/p&gt;

&lt;p&gt;The problem of retain cycles occurs when the Child needs a pointer to the Parent for any reason and it chooses to retain the Parent. This alters the diagram to the following:&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/Sm1Fo-w18SI/AAAAAAAAAYU/zw19VVnOH28/retaincycle2.png?imgmax=800" alt="retaincycle2.png" border="0" width="412" height="193" /&gt;

&lt;p&gt;In this diagram, when "Some Object" sends a &lt;code&gt;release&lt;/code&gt; to the Parent, the &lt;code&gt;retainCount&lt;/code&gt; does not reach zero (since the Child's retain of the Parent has incremented the &lt;code&gt;retainCount&lt;/code&gt; for itself). Since the Parent's &lt;code&gt;retainCount&lt;/code&gt; does not reach zero, its &lt;code&gt;dealloc&lt;/code&gt; method never gets called and so it never sends a &lt;code&gt;release&lt;/code&gt; to the Child.&lt;/p&gt;

&lt;p&gt;This is a retain cycle: with the Parent retaining the Child and the Child retaining the Parent, they continue to exist, cut off from the rest of the objects in the program but keeping themselves alive. They have leaked.&lt;/p&gt;

&lt;h4&gt;Avoiding retain cycles rule #1: An object must never retain its parent&lt;/h4&gt;

&lt;p&gt;The first rule to avoid retain cycles is that an object must never retain its parent. This changes the previous diagram to the following:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Sm1m4LCdgCI/AAAAAAAAAYY/MapiBpwPXxw/retaincycle3.png?imgmax=800" alt="retaincycle3.png" border="0" width="412" height="193" /&gt;

&lt;p&gt;This is the easy case: an object should never retain its parent when it makes a pointer to the parent.&lt;/p&gt;

&lt;p&gt;Notice that the term "weak pointer" is used. A weak pointer is one that does not retain its target.&lt;/p&gt;

&lt;p&gt;Of course, now that the child doesn't retain the parent, the child must be aware of any situation where the parent becomes invalid (freed) and not use its pointer to the parent in that case.&lt;/p&gt;

&lt;p&gt;So, either:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;The parent must set the &lt;code&gt;parent&lt;/code&gt; pointer in the child to &lt;code&gt;nil&lt;/code&gt; when the relationship is broken.&lt;/li&gt;
&lt;p&gt;or&lt;/p&gt;
&lt;li&gt;The design must guarantee that the parent pointer is always valid for the child's lifetime (or if the parent uses &lt;code&gt;autorelease&lt;/code&gt; to free children, valid except in the child's &lt;code&gt;dealloc&lt;/code&gt; method).&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;These two options apply to weak pointers in general: once the target becomes invalid, the pointer must be set to &lt;code&gt;nil&lt;/code&gt; or the design must otherwise prevent invalid use.&lt;/p&gt;

&lt;p&gt;Generally speaking, the option of setting to &lt;code&gt;nil&lt;/code&gt; is much safer. The only downside is that it requires a way of detecting the pending release of the target and nominating an object whose role it is to make that detection and update the pointer accordingly. It is easy here where the parent (the target of the weak pointer) knows about the child and is also the hierarchical manager of the child but not all retain cycles are one-to-one like this.&lt;/p&gt;

&lt;h4&gt;Avoiding retain cycles rule #2: no hierarchical ancestor can be retained&lt;/h4&gt;

&lt;p&gt;It may seem obvious but this is where retain cycles can be subtle: an object must not retain any of its parent's parents, or any of their parents.&lt;/p&gt;

&lt;p&gt;&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Sm1shfxWAgI/AAAAAAAAAYc/bK5Ko8QTpaY/retaincycle4.png?imgmax=800" alt="retaincycle4.png" border="0" width="412" height="280" /&gt;

&lt;p&gt;This rule applies to many different situations. Some important considerations in Cocoa:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If an object retains an &lt;code&gt;NSArray&lt;/code&gt;, &lt;code&gt;NSDictionary&lt;/code&gt; or &lt;code&gt;NSSet&lt;/code&gt; that collection must not retain the object or any of its parents.&lt;/li&gt;
&lt;li&gt;If an object retains an &lt;code&gt;NSInvocation&lt;/code&gt; where one of the arguments is the object or one of its ancestors, the &lt;code&gt;NSInvocation&lt;/code&gt; may not retain its arguments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to store a collection of objects that may include one or more parents, you may want to consider one of the collections capable of non-retained pointers ("weak" collections):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;CFArray&lt;/code&gt;, &lt;code&gt;CFDictionary&lt;/code&gt; or &lt;code&gt;CFSet&lt;/code&gt; with &lt;code&gt;NULL&lt;/code&gt; for the callbacks structure. i.e.:&lt;br/&gt;&lt;code&gt;CFArrayCreateMutable(NULL, 0, NULL);&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;+[NSPointerArray pointerArrayWithWeakObjects]&lt;/code&gt; (Mac OS X only)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;+[NSMapTable mapTableWithWeakToWeakObjects]&lt;/code&gt; (Mac OS X only)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;+[NSMapTable hashTableWithWeakObjects]&lt;/code&gt; (Mac OS X only)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the rare situation where you must put a parent into a collection which retains its contents (like &lt;code&gt;NSArray&lt;/code&gt;) you can wrap the contents in a non-retained object &lt;code&gt;NSValue&lt;/code&gt;. i.e.:&lt;/p&gt;

&lt;pre&gt;[arrayOfParents addObject:[NSValue valueWithNonretainedObject:aParent]];&lt;/pre&gt;

&lt;p&gt;Despite this non-retain requirement for direct ancestors, it is okay to retain non-direct ancestors. However, once an object retains a non-direct ancestor, it becomes a direct ancestor to the object it retains.&lt;/p&gt;

&lt;p&gt;For example, consider a situation where one child of a parent retains another:&lt;/p&gt;

&lt;img src="http://lh3.ggpht.com/_gfktUGS0ov0/Sm1urYq0yVI/AAAAAAAAAYg/z_GGJohcrnA/retaincycle5.png?imgmax=800" alt="retaincycle5.png" border="0" width="412" height="241" /&gt;

&lt;p&gt;Before the "senior" child retained the other, they were both level siblings. Once one child retains another, it becomes a direct ancestor to the other. This now "junior" child may not retain its senior sibling without creating a loop. Any connection from this "junior" child back to the "senior" child must follow the "weak pointer" rules.&lt;/p&gt;

&lt;p&gt;If you have lots of sibling nodes that you'd like to connect in complex ways, it's best to leave the ownership to the parent and connect all the siblings using non-retained pointers.&lt;/p&gt;

&lt;h4&gt;Avoiding retain cycles rule #3: "Connection" objects should not retain their target&lt;/h4&gt;

&lt;p&gt;Any object which connects itself to an arbitrary target object, without knowing their relationship, must not retain its target.&lt;/p&gt;

&lt;p&gt;Connection objects include:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;objects with a target and action (like a button)&lt;/li&gt;
&lt;li&gt;objects that take a delegate&lt;/li&gt;
&lt;li&gt;observees (objects to which observers are added)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lets consider this by looking at the example of a button in a user-interface. A button connects the view hierarchy (through the button's &lt;code&gt;superview&lt;/code&gt;) to the target of its action (it invokes the action method on its target when clicked).&lt;/p&gt;

&lt;p&gt;A button must not retain its target. The reason for this becomes clear when you consider that a connection may need to point to a parent object:&lt;/p&gt; 

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Sm1zFPYL57I/AAAAAAAAAYo/eFqpjsW8Uys/retaincycle6.png?imgmax=800" alt="retaincycle6.png" border="0" width="412" height="134" /&gt;

&lt;p&gt;This diagram models the common situation where button invokes a method on the controller. The "Parent" is the view controller, the "Child" is the view which contains the button and the "Object with connection" is the button.&lt;/p&gt;

&lt;p&gt;Clearly, if the button retained its target, there would be a retain cycle.&lt;/p&gt;

&lt;p&gt;Obviously though, this creates a management problem: the button's controller must ensure that its target is updated if the target disappears (since the button object won't notice on its own).&lt;/p&gt;

&lt;p&gt;Responsibility for maintaining connections invariably lies with that object's manager &amp;mdash; following the design of your code, you must decide which object is responsible for managing the connection and it must detect when the connection becomes invalid and set it to &lt;code&gt;nil&lt;/code&gt; or delete the connection entirely.&lt;/p&gt;

&lt;p&gt;Fortunately, in most situations the solution is straightforward: the target is ultimately the owner and controller of the connection object, so the target just needs to release its children correctly when it is released and the connection will never persist past the lifetime of the target.&lt;/p&gt;

&lt;h4&gt;Avoiding retain cycles rule #4: use "close" methods to break cycles&lt;/h4&gt;

&lt;p&gt;If you have a hierarchy that is difficult to work out, it may be easier to retain any object you wish, and implement a "close" method to address the problem of cycles. A "close" method is one that is guaranteed to be sent to an object when its primary function is complete.&lt;/p&gt;

&lt;p&gt;An example of this is a retain cycle between two &lt;code&gt;NSView&lt;/code&gt;s. If you want to create retain cycles between two views, then go ahead. All you need to remember to do is disconnect each view in its &lt;code&gt;willRemoveSubview:&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;willRemoveSubview:&lt;/code&gt; acts to warn each view about a pending removal from the display (an end to its primary function) and the method is sent regardless of retain count &amp;mdash; so you can use it to break any possible retain cycles so that the object will be &lt;code&gt;dealloc&lt;/code&gt;'d as normal when its parents release it.&lt;/p&gt;

&lt;h4&gt;Avoiding retain cycles rule #5: temporary retains must be temporary&lt;/h4&gt;

&lt;p&gt;Any of these rules can be broken for short periods of time &amp;mdash; however the rule must by "unbroken" automatically, without further intervention, for example: when an animation or other triggered process completes.&lt;/p&gt;

&lt;p&gt;This is particularly useful for actions expected to delete, disrupt, sort or rearrange hierarchies temporarily.  You must remain mindful that this could inflate memory use if you hold on for too long, so only use this approach sparingly.&lt;/p&gt;

&lt;p&gt;An example of a temporary broken rule is the &lt;code&gt;NSURLConnection&lt;/code&gt; &lt;code&gt;delegate&lt;/code&gt;. By default, a &lt;code&gt;delegate&lt;/code&gt; should not be retained as it is the target of an arbitrary connection (see Rule #3). However, an &lt;code&gt;NSURLConnection&lt;/code&gt;'s use of its &lt;code&gt;delegate&lt;/code&gt; is guaranteed to complete automatically (either by connection complete or by timeout) so this object can safely retain its &lt;code&gt;delegate&lt;/code&gt;. To be a good citizen in this situation, the &lt;code&gt;NSURLConnection&lt;/code&gt; also provides the &lt;code&gt;cancel&lt;/code&gt; method which acts as a "close" and will release the &lt;code&gt;delegate&lt;/code&gt; sooner if desired (although the release is deferred through the run loop; it is not synchronous to the method invocation).&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;You may be tempted to retain every object you use out of fear that it will disappear while you're using it. Unfortunately, you can't simply retain everything &amp;mdash; you must be aware of the hierarchical structure and think about what you are retaining and why.&lt;/p&gt;

&lt;p&gt;I've listed 5 rules here but if you want a simpler message to remember: an object may only retain something indefinitely if it is hierarchically senior. If you don't know which object is senior, you must work it out before you retain. If there is no clear senior object &amp;mdash; you should redesign so that there is.&lt;/p&gt;

&lt;/span&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-6818401115770833673?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/6818401115770833673?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/6818401115770833673?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/07/rules-to-avoid-retain-cycles.html" title="Rules to avoid retain cycles" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;CEcBRns-eyp7ImA9WxNREU8.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-4820161915177003390</id><published>2009-07-23T00:09:00.001-07:00</published><updated>2009-09-04T20:40:57.553-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-04T20:40:57.553-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Foundation" /><category scheme="http://www.blogger.com/atom/ns#" term="Standard C" /><title>Temporary files and folders in Cocoa</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;If you need to use temporary files in your application and you search the Cocoa documentation for "temporary file", you're unlikely to find anything that explains how to create one. Since temporary files and folders are subject to a number of security issues and race conditions when done wrong, it is important to know the correct way to create them. I'll show you some code that you can copy and paste into your applications to create temporary files and folders safely.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;

&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;With large amounts of RAM on modern computers and alternatives such as the cache directories and application support directories, genuine temporary files are not needed in most Cocoa applications. Even when they are needed, for atomic write operations or for Core Data databases, Cocoa libraries often create them automatically.&lt;/p&gt;

&lt;p&gt;Eventually though, you're likely to encounter a situation where you need to create a temporary file yourself. You need to be careful when creating temporary files because:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;Predictable temporary file locations can be a security hole in your applications.&lt;/li&gt;
&lt;li&gt;On Mac OS X, multiple users on the computer may have their own copies of your application open, so the creation must be atomic (safe when concurrent).&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;In addition to this, you must be able to find the correct directories to place your files, be aware of the lifetime of files in these locations and manage cleanup correctly when you are done.&lt;/p&gt;

&lt;h4&gt;Required steps&lt;/h4&gt;

&lt;h5&gt;Choosing the right enclosing directory&lt;/h5&gt;

&lt;p&gt;The directory for temporary files needs to be writeable by the current user. This means that the directory will need to be user-specific.&lt;/p&gt;

&lt;p&gt;The correct directory is almost always the one returned by the Foundation function &lt;code&gt;NSTemporaryDirectory&lt;/code&gt;. This directory is unique for each user (so each user has write permissions to it).&lt;/p&gt;

&lt;p&gt;If you choose this directory though, it is important to know that it is cleaned out automatically every 3 days but otherwise persists between application launches and reboots. This directory is in a hashed location (not predictable in advance) and is therefore safe against security issues associated with predicatable locations.&lt;/p&gt;

&lt;p&gt;If you need a location that can persist longer than 3 days, you probably want to use the Application Support directory or a Cache directory instead. Both of these locations are permanent (until your application deletes the contents) but Application Support is considered "important data" and backed up by Time Machine, whereas Cache is considered "user deletable at any time" and is not backed up. The backup point is important: don't store large amounts of temporary data in a location that will fill someone's backup drive.&lt;/p&gt;

&lt;p&gt;These alternate directories are obtained using the Foundation function &lt;code&gt;NSSearchPathForDirectoriesInDomains&lt;/code&gt; with a first parameter of &lt;code&gt;NSApplicationSupportDirectory&lt;/code&gt; or &lt;code&gt;NSCachesDirectory&lt;/code&gt;, a second parameter of &lt;code&gt;NSUserDomainMask&lt;/code&gt; (occasionally a different value if you need a directory shared between users on the system or network &amp;mdash; but this is uncommon). This function returns an array but you'll normally get just one result if you use &lt;code&gt;NSUserDomainMask&lt;/code&gt; and you'll need to append your bundle identifier to get a location unique to your application.&lt;/p&gt;

&lt;pre&gt;// an alternative to the NSTemporaryDirectory
NSString *path = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(
    NSCachesDirectory, NSUserDomainMask, YES);
if ([paths count])
{
    NSString *bundleName =
        [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];
    path = [[paths objectAtIndex:0] stringByAppendingPathComponent:bundleName];
}&lt;/pre&gt;

&lt;p&gt;This &lt;code&gt;path&lt;/code&gt; value can be used instead of the &lt;code&gt;NSTemporaryDirectory()&lt;/code&gt; invocations in the code samples below.&lt;/p&gt;

&lt;h5&gt;Creating and opening a file or subdirectory&lt;/h5&gt;

&lt;p&gt;To avoid concurrency issues (race conditions), you need to choose a name for any file or directory placed directly in the temporary directory that is unique but which also can't be stolen by another process between choosing the name and creating/opening the file or directory. Even though &lt;code&gt;NSTemporaryDirectory()&lt;/code&gt; is unique for each user, you still must avoid potential conflicts within the user's account.&lt;/p&gt;

&lt;p&gt;To do this, we use the POSIX function &lt;code&gt;mkstemp&lt;/code&gt; for files and &lt;code&gt;mkdtemp&lt;/code&gt; for directories. The former will return an already open file descriptor for the file and the latter will have already created the directory for us.&lt;/p&gt;

&lt;p&gt;We could simply generate a universally unique identifier (UUID) and use that for the filename but these IDs are guessable which can create security problems in obscure cases where we don't also check for a name conflict &amp;mdash; better to use something that looks for a collision, in the extremely unlikely case that it occurs. If you must use a UUID filename instead of &lt;code&gt;mkstemp&lt;/code&gt; for some reason, be certain that it is for non-critical data.&lt;/p&gt;

&lt;h6&gt;Creating a temporary file:&lt;/h6&gt;

&lt;pre&gt;NSString *tempFileTemplate =
    [NSTemporaryDirectory() stringByAppendingPathComponent:@"myapptempfile.XXXXXX"];
const char *tempFileTemplateCString =
    [tempFileTemplate fileSystemRepresentation];
char *tempFileNameCString = (char *)malloc(strlen(tempFileTemplateCString) + 1);
strcpy(tempFileNameCString, tempFileTemplateCString);
int fileDescriptor = mkstemp(tempFileNameCString);

if (fileDescriptor == -1)
{
	// handle file creation failure
}

// This is the file name if you need to access the file by name, otherwise you can remove
// this line.
tempFileName =
    [[NSFileManager defaultManager]
        stringWithFileSystemRepresentation:tempFileNameCString
        length:strlen(tempFileNameCString)];

free(tempFileNameCString);
tempFileHandle =
    [[NSFileHandle alloc]
        initWithFileDescriptor:fileDescriptor
        closeOnDealloc:NO];&lt;/pre&gt;

&lt;p&gt;It is important to handle all reading and writing from the temporary file using this &lt;code&gt;fileDescriptor&lt;/code&gt; or something created directly from the &lt;code&gt;fileDescriptor&lt;/code&gt; like the &lt;code&gt;NSFileHandle&lt;/code&gt; in this example. This guarantees the operation remains safe for concurrency &amp;mdash; if the &lt;code&gt;fileDescriptor&lt;/code&gt; is closed before use, a race condition could occur.&lt;/p&gt;

&lt;p&gt;The "X"s in the file name are replaced by the unique hash for the file's name. You'll probably want to replace the "&lt;code&gt;myapptempfile&lt;/code&gt;" name with something appropriate, although it isn't required (the file is guaranteed unique regardless).&lt;/p&gt;

&lt;p&gt;Also notice the use of &lt;code&gt;fileSystemRepresentation&lt;/code&gt; and &lt;code&gt;stringWithFileSystemRepresentation:length:&lt;/code&gt; to convert to and from the C strings &amp;mdash; this is helpful to handle weird path quirks on different filesystems.&lt;/p&gt;


&lt;h6&gt;Creating a temporary folder:&lt;/h6&gt;

&lt;pre&gt;NSString *tempDirectoryTemplate =
    [NSTemporaryDirectory() stringByAppendingPathComponent:@"myapptempdirectory.XXXXXX"];
const char *tempDirectoryTemplateCString =
    [tempDirectoryTemplate fileSystemRepresentation];
char *tempDirectoryNameCString =
    (char *)malloc(strlen(tempDirectoryTemplateCString) + 1);
strcpy(tempDirectoryNameCString, tempDirectoryTemplateCString);

char *result = mkdtemp(tempDirectoryNameCString);
if (!result)
{
    // handle directory creation failure
}

NSString *tempDirectoryPath =
    [NSString
        stringWithFileSystemRepresentation:tempFileNameCString
        length:strlen(result)];
free(tempDirectoryNameCString);&lt;/pre&gt;

&lt;p&gt;You can now use the &lt;code&gt;tempDirectoryPath&lt;/code&gt; as the container for any files. As with the previous example, you probably want to replace "&lt;code&gt;myapptempdirectory&lt;/code&gt;" with something appropriate to your application and usage.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;You could simply create a file in the &lt;code&gt;/tmp&lt;/code&gt; directory but this approach is filled with many problems &amp;mdash; write permissions, concurrency issues, security issues and duration or persistence issues.&lt;/p&gt;

&lt;p&gt;Fortunately, the code to create a temporary file or temporary directory is consistent &amp;mdash; you can normally use these code samples without modification. The only choices you need to make is whether to use an alternative directory (like the Application Support directory or the Caches directory).&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-4820161915177003390?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/4820161915177003390?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/4820161915177003390?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/07/temporary-files-and-folders-in-cocoa.html" title="Temporary files and folders in Cocoa" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;DUYCSHs8eip7ImA9WxJUF0w.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-1814284896744429770</id><published>2009-07-13T18:17:00.001-07:00</published><updated>2009-07-15T21:06:09.572-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-15T21:06:09.572-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cocoa Touch" /><category scheme="http://www.blogger.com/atom/ns#" term="Foundation" /><title>A simple, extensible HTTP server in Cocoa</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;HTTP is one of the simpler protocols to implement for communication between computers. On the iPhone, since there are no APIs for data synchronization or file sharing, embedding an HTTP server is one of the best ways to transfer data from your iPhone application to a computer. In this post I'll show you how to write your own simple but extensible HTTP server. The server classes will also work on Mac OS X (Cocoa un-Touched).&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;In this post I will present the following sample application:&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Slsp2-witbI/AAAAAAAAAX4/t6-D7T6Mttw/httpserver.png?imgmax=800" alt="httpserver.png" border="0" width="520" height="306" /&gt;

&lt;p&gt;The application is very simple: you can edit text and save it to a file (it is always saved to the same file).&lt;/p&gt;

&lt;p&gt;While the application is running, it also runs an HTTP server on port 8080. If the path "/" is requested, it will return the content of the saved file. All other requests return a 501 error.&lt;/p&gt;

&lt;p&gt;To transfer the text file from the iPhone application, just enter the IP address of the phone followed by ":8080" in any web browser.&lt;/p&gt;

&lt;h4&gt;HTTPServer and HTTPResponseHandler classes&lt;/h4&gt;

&lt;p&gt;The approach I use for an HTTP server involves two classes: the server (which listens for connections and reads data up to the end of the HTTP header) and the response handler (which sends the response and may choose to read from the connection past the header).&lt;/p&gt;

&lt;p&gt;The key design choice for me was simplicity of each new response implementation: the server and response classes are designed so that a new response implementation need only implement three methods:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;&lt;code&gt;canHandleRequest:method:url:headerFields:&lt;/code&gt; &amp;mdash; to decide if the implementation can handle a specific request&lt;/li&gt;
&lt;li&gt;&lt;code&gt;startResponse&lt;/code&gt; &amp;mdash; to begin writing (or completely write) the response&lt;/li&gt;
&lt;li&gt;&lt;code&gt;load&lt;/code&gt; &amp;mdash; all subclasses should implement the standard &lt;code&gt;+[NSObject load]&lt;/code&gt; method to register themselves with the base class&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is just a tiny HTTP server but the approach should allow you to quickly integrate HTTP communications into any application.&lt;/p&gt;

&lt;h4&gt;Opening a socket for listening&lt;/h4&gt;

&lt;p&gt;Most server communications, HTTP included, begin by creating a socket for listening.&lt;/p&gt;

&lt;p&gt;Sockets in Cocoa can be created and configured entirely using the BSD sockets code but it's often marginally easier to use the CoreFoundation &lt;code&gt;CFSocket&lt;/code&gt; API where possible. Unfortunately, that only makes it marginally easier &amp;mdash; we still have a large block of boilerplate code to throw down just to open a socket.&lt;/p&gt;

&lt;p&gt;From the &lt;code&gt;-[HTTPServer start]&lt;/code&gt; method:&lt;/p&gt;

&lt;pre&gt;socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM,
    IPPROTO_TCP, 0, NULL, NULL);
if (!socket)
{
    [self errorWithName:@"Unable to create socket."];
    return;
}

int reuse = true;
int fileDescriptor = CFSocketGetNative(socket);
if (setsockopt(fileDescriptor, SOL_SOCKET, SO_REUSEADDR,
    (void *)&amp;reuse, sizeof(int)) != 0)
{
    [self errorWithName:@"Unable to set socket options."];
    return;
}

struct sockaddr_in address;
memset(&amp;address, 0, sizeof(address));
address.sin_len = sizeof(address);
address.sin_family = AF_INET;
address.sin_addr.s_addr = htonl(INADDR_ANY);
address.sin_port = htons(HTTP_SERVER_PORT);
CFDataRef addressData =
    CFDataCreate(NULL, (const UInt8 *)&amp;address, sizeof(address));
[(id)addressData autorelease];

if (CFSocketSetAddress(socket, addressData) != kCFSocketSuccess)
{
    [self errorWithName:@"Unable to bind socket to address."];
    return;
}
&lt;/pre&gt;

&lt;p&gt;This is a large block of code but it's really only doing one thing: opening a socket to listen for TCP connections on the port specified by &lt;code&gt;HTTP_SERVER_PORT&lt;/code&gt; (which is 8080 for this application).&lt;/p&gt;

&lt;p&gt;There is some additional work because I like to specify &lt;code&gt;SO_REUSEADDR&lt;/code&gt;. This lets us reclaim the port if it is open but idle (a common occurrence if we restart the program immediately after a crash or killing the application).&lt;/p&gt;

&lt;h4&gt;Receiving incoming connections&lt;/h4&gt;

&lt;p&gt;After the socket is setup, Cocoa handles a little more of the work so things get easier.&lt;/p&gt;

&lt;p&gt;We can receive each incoming connection by constructing an &lt;code&gt;NSFileHandle&lt;/code&gt; from the &lt;code&gt;fileDescriptor&lt;/code&gt; above and listening for connection notifications&lt;/p&gt;

&lt;p&gt;From the &lt;code&gt;-[HTTPServer start:]&lt;/code&gt; method (immediately below the previous code):&lt;/p&gt;

&lt;pre&gt;listeningHandle = [[NSFileHandle alloc]
    initWithFileDescriptor:fileDescriptor
    closeOnDealloc:YES];

[[NSNotificationCenter defaultCenter]
    addObserver:self
    selector:@selector(receiveIncomingConnectionNotification:)
    name:NSFileHandleConnectionAcceptedNotification
    object:nil];
[listeningHandle acceptConnectionInBackgroundAndNotify];&lt;/pre&gt;

&lt;p&gt;When &lt;code&gt;receiveIncomingConnectionNotification:&lt;/code&gt; is invoked, each new incoming connection will get its own &lt;code&gt;NSFileHandle&lt;/code&gt;. If you're keeping track, that was:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;1 file handle (&lt;code&gt;listeningHandle&lt;/code&gt;) manually created from the socket &lt;code&gt;fileDesriptor&lt;/code&gt; to listen on the socket for new connections.&lt;/li&gt;
&lt;li&gt;1 file handle automatically created for &lt;em&gt;each&lt;/em&gt; new connection received through &lt;code&gt;listeningHandle&lt;/code&gt;. We'll continue to listen to these new handles (the keys in the &lt;code&gt;incomingRequests&lt;/code&gt; dictionary) to record the data for each connection.&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;So, now that we've received a new, automatically created file handle, we create a &lt;code&gt;CFHTTPMessageRef&lt;/code&gt; (which will store the incoming data) we receive over the file handle. We store these as the objects in &lt;code&gt;incomingRequests&lt;/code&gt; dictionary to allow easy access to the &lt;code&gt;CFHTTPMessageRef&lt;/code&gt; for each file handle&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;CFHTTPMessageRef&lt;/code&gt; is both storage and the parser for the incoming data. We can invoke &lt;code&gt;CFHTTPMessageIsHeaderComplete()&lt;/code&gt; every time we add data to check when the HTTP headers are complete and we can spawn a response handler.&lt;/p&gt;

&lt;p&gt;The response handler is spawned in the &lt;code&gt;-[HTTPServer receiveIncomingDataNotification:]&lt;/code&gt; method:&lt;/p&gt;

&lt;pre&gt;if(CFHTTPMessageIsHeaderComplete(incomingRequest))
{
    HTTPResponseHandler *handler =
        [HTTPResponseHandler
            handlerForRequest:incomingRequest
            fileHandle:incomingFileHandle
            server:self];
    
    [responseHandlers addObject:handler];
    [self stopReceivingForFileHandle:incomingFileHandle close:NO];

    [handler startResponse];
    return;
}
&lt;/pre&gt;

&lt;p&gt;The server stops listening to the file handle for the connection at this point but it doesn't close it, since the file handle is passed to the &lt;code&gt;HTTPResponseHandler&lt;/code&gt; so that the HTTP response can be sent back over the same file handle.&lt;/p&gt;

&lt;h4&gt;Flexible response handling&lt;/h4&gt;

&lt;p&gt;Exactly which subclass the &lt;code&gt;+[HTTPResponseHandler handlerForRequest:fileHandle:server:]&lt;/code&gt; method chooses to return determines the entire content of the response. It does this by iterating over a priority ordered array of the registered handlers and asking each one if it wants to handle the request.&lt;/p&gt;

&lt;pre&gt;+ (Class)handlerClassForRequest:(CFHTTPMessageRef)aRequest
    method:(NSString *)requestMethod
    url:(NSURL *)requestURL
    headerFields:(NSDictionary *)requestHeaderFields
{
    for (Class handlerClass in registeredHandlers)
    {
        if ([handlerClass canHandleRequest:aRequest
            method:requestMethod
            url:requestURL
            headerFields:requestHeaderFields])
        {
            return handlerClass;
        }
    }
    
    return nil;
}&lt;/pre&gt;

&lt;p&gt;For this to work, all &lt;code&gt;HTTPResponseHandler&lt;/code&gt;s need to be registered with the base class. The easiest way to do this is to add an implementation of the &lt;code&gt;+[NSObject load]&lt;/code&gt; method to every subclass:&lt;/p&gt;

&lt;pre&gt;+ (void)load
{
    [HTTPResponseHandler registerHandler:self];
}&lt;/pre&gt;

&lt;p&gt;In the sample application, the only response handler other than the default is the &lt;code&gt;AppTextFileResponse&lt;/code&gt;. This class chooses to handle the response when the &lt;code&gt;requestURL&lt;/code&gt; is equal to "/".&lt;/p&gt;

&lt;p&gt;From the &lt;code&gt;AppTextFileResponse&lt;/code&gt; class:&lt;/p&gt;

&lt;pre&gt;+ (BOOL)canHandleRequest:(CFHTTPMessageRef)aRequest
    method:(NSString *)requestMethod
    url:(NSURL *)requestURL
    headerFields:(NSDictionary *)requestHeaderFields
{
    if ([requestURL.path isEqualToString:@"/"])
    {
        return YES;
    }
    
    return NO;
}&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;AppTextFileResponse&lt;/code&gt; then handles the entire response synchronously (before returning from the &lt;code&gt;startResponse&lt;/code&gt; method) by writing the text file saved by the application as the response body.&lt;/p&gt;

&lt;pre&gt;- (void)startResponse
{
    NSData *fileData =
        [NSData dataWithContentsOfFile:[AppTextFileResponse pathForFile]];

    CFHTTPMessageRef response =
        CFHTTPMessageCreateResponse(
            kCFAllocatorDefault, 200, NULL, kCFHTTPVersion1_1);
    CFHTTPMessageSetHeaderFieldValue(
        response, (CFStringRef)@"Content-Type", (CFStringRef)@"text/plain");
    CFHTTPMessageSetHeaderFieldValue(
        response, (CFStringRef)@"Connection", (CFStringRef)@"close");
    CFHTTPMessageSetHeaderFieldValue(
        response,
        (CFStringRef)@"Content-Length",
        (CFStringRef)[NSString stringWithFormat:@"%ld", [fileData length]]);
    CFDataRef headerData = CFHTTPMessageCopySerializedMessage(response);

    @try
    {
        [fileHandle writeData:(NSData *)headerData];
        [fileHandle writeData:fileData];
    }
    @catch (NSException *exception)
    {
        // Ignore the exception, it normally just means the client
        // closed the connection from the other end.
    }
    @finally
    {
        CFRelease(headerData);
        [server closeHandler:self];
    }
}&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;[server closeHandler:self];&lt;/code&gt; invocation tells the server to remove this &lt;code&gt;HTTPResponseHandler&lt;/code&gt; from the set of active handlers. The server will invoke &lt;code&gt;endReponse&lt;/code&gt; when it removes this handler (which is where we close the connection &amp;mdash; since this handler does not support &lt;code&gt;keep-alive&lt;/code&gt;).&lt;/p&gt;

&lt;h4&gt;Work not implemented&lt;/h4&gt;

&lt;p&gt;The biggest task not handled in this implementation is parsing the HTTP request body.&lt;/p&gt;

&lt;p&gt;The reason for this is that a general HTTP body solution is very complicated. The body's size may be specified by the &lt;code&gt;Content-Length&lt;/code&gt; header but it need not be &amp;mdash; so knowing where the body ends can be difficult. The body may also be encoded in one of about a dozen different &lt;code&gt;Transfer-Encoding&lt;/code&gt;s, including &lt;code&gt;chunk&lt;/code&gt;, &lt;code&gt;quoted-printable&lt;/code&gt;, &lt;code&gt;base64&lt;/code&gt;, &lt;code&gt;gzip&lt;/code&gt; &amp;mdash; each of which require different processing.&lt;/p&gt;

&lt;p&gt;However, I have never needed to implement a generic solution. It is normally easiest to determine what is needed for your specific needs and handle the HTTP body in accordance with those needs. You can handle the request body by overriding &lt;code&gt;-[HTTPRequestHandler receiveIncomingDataNotification:]&lt;/code&gt;. The default implementation ignores all data it receives after the HTTP request headers.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Data handling note&lt;/strong&gt;: the first time the &lt;code&gt;-[HTTPRequestHandler receiveIncomingDataNotification:]&lt;/code&gt; method is called, the initial bytes of the HTTP body will already have been read from the &lt;code&gt;fileHandle&lt;/code&gt; and appended to the &lt;code&gt;request&lt;/code&gt; instance variable. If you need to read the body, either continue reading into the &lt;code&gt;request&lt;/code&gt; object, or remember to include this initial data.&lt;/blockquote&gt;

&lt;p&gt;Another task not handled are Keep-Alive connections. These also need to be handled in &lt;code&gt;-[HTTPRequestHandler receiveIncomingDataNotification:]&lt;/code&gt; and I've left a big comment on the method about what would be involved. The reality is that it's probably easier to set the &lt;code&gt;Connection&lt;/code&gt; header field to &lt;code&gt;close&lt;/code&gt; for every response to tell the client that you're not going to handle Keep-Alive (see the &lt;code&gt;startResponse&lt;/code&gt; code sample above for an example).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;HTTPReseponseHandler&lt;/code&gt; priority does not take the requested &lt;code&gt;Content-Type&lt;/code&gt; into account. If this is an important consideration for you, you might want to change how &lt;code&gt;+[HTTPResponseHandler handlerClassForRequest:method:url:headerFields:]&lt;/code&gt; selects its handler.&lt;/p&gt;

&lt;p&gt;Finally, this server does not handle SSL/TLS. It is intended for local network transfers where the network itself is relatively secure. If you are transferring over the open internet and want a secure connection, there's a lot to change and manage at the socket level. You could try it yourself but if security is really important, you probably shouldn't risk writing your own server &amp;mdash; if you can arrange it, use a mature, TLS-enabled HTTP server and only handle the client-side in your application. Client-side security in Cocoa is very easy &amp;mdash; it is automatic and transparent in &lt;code&gt;CFReadStream&lt;/code&gt; and &lt;code&gt;NSURLConnection&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;&lt;a href="http://projectswithlove.com/projects/TextTransfer.zip"&gt;Download the sample app TextTransfer.zip&lt;/a&gt; (45kB) which includes the &lt;code&gt;HTTPServer&lt;/code&gt; and &lt;code&gt;HTTPResponseHandler&lt;/code&gt; classes.&lt;/blockquote&gt;

&lt;p&gt;Just because mainstream HTTP servers are large, complex pieces of software, doesn't mean an HTTP server is necessarily large and complex &amp;mdash; the core implementation here is only two classes, yet is flexible and configurable.&lt;/p&gt;

&lt;p&gt;Of course, the end result is not intended for use as a complete web server solution, however it should work well as a small communications portal into your custom iPhone or Mac applications.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-1814284896744429770?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1814284896744429770?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1814284896744429770?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/07/simple-extensible-http-server-in-cocoa.html" title="A simple, extensible HTTP server in Cocoa" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;AkEERnw5eCp7ImA9WxNSEk4.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-7810400073000492476</id><published>2009-07-06T03:41:00.001-07:00</published><updated>2009-08-25T15:16:47.220-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-08-25T15:16:47.220-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Foundation" /><title>HashValue: an object for holding MD5 and SHA hashes</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Hash values are small, convenient values that you can generate from larger blocks of data for easy indexing, sorting and tracking. The traditional approach for generating MD5 and SHA hashes on Unix platforms to is to use command-line programs like openssl and md5. Apple provide easier approaches in the CommonCrypto library: here's how to use it, along with an NSValue subclass to wrap the result for interoperability with other Cocoa classes.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction to hashes&lt;/h4&gt;
&lt;p&gt;A hash value is a small, convenient number used to track or sort an arbitrary block of data.&lt;/p&gt;

&lt;p&gt;A real-world example of a hash value is the initial letter in a word. You can use the initial letter of a word to lookup that word in a dictionary. If two words have different starting letters, they cannot be equal but if two words have the same starting letter, that doesn't guarantee they are the same.&lt;/p&gt;

&lt;p&gt;For fast searching, you can immediately see the problem with only using an initial letter: if all you had to look up a word was its initial letter, you'd still have thousands of words to go through that all start with the same letter. You could use the first four letters but some combinations will be rare (like "aard") but others will contain hundreds of matches (like "stra").&lt;/p&gt;

&lt;p&gt;In computing, we rarely ever use the first values in a block of data to track that block of data. Starting values of blocks of data are too often the same or similar &amp;mdash; especially in the common case where we are sorting data that already has traits in common.&lt;/p&gt;

&lt;p&gt;Instead, we use hash functions that use relatively complex mathematics to generate values from the source data that are well spread, even for source data that is nearly identical. Fortunately, you don't need to know the underlying mathematics, all you need to know is that a hash value can be used to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;check if two blocks of data are the same&lt;/li&gt;
&lt;li&gt;sort data into hash tables&lt;/li&gt;
&lt;li&gt;checksum data (make certain your data hasn't changed)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Though these are the main purposes for which you should use hashes, MD5 and SHA hashes were actually developed for cryptography, not basic data handling. Nevertheless, for encryption and password handling in your own applications, I recommend using the Keychain (Security.framework) rather than manually using cryptographic hashes.&lt;/p&gt;

&lt;h4&gt;Generating an MD5&lt;/h4&gt;

&lt;p&gt;MD5 is one of the most common hash functions. While it is no longer considered safe for security, its use as a checksum is very common.&lt;/p&gt;

&lt;p&gt;The traditional Unix approach is to use the md5 program on the command-line:&lt;/p&gt;

&lt;pre&gt;matt$ md5 -s "Some data value."
MD5 ("Some data value.") = db7116c8634ad7fe3bd90bee94274ee0&lt;/pre&gt;

&lt;p&gt;The 32 character hexadecimal string is a human readable representation of the 16 byte output of the MD5 function.&lt;/p&gt;

&lt;p&gt;On the Mac and iPhone, we can generate this value as follows:&lt;/p&gt;

&lt;pre&gt;#import &amp;lt;CommonCrypto/CommonDigest.h&amp;gt;

char input[] = "Some data value.";
char result[16];
CC_MD5(input, strlen(input), result);&lt;/pre&gt;

&lt;p&gt;However, we frequently want the human-readable hexadecimal string. The following will produce an identical ouput to the previous command-line invocation:&lt;/p&gt;

&lt;pre&gt;printf("MD5 (\"%s\") = %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
    input,
    result[0], result[1], result[2], result[3], 
    result[4], result[5], result[6], result[7],
    result[8], result[9], result[10], result[11],
    result[12], result[13], result[14], result[15]);&lt;/pre&gt;

&lt;p&gt;Producing other kinds of hash works in the same way. e.g. For SHA256, use &lt;code&gt;CC_SHA256&lt;/code&gt; instead of &lt;code&gt;CC_MD5&lt;/code&gt; and increase the size of the result to 32 from 16.&lt;/p&gt;

&lt;h4&gt;The HashValue class&lt;/h4&gt;

&lt;p&gt;Since hash values are frequently used to track blocks of data in a program, it would be nice to have an Objective-C class that wraps the hash values so we can use them in &lt;code&gt;NSDictionary&lt;/code&gt; objects as keys for our data.&lt;/p&gt;

&lt;p&gt;If we consider a hash value simply as a small C struct, i.e:&lt;/p&gt;

&lt;pre&gt;typedef struct
{
    char value[CC_MD5_DIGEST_LENGTH];
} HashValueMD5Hash;

typedef struct
{
    char value[CC_SHA256_DIGEST_LENGTH];
} HashValueShaHash;&lt;/pre&gt;

&lt;p&gt;then the easiest way to make it a fully fledged Objective-C object is to create an &lt;code&gt;NSValue&lt;/code&gt; from it:&lt;/p&gt;

&lt;pre&gt;char input[] = "Some data value.";
HashValueMD5Hash result;
CC_MD5(input, strlen(input), &amp;result);

NSValue *myHashValue = [NSValue valueWithBytes:&amp;result objCType:@encode(HashValueMD5Hash)];&lt;/pre&gt;

&lt;p&gt;That's an okay solution but if you're generating a lot of hashes in your program, it would be good to have a class that:&lt;/p&gt;

&lt;ul&gt;&lt;li&gt;has an optimized construction method that can generate the hash directly from &lt;code&gt;NSData&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;abstracts away the C struct so you can deal exclusively with the Objective-C objects&lt;/li&gt;
&lt;li&gt;overrides the &lt;code&gt;description&lt;/code&gt; method to easily generate human-readable strings&lt;/li&gt;&lt;/ul&gt;

&lt;p&gt;So I wrote the &lt;code&gt;HashValue&lt;/code&gt; class.&lt;/p&gt;

&lt;pre&gt;@interface HashValue : NSObject &amp;lt;NSCoding, NSCopying&amp;gt;
{
    unsigned char value[HASH_VALUE_STORAGE_SIZE];
    HashValueType type;
}

- (id)initMD5HashWithBytes:(const void *)bytes length:(NSUInteger)length;
+ (HashValue *)md5HashWithData:(NSData *)data;
- (id)initSha256HashWithBytes:(const void *)bytes length:(NSUInteger)length;
+ (HashValue *)sha256HashWithData:(NSData *)data;

- (const void *)value;
- (HashValueType)type;

@end&lt;/pre&gt;

&lt;p&gt;Despite being a class that wraps a value, there's no explicit reason to make it a subclass of &lt;code&gt;NSValue&lt;/code&gt;. Since subclassing &lt;code&gt;NSValue&lt;/code&gt; has inherent difficulties (you need to carefully override a lot of inherited methods) I've made the class a basic subclass of &lt;code&gt;NSObject&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;init&lt;/code&gt; method implementations are fairly simple:&lt;/p&gt;

&lt;pre&gt;- (id)initMD5HashWithBytes:(const void *)bytes length:(NSUInteger)length
{
    self = [super init];
    if (self != nil)
    {
        CC_MD5(bytes, length, value);
        type = HASH_VALUE_MD5_TYPE;
    }
    return self;
}&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;description&lt;/code&gt; method is overridden to provide the human-readable hexadecimal string:&lt;/p&gt;

&lt;pre&gt;- (NSString *)description
{
    NSInteger byteLength;
    if (type == HASH_VALUE_MD5_TYPE)
    {
        byteLength = sizeof(HashValueMD5Hash);
    }
    else if (type == HASH_VALUE_SHA_TYPE)
    {
        byteLength = sizeof(HashValueShaHash);
    }

    NSMutableString *stringValue =
        [NSMutableString stringWithCapacity:byteLength * 2];
    NSInteger i;
    for (i = 0; i &lt; byteLength; i++)
    {
        [stringValue appendFormat:@"%02x", value[i]];
    }
    
    return stringValue;
}&lt;/pre&gt;

&lt;p&gt;Most of the other methods in the class are basic accessors or &lt;code&gt;NSCopying&lt;/code&gt;, &lt;code&gt;NSCoding&lt;/code&gt; and &lt;code&gt;NSObject&lt;/code&gt; methods. The copying methods in particular are essential so that the object can be used as a key in an &lt;code&gt;NSDictionary&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I will highlight one other method:&lt;/p&gt;

&lt;pre&gt;- (NSUInteger)hash
{
    return *((NSUInteger *)value);
}&lt;/pre&gt;

&lt;p&gt;You may wonder why it's necessary to have a hash method on a class that is itself a hash value. Hash methods in Cocoa are used for the same indexing and sorting tasks I identified above: sorting and finding objects in &lt;code&gt;NSSet&lt;/code&gt; and &lt;code&gt;NSDictionary&lt;/code&gt;. In Cocoa the default &lt;code&gt;hash&lt;/code&gt; method calculates its hash value from the memory address of the object. Because we have overridden &lt;code&gt;isEqual:&lt;/code&gt; to compare the object's internal &lt;code&gt;value&lt;/code&gt;, we also need to override the &lt;code&gt;hash&lt;/code&gt; method to also reflect this change. This is a basic requirement of hashes &amp;mdash; equal objects must return the same hash value (imagine the confusion if two identically spelled words were sorted to different locations in a dictionary).&lt;/p&gt;

&lt;p&gt;It may seem a little odd to simply return the first few bytes of the &lt;code&gt;value&lt;/code&gt; as our new hash (after I explained that the first few bytes is rarely the best hash) but this case is an exception to the rule: our data is already "well-spread" and every bit in our hash is as well-spread as the next.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can download the &lt;a href="http://projectswithlove.com/projects/HashValue.zip"&gt;HashValue class as a .zip file&lt;/a&gt; (2kB)&lt;/blockquote&gt;

&lt;p&gt;Hash values are used everywhere. Git uses SHA1 to track file changes in its repository, BitTorrent uses MD5s to identify torrents and many download programs use hashes to checksum downloaded data.&lt;/p&gt;

&lt;p&gt;The CommonCrypto library (part of Foundation on the Mac and iPhone through libSystem) makes generating common hash functions very simple.&lt;/p&gt;

&lt;p&gt;As with all data manipulation, I think a nice Cocoa class around the data makes it easier to use. I have only added MD5 and SHA256 to this particular implementation but it should be very simple to add other CommonCrypto hashes to the class should you require them.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-7810400073000492476?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/7810400073000492476?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/7810400073000492476?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/07/hashvalue-object-for-holding-md5-and.html" title="HashValue: an object for holding MD5 and SHA hashes" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;DU8HR3o9eyp7ImA9WxJVFUU.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-1329114706463822659</id><published>2009-07-02T02:23:00.001-07:00</published><updated>2009-07-02T19:23:56.463-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-02T19:23:56.463-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Xcode" /><category scheme="http://www.blogger.com/atom/ns#" term="AppKit" /><title>Custom views in Interface Builder using IBPlugins</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;If you have custom views configured in code, it can be time consuming to configure them for each instance and make them look right in context. To make the process smoother, you can create Interface Builder plugins and configure your objects in Interface Builder. While the Xcode documentation explains how to do this, it is long, thorough and confusing. Here is the simplified set of steps that I use to create Interface Builder plugins quickly.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;

&lt;p&gt;Apple do have extensive documentation on &lt;a href="http://developer.apple.com/documentation/developertools/Conceptual/IBPlugInGuide/Introduction/Introduction.html"&gt;Interface Builder Plugin creation&lt;/a&gt;. However, their documentation is thorough enough that may be overwhelming the first time you want to write an Interface Builder plugin.&lt;/p&gt;

&lt;p&gt;I also find the workflow in Apple's IBPluginGuide very different to my typical workflow. I think this is because I normally just want an existing class to show up in Interface Builder so I can tweak one or two attributes &amp;mdash; the processes for creating a redistributable library of components is more than I need.&lt;/p&gt;

&lt;p&gt;So I was inspired to write this post: a shorter, workflow-optimised version of the same process described in the IBPluginGuide &amp;mdash; using Interface Builder to configure a custom button.&lt;/p&gt;

&lt;h4&gt;A custom buttom&lt;/h4&gt;

&lt;p&gt;Consider the button in the following window:&lt;/p&gt;

&lt;img src="http://lh5.ggpht.com/_gfktUGS0ov0/Skwv9EqkB2I/AAAAAAAAAVo/GkQcQJEHeN0/ibplugin1.png?imgmax=800" alt="ibplugin1.png" border="0" width="226" height="318" /&gt;

&lt;p style="text-align:center;"&gt;&lt;em&gt;A big, drab, gray button. Maybe gray is an acceptable default but it doesn't really match this window. This post will make it easy to adjust this color in Interface Builder.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The large gray button here uses a custom button cell which draws the button using the &lt;a href="http://cocoawithlove.com/2008/09/drawing-gloss-gradients-in-coregraphics.html"&gt;Gloss Gradient from one of my earlier posts&lt;/a&gt;. The drawing code is:&lt;/p&gt;

&lt;pre&gt;- (void)drawWithFrame:(NSRect)cellFrame inView:(NSView *)controlView
{
    NSBezierPath *roundRectPath =
        [NSBezierPath
            bezierPathWithRoundedRect:NSInsetRect(cellFrame, 2, 2)
            xRadius:5
            yRadius:5];

    NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
    [graphicsContext saveGraphicsState];
    [roundRectPath addClip];

    DrawGlossGradient(
        [graphicsContext graphicsPort],
        &lt;strong&gt;self.buttonColor&lt;/strong&gt;, // &lt;-- this determines the color of the button
        cellFrame);

    if ([self isHighlighted])
    {
        [[NSColor colorWithCalibratedRed:0.0 green:0.15 blue:0.35 alpha:0.5]
            set];
        [roundRectPath fill];
    }
    [graphicsContext restoreGraphicsState];

    [[NSColor lightGrayColor] set];
    [roundRectPath setLineWidth:2.0];
    [roundRectPath stroke];

    [self drawInteriorWithFrame:cellFrame inView:controlView];
}&lt;/pre&gt;

&lt;p&gt;This is all fine except that the color of the button is determined by the &lt;code&gt;self.buttonColor&lt;/code&gt; property and if we have to choose this in code (continually changing the value, fixing, continuing, refreshing and repeating) it could get very time consuming.&lt;/p&gt;

&lt;p&gt;A better solution would be to edit the button's color in Interface Builder. That way, we will be able to use color sliders to update the button drawn in the complete context of the window, in real-time.&lt;/p&gt;

&lt;h4&gt;Creating the IBPlugin project&lt;/h4&gt;

&lt;p&gt;My process normally starts by creating a custom view component. In this case, I have already created a class named &lt;code&gt;CustomButtonCell&lt;/code&gt; in the project for my main application (AppWithButton). After creating the class, I have decided it would be a good idea to have an Interface Builder Plug-In.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;A quick point about class requirements&lt;/strong&gt;: every property we want to configure in Interface Builder must be encoded and decoded for the object using implementations of the &lt;code&gt;NSCoder&lt;/code&gt; protocol methods &lt;code&gt;initWithCoder:&lt;/code&gt; and &lt;code&gt;encodedWithCoder:&lt;/code&gt; overrides. Download the project linked below to see how this is done.&lt;/blockquote&gt;

&lt;h5&gt;1. Create and name the project&lt;/h5&gt;

&lt;p&gt;"Interface Builder Plug-In" is a project template in Xcode. In the New Project window, it's in the "Mac OS X -&gt; Standard Apple Plug-ins" section.&lt;/p&gt;

&lt;p&gt;An important point to consider is the name for the project &amp;mdash; it should not be the same as the custom view component (in this case, &lt;code&gt;CustomButtonCell&lt;/code&gt;) because the template will create a class with the name and it can't conflict with the existing view component.&lt;/p&gt;

&lt;p&gt;I chose "ButtonPlugin" and saved the new project in the folder for my existing AppWithButton project.&lt;/p&gt;

&lt;h5&gt;2. Make the new project use the existing CustomButtonCell&lt;/h5&gt;

&lt;h6&gt;Delete the default files and insert our own&lt;/h6&gt;

&lt;p&gt;The template creates a custom view in the ButtonPlugin project. I never use this (since I want to use my existing view). So I delete the ButtonPluginView.m, ButtonPluginView.h references and files.&lt;/p&gt;

&lt;p&gt;I add my CustomButtonCell.m and CustomButtonCell.h files to the ButtonPlugin project but I don't copy or move the files &amp;mdash; I leave the files at their current locations in AppWithButton project but drag them into the ButtonPlugin's Source Tree.&lt;/p&gt;

&lt;h6&gt;Make certain these new files get built&lt;/h6&gt;

&lt;p&gt;You need to check that the CustomButtonCell.m is added to the Compile Sources build phase of the ButtonPluginFramework Target and the CustomButtonCell.h is added to the Copy Headers build phase of the ButtonPluginFramework. Neither should appear in the ButtonPlugin target.&lt;/p&gt;

&lt;p&gt;Then, select the "CustomButtonCell.h" file from the "Copy Headers" build phase and in the Detail View, change the "Role" from "Project" to "Public". This is a pretty obscure thing to do. I normally don't have the Detail View visible &amp;mdash; if you don't know which view is the Detail View, it's time to learn because there is no other way to change this value in Xcode.&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SkxgFIoJy4I/AAAAAAAAAVw/Dzss2-hxUy8/ibplugin3.png?imgmax=800" alt="ibplugin3.png" border="0" width="519" height="313" /&gt;
&lt;p style="text-align:center;"&gt;&lt;em&gt;Change the Role of the "CustomButtonCell.h" to "public" in the Detail View&lt;/em&gt;&lt;p&gt;

&lt;p&gt;Rename the file ButtonPluginViewIntegration.m to CustomButtonCellIntegration.m and replace every occurrence of ButtonPluginView in this file to CustomButtonCell.&lt;/p&gt;

&lt;h5&gt;3. Prepare all the other files in the project&lt;/h5&gt;

&lt;p&gt;Make the following file changes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find the ButtonPluginView.classdescription and rename this file to CustomButtonCell.classdecription (same as our custom cell).&lt;/li&gt;
&lt;li&gt;In the contents of this file, change the &lt;code&gt;ClassName&lt;/code&gt; to match the actual class name &lt;code&gt;CustomButtonCell&lt;/code&gt; and change the &lt;code&gt;SuperClass&lt;/code&gt; to be &lt;code&gt;NSButtonCell&lt;/code&gt; (again, matching the actual super class for our custom button cell).&lt;/li&gt;
&lt;li&gt;In ButtonPlugin.m (the top level class in the ButtonPlugin project), set the bundle identifier to something appropriate. I used &lt;code&gt;com.mattgallagher.ButtonPlugin&lt;/code&gt; &amp;mdash; this needs to be unique among Interface Builder plugins, so you pick an appropriate value each time.&lt;/li&gt;
&lt;li&gt;Set the bundle identifier in the Info.plist and the ButtonPlugin-Info.plist to the same &lt;code&gt;com.mattgallagher.ButtonPlugin&lt;/code&gt; value.&lt;/li&gt;
&lt;/ol&gt;

&lt;h5&gt;4. Configure the display of the button cell for the Interface Builder Library panel&lt;/h5&gt;

&lt;p&gt;Open the ButtonPluginLibrary.nib. This file contains the "Library Object Template" view (an instance of IBLibraryObjectTemplate). You can find it in the "Library Objects" view at the top level.&lt;/p&gt;

&lt;h6&gt;Delete the library template that doesn't apply&lt;/h6&gt;

&lt;p&gt;The Library Object Template will contain a "Template" and an "Example" square. The "Template" version is for &lt;code&gt;NSView&lt;/code&gt; subclasses but our &lt;code&gt;CustomButtonCell&lt;/code&gt; needs to be embedded in another object (an &lt;code&gt;NSButton&lt;/code&gt;) so we will use the "Example" square &amp;mdash; so delete the "Template" square.&lt;/p&gt;

&lt;h6&gt;Set our custom class in the library template&lt;/h6&gt;

&lt;p&gt;If you click on the button in the "Example" square then click again, it will select the &lt;code&gt;NSButtonCell&lt;/code&gt; inside the button (these clicks should be slower than a double-click, since a double-click will edit the text of the &lt;code&gt;NSButton&lt;/code&gt; instead of selecting the &lt;code&gt;NSButtonCell&lt;/code&gt; inside). With the &lt;code&gt;NSButtonCell&lt;/code&gt; selected:

&lt;ol&gt;
&lt;li&gt;Type Command-6 to select the correct inspector panel.&lt;/li&gt;
&lt;li&gt;Enter the custom class name in the "Class" field of the inspector &amp;mdash; in our case, we need this to be &lt;code&gt;CustomButtonCell&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set the button cell class for the &lt;code&gt;NSButton&lt;/code&gt; to the right of the "Example" box in the same way.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Select the Library Object Template (ButtonPluginLibrary.nib window -&gt; Library Objects -&gt; Library Object Template) and:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Type Command-1 to select the correct inspector panel.&lt;/li&gt;
&lt;li&gt;Fill in the "Label", "Summary" and "Description" for your Library Object as you choose. I like to delete the Path and leave it blank but you can add a path if you want to categorize your custom classes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h5&gt;5. Configure the Interface Builder Inspector panel&lt;/h5&gt;

&lt;p&gt;Back in the ButtonPlugin project again, open the ButtonPluginInspector.xib.&lt;/p&gt;

&lt;h6&gt;Set all the controls in the Inspector panel how we want them&lt;/h6&gt;

&lt;p&gt;I deleted everything in the "Inspector View" window except 1 label and the &lt;code&gt;NSColorWell&lt;/code&gt;. I moved these controls to the top of the view and then made the view 35 pixels high.&lt;/p&gt;

&lt;h6&gt;Connect the controls so they act on our object&lt;/h6&gt;

&lt;p&gt;To make the color selector do something, I used bindings. Select the &lt;code&gt;NSColorWell&lt;/code&gt; and:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Type Command-4 to select the correct inspector panel.&lt;/li&gt;
&lt;li&gt;Under the "Value" subheading, bind to File's Owner (make sure the checkbox is selected too).&lt;/li&gt;
&lt;li&gt;Set the Model Key Path to &lt;code&gt;inspectedObjectsController.selection.buttonColor&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This binding needs one other change to work. Back in the ButtonPlugin project, open the CustomButtonCellIntegration.m file. Change the &lt;code&gt;[[keyPaths objectForKey:IBAttributeKeyPaths&lt;/code&gt;... line to:&lt;/p&gt;

&lt;pre&gt;[[keyPaths objectForKey:IBAttributeKeyPaths]
    addObjectsFromArray:[NSArray arrayWithObjects:@"buttonColor", nil]];&lt;/pre&gt;

&lt;p&gt;This tells Interface Builder to track and monitor the &lt;code&gt;buttonColor&lt;/code&gt; property on the &lt;code&gt;CustomButtonCell&lt;/code&gt; class. It does not actually perform the value changing (the binding we established will change the value directly) but it will make certain that this value will be tracked for undos and can be edited correctly.&lt;/p&gt;

&lt;h4&gt;Using the IBPlugin&lt;/h4&gt;

&lt;p&gt;At this point, you can run the ButtonPlugin project and it will launch Interface Builder with the plugin visible. The only problem is that the plugin won't be visible if you launch Interface Builder in any other way.&lt;/p&gt;

&lt;h5&gt;Build Settings&lt;/h5&gt;

&lt;p&gt;The following steps will make the ButtonPlugin project build the ButtonPlugin.framework and ButtonPlugin.ibplugin and install it in your Library.&lt;/p&gt;

&lt;p&gt;Double click the ButtonPlugin project item in the ButtonPlugin project Source Tree to edit the project settings. Select the "Build" tab, then choose "Configuration: All Configurations". Then make the following changes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set the "Deployment Location" checkbox to checked.&lt;/li&gt;
&lt;li&gt;Set the "Installation Build Products Location" to "$(HOME)/Library/Frameworks".&lt;/li&gt;
&lt;li&gt;Set the "Installation Directory" to "/".&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Double-click the "ButtonPlugin" target in the Source Tree to edit that target's settings. Select the "Build" tab, then choose "Configuration: All Configurations". Then make the following change:&lt;/p&gt;

&lt;ol&gt;&lt;li&gt;Set the "Installation Directory" to "/ButtonPlugin.framework/Resources.&lt;/li&gt;&lt;/ol&gt;

&lt;h5&gt;And now it's installed&lt;/h5&gt;

&lt;p&gt;With these changes made, build and run the ButtonPlugin project and it will install the ButtonPlugin.framework in your ~/Library/Frameworks directory and load it in Interface Builder. From now until you remove the framework from your library, it will remain in Interface Builder and you can use it at any time.&lt;/p&gt;

&lt;p&gt;I realize that this configures the app to install the "Debug" build in the user's library, over the top of the "Release" build (if the Release build is already built) but this is really just for local use, so I don't really care. If you do care, you might not want to apply these settings to all configurations. For me: this is faster to implement and easier to manage.&lt;/p&gt;

&lt;h4&gt;Integration with the original AppWithButton project&lt;/h4&gt;

&lt;p&gt;After setting up the Interface Builder plugin, instance of CustomButtonCell in your existing .xib and .nib files will not instantly update. You'll probably need to create new versions of the cell by dragging them out from the Library.&lt;/p&gt; 

&lt;p&gt;In this example, I have chosen to not link the original AppWithButton project with the ButtonPlugin.framework. This is because I don't want to distribute either the framework or the plugin &amp;mdash; they are both for my purposes only.&lt;/p&gt;

&lt;p&gt;If you wanted to link them, you could remove the CustomButtonCell.m and CustomButtonCell.h files from the original project and replace them with the ButtonPlugin.framework. According to the Xcode documentation, this arrangement would allow you to avoid installing the ButtonPlugin.framework in your ~/Library/Frameworks directory (Interface Builder would automatically find the plugin for any .nib or .xib file in the project). That's a nice idea but it has never worked for me, so I never bother.&lt;/p&gt;

&lt;h6&gt;Set a build dependency to keep ButtonPlugin up-to-date&lt;/h6&gt;

&lt;p&gt;Instead, I like to drag the ButtonPlugin.xcodeproj file into the AppWithButton Source Tree and edit the AppWithButton target, go to the "General" tab and add the ButtonPlugin.xcodeproj as a Direct Dependency.&lt;/p&gt;

&lt;p&gt;The reason for this is that if I change the CustomButtonCell class and rebuild, it will automatically rebuild the Interface Builder plugin accordingly (you need to restart Interface Builder to see the changes).&lt;/p&gt;

&lt;img src="http://lh6.ggpht.com/_gfktUGS0ov0/SkxejRb45dI/AAAAAAAAAVs/_QEbecxLgvI/ibplugin2.png?imgmax=800" alt="ibplugin2.png" border="0" width="538" height="280" /&gt;

&lt;p style="text-align:center;"&gt;&lt;em&gt;The AppWithButton window in Interface Builder, adjusting the color of the button in real-time.&lt;/em&gt;&lt;p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can download the complete &lt;a href="http://projectswithlove.com/projects/AppWithButton.zip"&gt;AppWithButton project zip file (including the ButtonPlugin project)&lt;/a&gt; (385kB).&lt;/blockquote&gt;

&lt;p&gt;It takes quite a few steps to set up an Interface Builder plugin. Fortunately, they're all simple, if a little menial.&lt;/p&gt;

&lt;p&gt;Notice how little code was actually written though: bindings and Objective-C 2.0 properties make this whole process considerably easier &amp;mdash; there is no actual code written to set the &lt;code&gt;buttonColor&lt;/code&gt; (except in the &lt;code&gt;NSCoder&lt;/code&gt; method implementations) since the bindings do it all for us.&lt;/p&gt;

&lt;p&gt;Once you're practiced at making plugins in this way, the effort to create one may be justified, even just to tweak simple properties like this.&lt;/p&gt;

&lt;p&gt;Do I know how to do this for Cocoa Touch classes for iPhone development? No. I imagine it's possible but you'd need to completely change the IBPlugin project from the template and I've never tried.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-1329114706463822659?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1329114706463822659?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1329114706463822659?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/07/custom-views-in-interface-builder-using.html" title="Custom views in Interface Builder using IBPlugins" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;CkIFR3s7fSp7ImA9WxJWF0s.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-3272576292203531801</id><published>2009-06-23T05:33:00.001-07:00</published><updated>2009-06-23T05:35:16.505-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-23T05:35:16.505-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cocoa Touch" /><category scheme="http://www.blogger.com/atom/ns#" term="Foundation" /><title>Verifying that a string contains an email address using NSPredicate</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;To celebrate the official release of iPhone OS 3.0 this week, I will show you how to verify that an NSString contains a syntactically valid email address using NSPredicate &amp;mdash; a class that joins the iPhone SDK 3.0 as part of the Core Data additions. This code will work on Mac OS X too since, as with the rest of Core Data, NSPredicate has been part of Mac OS X since 10.4 (Tiger).&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Before I begin...&lt;/h4&gt;
&lt;p&gt;I gave an interview to Anthony Agius of &lt;a href="http://www.mactalk.com.au"&gt;MacTalk.com.au&lt;/a&gt; this week. You can &lt;a href="http://www.mactalk.com.au/2009/06/23/mactalk-interviews-10-matt-gallagher-cocoa-with-love/"&gt;download the MP3 from their website&lt;/a&gt;. I'm hesitant to listen to my own voice but I think I talked about what it's like to be an independent Mac/iPhone developer in Melbourne, Australia.&lt;/p&gt;

&lt;h4&gt;Back to predicates&lt;/h4&gt;
&lt;p&gt;In programming, a predicate is a condition that returns true or false if the object it processes has the properties that the predicate describes. The key difference between a predicate and a regular boolean expression is that a predicate only considers the properties of one object, where a boolean expression may consider multiple, unrelated objects.&lt;/p&gt;

&lt;p&gt;Many programmers are familiar with predicates as used in SQL database queries. For example a query to extract the complete row from the "people" database table for every person named "John Smith" might look like this in SQL:&lt;/p&gt;

&lt;pre&gt;SELECT * FROM people WHERE firstname = 'John' AND lastname = 'Smith'&lt;/pre&gt;

&lt;p&gt;Everything after the "WHERE" is the predicate &amp;mdash; it looks at properties of the row only and is either true (the row will be extracted) or false (the row will be ignored).&lt;/p&gt;

&lt;h4&gt;Using NSPredicate to evaluate predicates&lt;/h4&gt;

&lt;p&gt;In Cocoa, &lt;code&gt;NSPredicate&lt;/code&gt; works in much the same way as the "WHERE" clause of SQL. The main reason that &lt;code&gt;NSPredicate&lt;/code&gt; is being brought to the iPhone is that &lt;code&gt;NSPredicate&lt;/code&gt; fulfils the same role in Core Data that "WHERE" clauses fulfil in SQL &amp;mdash; to allow the persistent store to fetch objects that satisfy specific criteria.&lt;/p&gt;

&lt;p&gt;Imagine we had an &lt;code&gt;NSDictionary&lt;/code&gt; created using the following method:&lt;/p&gt;

&lt;pre&gt;- (NSDictionary *)personRowWithFirstname:(NSString *)aFirstname
    lastname:(NSString *)aLastname
{
    return
        [NSDictionary dictionaryWithObjectsAndKeys:
            aFirstname, @"firstname",
            aLastname, @"lastname",
        nil];
}&lt;/pre&gt;

&lt;p&gt;we could test if a given row created by this method matched the predicate "&lt;code&gt;firstname = 'John' AND lastname = 'Smith'&lt;/code&gt;" with the following:&lt;/p&gt;

&lt;pre&gt;// given an NSDictionary created used the above method named "row"...
NSPredicate *johnSmithPredicate =
    [NSPredicate predicateWithFormat:@"firstname = 'John' AND lastname = 'Smith'"];
BOOL rowMatchesPredicate = [johnSmithPredicate evaluateWithObject:row];&lt;/pre&gt;

&lt;p&gt;The &lt;a href="http://developer.apple.com/DOCUMENTATION/Cocoa/Conceptual/Predicates/Articles/pSyntax.html#//apple_ref/doc/uid/TP40001795"&gt;string format used to construct an &lt;code&gt;NSPredicate&lt;/code&gt; in Cocoa&lt;/a&gt; is very similar to the syntax of the "WHERE" clause in SQL. You can also construct this &lt;code&gt;NSPredicate&lt;/code&gt; in code by building it from two &lt;code&gt;NSComparisonPredicate&lt;/code&gt;s and an &lt;code&gt;NSCompoundPredicate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A more common use of &lt;code&gt;NSPredicate&lt;/code&gt; is filtering &amp;mdash; extracting rows that match an &lt;code&gt;NSPredicate&lt;/code&gt; from a larger collection:&lt;/p&gt;

&lt;pre&gt;// given an NSArray of rows named "rows" and the above "johnSmithPredicate"...
NSArray *rowsMatchingPredicate = [rows filteredArrayUsingPredicate:johnSmithPredicate];&lt;/pre&gt;

&lt;p&gt;This is then more like an SQL query where we have selected matching rows from the larger table of data.&lt;/p&gt;

&lt;blockquote&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;NSPredicate&lt;/code&gt; handles filtering only. If you'd like to replicate SQL's "ORDER BY" clause, you can apply &lt;code&gt;NSSortDescriptor&lt;/code&gt; as a separate step.&lt;/blockquote&gt;

&lt;h4&gt;Verifying an email address&lt;/h4&gt;

&lt;p&gt;The "LIKE" comparison operator in &lt;code&gt;NSPredicate&lt;/code&gt; (&lt;code&gt;NSLikePredicateOperatorType&lt;/code&gt;) is commonly used as a convenient means of testing if an &lt;code&gt;NSString&lt;/code&gt; matches a Regular Expression. It's advantage over full libraries with greater options and replacement capability is that it is already in Cocoa &amp;mdash; no libraries, no linkage, no hassle.&lt;/p&gt;

&lt;p&gt;To test if an &lt;code&gt;NSString&lt;/code&gt; matches a regular expression, we can use the following code:&lt;/p&gt;

&lt;pre&gt;NSPredicate *regExPredicate =
    [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regularExpressionString];
BOOL myStringMatchesRegEx = [regExPredicate evaluateWithObject:myString];&lt;/pre&gt;

&lt;p&gt;The only question that remains is: what is a regular expression that can be used to verify that an &lt;code&gt;NSString&lt;/code&gt; contains a syntactically valid email address?&lt;/p&gt;

&lt;pre&gt;NSString *emailRegEx =
    @"(?:[a-z0-9!#$%\\&amp;'*+/=?\\^_`{|}~-]+(?:\\.[a-z0-9!#$%\\&amp;'*+/=?\\^_`{|}"
    @"~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\"
    @"x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-"
    @"z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5"
    @"]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-"
    @"9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21"
    @"-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])";&lt;/pre&gt;

&lt;p&gt;This regular expression is adapted from a version at &lt;a href="http://www.regular-expressions.info/email.html"&gt;regular-expressions.info&lt;/a&gt; and is a complete verification of RFC 2822.&lt;/p&gt;

&lt;p&gt;This adaptation involved escaping all backslashes with another backslash (otherwise the &lt;code&gt;NSString&lt;/code&gt; will try to interpret them before they are used in the Regular Expression) and escaping the ampersands (&amp;amp;) so it isn't interpreted as a Unicode escape sequence and caret (^) characters because &amp;mdash; actually I have no idea why except that the expression wouldn't parse without it.&lt;/p&gt;

&lt;p&gt;The linked &lt;a href="http://www.regular-expressions.info/email.html"&gt;regular-expressions.info&lt;/a&gt; page recommends using slightly different regular expressions that force the top-level domain to be a country code or a known top-level domain. With the number of top-level domains due to increase in the near future, I'm not sure this is a good constraint to impose &amp;mdash; since this check isn't intended to verify that the provided domain name is valid.&lt;/p&gt;

&lt;p&gt;Since this regular expression &lt;code&gt;NSString&lt;/code&gt; is so long, I've split it over 7 lines. This is an underused feature in Standard C languages &amp;mdash; if you split a string into pieces but put nothing except whitespace between the pieces, the compiler will treat it as one continuous string. You don't need to write an extremely long string on a single long line.&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;Just a few lines of code this week but I thought it would be good to draw attention to one of the minor additions making its way to the iPhone in SDK 3.0. I use &lt;code&gt;NSPredicate&lt;/code&gt; all the time on Mac OS to perform searches, extract subarrays and perform quick Regular Expression tests. Without it, the only alternatives on the iPhone were methodical array iterations and manual comparisons in code.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-3272576292203531801?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/3272576292203531801?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/3272576292203531801?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/06/verifying-that-string-is-email-address.html" title="Verifying that a string contains an email address using NSPredicate" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry><entry gd:etag="W/&quot;A0IASHg6fSp7ImA9WxJWFEg.&quot;"><id>tag:blogger.com,1999:blog-371408380585915800.post-1227978711636506887</id><published>2009-06-17T00:39:00.001-07:00</published><updated>2009-06-19T17:59:09.615-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-06-19T17:59:09.615-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="CoreAudio" /><category scheme="http://www.blogger.com/atom/ns#" term="UIKit" /><category scheme="http://www.blogger.com/atom/ns#" term="AppKit" /><title>Revisiting an old post: Streaming and playing an MP3 stream</title><content type="html">&lt;span class="introduction"&gt;&lt;p&gt;Given the attention it received and the number of bugs I know it contained, I wanted to revisit an old post of mine: Streaming and playing an MP3 stream. In this post, I'll talk about the problems the original contained, how I fixed those problems and I'll present the updated result.&lt;/p&gt;&lt;/span&gt;

&lt;span class="fullpost"&gt;
&lt;h4&gt;Introduction&lt;/h4&gt;
&lt;p&gt;Last September, I wrote a post titled "&lt;a href="http://cocoawithlove.com/2008/09/streaming-and-playing-live-mp3-stream.html"&gt;Streaming and playing an MP3 stream&lt;/a&gt;". The post was largely an experiment &amp;mdash; I just wanted to see if I could play a streaming MP3 by quickly adapting Apple's AudioFileStreamExample to accept an HTTP data stream.&lt;/p&gt;

&lt;p&gt;Unexpectedly, the post became one of my most popular. The attention quickly revealed the limitations in my approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The blend of Objective-C and C was muddled and led to a situation where neither were being used cleanly.&lt;/li&gt;
&lt;li&gt;The boolean flags I copied from the original example were a bad way to describe the playback state and lots of situations were not covered by these flags.&lt;/li&gt;
&lt;li&gt;Sending notifications to the user-interface on a thread that isn't the main thread causes problems.&lt;/li&gt;
&lt;li&gt;The extra thread I added (the download thread) was never thread-safe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I've finally decided to take the time to present a solution to these issues and present an approach which is a little more robust and a little easier to extend if needed.&lt;/p&gt;

&lt;blockquote&gt;You can download the complete &lt;a href="http://github.com/mattgallagher/AudioStreamer/zipball/master"&gt;AudioStreamer project as a zip file&lt;/a&gt; (around 110kB) which contains Xcode projects for both iPhone and Mac OS. You can also &lt;a href="http://github.com/mattgallagher/AudioStreamer"&gt;browse the source code repository&lt;/a&gt;.&lt;/blockquote&gt;

&lt;h4&gt;Limited scope&lt;/h4&gt;

&lt;p&gt;One point should be clarified before I continue: this class is intended for &lt;em&gt;streaming&lt;/em&gt; audio. By streaming, I don't simply mean "an audio file transferred over HTTP". Instead, I mean a continuous HTTP source without an end that continues indefinitely (like a radio station, not a single song).&lt;/p&gt;

&lt;p&gt;Yes, this class will handle fixed-length files transferred over HTTP but it is not ideal for the task.&lt;/p&gt;

&lt;p&gt;This class does not handle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Buffering of data to a file&lt;/li&gt;
&lt;li&gt;Seeking within downloaded data&lt;/li&gt;
&lt;li&gt;Feedback about the total length of the file&lt;/li&gt;
&lt;li&gt;Parsing of ID3 metadata&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These things often can't be done on streaming data, so this class doesn't try. See the "Adding other functionality" section for hints about how the class could be reorganised to handle some of these features.&lt;/p&gt;

&lt;h4&gt;Taking code out of C functions&lt;/h4&gt;

&lt;p&gt;Since I had borrowed the &lt;code&gt;AudioFileStream&lt;/code&gt; and &lt;code&gt;AudioQueue&lt;/code&gt; callback functions from Apple's example, they were Standard C.&lt;/p&gt;

&lt;p&gt;My first change was to make these 6 callback functions (7 including the &lt;code&gt;CFReadStream&lt;/code&gt; callback) little more than wrappers around Objective-C methods:&lt;/p&gt;

&lt;pre&gt;void MyPacketsProc(
    void *inClientData,
    UInt32 inNumberBytes,
    UInt32 inNumberPackets,
    const void *inInputData,
    AudioStreamPacketDescription *inPacketDescriptions)
{
    // this is called by audio file stream when it finds packets of audio
    AudioStreamer* streamer = (AudioStreamer *)inClientData;
    [streamer
        handleAudioPackets:inInputData
        numberBytes:inNumberBytes
        numberPackets:inNumberPackets
        packetDescriptions:inPacketDescriptions];
}&lt;/pre&gt;

&lt;p&gt;At a compiled code level, this is a step backwards: all I've done is slowed the program down by an extra Objective-C message send.&lt;/p&gt;

&lt;p&gt;Technically, a C function that takes a "context" pointer (like the &lt;code&gt;inClientData&lt;/code&gt; pointer here) is not significantly different to a method. What a method does is makes data hiding and data abstracted actions easier. Within a method, you can easily access the instance variables of an object and you don't need to explicitly pass context into each function.&lt;/p&gt;

&lt;p&gt;This is the cliché argument in favor of object-orientation &amp;mdash; but it isn't why I reorganized these functions and methods.&lt;/p&gt;

&lt;p&gt;The honest reason why I did it is aesthetics: it is easier to read a class that is implemented using Objective-C methods alone &amp;mdash; it's more consistent. I chose to move towards an Objective-C aesthetic and away from the Standard C aesthetic of the CoreAudio sample code to promote consistent formatting, consistent means of accessing state variables, consistent ways of invoking methods and consistent ways of synchronizing access to the class.&lt;/p&gt;

&lt;h4&gt;Describing state&lt;/h4&gt;

&lt;p&gt;With the majority of code now inside the class, I was in a better position to start handling changes through methods rather than direct member access.&lt;/p&gt;

&lt;p&gt;My original approach to state came from Apple's original example. This example had just one piece of state: a &lt;code&gt;bool&lt;/code&gt; named &lt;code&gt;finished&lt;/code&gt; (which indicated that the run loop should exit).&lt;/p&gt;

&lt;p&gt;The problem with this flag is how simple it is. It is unable to distinguish between the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;End of file, normal automatic stop.&lt;/li&gt;
&lt;li&gt;The user has asked the &lt;code&gt;AudioStreamer&lt;/code&gt; to stop but the &lt;code&gt;AudioQueue&lt;/code&gt; thread has not yet responded.&lt;/li&gt;
&lt;li&gt;An error has occurred before the &lt;code&gt;AudioQueue&lt;/code&gt; thread is created and we must exit.&lt;/li&gt;
&lt;li&gt;We are stopping the &lt;code&gt;AudioQueue&lt;/code&gt; for temporary reasons (clearing it, changing device, seeking to a new point) but we don't want the loop to stop.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For Apple's example, there was no problem: the first case was the only one that ever occurred.&lt;/p&gt;

&lt;p&gt;As a hasty solution, I had added &lt;code&gt;started&lt;/code&gt; and &lt;code&gt;failed&lt;/code&gt; flags but these really only covered the first and third case adequately.&lt;/p&gt;

&lt;p&gt;In the end, I realized that the &lt;code&gt;AudioStreamer&lt;/code&gt; needed much more descriptive state where every combination of progress within each thread had a different position:&lt;/p&gt;

&lt;pre&gt;typedef enum
{
    AS_INITIALIZED = 0,
    AS_STARTING_FILE_THREAD,
    AS_WAITING_FOR_DATA,
    AS_WAITING_FOR_QUEUE_TO_START,
    AS_PLAYING,
    AS_BUFFERING,
    AS_STOPPING,
    AS_STOPPED,
    AS_PAUSED
} AudioStreamerState;&lt;/pre&gt;

&lt;p&gt;and when stopping, one of the following values would also be needed:&lt;/p&gt;

&lt;pre&gt;typedef enum
{
    AS_NO_STOP = 0,
    AS_STOPPING_EOF,
    AS_STOPPING_USER_ACTION,
    AS_STOPPING_ERROR,
    AS_STOPPING_TEMPORARILY
} AudioStreamerStopReason;&lt;/pre&gt;

&lt;p&gt;In this way, the state always describes where every thread is and the stop reason explains why a transition is occurring.&lt;/p&gt;

&lt;p&gt;Combining this with an error code that replaces the old &lt;code&gt;failed&lt;/code&gt; flag, I now have a complete desription of the state.&lt;/p&gt;

&lt;p&gt;By cleaning up the state of the object, I was able to make the object capable of state transitions that weren't previously possible including pausing/unpausing and returning to the &lt;code&gt;AS_INITIALIZED&lt;/code&gt; state after a stop (instead of requiring that the class be released after stopping).&lt;/p&gt;

&lt;h4&gt;Notifications&lt;/h4&gt;

&lt;p&gt;In the old version of the project the only way for the user-interface to follow the playback state was to observe the &lt;code&gt;isPlaying&lt;/code&gt; property on the object which reflected the &lt;code&gt;kAudioQueueProperty_IsRunning&lt;/code&gt; property of the AudioQueue.&lt;/p&gt;

&lt;p&gt;This observing was handled through KeyValueObserving. I'm a big fan of KeyValueObserving for its simplicity and ubiquity but this was not the correct place to use it.&lt;/p&gt;

&lt;p&gt;KeyValueObserving always invokes the observer methods in the same thread as the change. Since all changes in AudioStreamer happen in secondary threads, this means that the observer methods were getting invoked in secondary threads.&lt;/p&gt;

&lt;p&gt;Why is this bad? A minor drawback is simply the unexpectedness for the observer but the biggest reason was that the sole purpose of observing this property was to update the user-interface and the user-interface on the iPhone cannot be updated from any thread except the main thread. Even on the Mac, performing updates off the main thread can have unexpected and glitchy results.&lt;/p&gt;

&lt;p&gt;The solution is to retain the &lt;code&gt;NSNotificationCenter&lt;/code&gt; of the thread that first calls &lt;code&gt;start&lt;/code&gt; on the object and use this center to send messages as follows:&lt;/p&gt;

&lt;pre&gt;NSNotification *notification =
    [NSNotification
        notificationWithName:ASStatusChangedNotification
        object:self];
[notificationCenter
    performSelector:@selector(postNotification:)
    onThread:[NSThread mainThread]
    withObject:notification
    waitUntilDone:NO];&lt;/pre&gt;

&lt;p&gt;Don't invoke &lt;code&gt;postNotification:&lt;/code&gt; directly from the secondary thread as, like most methods, it is not thread safe and it could be in use from the main thread.&lt;/p&gt;

&lt;h4&gt;Thread safety&lt;/h4&gt;

&lt;p&gt;Despite adding an extra thread on top of Apple's AudioFileStreamExample, I never really spent any time thinking about thread safety &amp;mdash; a reckless approach to stability. In my defence Apple's example wasn't exactly cautious with its threads and would quit while the &lt;code&gt;AudioQueue&lt;/code&gt;'s thread was still playing the last buffer.&lt;/p&gt;

&lt;p&gt;The most efficient approach to threading is to carefully enter &lt;code&gt;@synchronized&lt;/code&gt; (or &lt;code&gt;NSLock&lt;/code&gt; or &lt;code&gt;pthread_mutex_lock&lt;/code&gt;) in a tight region around any use of a shared variable.&lt;/p&gt;

&lt;p&gt;Unfortunately for the &lt;code&gt;AudioStreamer&lt;/code&gt; class, almost everything in the class is shared. Instead, I decided to go for the decidedly less efficient approach of running almost everything in the class within a &lt;code&gt;@synchronized&lt;/code&gt; section, emerging only at points when control must be yielded to other threads.&lt;/p&gt;

&lt;p&gt;The drawback is that the code rarely runs simultaneously on multiple threads (although threading here is for blocking and I/O, not for multi-threaded performance reasons so that's not a probem). The advantage with this heavy-handed locking approach is that the only threading condition that may cause problems are deadlocks.&lt;/p&gt;

&lt;p&gt;When do deadlocks occurs? Only when you're waiting for another thread to do something while you're inside the synchronized section needed by that other thread. The simple solution: never wait for another thread inside a synchronized section.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;AudioStreamer&lt;/code&gt; has three situations where 1 thread waits for another:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The run loop (the &lt;code&gt;AudioFileStream&lt;/code&gt; thread waits for any kind of control communication from the main thread or playback finished notification from the &lt;code&gt;AudioQueue&lt;/code&gt; thread).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;enqueueBuffer&lt;/code&gt; method (&lt;code&gt;AudioFileStream&lt;/code&gt; thread waits for the &lt;code&gt;AudioQueue&lt;/code&gt; thread to free up a buffer).&lt;/li&gt;
&lt;li&gt;Synchronous &lt;code&gt;AudioQueueStop&lt;/code&gt; invocations (waits for the &lt;code&gt;AudioQueue&lt;/code&gt; to release all buffers).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first two points are easy: perform these actions (any any method invocation which invokes them) outside of the &lt;code&gt;@synchronized&lt;/code&gt; section.&lt;/p&gt;

&lt;p&gt;The final point is harder: the synchronous stop must be performed inside the &lt;code&gt;@synchronized&lt;/code&gt; section to prevent multiple &lt;code&gt;AudioQueueStop&lt;/code&gt; actions occurring at once. To address this, the release of buffers by the &lt;code&gt;AudioQueue&lt;/code&gt; (in &lt;code&gt;handleBufferCompleteForQueue:buffer:&lt;/code&gt;) must perform its work without entering the &lt;code&gt;@synchronized&lt;/code&gt; section (although it's allowed to use the &lt;code&gt;queueBuffersMutex&lt;/code&gt; as normal since that isn't used by anything else during a synchronous stop).&lt;/p&gt;

&lt;p&gt;Of course, every time the &lt;code&gt;@sychronized&lt;/code&gt; section is re-entered, a check must be performed to see if "control communication" has occurred (the class checks this by invoking the &lt;code&gt;isFinishing&lt;/code&gt; method and exiting if it returns &lt;code&gt;YES&lt;/code&gt;).&lt;/p&gt;

&lt;h4&gt;Adding other functionality&lt;/h4&gt;

&lt;h5&gt;Get metadata&lt;/h5&gt;

&lt;p&gt;The easiest source of metadata comes from the HTTP headers. Inside the &lt;code&gt;handleReadFromStream:eventType:&lt;/code&gt; method, use &lt;code&gt;CFReadStreamCopyProperty&lt;/code&gt; to copy the &lt;code&gt;kCFStreamPropertyHTTPResponseHeader&lt;/code&gt; property from the &lt;code&gt;CFReadStreamRef&lt;/code&gt;, then you can use &lt;code&gt;CFHTTPMessageCopyAllHeaderFields&lt;/code&gt; to copy the header fields out of the response. For many streaming audio servers, the stream name is one of these fields.&lt;/p&gt;

&lt;p&gt;The considerably harder source of metadata are the ID3 tags. ID3v1 is always at the end of the file (so is useless when streaming). ID3v2 is located at the start so may be more accessible.&lt;/p&gt;

&lt;p&gt;I've never read the ID3 tags but I suspect that if you cache the first few hundred kilobytes of the file somewhere as it loads, open that cache with &lt;code&gt;AudioFileOpenWithCallbacks&lt;/code&gt; and then read the &lt;code&gt;kAudioFilePropertyID3Tag&lt;/code&gt; with &lt;code&gt;AudioFileGetProperty&lt;/code&gt; you may be able to read the ID3 data (if it exists). Like I said though: I've never actually done this so I don't know for certain that it would work.&lt;/p&gt;

&lt;h5&gt;Stream fixed-length files&lt;/h5&gt;

&lt;p&gt;The biggest variation you may want to make to the class is to download fixed-length files, rather than streaming audio.&lt;/p&gt;

&lt;p&gt;To handle this, the best approach is to remove the download from the class entirely. Download elsewhere and when "enough" (an amount you should determine on your own) of the file is downloaded, start a variation of the class that plays by streaming from a file on disk.&lt;/p&gt;

&lt;p&gt;To adapt the class for streaming from a file on disk, remove the &lt;code&gt;CFHTTPMessageRef&lt;/code&gt; and &lt;code&gt;CFReadStreamRef&lt;/code&gt; code from &lt;code&gt;openFileStream&lt;/code&gt; and replace it with &lt;code&gt;NSFileHandle&lt;/code&gt; code that uses &lt;code&gt;waitForDataInBackgroundAndNotify&lt;/code&gt; to asynchronously stream the file in the same way that &lt;code&gt;CFReadStreamRef&lt;/code&gt; streamed the network data.&lt;/p&gt;

&lt;p&gt;Once you're streaming from a file, you'll probably want to permit seeking within the file. I've already put hooks within the file to seek (set the &lt;code&gt;seekNeeded&lt;/code&gt; flag to true and set the &lt;code&gt;seekTime&lt;/code&gt; to the time in seconds to which you want to seek) &amp;mdash; however, the mechanics of seeking within the file would be dependent on how you access the file.&lt;/p&gt;

&lt;p&gt;Incidentally, the &lt;code&gt;AudioFileStreamSeek&lt;/code&gt; function seems completely broken. If you can't get it to work (as I couldn't) just seek to a new point in the file, set &lt;code&gt;discontinuous&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt; and let &lt;code&gt;AudioFileStream&lt;/code&gt; deal with it.&lt;/p&gt;

&lt;h5&gt;Handling data interruptions&lt;/h5&gt;

&lt;p&gt;At the moment, if the &lt;code&gt;AudioQueue&lt;/code&gt; has no more buffers to play, the state will transition to &lt;code&gt;AS_BUFFERING&lt;/code&gt;. At this point, no specific action is taken to resolve this situation &amp;mdash; it assumes that the network will eventually resume and requeue enough buffers.&lt;/p&gt;

&lt;p&gt;I actually expect there will be cases where this action is insufficient &amp;mdash; you may need to ensure that the &lt;code&gt;AudioQueue&lt;/code&gt; is paused until enough buffers are filled before resuming or even restart the download entirely. I haven't experimented much since it is easiest with streaming audio just to stop and start new.&lt;/p&gt;

&lt;p&gt;Incidentally, if you're curious to know how many audio buffers are in use at any given time, uncomment the &lt;code&gt;NSLog&lt;/code&gt; line in the &lt;code&gt;handleBufferCompleteForQueue:buffer:&lt;/code&gt; method. This will log how many 1 kilobyte audio buffers are queued waiting for playback (when the queue reaches zero, the &lt;code&gt;AudioStreamer&lt;/code&gt; enters the &lt;code&gt;AS_BUFFERING&lt;/code&gt; state).&lt;/p&gt;

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;blockquote&gt;You can download the complete &lt;a href="http://github.com/mattgallagher/AudioStreamer/zipball/master"&gt;AudioStreamer project as a zip file&lt;/a&gt; (around 110kB) which contains Xcode projects for both iPhone and Mac OS. You can also &lt;a href="http://github.com/mattgallagher/AudioStreamer"&gt;browse the source code repository&lt;/a&gt;.&lt;/blockquote&gt;

&lt;p&gt;The functionality of this new version has not changed greatly &amp;mdash; my purposed was to present a version that is more stable and tolerant of unexpected situations, rather than add new features.&lt;/p&gt;

&lt;p&gt;As before, the AudioStreamer class should work on Mac OS X 10.5 and on the iPhone (SDK 2.0 and greater).&lt;/p&gt;

&lt;p&gt;The source repository is hosted on github so you can browse, fork or track updates as you choose. I will likely update again in future (I can't imagine I've written this much code without causing more problems) and this way, you can see the changes I've made.&lt;/p&gt;

&lt;p&gt;I hope this post has shown you a number of problems that can happen when code is written hastily. This doesn't mean you should always avoid hastily written code (timeliness and proof of concepts are important) but it does mean you should be practised at refactoring code and not simply slap poor fixes onto code that doesn't cleanly solve a problem in the first place.&lt;/p&gt;

&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/371408380585915800-1227978711636506887?l=cocoawithlove.com'/&gt;&lt;/div&gt;</content><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1227978711636506887?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/371408380585915800/posts/default/1227978711636506887?v=2" /><link rel="alternate" type="text/html" href="http://cocoawithlove.com/2009/06/revisiting-old-post-streaming-and.html" title="Revisiting an old post: Streaming and playing an MP3 stream" /><author><name>Matt Gallagher</name><uri>http://www.blogger.com/profile/12617910364694969282</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="14290033605020307432" /></author></entry></feed>
