<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Cocoanetics &#187; Administrative</title>
	<atom:link href="http://www.cocoanetics.com/category/administrative/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.cocoanetics.com</link>
	<description>Our DNA is written in Objective-C</description>
	<lastBuildDate>Mon, 17 Jun 2013 16:15:33 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
	<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F&amp;language=en_US&amp;category=text&amp;title=Cocoanetics&amp;description=Our+DNA+is+written+in+Objective-C&amp;tags=blog" type="text/html" />
		<item>
		<title>Highlight: Pocket Informant Pro</title>
		<link>http://www.cocoanetics.com/2013/05/highlight-pocket-informant-pro/</link>
		<comments>http://www.cocoanetics.com/2013/05/highlight-pocket-informant-pro/#comments</comments>
		<pubDate>Sat, 18 May 2013 06:17:18 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=8208</guid>
		<description><![CDATA[Alex Kac, CEO/Founder of WebIS yesterday announced that Apple had approved their major new version 3 of Pocket Informant. We like to highlight satisfied clients who put our components to good use, Pocket Informant 3 uses DTRichTextEditor. WebIS highlights &#8220;Rich Notes&#8221; as major new feature of the new version. Rich Notes - we now have a full featured Rich Text editor for notes. We’ve got a lot more coming here, but today you can set styles, fonts, typefaces, lists, and more. WebIS has been a key sponsor of the component helping us to enhance the feature set and API of the component with support for lists. This had long been on our roadmap, but without WebIS&#8217; sponsorship we could not have brought it to fruition. WebIS integrated the cutting edge version 1.5 of DTRichTextEditor to enable this feature. Kac had this to say when asked for a testimonial: &#8220;Working with Oliver has been a tremendous joy. We simply could not have shipped on-time and with the quality of rich text support as we did without him. The DTRichTextEditor is a fabulous control with lots of great tools, utilities that we were able to use such as DTHTMLWriter and other classes. I heartily recommend both the control and Oliver.&#8221; The Pro Version of Pocket Informant will be released on Tuesday May 21st as a free update to existing 2.x customers. WebIS also offers a free Go! version which will be receiving the 3.0 treatment in the near future. If you buy a license to DTRichTextEditor you receive full access to all source code residing on our private git server. To celebrate the launch of Pocket Informant please mention keyword PI10 for 10% discount when you buy a license until May 31st.]]></description>
				<content:encoded><![CDATA[<p>Alex Kac, CEO/Founder of <a href="http://webis.net/wp/">WebIS</a> <a href="http://www.pocketinformant.com/Forums/index.php?s=ae222725f9d27a77613142d9d0e9042c&amp;app=blog&amp;module=display&amp;section=blog&amp;blogid=1&amp;showentry=303">yesterday announced</a> that Apple had approved their major new version 3 of <a href="http://webis.net/wp/pocket-informant-pro/">Pocket Informant</a>. We like to highlight satisfied clients who put <a href="http://www.cocoanetics.com/parts-store/">our components</a> to good use, Pocket Informant 3 uses <a href="https://www.cocoanetics.com/parts/dtrichtexteditor/">DTRichTextEditor</a>.</p>
<p><span id="more-8208"></span></p>
<div id="more-8208"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<p>WebIS highlights &#8220;Rich Notes&#8221; as major new feature of the new version.</p>
<blockquote><p><strong>Rich Notes</strong> - we now have a full featured Rich Text editor for notes. We’ve got a lot more coming here, but today you can set styles, fonts, typefaces, lists, and more.</p></blockquote>
<p>WebIS has been a key sponsor of the component helping us to enhance the feature set and <a href="https://docs.cocoanetics.com/DTRichTextEditor/Classes/DTRichTextEditorView.html">API</a> of the component with support for <strong>lists</strong>. This had long been on our roadmap, but without WebIS&#8217; sponsorship we could not have brought it to fruition.</p>
<p><a href="http://i0.wp.com/www.cocoanetics.com/files/iPhone-4-Inch-Screenshot-29.png"><img class="alignnone size-full wp-image-8209" alt="Pocket Informant Pro 3" src="http://i0.wp.com/www.cocoanetics.com/files/iPhone-4-Inch-Screenshot-29.png?resize=320%2C517" data-recalc-dims="1" /></a></p>
<p><strong></strong>WebIS integrated the cutting edge <a title="Rich Text Update 1.5" href="http://www.cocoanetics.com/2013/05/rich-text-update-1-5/">version 1.5</a> of DTRichTextEditor to enable this feature. Kac had this to say when asked for a testimonial:</p>
<blockquote><p>&#8220;Working with Oliver has been a tremendous joy. We simply could not have shipped on-time and with the quality of rich text support as we did without him. The DTRichTextEditor is a fabulous control with lots of great tools, utilities that we were able to use such as DTHTMLWriter and other classes. I heartily recommend both the control and Oliver.&#8221;</p></blockquote>
<p>The Pro Version of Pocket Informant will be released on Tuesday May 21st as a <a href="https://itunes.apple.com/at/app/pocket-informant-pro/id380732176?mt=8">free update</a> to existing 2.x customers. WebIS also offers a free Go! version which will be receiving the 3.0 treatment in the near future.</p>
<p>If you buy a license to DTRichTextEditor you receive full access to all source code residing on our private git server. To celebrate the launch of Pocket Informant please mention keyword <strong>PI10</strong> for 10% discount when you buy a license until May 31st.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=8208&amp;md5=817ecf284d398a8fe8d3603ca4b03e90" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2013/05/highlight-pocket-informant-pro/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2013%2F05%2Fhighlight-pocket-informant-pro%2F&amp;language=en_GB&amp;category=text&amp;title=Highlight%3A+Pocket+Informant+Pro&amp;description=Alex+Kac%2C+CEO%2FFounder+of+WebIS+yesterday+announced+that+Apple+had+approved+their+major+new+version+3+of+Pocket+Informant.+We+like+to+highlight+satisfied+clients+who+put+our+components+to...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>AutoIngest for Mac 0.4.1</title>
		<link>http://www.cocoanetics.com/2013/05/autoingest-for-mac-0-4-1/</link>
		<comments>http://www.cocoanetics.com/2013/05/autoingest-for-mac-0-4-1/#comments</comments>
		<pubDate>Sat, 11 May 2013 12:44:46 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=8172</guid>
		<description><![CDATA[Sorry, but some bugs had crept into yesterday&#8217;s release of AutoIngest for Mac. So we fixed them. Changes FIXED: Crash if report download folder had spaces FIXED: Auto-Organizer was watching non-existent folder FIXED: Uncompressing files did not remove .gz extension FIXED: Menu Option was not modified if Auto-Sync was occurring We have already been able to verify that Newsstand report downloading works. Though we still are looking for somebody who has Opt-In reports to help us see if the downloading works for these as well. I hope you are enjoying this new version AutoIngest for Mac! It is available via auto-update, direct download as well as full source on GitHub. The binary builds have Sparkle for OTA updating and are signed with Developer ID.]]></description>
				<content:encoded><![CDATA[<p>Sorry, but some bugs had crept into <a title="AutoIngest for Mac 0.4.0" href="http://www.cocoanetics.com/2013/05/autoingest-for-mac-0-4-0/">yesterday&#8217;s release</a> of AutoIngest for Mac. So we fixed them.</p>
<p><span id="more-8172"></span></p>
<div id="more-8172"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<h3>Changes</h3>
<ul>
<li><span style="line-height: 13px;">FIXED: Crash if report download folder had spaces</span></li>
<li>FIXED: Auto-Organizer was watching non-existent folder</li>
<li>FIXED: Uncompressing files did not remove .gz extension</li>
<li>FIXED: Menu Option was not modified if Auto-Sync was occurring</li>
</ul>
<p>We have already been able to verify that <strong>Newsstand report downloading works</strong>. Though we still are looking for somebody who has <strong>Opt-In</strong> reports to help us see if the downloading works for these as well.</p>
<p>I hope you are enjoying this new version AutoIngest for Mac! It is available via auto-update, <a href="http://beta.cocoanetics.com/Cocoanetics/com.cocoanetics.AutoIngest/56/AutoIngest.zip">direct download</a> as well as full source <a href="https://github.com/Cocoanetics/AutoIngest">on GitHub</a>. The binary builds have Sparkle for OTA updating and are signed with Developer ID.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=8172&amp;md5=ad0cf8fd781a312c11800d78bf417810" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2013/05/autoingest-for-mac-0-4-1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2013%2F05%2Fautoingest-for-mac-0-4-1%2F&amp;language=en_GB&amp;category=text&amp;title=AutoIngest+for+Mac+0.4.1&amp;description=Sorry%2C+but+some+bugs+had+crept+into+yesterday%26%238217%3Bs+release+of+AutoIngest+for+Mac.+So+we+fixed+them.+Changes+FIXED%3A+Crash+if+report+download+folder+had+spaces+FIXED%3A+Auto-Organizer+was+watching...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Component Clients: We Moved to GIT</title>
		<link>http://www.cocoanetics.com/2013/04/component-clients-we-moved-to-git/</link>
		<comments>http://www.cocoanetics.com/2013/04/component-clients-we-moved-to-git/#comments</comments>
		<pubDate>Thu, 04 Apr 2013 17:30:18 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">https://www.cocoanetics.com/?p=7957</guid>
		<description><![CDATA[If you have purchased components from us in the past you should have received a note from our sales team asking you for what credentials you would like on our new GitLab server. As of this moment all Subversion access has been terminated. The components that we are still offering for sale have all been migrated to git. Of the discontinued products a few might be moved to DTFoundation are another open source project if there is any interest. If you have no email from our sales team regarding your new credentials please email us.]]></description>
				<content:encoded><![CDATA[<p>If you have purchased components from us in the past you should have received a note from our sales team asking you for what credentials you would like on our new GitLab server.</p>
<p>As of this moment <strong>all Subversion access has been terminated</strong>. The components that we are still <a href="https://www.cocoanetics.com/parts-store/">offering for sale</a> have all been migrated to git. Of the discontinued products a few might be moved to DTFoundation are another open source project if there is any interest.</p>
<p>If you have no email from our sales team regarding your new credentials please <a href="mailto:sales@cocoanetics.com?subject=GIT">email us</a>.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=7957&amp;md5=3c06622c8e5da2db0d56f313b656247f" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2013/04/component-clients-we-moved-to-git/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2013%2F04%2Fcomponent-clients-we-moved-to-git%2F&amp;language=en_GB&amp;category=text&amp;title=Component+Clients%3A+We+Moved+to+GIT&amp;description=If+you+have+purchased+components+from+us+in+the+past+you+should+have+received+a+note+from+our+sales+team+asking+you+for+what+credentials+you+would+like+on+our...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>We&#8217;ll be back soon</title>
		<link>http://www.cocoanetics.com/2013/03/well-be-back-soon-3/</link>
		<comments>http://www.cocoanetics.com/2013/03/well-be-back-soon-3/#comments</comments>
		<pubDate>Tue, 26 Mar 2013 06:53:57 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=7927</guid>
		<description><![CDATA[We&#8217;re out of office until March 31st. There will be no e-mail checking until we get back, so please be patient with your requests and wishes. We&#8217;ll be back at your service on March 31st.]]></description>
				<content:encoded><![CDATA[<p>We&#8217;re out of office until March 31st. There will be no e-mail checking until we get back, so please be patient with your requests and wishes.</p>
<p><a href="http://i0.wp.com/www.cocoanetics.com/files/backsoon.jpg"><img class="alignnone size-full wp-image-5257" title="back soon" src="http://i0.wp.com/www.cocoanetics.com/files/backsoon.jpg?resize=193%2C167" alt="" data-recalc-dims="1" /></a></p>
<p>We&#8217;ll be back at your service on March 31st. </p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=7927&amp;md5=de01dca0df02f83d3e510fc195e238a2" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2013/03/well-be-back-soon-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2013%2F03%2Fwell-be-back-soon-3%2F&amp;language=en_GB&amp;category=text&amp;title=We%26%238217%3Bll+be+back+soon&amp;description=We%26%238217%3Bre+out+of+office+until+March+31st.+There+will+be+no+e-mail+checking+until+we+get+back%2C+so+please+be+patient+with+your+requests+and+wishes.+We%26%238217%3Bll+be+back+at...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Fast Hashing</title>
		<link>http://www.cocoanetics.com/2013/02/fast-hashing/</link>
		<comments>http://www.cocoanetics.com/2013/02/fast-hashing/#comments</comments>
		<pubDate>Mon, 25 Feb 2013 17:21:06 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=7663</guid>
		<description><![CDATA[In DTCoreText there is the DTCoreTextParagraphStyle class which represents an Objective-C wrapper around CTParagraphStyle. This has a method createCTParagraphStyle which creates the actual Core Text object to put in attributes of an NSAttributedString. It also knows how to create an NSParagraphStyle, but since this only exists from iOS 6 upwards and lacks a few features we&#8217;re still using the Core Text variant everywhere. Due to the way how DTCoreText works I need to createCTParagraphStyle whenever I am constructing a sub string of the generated attributed string. This led to an unnecessarily large amount of CTParagraphStyle instances being created. So I had implemented a method long time ago to cache thusly created CoreText objects based on the ivars. Though this was causing some problems in DTRichTextEditor and so I yanked the caching back out. Now the project has developed much further and so I felt I would want to give the caching another go. Here&#8217;s something interesting I learned. As always please don&#8217;t hesitate to leave a comment if you have a better method to share &#8230; The previous method of getting a unique key was using a naughty trick. Even Core Foundation objects usually have a description and this I was using as the key: // this is naughty: CTParagraphStyle has a description NSString *key = &#91;&#40;__bridge id&#41;ctParagraphStyle description&#93;; This had several drawbacks. First creating an NSString description for many internal values is rather slow and also for reasons that I did not investigate much further there where scenarios where this would break. Possibly because I have 2 additional items inside the paragraph style that this would ignore: lists and blocks. NSString as Cache Key So the first approach I came up with this morning was to create my own NSString to be used as the cache key. - &#40;NSString *&#41;_cacheKey &#123; NSMutableString *key = &#91;NSMutableString stringWithFormat:@&#34;%d-%f-%f-%f-%f-%f-%f-%d-%f-%f-%f&#34;, _alignment, _firstLineHeadIndent, _defaultTabInterval, _paragraphSpacing, _paragraphSpacingBefore, _headIndent, _tailIndent, _baseWritingDirection, _lineHeightMultiple, _minimumLineHeight, _maximumLineHeight&#93;; &#160; for &#40;id tab in _tabStops&#41; &#123; CTTextTabRef tabStop = &#40;__bridge CTTextTabRef&#41;tab; &#160; CTTextAlignment alignment = CTTextTabGetAlignment&#40;tabStop&#41;; double location = CTTextTabGetLocation&#40;tabStop&#41;; &#160; &#91;key appendFormat:@&#34;-tab:%d-%f&#34;, alignment, location&#93;; &#125; &#160; for &#40;DTTextBlock *textBlock in _textBlocks&#41; &#123; &#91;key appendFormat:@&#34;-block:%lx&#34;, &#40;unsigned long&#41;&#91;textBlock hash&#93;&#93;; &#125; &#160; for &#40;DTCSSListStyle *listStyle in _textLists&#41; &#123; &#91;key appendFormat:@&#34;-list:%lx&#34;, &#40;unsigned long&#41;&#91;listStyle hash&#93;&#93;; &#125; &#160; return key; &#125; To prove that this indeed works, I constructed a new unit test case. @implementation DTCoreTextParagraphStyleTest &#160; - &#40;void&#41;testCache &#123; // make a test style DTCoreTextParagraphStyle *paraStyle = &#91;&#91;DTCoreTextParagraphStyle alloc&#93; init&#93;; paraStyle.lineHeightMultiple = 2.0f; paraStyle.headIndent = 30; &#160; CTParagraphStyleRef para1 = &#91;paraStyle createCTParagraphStyle&#93;; CTParagraphStyleRef para2 = &#91;paraStyle createCTParagraphStyle&#93;; &#160; STAssertEquals&#40;para1, para2, @&#34;Two successife Paragraph Styles should be identical&#34;&#41;; &#160; // change something &#160; paraStyle.tailIndent = -20; &#160; CTParagraphStyleRef para3 = &#91;paraStyle createCTParagraphStyle&#93;; &#160; STAssertTrue&#40;para2!=para3, @&#34;Paragraph Styles should not be identical after change&#34;&#41;; &#160; // change back &#160; paraStyle.tailIndent = 0; &#160; CTParagraphStyleRef para4 = &#91;paraStyle createCTParagraphStyle&#93;; &#160; STAssertEquals&#40;para1, para4, @&#34;Paragraph Styles should be identical after change back&#34;&#41;; &#160; // cleanup &#160; CFRelease&#40;para1&#41;; CFRelease&#40;para2&#41;; CFRelease&#40;para3&#41;; CFRelease&#40;para4&#41;; &#125; &#160; @end The point of this test was to first show that creating two CTParagraphStyle instances in succession should return the same result. Then by modifying the underlying DTCoreTextParagraphStyle I would get a different result. Finally by reverting the change I would again get the same result as the first two. Unfortunately this method is not very fast. Especially if it is called many times over a lengthy HTML document you would see it become a hot spot in Instruments. In this screenshot the marked purple mountain is me parsing the War&#38;Peace HTML in the DTCoreText demo app. You can see how the createCTParagraphStyle method is calling _cacheKey and this making up the lion share of the execution time in this method (432 ms of 553 ms). If you double-click on it you see a big red sea. Apparently 97.7% of the samples taken execution was within this stringWithFormat: method. At this point it is quite clear that this is not an optimal approach. I suspect the main reason for lackluster performance on this line is that it takes quite some time to format floating point numbers as NSString. I googled around a bit further, but couldn&#8217;t find a simple, yet easy to implement method for getting a better cache key. Then it dawned on me &#8230; CommonCrypto Why not simply putting all values in a struct and then creating an md5 checksum over that? - &#40;id &#41;_cacheKey &#123; NSMutableString *tabsBlocksListsDescription = &#91;NSMutableString string&#93;; &#160; for &#40;id tab in _tabStops&#41; &#123; CTTextTabRef tabStop = &#40;__bridge CTTextTabRef&#41;tab; &#160; CTTextAlignment alignment = CTTextTabGetAlignment&#40;tabStop&#41;; double location = CTTextTabGetLocation&#40;tabStop&#41;; &#160; &#91;tabsBlocksListsDescription appendFormat:@&#34;-tab:%d-%f&#34;, alignment, location&#93;; &#125; &#160; for &#40;DTTextBlock *textBlock in _textBlocks&#41; &#123; &#91;tabsBlocksListsDescription appendFormat:@&#34;-block:%x&#34;, &#91;textBlock hash&#93;&#93;; &#125; &#160; for &#40;DTCSSListStyle *listStyle in _textLists&#41; &#123; &#91;tabsBlocksListsDescription appendFormat:@&#34;-list:%x&#34;, &#91;listStyle hash&#93;&#93;; &#125; &#160; struct &#123; CGFloat firstLineHeadIndent; CGFloat defaultTabInterval; CGFloat paragraphSpacingBefore; CGFloat paragraphSpacing; CGFloat headIndent; CGFloat tailIndent; CGFloat [...]]]></description>
				<content:encoded><![CDATA[<p>In DTCoreText there is the DTCoreTextParagraphStyle class which represents an Objective-C wrapper around CTParagraphStyle. This has a method createCTParagraphStyle which creates the actual Core Text object to put in attributes of an NSAttributedString. It also knows how to create an NSParagraphStyle, but since this only exists from iOS 6 upwards and lacks a few features we&#8217;re still using the Core Text variant everywhere.</p>
<p>Due to the way how DTCoreText works I need to createCTParagraphStyle whenever I am constructing a sub string of the generated attributed string. This led to an unnecessarily large amount of CTParagraphStyle instances being created. So I had implemented a method long time ago to cache thusly created CoreText objects based on the ivars.</p>
<p>Though this was causing some problems in DTRichTextEditor and so I yanked the caching back out. Now the project has developed much further and so I felt I would want to give the caching another go. Here&#8217;s something interesting I learned.</p>
<p><span id="more-7663"></span></p>
<div id="more-7663"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<p>As always please don&#8217;t hesitate to leave a comment if you have a better method to share &#8230;</p>
<p>The previous method of getting a unique key was using a naughty trick. Even Core Foundation objects usually have a description and this I was using as the key:</p>

<div class="wp_codebox"><table><tr id="p76637"><td class="code" id="p7663code7"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// this is naughty: CTParagraphStyle has a description</span>
<a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span>key <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#40;</span>__bridge <span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>ctParagraphStyle description<span style="color: #002200;">&#93;</span>;</pre></td></tr></table></div>

<p>This had several drawbacks. First creating an NSString description for many internal values is rather slow and also for reasons that I did not investigate much further there where scenarios where this would break. Possibly because I have 2 additional items inside the paragraph style that this would ignore: lists and blocks.</p>
<h3>NSString as Cache Key</h3>
<p>So the first approach I came up with this morning was to create my own NSString to be used as the cache key.</p>

<div class="wp_codebox"><table><tr id="p76638"><td class="code" id="p7663code8"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>_cacheKey
<span style="color: #002200;">&#123;</span>
   <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableString_Class/"><span style="color: #400080;">NSMutableString</span></a> <span style="color: #002200;">*</span>key <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableString_Class/"><span style="color: #400080;">NSMutableString</span></a> stringWithFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;%d-%f-%f-%f-%f-%f-%f-%d-%f-%f-%f&quot;</span>, 
                              _alignment, 
                              _firstLineHeadIndent, 
                              _defaultTabInterval, 
                              _paragraphSpacing, 
                              _paragraphSpacingBefore, 
                              _headIndent, 
                              _tailIndent, 
                              _baseWritingDirection, 
                              _lineHeightMultiple, 
                              _minimumLineHeight, 
                              _maximumLineHeight<span style="color: #002200;">&#93;</span>;
&nbsp;
   <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> tab <span style="color: #a61390;">in</span> _tabStops<span style="color: #002200;">&#41;</span>
   <span style="color: #002200;">&#123;</span>
      CTTextTabRef tabStop <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>__bridge CTTextTabRef<span style="color: #002200;">&#41;</span>tab;
&nbsp;
      CTTextAlignment alignment <span style="color: #002200;">=</span> CTTextTabGetAlignment<span style="color: #002200;">&#40;</span>tabStop<span style="color: #002200;">&#41;</span>;
      <span style="color: #a61390;">double</span> location <span style="color: #002200;">=</span> CTTextTabGetLocation<span style="color: #002200;">&#40;</span>tabStop<span style="color: #002200;">&#41;</span>;
&nbsp;
      <span style="color: #002200;">&#91;</span>key appendFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;-tab:%d-%f&quot;</span>, alignment, location<span style="color: #002200;">&#93;</span>;
   <span style="color: #002200;">&#125;</span>
&nbsp;
   <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>DTTextBlock <span style="color: #002200;">*</span>textBlock <span style="color: #a61390;">in</span> _textBlocks<span style="color: #002200;">&#41;</span>
   <span style="color: #002200;">&#123;</span>
      <span style="color: #002200;">&#91;</span>key appendFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;-block:%lx&quot;</span>, <span style="color: #002200;">&#40;</span><span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">long</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>textBlock hash<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
   <span style="color: #002200;">&#125;</span>
&nbsp;
   <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>DTCSSListStyle <span style="color: #002200;">*</span>listStyle <span style="color: #a61390;">in</span> _textLists<span style="color: #002200;">&#41;</span>
   <span style="color: #002200;">&#123;</span>
      <span style="color: #002200;">&#91;</span>key appendFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;-list:%lx&quot;</span>, <span style="color: #002200;">&#40;</span><span style="color: #a61390;">unsigned</span> <span style="color: #a61390;">long</span><span style="color: #002200;">&#41;</span><span style="color: #002200;">&#91;</span>listStyle hash<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
   <span style="color: #002200;">&#125;</span>
&nbsp;
   <span style="color: #a61390;">return</span> key;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>To prove that this indeed works, I constructed a new unit test case.</p>

<div class="wp_codebox"><table><tr id="p76639"><td class="code" id="p7663code9"><pre class="objc" style="font-family:monospace;"><span style="color: #a61390;">@implementation</span> DTCoreTextParagraphStyleTest
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>testCache
<span style="color: #002200;">&#123;</span>
   <span style="color: #11740a; font-style: italic;">// make a test style</span>
   DTCoreTextParagraphStyle <span style="color: #002200;">*</span>paraStyle <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><span style="color: #002200;">&#91;</span>DTCoreTextParagraphStyle alloc<span style="color: #002200;">&#93;</span> init<span style="color: #002200;">&#93;</span>;
   paraStyle.lineHeightMultiple <span style="color: #002200;">=</span> 2.0f;
   paraStyle.headIndent <span style="color: #002200;">=</span> <span style="color: #2400d9;">30</span>;
&nbsp;
   CTParagraphStyleRef para1 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>paraStyle createCTParagraphStyle<span style="color: #002200;">&#93;</span>;
   CTParagraphStyleRef para2 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>paraStyle createCTParagraphStyle<span style="color: #002200;">&#93;</span>;
&nbsp;
   STAssertEquals<span style="color: #002200;">&#40;</span>para1, para2, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Two successife Paragraph Styles should be identical&quot;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
   <span style="color: #11740a; font-style: italic;">// change something</span>
&nbsp;
   paraStyle.tailIndent <span style="color: #002200;">=</span> <span style="color: #002200;">-</span><span style="color: #2400d9;">20</span>;
&nbsp;
   CTParagraphStyleRef para3 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>paraStyle createCTParagraphStyle<span style="color: #002200;">&#93;</span>;
&nbsp;
   STAssertTrue<span style="color: #002200;">&#40;</span>para2<span style="color: #002200;">!=</span>para3, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Paragraph Styles should not be identical after change&quot;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
   <span style="color: #11740a; font-style: italic;">// change back</span>
&nbsp;
   paraStyle.tailIndent <span style="color: #002200;">=</span> <span style="color: #2400d9;">0</span>;
&nbsp;
   CTParagraphStyleRef para4 <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>paraStyle createCTParagraphStyle<span style="color: #002200;">&#93;</span>;
&nbsp;
   STAssertEquals<span style="color: #002200;">&#40;</span>para1, para4, <span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Paragraph Styles should be identical after change back&quot;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
   <span style="color: #11740a; font-style: italic;">// cleanup</span>
&nbsp;
   CFRelease<span style="color: #002200;">&#40;</span>para1<span style="color: #002200;">&#41;</span>;
   CFRelease<span style="color: #002200;">&#40;</span>para2<span style="color: #002200;">&#41;</span>;
   CFRelease<span style="color: #002200;">&#40;</span>para3<span style="color: #002200;">&#41;</span>;
   CFRelease<span style="color: #002200;">&#40;</span>para4<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #a61390;">@end</span></pre></td></tr></table></div>

<p>The point of this test was to first show that creating two CTParagraphStyle instances in succession should return the same result. Then by modifying the underlying DTCoreTextParagraphStyle I would get a different result. Finally by reverting the change I would again get the same result as the first two.</p>
<p>Unfortunately this method is not very fast. Especially if it is called many times over a lengthy HTML document you would see it become a hot spot in Instruments. In this screenshot the marked purple mountain is me parsing the War&amp;Peace HTML in the DTCoreText demo app.</p>
<p><a href="http://i1.wp.com/www.cocoanetics.com/files/Bildschirmfoto-2013-02-25-um-4.31.42-PM.png"><img class="alignnone  wp-image-7664" alt="Parsing War &amp; Peace" src="http://i1.wp.com/www.cocoanetics.com/files/Bildschirmfoto-2013-02-25-um-4.31.42-PM.png?resize=614%2C382" data-recalc-dims="1" /></a></p>
<p>You can see how the createCTParagraphStyle method is calling _cacheKey and this making up the lion share of the execution time in this method (432 ms of 553 ms). If you double-click on it you see a big red sea.</p>
<p><a href="http://i2.wp.com/www.cocoanetics.com/files/Bildschirmfoto-2013-02-25-um-4.35.17-PM.png"><img class="alignnone size-full wp-image-7665" alt="NSString Construction" src="http://i2.wp.com/www.cocoanetics.com/files/Bildschirmfoto-2013-02-25-um-4.35.17-PM.png?resize=565%2C284" data-recalc-dims="1" /></a></p>
<p>Apparently 97.7% of the samples taken execution was within this stringWithFormat: method. At this point it is quite clear that this is not an optimal approach. I suspect the main reason for lackluster performance on this line is that it takes quite some time to format floating point numbers as NSString.</p>
<p>I googled around a bit further, but couldn&#8217;t find a simple, yet easy to implement method for getting a better cache key. Then it dawned on me &#8230;</p>
<h3>CommonCrypto</h3>
<p>Why not simply putting all values in a struct and then creating an md5 checksum over that?</p>

<div class="wp_codebox"><table><tr id="p766310"><td class="code" id="p7663code10"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> <span style="color: #002200;">&#41;</span>_cacheKey
<span style="color: #002200;">&#123;</span>
   <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableString_Class/"><span style="color: #400080;">NSMutableString</span></a> <span style="color: #002200;">*</span>tabsBlocksListsDescription <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableString_Class/"><span style="color: #400080;">NSMutableString</span></a> <span style="color: #a61390;">string</span><span style="color: #002200;">&#93;</span>;
&nbsp;
   <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span> tab <span style="color: #a61390;">in</span> _tabStops<span style="color: #002200;">&#41;</span>
   <span style="color: #002200;">&#123;</span>
      CTTextTabRef tabStop <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>__bridge CTTextTabRef<span style="color: #002200;">&#41;</span>tab;
&nbsp;
      CTTextAlignment alignment <span style="color: #002200;">=</span> CTTextTabGetAlignment<span style="color: #002200;">&#40;</span>tabStop<span style="color: #002200;">&#41;</span>;
      <span style="color: #a61390;">double</span> location <span style="color: #002200;">=</span> CTTextTabGetLocation<span style="color: #002200;">&#40;</span>tabStop<span style="color: #002200;">&#41;</span>;
&nbsp;
      <span style="color: #002200;">&#91;</span>tabsBlocksListsDescription appendFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;-tab:%d-%f&quot;</span>, alignment, location<span style="color: #002200;">&#93;</span>;
   <span style="color: #002200;">&#125;</span>
&nbsp;
   <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>DTTextBlock <span style="color: #002200;">*</span>textBlock <span style="color: #a61390;">in</span> _textBlocks<span style="color: #002200;">&#41;</span>
   <span style="color: #002200;">&#123;</span>
      <span style="color: #002200;">&#91;</span>tabsBlocksListsDescription appendFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;-block:%x&quot;</span>, <span style="color: #002200;">&#91;</span>textBlock hash<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
   <span style="color: #002200;">&#125;</span>
&nbsp;
   <span style="color: #a61390;">for</span> <span style="color: #002200;">&#40;</span>DTCSSListStyle <span style="color: #002200;">*</span>listStyle <span style="color: #a61390;">in</span> _textLists<span style="color: #002200;">&#41;</span>
   <span style="color: #002200;">&#123;</span>
      <span style="color: #002200;">&#91;</span>tabsBlocksListsDescription appendFormat<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;-list:%x&quot;</span>, <span style="color: #002200;">&#91;</span>listStyle hash<span style="color: #002200;">&#93;</span><span style="color: #002200;">&#93;</span>;
   <span style="color: #002200;">&#125;</span>
&nbsp;
   <span style="color: #a61390;">struct</span>  <span style="color: #002200;">&#123;</span>
      CGFloat firstLineHeadIndent;
      CGFloat defaultTabInterval;
      CGFloat paragraphSpacingBefore;
      CGFloat paragraphSpacing;
      CGFloat headIndent;
      CGFloat tailIndent;
      CGFloat listIndent;
      CGFloat lineHeightMultiple;
      NSInteger alignment; <span style="color: #11740a; font-style: italic;">// make it full width, origin is uint8</span>
      NSInteger baseWritingDirection; <span style="color: #11740a; font-style: italic;">// make it full width, origin is int8</span>
      NSUInteger tabsBlocksListsHash;
   <span style="color: #002200;">&#125;</span> allvalues <span style="color: #002200;">=</span> <span style="color: #002200;">&#123;</span><span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#125;</span>;
&nbsp;
   <span style="color: #11740a; font-style: italic;">// pack all values in the struct</span>
   allvalues.firstLineHeadIndent <span style="color: #002200;">=</span> _firstLineHeadIndent;
   allvalues.defaultTabInterval <span style="color: #002200;">=</span> _defaultTabInterval;
   allvalues.paragraphSpacingBefore <span style="color: #002200;">=</span> _paragraphSpacingBefore;
   allvalues.paragraphSpacing <span style="color: #002200;">=</span> _paragraphSpacing;
   allvalues.headIndent <span style="color: #002200;">=</span> _headIndent;
   allvalues.tailIndent <span style="color: #002200;">=</span> _tailIndent;
   allvalues.listIndent <span style="color: #002200;">=</span> _listIndent;
   allvalues.lineHeightMultiple <span style="color: #002200;">=</span> _lineHeightMultiple;
   allvalues.minimumLineHeight <span style="color: #002200;">=</span> _minimumLineHeight;
   allvalues.maximumLineHeight <span style="color: #002200;">=</span> _maximumLineHeight;
   allvalues.baseWritingDirection <span style="color: #002200;">=</span> _baseWritingDirection;
   allvalues.alignment <span style="color: #002200;">=</span> _alignment;
   allvalues.tabsBlocksListsHash <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>tabsBlocksListsDescription hash<span style="color: #002200;">&#93;</span>;
&nbsp;
   <span style="color: #11740a; font-style: italic;">// create md5</span>
   <span style="color: #a61390;">void</span> <span style="color: #002200;">*</span>cStr <span style="color: #002200;">=</span> <span style="color: #002200;">&amp;</span>amp;allvalues;
&nbsp;
   <span style="color: #a61390;">void</span> <span style="color: #002200;">*</span>digest <span style="color: #002200;">=</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/malloc.html"><span style="color: #a61390;">malloc</span></a><span style="color: #002200;">&#40;</span>CC_MD5_DIGEST_LENGTH<span style="color: #002200;">&#41;</span>;
   CC_MD5<span style="color: #002200;">&#40;</span> cStr, <span style="color: #002200;">&#40;</span>CC_LONG<span style="color: #002200;">&#41;</span><a href="http://www.opengroup.org/onlinepubs/009695399/functions/sizeof.html"><span style="color: #a61390;">sizeof</span></a><span style="color: #002200;">&#40;</span>allvalues<span style="color: #002200;">&#41;</span>, digest<span style="color: #002200;">&#41;</span>;
&nbsp;
   <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/"><span style="color: #400080;">NSData</span></a> dataWithBytesNoCopy<span style="color: #002200;">:</span>digest length<span style="color: #002200;">:</span><a href="http://www.opengroup.org/onlinepubs/009695399/functions/sizeof.html"><span style="color: #a61390;">sizeof</span></a><span style="color: #002200;">&#40;</span>digest<span style="color: #002200;">&#41;</span> freeWhenDone<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>There are some things that &#8211; due to their dynamic nature &#8211; still have to go in a string. Then I am putting all numbers into the allvalues struct. The dynamic string is represented by its hash. CC_MD5 creates an MD5 digest/checksum of a few bytes length. Finally we transfer malloc&#8217;ed digest into an NSData which takes over the responsibility of freeing the bytes when it is being deallocated.</p>
<p>Note how I am changing the width of baseWritingDirection and alignment in the struct. The reason for this &#8211; as I found out later &#8211; is that the compiler apparently pads narrower values to word boundaries, probably for performance reasons. If you leave these as 1-byte-wide then the assignment zeroes out the member variable, but the padding bytes are still random values.</p>
<p>This is the fasted method of getting bytes into an Objective-C object because it uses the bytes as they are without needing to copying them off somewhere. Speaking of copying, NSData kindly implements the NSCopying protocol which is needed if you want to use it as a cache key. Keys for NSCache and NSDictionary need to be copyable, i.e. implement the NSCopying protocol.</p>
<p>Another thing I learned only by finding that some other unit tests would suddenly break with the new implementation. I didn&#8217;t zero the contents of the struct instead relying on LLVM doing that for me. But apparently there are some instances where this is not true. By setting all values to 0 first I was able to get all unit tests back to working.</p>
<h3>How does it Measure Up?</h3>
<p>This can easily be determined by using CFAbsoluteTime to measure the duration it takes to execute this method.</p>

<div class="wp_codebox"><table><tr id="p766311"><td class="code" id="p7663code11"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span>CTParagraphStyleRef<span style="color: #002200;">&#41;</span>createCTParagraphStyle
<span style="color: #002200;">&#123;</span>
   CFAbsoluteTime startTime <span style="color: #002200;">=</span> CFAbsoluteTimeGetCurrent<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
   <span style="color: #a61390;">id</span> cacheKey <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>self _cacheKey<span style="color: #002200;">&#93;</span>;
   CFAbsoluteTime endTime <span style="color: #002200;">=</span> CFAbsoluteTimeGetCurrent<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
   NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;time: %f&quot;</span>, endTime <span style="color: #002200;">-</span> startTime<span style="color: #002200;">&#41;</span>;
&nbsp;
   <span style="color: #11740a; font-style: italic;">//...</span></pre></td></tr></table></div>

<p>Putting a few results for the same UI activity next to each other we find that the md5 method is 5 times as fast as the stringWithFormat: approach.</p>
<p><a href="http://i0.wp.com/www.cocoanetics.com/files/Bildschirmfoto-2013-02-25-um-4.51.00-PM.png"><img class="alignnone size-full wp-image-7666" alt="Comparison" src="http://i0.wp.com/www.cocoanetics.com/files/Bildschirmfoto-2013-02-25-um-4.51.00-PM.png?resize=153%2C208" data-recalc-dims="1" /></a></p>
<p>I&#8217;ll take the left column please, thank you.</p>
<p>Inspecting this in Instruments paints the same picture. Time spent in _cacheKey dropped to around 100 ms. Much better.</p>
<h3>NSData Direct?</h3>
<p>There is even another way to use NSData as cache key. Apparently NSData is using up to 80 bytes from its bytes payload as good hash as we can see in Apple&#8217;s <a href="http://opensource.apple.com/source/CF/CF-635.21/CFData.c">Open Source code</a>. They use an CFHashBytes macro which uses the ELF hashing algorithm, as explained in this <a href="http://stackoverflow.com/questions/10768467/how-does-nsdatas-implementation-of-the-hash-method-work">question on Stack Overflow</a>. Thanks <a href="http://twitter.com/saurabhg">Saurabh Garg</a> for pointing this out to me!</p>
<p>This basically means that if the number of your ivar bytes is guaranteed to be less than 80, then you can also directly wrap the struct into an NSData and use this as key instead.</p>
<p>My first try actually seemed to reduce performance again, because having to unnecessarily copy around bytes takes a bit of time. The duration of _cacheKey went up from 100 to around 120 ms.</p>
<p><a href="http://i0.wp.com/www.cocoanetics.com/files/Bildschirmfoto-2013-02-25-um-5.06.03-PM.png"><img class="alignnone size-full wp-image-7668" alt="NSData with copy" src="http://i0.wp.com/www.cocoanetics.com/files/Bildschirmfoto-2013-02-25-um-5.06.03-PM.png?resize=504%2C108" data-recalc-dims="1" /></a></p>
<p>So I rolled up my sleeves and thought back to a time when I was still creating C-structures dynamically with malloc. Since we know that the struct&#8217;s data will be put into an NSData anyway there is no need to let the compiler create an allvalues variable on the stack (as all temporary variables are) but use malloc to create it on the heap right from the start.</p>
<p>Instead of creating a new variable we just define a variable type allvalues_t. Then we use the arrow operator to fill in the member variables.</p>

<div class="wp_codebox"><table><tr id="p766312"><td class="code" id="p7663code12"><pre class="objc" style="font-family:monospace;"><span style="color: #11740a; font-style: italic;">// ...</span>
   <span style="color: #11740a; font-style: italic;">// a struct that takes on all sub-values</span>
   <span style="color: #a61390;">typedef</span> <span style="color: #a61390;">struct</span> <span style="color: #002200;">&#123;</span>
      CGFloat firstLineHeadIndent;
      CGFloat defaultTabInterval;
      CGFloat paragraphSpacingBefore;
      CGFloat paragraphSpacing;
      CGFloat headIndent;
      CGFloat tailIndent;
      CGFloat listIndent;
      CGFloat lineHeightMultiple;
      CGFloat minimumLineHeight;
      CGFloat maximumLineHeight;
      CTTextAlignment alignment;
      CTWritingDirection baseWritingDirection;
      NSUInteger tabsBlocksListsHash;
   <span style="color: #002200;">&#125;</span> allvalues_t;
&nbsp;
   allvalues_t <span style="color: #002200;">*</span>allvalues <span style="color: #002200;">=</span> <a href="http://www.opengroup.org/onlinepubs/009695399/functions/malloc.html"><span style="color: #a61390;">malloc</span></a><span style="color: #002200;">&#40;</span><a href="http://www.opengroup.org/onlinepubs/009695399/functions/sizeof.html"><span style="color: #a61390;">sizeof</span></a><span style="color: #002200;">&#40;</span>allvalues_t<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#41;</span>;
&nbsp;
   <span style="color: #002200;">*</span>allvalues <span style="color: #002200;">=</span> <span style="color: #002200;">&#40;</span>allvalues_t<span style="color: #002200;">&#41;</span><span style="color: #002200;">&#123;</span><span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>,<span style="color: #2400d9;">0</span>, <span style="color: #a61390;">nil</span><span style="color: #002200;">&#125;</span>;
   <span style="color: #11740a; font-style: italic;">//memset(allvalues, 0, sizeof(allvalues_t));</span>
&nbsp;
   <span style="color: #11740a; font-style: italic;">// pack all values in the struct</span>
   allvalues<span style="color: #002200;">-</span>&gt;firstLineHeadIndent <span style="color: #002200;">=</span> _firstLineHeadIndent;
   allvalues<span style="color: #002200;">-</span>&gt;defaultTabInterval <span style="color: #002200;">=</span> _defaultTabInterval;
   allvalues<span style="color: #002200;">-</span>&gt;paragraphSpacingBefore <span style="color: #002200;">=</span> _paragraphSpacingBefore;
   allvalues<span style="color: #002200;">-</span>&gt;paragraphSpacing <span style="color: #002200;">=</span> _paragraphSpacing;
   allvalues<span style="color: #002200;">-</span>&gt;headIndent <span style="color: #002200;">=</span> _headIndent;
   allvalues<span style="color: #002200;">-</span>&gt;tailIndent <span style="color: #002200;">=</span> _tailIndent;
   allvalues<span style="color: #002200;">-</span>&gt;listIndent <span style="color: #002200;">=</span> _listIndent;
   allvalues<span style="color: #002200;">-</span>&gt;lineHeightMultiple <span style="color: #002200;">=</span> _lineHeightMultiple;
   allvalues<span style="color: #002200;">-</span>&gt;minimumLineHeight <span style="color: #002200;">=</span> _minimumLineHeight;
   allvalues<span style="color: #002200;">-</span>&gt;maximumLineHeight <span style="color: #002200;">=</span> _maximumLineHeight;
   allvalues<span style="color: #002200;">-</span>&gt;baseWritingDirection <span style="color: #002200;">=</span> _baseWritingDirection;
   allvalues<span style="color: #002200;">-</span>&gt;alignment <span style="color: #002200;">=</span> _alignment;
   allvalues<span style="color: #002200;">-</span>&gt;tabsBlocksListsHash <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span>tabsBlocksListsDescription hash<span style="color: #002200;">&#93;</span>;
&nbsp;
   <span style="color: #a61390;">return</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/"><span style="color: #400080;">NSData</span></a> dataWithBytesNoCopy<span style="color: #002200;">:</span>allvalues length<span style="color: #002200;">:</span><a href="http://www.opengroup.org/onlinepubs/009695399/functions/sizeof.html"><span style="color: #a61390;">sizeof</span></a><span style="color: #002200;">&#40;</span>allvalues_t<span style="color: #002200;">&#41;</span> freeWhenDone<span style="color: #002200;">:</span><span style="color: #a61390;">YES</span><span style="color: #002200;">&#93;</span>;
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>Note the commented out memset. My experiments have shown it to be slightly slower than setting all values via the curly-bracketed list.</p>
<p>The result in Instruments is another saved 20 ms which causes _cacheKey to no longer appear in the list of hot spots in the right-hand panel.</p>
<p><a href="http://i1.wp.com/www.cocoanetics.com/files/Bildschirmfoto-2013-02-25-um-5.59.54-PM.png"><img class="alignnone  wp-image-7669" alt="_cacheKey no longer there" src="http://i1.wp.com/www.cocoanetics.com/files/Bildschirmfoto-2013-02-25-um-5.59.54-PM.png?resize=614%2C386" data-recalc-dims="1" /></a></p>
<p>It is a bit further down with 84ms. In fact you can see NSCache&#8217;s objectForKey take up even more time than our highly optimized _cacheKey method function. I would call this a good optimization success.</p>
<h3>Conclusion</h3>
<p>If you need a fast hashing function and you have less than 80 bytes you can wrap a temporary struct into an NSData and use the built-in hashing function which is slightly faster than even the highly optimized MD5 function from CommonCrypto.</p>
<p>For more than 80 bytes of key data you cannot do anything wrong with and MD5. No need to convert that into a string since NSData implements NSCopying and is fine for using as a cache key as well. Constructing long NSStrings from your key data should be the least favored option since the performance gap is as wide as a factor of 5.</p>
<p>Another thing though that I learned from my experiments today is that this kind of optimization needs a good set of unit tests to immediately know if your wonderful optimization doesn&#8217;t actually break something. I only noticed the need to zero the struct values from suddenly my Right-to-Left writing direction tests failing.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=7663&amp;md5=bb961079770bf0961dd1a55997b405be" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2013/02/fast-hashing/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2013%2F02%2Ffast-hashing%2F&amp;language=en_GB&amp;category=text&amp;title=Fast+Hashing&amp;description=In+DTCoreText+there+is+the+DTCoreTextParagraphStyle+class+which+represents+an+Objective-C+wrapper+around+CTParagraphStyle.+This+has+a+method%C2%A0createCTParagraphStyle+which+creates+the+actual+Core+Text+object+to+put+in+attributes+of...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>iPhone 5 Image Decompression Benchmarked</title>
		<link>http://www.cocoanetics.com/2012/09/iphone-5-image-decompression-benchmarked/</link>
		<comments>http://www.cocoanetics.com/2012/09/iphone-5-image-decompression-benchmarked/#comments</comments>
		<pubDate>Sun, 30 Sep 2012 19:06:30 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=7114</guid>
		<description><![CDATA[One of the first lucky owners of the iPhone 5, David Smith, kindly ran my Image Decompression Benchmark on the latest 3 generations of iPhone. These benchmarks measure the time it takes for an image to get from disk to screen and encompass 5 resolutions, PNG crushed and uncrushed, as well as 10 compression levels of JPEG. Christian Pfandler prepared the charts for us. We like to repeat the same benchmarks on every new CPU that Apple likes to solder into their devices, you can read past analyses iPhone 3G through iPad 2,  iPad 3. One note of caution if you want to compare these to the results in this article, we changed the methodology of logging the times from NSLog to CFAbsoluteTime. NSLog itself takes up to 50 ms per logged statement. The new method is more exact and does not have this drawback of including the logging time in the measurements. Executive Summary: the iPhone 5 can indeed be claimed to be twice as the predecessor. Running this benchmark on earlier iOS devices had shown the pattern that increases in GPU power did have no relevant impact on the numbers. At the same time the rendering speed improvements seemed to be entirely a function of the CPU. This theory was confirmed by an Apple engineer at WWDC who told me that all the UIKit image decompression indeed happens on the CPU. The only way to get images to be decoded on the GPU would be via CoreImage. The problem is while image decoding there would be faster you still have the bottleneck of having to get the decoded image transferred to a CALayer and again back into the render tree. So decoding images via CoreImage probably only makes sense if you can keep them on the GPU, like for video compositing or use as 3D textures. Knowing that this benchmark only looks at the CPU however we still think that it is a valid method to evaluate overall CPU performance from one iOS device generation to the next. iPhone 5 Results Small images sizes do not show much of a difference dealing with JPGs, though PNGs (both crushed and uncrushed) are showing a definite improvement there. The blue area which measures the alloc/init of a UIImage with the corresponding test image seems to be about constant. The reason is probably that the SSD in the iPhone has not much increased in throughput. The green parts measure the time it takes to draw the images into a bitmap context of identical size to avoid skewing of the number by adding the need to resize the image. There was a bit of an improvement there from the 4S over iPhone 4 for the smallest two images sizes the potential increased memory bandwidth from CPU to GPU does not yet show here. 512&#215;384 is the first time that we really see an effect of better throughput from the CPU to the GPU with the green parts being noticeably shorter. Uncrushed PNGs are way quicker to decompress. For the first time we see PNGs of this size clock in slightly faster than 100% JPGs. The remarkable increase in PNG decoding performance again beats 100% JPGs. Accross the board the time to decompress and render on the iPhone 5 is equal to the uncompression time alone on iPhone 4S and 4. PNGs have always been the slowest at higher resolutions. Which is why in my original benchmark article we concluded that PNGs are great for small UI elements and icons. But for full screen catalogs we went with 80% JPGs because of the overall speed benefit. Out of all these numbers my personal favorite is to compare the highest resolution on all three devices: iPhone 4: Flower_2048x1536.png (JPG 80%) init: 4 ms decompress: 168 ms draw: 76 ms total 248 ms iPhone 4S: Flower_2048x1536.png (JPG 80%) init: 2 ms decompress: 160 ms draw: 72 ms total 234 ms iPhone 5: Flower_2048x1536.png (JPG 80%) init: 3 ms decompress: 91 ms draw: 31 ms total 124 ms At this level you can easily see the 2x improvement the CPU has over the previous generation. JPEGs from 10% to 90% all prove this point. Contrasting to the numbers of the iPad 3 both PNG and JPEG performance gets a benefit. If you remember, when we benchmarked the iPad 3 there was almost no speed improvement in JPEGs, but only some on PNGs. With the iPhone 5, the improvement for decoding PNGs is just as remarkable: crushed a little less, uncrushed a little more. On the iPhone 5 the difference is almost not noticeable, but for earlier devices it still pays to have Xcode automatically crush the PNGs when building apps. Conclusion The A6 processor in the iPhone supports VFPv4, a special set up instructions to highly parallelize floating point [...]]]></description>
				<content:encoded><![CDATA[<p>One of the first lucky owners of the iPhone 5, <a href="http://david-smith.org">David Smith</a>, kindly ran my <a href="https://github.com/Cocoanetics/Cocoanetics-Benchmarks">Image Decompression Benchmark</a> on the latest 3 generations of iPhone. These benchmarks measure the time it takes for an image to get from disk to screen and encompass 5 resolutions, PNG crushed and uncrushed, as well as 10 compression levels of JPEG. <a href="http://www.pfandler.com">Christian Pfandler</a> prepared the charts for us.</p>
<p>We like to repeat the same benchmarks on every new CPU that Apple likes to solder into their devices, you can read past analyses <a href="http://www.cocoanetics.com/2011/10/avoiding-image-decompression-sickness/">iPhone 3G through iPad 2</a>,  <a href="http://www.cocoanetics.com/2012/03/ipad-3-image-decompression-benchmarked/">iPad 3</a>. One note of caution if you want to compare these to the results in this article, we changed the methodology of logging the times from NSLog to CFAbsoluteTime. NSLog itself takes up to 50 ms per logged statement. The new method is more exact and does not have this drawback of including the logging time in the measurements.</p>
<p>Executive Summary: the iPhone 5 can indeed be claimed to be twice as the predecessor.</p>
<p><span id="more-7114"></span></p>
<div id="more-7114"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<p>Running this benchmark on earlier iOS devices had shown the pattern that increases in GPU power did have no relevant impact on the numbers. At the same time the rendering speed improvements seemed to be entirely a function of the CPU. This theory was confirmed by an Apple engineer at WWDC who told me that all the UIKit image decompression indeed happens on the CPU.</p>
<p>The only way to get images to be decoded on the GPU would be via CoreImage. The problem is while image decoding there would be faster you still have the bottleneck of having to get the decoded image transferred to a CALayer and again back into the render tree. So decoding images via CoreImage probably only makes sense if you can keep them on the GPU, like for video compositing or use as 3D textures.</p>
<p>Knowing that this benchmark only looks at the CPU however we still think that it is a valid method to evaluate overall CPU performance from one iOS device generation to the next.</p>
<h3>iPhone 5 Results</h3>
<p>Small images sizes do not show much of a difference dealing with JPGs, though PNGs (both crushed and uncrushed) are showing a definite improvement there.</p>
<p><a href="http://i2.wp.com/www.cocoanetics.com/files/128x96.png"><img class="alignnone size-full wp-image-7115" title="iPhone 4-5 128x96" src="http://i2.wp.com/www.cocoanetics.com/files/128x96.png?resize=445%2C311" alt="" data-recalc-dims="1" /></a></p>
<p>The blue area which measures the alloc/init of a UIImage with the corresponding test image seems to be about constant. The reason is probably that the SSD in the iPhone has not much increased in throughput.</p>
<p><a href="http://i2.wp.com/www.cocoanetics.com/files/256x192.png"><img class="alignnone size-full wp-image-7116" title="iPhone 4-5 256x192" src="http://i2.wp.com/www.cocoanetics.com/files/256x192.png?resize=445%2C311" alt="" data-recalc-dims="1" /></a></p>
<p>The green parts measure the time it takes to draw the images into a bitmap context of identical size to avoid skewing of the number by adding the need to resize the image. There was a bit of an improvement there from the 4S over iPhone 4 for the smallest two images sizes the potential increased memory bandwidth from CPU to GPU does not yet show here.</p>
<p><a href="http://i2.wp.com/www.cocoanetics.com/files/512x384.png"><img class="alignnone size-full wp-image-7117" title="iPhone 4-5 512x384" src="http://i2.wp.com/www.cocoanetics.com/files/512x384.png?resize=445%2C311" alt="" data-recalc-dims="1" /></a></p>
<p>512&#215;384 is the first time that we really see an effect of better throughput from the CPU to the GPU with the green parts being noticeably shorter. Uncrushed PNGs are way quicker to decompress. For the first time we see PNGs of this size clock in slightly faster than 100% JPGs.</p>
<p><a href="http://i1.wp.com/www.cocoanetics.com/files/1024x768.png"><img class="alignnone size-full wp-image-7118" title="iPhone 4-5 1024x768" src="http://i1.wp.com/www.cocoanetics.com/files/1024x768.png?resize=445%2C311" alt="" data-recalc-dims="1" /></a></p>
<p>The remarkable increase in PNG decoding performance again beats 100% JPGs. Accross the board the time to decompress and render on the iPhone 5 is equal to the uncompression time alone on iPhone 4S and 4.</p>
<p><a href="http://i0.wp.com/www.cocoanetics.com/files/2048x1536.png"><img class="alignnone size-full wp-image-7119" title="iPhone 4-5 2048x1536" src="http://i0.wp.com/www.cocoanetics.com/files/2048x1536.png?resize=445%2C311" alt="" data-recalc-dims="1" /></a></p>
<p>PNGs have always been the slowest at higher resolutions. Which is why in my original benchmark article we concluded that PNGs are great for small UI elements and icons. But for full screen catalogs we went with 80% JPGs because of the overall speed benefit.</p>
<p>Out of all these numbers my personal favorite is to compare the highest resolution on all three devices:</p>
<p><strong>iPhone 4:</strong> Flower_2048x1536.png (JPG 80%) init: 4 ms decompress: 168 ms draw: 76 ms total 248 ms</p>
<p><strong>iPhone 4S:</strong> Flower_2048x1536.png (JPG 80%) init: 2 ms decompress: 160 ms draw: 72 ms total 234 ms</p>
<p><strong>iPhone 5:</strong> Flower_2048x1536.png (JPG 80%) init: 3 ms decompress: 91 ms draw: 31 ms total 124 ms</p>
<p>At this level you can easily see the 2x improvement the CPU has over the previous generation. JPEGs from 10% to 90% all prove this point. Contrasting to the numbers of the iPad 3 both PNG and JPEG performance gets a benefit. If you remember, when we benchmarked the iPad 3 there was almost no speed improvement in JPEGs, but only some on PNGs.</p>
<p>With the iPhone 5, the improvement for decoding PNGs is just as remarkable: crushed a little less, uncrushed a little more. On the iPhone 5 the difference is almost not noticeable, but for earlier devices it still pays to have Xcode automatically crush the PNGs when building apps.</p>
<h3>Conclusion</h3>
<p>The A6 processor in the iPhone supports VFPv4, a special set up instructions to highly parallelize floating point operations, VFP is short for &#8220;Vector Floating Point&#8221;. The presence of these instructions leads Anandtech to conclude that it must be the <a href="http://www.anandtech.com/show/6292/iphone-5-a6-not-a15-custom-core">first SoC entirely designed by Apple in-house</a>, albeit based on the ARM 7 architecture.</p>
<p>If I&#8217;m reading this right then the improved VFP performance comes from having 32 registers in there, twice as many as the VFPv3 previously had. This simply means that twice as many floating point numbers can be crunched in parallel, explaining the doubling of floating point performance on the CPU. This &#8220;going wider&#8221; yields its benefit at roughly the same battery usage.</p>
<p>The custom silicon that Apple invented for the iPhone 5 lets it easily win by a factor of 2 over previous generation devices.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=7114&amp;md5=d9b4f93270353ed1067c0079d11a8a1c" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/09/iphone-5-image-decompression-benchmarked/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F09%2Fiphone-5-image-decompression-benchmarked%2F&amp;language=en_GB&amp;category=text&amp;title=iPhone+5+Image+Decompression+Benchmarked&amp;description=One+of+the+first+lucky+owners+of+the+iPhone+5%2C+David+Smith%2C+kindly+ran+my+Image+Decompression+Benchmark+on+the+latest+3+generations+of+iPhone.+These+benchmarks+measure+the+time...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Component Shuffling</title>
		<link>http://www.cocoanetics.com/2012/09/component-shuffling/</link>
		<comments>http://www.cocoanetics.com/2012/09/component-shuffling/#comments</comments>
		<pubDate>Sat, 22 Sep 2012 16:34:21 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=7057</guid>
		<description><![CDATA[I made some updates recently that I wanted to mention so as to minimize some surprises. Also there are some  changes that were prompted by iOS 6 being released. DTLoupeView The component is for sale by itself or as part of DTRichTextEditor. It is a perfect copy of the 3 magnifying glasses that are part of iOS including the showing and hiding animations. Since Apple still does not give access to the native loupe this component still has a reason to live. Yesterday I did some major reworking due to a crash that started to occur on iOS 6. When presenting the loupe the developer specifies a target view. I would walk up the view hierarchy until I reached the UIWindow and then moved back down one level to find the root view. UIWindows don&#8217;t get rotated when the device is rotated, but the first view does which made this the perfect spot to mount the loupe view on. There is a bug/feature in iOS 6 that a modally presented view controller does not like if a subview is added higher up in the view hierarchy than the internal views that are used to display the shadow of the modal view. Strangely this would result in a crash on [CALayer layer] in Apple&#8217;s code. Probably a bug, but I cannot be certain because I was doing a nasty hack anyway. The loupe contents comes from a renderLayerInContext and to avoid the loupe seeing itself I was briefly hiding it, rendering the layers and then immediately showing it again. Another nasty hack. To work around the problem I changed the strategy such to give the loupe its own UIWindow. Now when the loupe is being presented I am synching the rotation and bounds of the loupe special window with the root view. This extra window has the additional benefit that I don&#8217;t need the hide/show hack any more as well. While I was at it I also made the loupe window and instance a singleton. Now you don&#8217;t call alloc/init any more on the loupe but retrieve the singleton via [DTLoupeView sharedLoupe]. To be honest the previous implementation sucked, because it would cause loupes to pile up over time. The new one doesn&#8217;t have this effect. DTFoundation This project is the repository for all the kinds of helper methods that I am using myself all the time. It also has become home to several key classes that I want a central place to maintain them at. I found some categories on classes that exist both on iOS and Mac very useful, but the previous monolithic static library several annoying drawbacks. It mixed stuff that is platform-independent with categories on UIKit views. So I started a solo target that allows me to include the pieces that also work on Mac via Mac library. The other annoying thing was that some components in DTFoundation would have dependencies. DTHTMLParser for example would require libxml2. If you included DTFoundation then the linker would force you to also link in libxml2, even if you didn&#8217;t do any HTML parsing in your project. The same is true for DTZipArchive which requires zlib and DTDownloadCache which requires CoreData. So I decided to split these out of DTFoundation and provide static library targets for these by themselves. The goal being that if you included DTFoundation you would never have to add additional dependencies that you don&#8217;t need. I want to add a podspec for DTFoundation as well and there it also makes sense to have specs for the individual parts that have dependencies independent from those which don&#8217;t. DTCoreText Something that was bugging me for quite some time was the fact that DTCoreText is using two classes that had found their home in my DTFoundation project: DTVersion and DTHTMLParser. I had to maintain a duplicate version of these inside of DTCoreText. I recently fixed a bug there when encountering a processing instruction and of course I had to copy this over into DTCoreText as well. So I removed the duplicate classes and instead added DTFoundation as git submodule. DTHTMLParser is linked in via the new static library containing only it. DTVersion is universal and comes from the standard DTFoundation static library. Both of these are merged into the DTCoreText static library. For developers who also use DTFoundation directly in their projects there is a static library target for DTCoreText that does not include the DTFoundation stuff. As more and more people seem to want to use CocoaPods to include other developer&#8217;s components into their projects I was nudged to think how to also resolve the duplication there. If I&#8217;m referencing DTFoundation and DTHTMLParser from one git submodule then there should be a method to model that via podspecs as well. Though here I still need to do a bit of [...]]]></description>
				<content:encoded><![CDATA[<p>I made some updates recently that I wanted to mention so as to minimize some surprises. Also there are some  changes that were prompted by iOS 6 being released.</p>
<p><span id="more-7057"></span></p>
<div id="more-7057"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<h3>DTLoupeView</h3>
<p>The component is for sale <a href="http://www.cocoanetics.com/parts/dtloupeview/">by itself</a> or as part of <a href="http://www.cocoanetics.com/parts/dtrichtexteditor/">DTRichTextEditor</a>. It is a perfect copy of the 3 magnifying glasses that are part of iOS including the showing and hiding animations. Since Apple still does not give access to the native loupe this component still has a reason to live.</p>
<p>Yesterday I did some major reworking due to a crash that started to occur on iOS 6. When presenting the loupe the developer specifies a target view. I would walk up the view hierarchy until I reached the UIWindow and then moved back down one level to find the root view. UIWindows don&#8217;t get rotated when the device is rotated, but the first view does which made this the perfect spot to mount the loupe view on.</p>
<p>There is a bug/feature in iOS 6 that a modally presented view controller does not like if a subview is added higher up in the view hierarchy than the internal views that are used to display the shadow of the modal view. Strangely this would result in a crash on [CALayer layer] in Apple&#8217;s code. Probably a bug, but I cannot be certain because I was doing a nasty hack anyway.</p>
<p>The loupe contents comes from a renderLayerInContext and to avoid the loupe seeing itself I was briefly hiding it, rendering the layers and then immediately showing it again. Another nasty hack.</p>
<p>To work around the problem I changed the strategy such to give the loupe its own UIWindow. Now when the loupe is being presented I am synching the rotation and bounds of the loupe special window with the root view. This extra window has the additional benefit that I don&#8217;t need the hide/show hack any more as well.</p>
<p>While I was at it I also made the loupe window and instance a singleton. Now you don&#8217;t call alloc/init any more on the loupe but retrieve the singleton via [DTLoupeView sharedLoupe]. To be honest the previous implementation sucked, because it would cause loupes to pile up over time. The new one doesn&#8217;t have this effect.</p>
<h3>DTFoundation</h3>
<p>This project is the repository for all the kinds of helper methods that I am using myself all the time. It also has become home to several key classes that I want a central place to maintain them at.</p>
<p>I found some categories on classes that exist both on iOS and Mac very useful, but the previous monolithic static library several annoying drawbacks. It mixed stuff that is platform-independent with categories on UIKit views. So I started a solo target that allows me to include the pieces that also work on Mac via Mac library.</p>
<p>The other annoying thing was that some components in DTFoundation would have dependencies. DTHTMLParser for example would require libxml2. If you included DTFoundation then the linker would force you to also link in libxml2, even if you didn&#8217;t do any HTML parsing in your project. The same is true for DTZipArchive which requires zlib and DTDownloadCache which requires CoreData.</p>
<p>So I decided to split these out of DTFoundation and provide static library targets for these by themselves. The goal being that if you included DTFoundation you would never have to add additional dependencies that you don&#8217;t need.</p>
<p>I want to add a podspec for DTFoundation as well and there it also makes sense to have specs for the individual parts that have dependencies independent from those which don&#8217;t.</p>
<h3>DTCoreText</h3>
<p>Something that was bugging me for quite some time was the fact that DTCoreText is using two classes that had found their home in my DTFoundation project: DTVersion and DTHTMLParser. I had to maintain a duplicate version of these inside of DTCoreText. I recently fixed a bug there when encountering a processing instruction and of course I had to copy this over into DTCoreText as well.</p>
<p>So I removed the duplicate classes and instead added DTFoundation as git submodule. DTHTMLParser is linked in via the new static library containing only it. DTVersion is universal and comes from the standard DTFoundation static library. Both of these are merged into the DTCoreText static library. For developers who also use DTFoundation directly in their projects there is a static library target for DTCoreText that does not include the DTFoundation stuff.</p>
<p>As more and more people seem to want to use CocoaPods to include other developer&#8217;s components into their projects I was nudged to think how to also resolve the duplication there. If I&#8217;m referencing DTFoundation and DTHTMLParser from one git submodule then there should be a method to model that via podspecs as well. Though here I still need to do a bit of research. Is it possible to create one podspec that works for both Mac and iOS and also have sub-specs that mirror the 3 new sub-libraries?</p>
<p>The 1.0.2 tag on the DTCoreText project is the last one that does not have the dependency on DTFoundation.</p>
<h3>DTRichTextEditor</h3>
<p>There is one more change of note in DTCoreText, related to my <a href="http://www.cocoanetics.com/parts/dtrichtexteditor/">rich text editor component</a>. Previously any HTML tag would inherit a plethora of attributes from its parent. If you copy a snippet from mobile Safari then it is encoded as a web archive on the pasteboard. It looks like iOS 6 is doing a more complete job there than it did previously.</p>
<p>One client of mine reported that if you copied a table that had a gray background color under iOS 6 the text pasted into DTRichTextEditor would now also get a gray background. The reason of course being the mentioned &#8220;brute force&#8221; inheritance. I modified DTCoreText to only inherit background-color from an inline element. A block-level element like div or table would be in charge of drawing the entire box in the stated color and thus it would not make sense to pass it on to contained inline-level elements.</p>
<p>Since I have the master repo for DTRichTextEditor on my Subversion server I need to have a repo-local mirror of DTRichText inside it. Again a form of duplication that bothers me for a long time now. Because of this I am considering to switch to git as soon as my Linux guru can set up a git server for me. I also thought about paying for a private GitHub repo, but I don&#8217;t feel comfortable having my most valuable code hosted by a third party.</p>
<p>And here the circle closes, because DTRichTextEditor is also a heavy user of DTLoupeView mentioned at the beginning of this article and also got an update there via svn sub-module. So if you are a user of that please make sure that you recursively update all the projects in there.</p>
<h3>Closing Thoughts: DTCoreText versus iOS 6</h3>
<p>iOS 6 added a few object-based attributes to CoreText and also the capability to display attributed strings using these new attributes in several UIKit classes, most importantly UITextView. This works fine for the most part unless&#8230;</p>
<ul>
<li>you have projects that still need to support earlier iOS versions</li>
<li>you want to embed images, video or custom objects in the text</li>
<li>you have HTML as the stuff to generated attributed strings out of</li>
</ul>
<p>A few months ago i had to rename the initWithHTML methods to initWithHTMLData because linking against the iOS 6 BETA SDKs would cause a duplicate symbol problem. This tells us that the initWithHTML is actually present in the OS now, as it has been for a while on Mac. But at present it is a private method and not app-store legal. (I filed a Radar for that: rdar://11664604, closed as duplicate of rdar://11689785)</p>
<p>I get the impression that Apple engineers where rushing to get rich text support into UIKit for iOS 6, but had to leave out several items to be on par with the Mac. There is NSFileWrapper, but NSTextAttachment (which is used for images on the Mac) didn&#8217;t make it into iOS so far.</p>
<p>The next big chance for Apple to completely sherlock DTCoreText+DTRichTextEditor+DTLoupeView+DTWebArchive is in Summer 2013 with iOS 7. This leaves these components a useful lifetime of at least a year from now.</p>
<p>The next big thing to do with DTCoreText is to add support for the new NS* tags where they can replace the CoreFoundation-based previous ones. Like for example NSParagraphStyle can replace CTParagraphStyle which is no Obj-C object and such had forced me to create the DTParagraphStyle wrapper in DTCoreText. I envision to detect the OS version this is running on and then use the new attributes where available or fall back on the old ones where not.</p>
<p>An attributed string that only uses attributes that are NSCoding-compliant (i.e. not CoreFoundation non-bridgable, but actual Objective-C objects) would also gain the ability of being persisted with NSKeyedArchiver. This would also solve a problem many people are experiencing. The only current way I have to persist attributed strings is by creating a so-so HTML representation. NSCoding would also allow for much faster caching of attributed strings because you could persist  anywhere that accepts NSData, like for example a CoreData table.</p>
<p>As far as I am aware NSAttributedStrings are NSCoding-compliant on the Mac. So it would be awesome if the outcome would be platform-independent to allow transferring thus persisted attributed strings between iOS and Mac.</p>
<p>All those big plans however have a big problem: so far I only found 2 companies willing to pay for enhancements on DTCoreText. I need to make a living as well and without somebody footing the bill I can only spend a few minutes here and there on it. DTCoreText is done entirely for the benefit of the community as I have no apps myself using it. So if you are interested in sponsoring improvements please get in touch.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=7057&amp;md5=886ce01104a8fbc40570d6787712fca3" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/09/component-shuffling/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F09%2Fcomponent-shuffling%2F&amp;language=en_GB&amp;category=text&amp;title=Component+Shuffling&amp;description=I+made+some+updates+recently+that+I+wanted+to+mention+so+as+to+minimize+some+surprises.+Also+there+are+some+%C2%A0changes+that+were+prompted+by+iOS+6+being+released.+DTLoupeView...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Out of Office</title>
		<link>http://www.cocoanetics.com/2012/07/out-of-office-2/</link>
		<comments>http://www.cocoanetics.com/2012/07/out-of-office-2/#comments</comments>
		<pubDate>Thu, 19 Jul 2012 00:00:31 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=6772</guid>
		<description><![CDATA[We&#8217;re offline for &#8220;maintenance&#8221; until August 2nd with no way to receive emails or respond to your requests and orders. We mention this so that you know why you won&#8217;t hear from us until then. We haven&#8217;t forgotten about you, we&#8217;ve just remembered about ourselves. So please be patient while we&#8217;re recharging.]]></description>
				<content:encoded><![CDATA[<p><a href="http://i0.wp.com/www.cocoanetics.com/files/backsoon.jpg"><img class="alignnone size-full wp-image-5257" title="back soon" src="http://i0.wp.com/www.cocoanetics.com/files/backsoon.jpg?resize=193%2C167" alt="" data-recalc-dims="1" /></a></p>
<p>We&#8217;re <strong>offline for &#8220;maintenance&#8221;</strong> <strong>until August 2nd</strong> with no way to receive emails or respond to your requests and orders. We mention this so that you know why you won&#8217;t hear from us until then. We haven&#8217;t forgotten about you, we&#8217;ve just remembered about ourselves.</p>
<p>So please be patient while we&#8217;re recharging.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=6772&amp;md5=2d1f024306fdbc6be0cc43f1ca149494" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2012/07/out-of-office-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2012%2F07%2Fout-of-office-2%2F&amp;language=en_GB&amp;category=text&amp;title=Out+of+Office&amp;description=We%26%238217%3Bre+offline+for+%26%238220%3Bmaintenance%26%238221%3B+until+August+2nd+with+no+way+to+receive+emails+or+respond+to+your+requests+and+orders.+We+mention+this+so+that+you+know+why+you+won%26%238217%3Bt...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>The Going Ons</title>
		<link>http://www.cocoanetics.com/2011/10/the-going-ons/</link>
		<comments>http://www.cocoanetics.com/2011/10/the-going-ons/#comments</comments>
		<pubDate>Thu, 20 Oct 2011 07:04:14 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=5591</guid>
		<description><![CDATA[Let me briefly summarize what&#8217;s going on in my iOS life at the moment and where you come in (if you like). My business revolves around several pillars which I established over the course of the past 2 years. My main income comes from 2 big contracts, one for developing for ELO Digital Office in Germany, one from a development partnership with International Color Services in Arizona. The former is about developing iPhone and iPad clients for their digital document archive. The latter is iCatalog. Now I am quite lucky to have won over my brother-in-law who happens to be an excellent developer with a background in Java and Android to work exclusively on these contracts. Right now he focusses on the iPad version of ELO. I myself have spent the past 3 weeks on a new release for iCatalog, the big items are being able to zoom catalog pages and lots of trouble to make it compatible with iOS 5. The main items regarding the new OS where to move all content to Library/Caches and I am still struggling with Apple&#8217;s decision to no longer send rotation events to fully covered view controllers. If I have a video that the users pinches-open to full screen the catalog view controller no longer gets informed about rotations. Instead you are supposed to use two new delegate methods that get called whenever the view hierarchy below the VC is about to or was performing layout. The problem there is that this happens far more often than rotations. I am hoping to get this version of iCatalog done before this week is out, because my brain is definitely in need of a break. Just yesterday, when one of our cats woke me by pawing the door to our master bedroom, I started coding at 4 am and worked through 4 pm. I did have lunch and Wednesdays I am getting a massage, but still I feel like chewed out. It&#8217;s almost there, the weekend, I need it. Now unfortunately I cannot clone myself so there are several items backlogged behind this iCatalog release. I promised my DTRichTextEditor clients to work on the layouting performance for longer documents. Everything longer than around 150 lines is lagging, because for every inserted character the entire document is being laid out presently. The idea here is to only layout the paragraph that was changed and move the following paragraphs up or down accordingly. Paragraphs because the beginning of a paragraph always coincides with the beginning of a CTLine. Or put in simpler terms, paragraph beginnings are always line beginnings. This makes it easy to automate the surgery. The second item for CoreText and my open source NSAttributedString+HTML project is to do a bit of clean up for one pull request I don&#8217;t have time to look at. Also I need to wrap this all into a library or framework because with so many classes in there it becomes tedious to having to copy all files to your apps. If there where a library target in the project then you could add the project as a sub project. Alternatively making a fake framework would give you the ability to automatically include the necessary heads in the bundle. Last week we had our annual sit down with the tax advisor. There I learned that my iOS endeavors made around 45000 Euros in 2009 (when I was by myself), and up until September (now 2 heads) we had a turnover of 93.000 Euros. So the additional help allowed me to more than double my turnover, probably to well above 100k for this year. But that&#8217;s about as far as I can grow with 100% of my own work. Granted I have some components and apps I&#8217;m selling providing passive income, but I generally still see a very tight coupling between time spent coding and cash-flow. And since I cannot clone myself that would be the limit of how much I can grow. So how can this grow further? I have 3 ideas on how to tackle this: I will hire somebody to take care of business development and the non-coding aspects of developing apps for clients. The idea is to incubate development for client in my existing company, using the synergies there and existing infrastructure to cost-effectively grow it. Then after a year or so &#8211; if this has proven that it can stand on its own &#8211; to spin it off into a new company. My current company will continue to own certain products, apps, components, licensing deals and build on these. But anything that goes into creating new products or maintaining existing ones would go into the new branch/spin-off. I would be my own client for this. I want to spin-off a website/blog to deal exclusively with topics [...]]]></description>
				<content:encoded><![CDATA[<p>Let me briefly summarize what&#8217;s going on in my iOS life at the moment and where you come in (if you like).</p>
<p>My business revolves around several pillars which I established over the course of the past 2 years. My main income comes from 2 big contracts, one for developing for ELO Digital Office in Germany, one from a development partnership with International Color Services in Arizona. The former is about developing iPhone and iPad clients for their digital document archive. The latter is <a title="iCatalog.framework brings Digital Catalogs to Life on iPad" href="http://www.cocoanetics.com/2010/10/icatalog-framework-brings-digital-catalogs-to-life-on-ipad/">iCatalog</a>.</p>
<p>Now I am quite lucky to have won over my brother-in-law who happens to be an excellent developer with a background in Java and Android to work exclusively on these contracts. Right now he focusses on the iPad version of ELO.</p>
<p><span id="more-5591"></span></p>
<div id="more-5591"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<p>I myself have spent the past 3 weeks on a new release for <strong>iCatalog</strong>, the big items are being able to zoom catalog pages and lots of trouble to make it compatible with iOS 5. The main items regarding the new OS where to move all content to Library/Caches and I am still struggling with Apple&#8217;s decision to no longer send rotation events to fully covered view controllers.</p>
<p>If I have a video that the users pinches-open to full screen the catalog view controller no longer gets informed about rotations. Instead you are supposed to use two new delegate methods that get called whenever the view hierarchy below the VC is about to or was performing layout. The problem there is that this happens far more often than rotations.</p>
<p>I am hoping to get this version of iCatalog done before this week is out, because my brain is definitely in need of a break. Just yesterday, when one of our cats woke me by pawing the door to our master bedroom, I started coding at 4 am and worked through 4 pm. I did have lunch and Wednesdays I am getting a massage, but still I feel like chewed out. It&#8217;s almost there, the weekend, I need it.</p>
<p>Now unfortunately I cannot clone myself so there are several items backlogged behind this iCatalog release. I promised my <a href="http://www.cocoanetics.com/parts/dtrichtexteditor/">DTRichTextEditor</a> clients to work on the layouting <strong>performance for longer documents</strong>. Everything longer than around 150 lines is lagging, because for every inserted character the entire document is being laid out presently.</p>
<p>The idea here is to only layout the paragraph that was changed and move the following paragraphs up or down accordingly. Paragraphs because the beginning of a paragraph always coincides with the beginning of a CTLine. Or put in simpler terms, paragraph beginnings are always line beginnings. This makes it easy to automate the surgery.</p>
<p>The second item for CoreText and my open source <strong>NSAttributedString+HTML</strong> project is to do a bit of clean up for one pull request I don&#8217;t have time to look at. Also I need to wrap this all into a library or framework because with so many classes in there it becomes tedious to having to copy all files to your apps. If there where a library target in the project then you could add the project as a sub project. Alternatively making a fake framework would give you the ability to automatically include the necessary heads in the bundle.</p>
<p>Last week we had our annual sit down with the tax advisor. There I learned that my iOS endeavors made around 45000 Euros in 2009 (when I was by myself), and up until September (now 2 heads) we had a turnover of 93.000 Euros. So the additional help allowed me to more than double my turnover, probably to well above 100k for this year.</p>
<p>But that&#8217;s about as far as I can grow with 100% of my own work. Granted I have some components and apps I&#8217;m selling providing passive income, but I generally still see a very tight coupling between time spent coding and cash-flow. And since I cannot clone myself that would be the limit of how much I can grow.</p>
<h3>So how can this grow further?</h3>
<p>I have 3 ideas on how to tackle this:</p>
<ol>
<li>I will hire somebody to take care of business development and the non-coding aspects of developing apps for clients. The idea is to incubate development for client in my existing company, using the synergies there and existing infrastructure to cost-effectively grow it. Then after a year or so &#8211; if this has proven that it can stand on its own &#8211; to spin it off into a new company.</li>
<li>My current company will continue to own certain products, apps, components, licensing deals and build on these. But anything that goes into creating new products or maintaining existing ones would go into the new branch/spin-off. I would be my own client for this.</li>
<li>I want to spin-off a website/blog to deal exclusively with topics related to working on developing for iOS. This would be a commercial endeavor in its own right because of the extreme niche focus. For developers it would give you a constant stream of what interesting jobs and projects are being staffed. For clients you would have a popular place to make your needs known. Of course I need somebody to head this new spin-off too, sort of like a Chief-Editor-Head-of-Business-Development hybrid.</li>
</ol>
<p>If the above only serves one purpose then that I hope you see that I am also interested in a META discussion with you as to how we could join forces to benefit the both of us.</p>
<p>When I got married two years ago I moved to the countryside. While I love to be working here it has several drawbacks when it comes to meeting clients or potential partners. But this is how it is meant to be, I even declined an opportunity that was presented to me by Apple itself. I am not moving. I have my own business to build.</p>
<p>So it has to be a virtual corporation. But then again, you can work on iOS projects anywhere you have Internet and a Mac handy. The only problem is that my stomach aches if I think of being billed by the hour by a contractor without having any way to check up on him and see how he spent this time. There is a big difference if I am paying for work out of my own pocket or whether it is a client footing the bill and the money is pass-through (with a margin off the top for my company).</p>
<h3>Summary: Own products. Develop for Clients in a separate Company.</h3>
<p>Right now we are focussing on external money, but I am planning to reinvest part of the surplus in my own products when it is feasible to do so. I am keeping lists of feature requests for my apps on a Mantis bug tracker. But as it stands there is no substantial budget to pay external contractors for work on these apps that only make me like a couple of hundred Euros per month. Without financing there are only three options:</p>
<ol>
<li>let it rot or take it off the app store.</li>
<li>labor of love (whenever, if ever, I have time)</li>
<li>hire somebody that I can afford, possibly part-time, who likes to gain experience working on my code</li>
</ol>
<p>I don&#8217;t know if I can be a true Entrepreneur in the sense that you start something that quickly beings to run by itself and then you move on. The other meaning of Entrepreneur is to build a business and stick with it and focus exclusively on it.</p>
<p>There are two guys that I greatly admire in this area, one is <a href="http://www.marco.org/">Marco Arment</a>, one is <a href="http://www.mindnode.com/">Markus Müller</a>. Marco only does Instapaper and due to his focus he does it extremely well. Markus only does Mindnode, and because Apple continues to feature his apps he is now looking to hire his first employee. Oh how great must it be to only having to think of ONE product, not being pulled into all directions at the same time as I am feeling like I am.</p>
<p>This envy &#8211; that I readily admit to &#8211; is one of the causes why I think that I must focus more on what my own products are. I want a simpler more focussed life. I seem to be a victim to the Austrian strategy &#8220;Kleinvieh macht auch Mist&#8221; (= &#8220;many small animals can also make a big pile of shit&#8221;). Because there is no single item forthcoming that I could bet my entire company on, I am dabbling in many small things. It pays the bills quite well, but I suspect that this approach is limiting my quality of life and also limits how much this business can grow.</p>
<p>Or maybe it is not all bad. Exactly this non-focus is what let me gain much experience with many different activities in a short time. So maybe you need to spend some time experimenting what activities satisfy you the most. And later in live you can still settle on on of the &#8220;next big things&#8221; (that seems to come around bi-weekly).</p>
<p>Whether you are still in the experimentation phase or whether you are already in a position to tackly your big idea, let&#8217;s talk! My e-mail address is no secret, there&#8217;s a big button right there at the top of my website.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=5591&amp;md5=b277833c1803ec0218b44051a5b9c418" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2011/10/the-going-ons/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2011%2F10%2Fthe-going-ons%2F&amp;language=en_GB&amp;category=text&amp;title=The+Going+Ons&amp;description=Let+me+briefly+summarize+what%26%238217%3Bs+going+on+in+my+iOS+life+at+the+moment+and+where+you+come+in+%28if+you+like%29.+My+business+revolves+around+several+pillars+which+I...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Back &#8230; and Many News</title>
		<link>http://www.cocoanetics.com/2011/08/back-and-many-news/</link>
		<comments>http://www.cocoanetics.com/2011/08/back-and-many-news/#comments</comments>
		<pubDate>Tue, 23 Aug 2011 19:26:57 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=5338</guid>
		<description><![CDATA[I spent last week at several beaches in Corsica and when I came back I figured I would want to prolong the silence of not reading e-mails for one more day. And how peaceful that felt, I can only recommend that. Instead I spent Monday in my hammock an continued reading a Clive Cussler novel. When I returned to my office on Tuesday I found more than 270 unread e-mails in my inbox. It took me around 4 hours to comb through these with a jackhammer and to trim it down to like a dozen or so that I will have to act upon. When I got around to perform the first actual work-related action it was that I added my first third-party component to my well-visited Parts Store. Third Party Components in Cocoanetics Parts Store The thing that I call the &#8220;Cocoanetics Parts Store&#8221; is basically a feature of my custom-built WordPress template that allows me to add &#8220;Parts&#8221; as one would add &#8220;Pages&#8221;. Ordering is done via e-mail and invoices are created manually as PDFs. Still I see hundreds of people &#8211; developers? &#8211; peruse these pages every day and so I decided a while ago to put an ad on there. With much success, this very ad is the only one that even has somebody on the waiting list. I figured that with hundred of people stumbling onto Cocoanetics.com every day why not also let them find some really great components that other developers are selling, provided that there is an affiliate system in place that lets me get a cut of purchases being made. Sensible TableView is my first such component that I get a share on. If you want to get the same kind of exposure as well, I am happy to provide it if you can furnish me an affiliation. MyAppSales Fixes &#8211; Hooray for Open Source Next order of business were several problems people had with MyAppSales since Apple again tinkered on iTunes Connect. Several countries had been moved to their own regions causing the financial reports for these regions to not show. Also some other change broke downloading of daily and weekly reports. I had open sourced MyAppSales a while ago for the express reason that well versed developers like the ones using it can contribute fixes for such problems. It took a bit of encouragement &#8211; as well as an acute problem coupled with my absence &#8211; to get two guys to step up to the plate and provide fixes for these two new issues. It seems to me that now many people seem to be aware how easy it is to contribute to some other developer&#8217;s project. So let me summarize the steps right now. How to contribute to Open Source Projects Generally the process to contribute to any open source project on GitHub is really simple once you did it for the first time. you set up git and GitHub you fork a project you want to contribute something &#8211; however small &#8211; to. you clone your fork to your local hard disk you modify your local copy and commit the changes, providing sensible descriptions in the commit messages you push your local clone to your online fork you create a pull request for the original master the owner might require some further changes, he will communicate with you via the pull request. If you respond to such e-mails they will automatically be appended to the conversion further commits you make to the branch you pushed will show up as updates to the pull request finally when the owner is happy he can merge your changes into the master with just one button You can see the individual changes and who made them on the MyAppSales commit history on GitHub. Those are also a great place to learn about how other developers are tackling certain issues. NSAttributedString+HTML Features My other big open source project next to MyAppSales is NSAttributedString+HTML and lately this is gathering more and more steam. In my absence two new pull request were sent, one about adding support for rule-based styles and one to make font creation thread-safe. Since there are several projects with 3.2 support dependent on this we have to keep 3.2 compatibility at least until 5.0 is out. So I had to ask the author of the update to also provide this and he did. After that I could merge it with master. The rule-based styles pull request need a bit further clean-up, so I am waiting for the author to provide that. It&#8217;s always very interesting to eavesdrop on such a commentary exchange. The original author can always decide to ignore a pull request if it is not up to his standards, but if a contributor steers his additions in a path that the maintainer [...]]]></description>
				<content:encoded><![CDATA[<p>I spent last week at several beaches in Corsica and when I came back I figured I would want to prolong the silence of not reading e-mails for one more day. And how peaceful that felt, I can only recommend that. Instead I spent Monday in my hammock an continued reading a Clive Cussler novel.</p>
<p>When I returned to my office on Tuesday I found more than 270 unread e-mails in my inbox. It took me around 4 hours to comb through these with a jackhammer and to trim it down to like a dozen or so that I will have to act upon.</p>
<p><span id="more-5338"></span></p>
<div id="more-5338"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<p>When I got around to perform the first actual work-related action it was that I added my first third-party component to my well-visited <a title="Parts Store" href="http://www.cocoanetics.com/parts-store/">Parts Store</a>.</p>
<h3>Third Party Components in Cocoanetics Parts Store</h3>
<p>The thing that I call the &#8220;Cocoanetics Parts Store&#8221; is basically a feature of my custom-built WordPress template that allows me to add &#8220;Parts&#8221; as one would add &#8220;Pages&#8221;. Ordering is done via e-mail and invoices are created manually as PDFs. Still I see hundreds of people &#8211; developers? &#8211; peruse these pages every day and so I decided a while ago to put an ad on there. With much success, this very ad is the only one that even has somebody on the waiting list.</p>
<p>I figured that with hundred of people stumbling onto Cocoanetics.com every day why not also let them find some really great components that other developers are selling, provided that there is an affiliate system in place that lets me get a cut of purchases being made.</p>
<p><a href="http://www.cocoanetics.com/parts/sensible-tableview/">Sensible TableView</a> is my first such component that I get a share on. If you want to get the same kind of exposure as well, I am happy to provide it if you can furnish me an affiliation.</p>
<h3>MyAppSales Fixes &#8211; Hooray for Open Source</h3>
<p>Next order of business were several problems people had with <strong>MyAppSales</strong> since Apple again tinkered on iTunes Connect. Several countries had been moved to their own regions causing the financial reports for these regions to not show. Also some other change broke downloading of daily and weekly reports.</p>
<p>I had <a title="OpenSource’ing MyAppSales" href="http://www.cocoanetics.com/2011/01/opensourceing-myappsales/">open sourced MyAppSales</a> a while ago for the express reason that well versed developers like the ones using it can contribute fixes for such problems. It took a bit of encouragement &#8211; as well as an acute problem coupled with my absence &#8211; to get two guys to step up to the plate and provide fixes for these two new issues.</p>
<p>It seems to me that now many people seem to be aware how easy it is to contribute to some other developer&#8217;s project. So let me summarize the steps right now.</p>
<h3>How to contribute to Open Source Projects</h3>
<p>Generally the process to contribute to any open source project on GitHub is really simple once you did it for the first time.</p>
<ol>
<li>you set up git and GitHub</li>
<li>you fork a project you want to contribute something &#8211; however small &#8211; to.</li>
<li>you clone your fork to your local hard disk</li>
<li>you modify your local copy and commit the changes, providing sensible descriptions in the commit messages</li>
<li>you push your local clone to your online fork</li>
<li>you create a pull request for the original master</li>
<li>the owner might require some further changes, he will communicate with you via the pull request. If you respond to such e-mails they will automatically be appended to the conversion</li>
<li>further commits you make to the branch you pushed will show up as updates to the pull request</li>
<li>finally when the owner is happy he can merge your changes into the master with just one button</li>
</ol>
<p>You can see the individual changes and who made them on the <a href="https://github.com/Cocoanetics/MyAppSales/commits/master">MyAppSales commit history</a> on GitHub. Those are also a great place to learn about how other developers are tackling certain issues.</p>
<h3>NSAttributedString+HTML Features</h3>
<p>My other big open source project next to <a href="https://github.com/Cocoanetics/MyAppSales">MyAppSales</a> is <a href="https://github.com/Cocoanetics/DTCoreText">NSAttributedString+HTML</a> and lately this is gathering more and more steam. In my absence two new pull request were sent, one about adding support for rule-based styles and one to <a href="https://github.com/Cocoanetics/DTCoreText/pull/63">make font creation thread-safe</a>. Since there are several projects with 3.2 support dependent on this we have to keep 3.2 compatibility at least until 5.0 is out. So I had to ask the author of the update to also provide this and he did. After that I could merge it with master.</p>
<p>The <a href="https://github.com/Cocoanetics/DTCoreText/pull/64">rule-based styles pull request</a> need a bit further clean-up, so I am waiting for the author to provide that. It&#8217;s always very interesting to eavesdrop on such a commentary exchange. The original author can always decide to ignore a pull request if it is not up to his standards, but if a contributor steers his additions in a path that the maintainer likes then magic happens.</p>
<p>This magic is also the reason why I prefer pull requests over patches because there you can actually reap the fame for the code you contributed because you show as author of the added lines for all eternity. Or put differently: the git blame command shows if a future problem stems from a change you made.</p>
<h3>And off again &#8230;</h3>
<p>I had to cut short my first work day after the vacation because stress started creeping back in after 4 hours sitting in front of my iMac. So I put off some other work items that still stand between me and Inbox Zero. Tomorrow is another great day for that.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=5338&amp;md5=26dcdb58311e92e4bbb3840fb571ec5b" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2011/08/back-and-many-news/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2011%2F08%2Fback-and-many-news%2F&amp;language=en_GB&amp;category=text&amp;title=Back+%26%238230%3B+and+Many+News&amp;description=I+spent+last+week+at+several+beaches+in+Corsica+and+when+I+came+back+I+figured+I+would+want+to+prolong+the+silence+of+not+reading+e-mails+for+one+more...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>We&#8217;ll be back soon</title>
		<link>http://www.cocoanetics.com/2011/08/well-be-back-soon-2/</link>
		<comments>http://www.cocoanetics.com/2011/08/well-be-back-soon-2/#comments</comments>
		<pubDate>Sat, 13 Aug 2011 19:27:52 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=5327</guid>
		<description><![CDATA[Seems like everybody is taking some time off in August. So we booked a last-minute vacation as well. There will be no e-mail checking until we get back, so please be patient with your requests and wishes. We&#8217;ll be back at your service on August 23rd.]]></description>
				<content:encoded><![CDATA[<p>Seems like everybody is taking some time off in August. So we booked a last-minute vacation as well. There will be no e-mail checking until we get back, so please be patient with your requests and wishes.</p>
<p><a href="http://i0.wp.com/www.cocoanetics.com/files/backsoon.jpg"><img class="alignnone size-full wp-image-5257" title="back soon" src="http://i0.wp.com/www.cocoanetics.com/files/backsoon.jpg?resize=193%2C167" alt="" data-recalc-dims="1" /></a></p>
<p>We&#8217;ll be back at your service on August 23rd.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=5327&amp;md5=de01dca0df02f83d3e510fc195e238a2" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2011/08/well-be-back-soon-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2011%2F08%2Fwell-be-back-soon-2%2F&amp;language=en_GB&amp;category=text&amp;title=We%26%238217%3Bll+be+back+soon&amp;description=Seems+like+everybody+is+taking+some+time+off+in+August.+So+we+booked+a+last-minute+vacation+as+well.+There+will+be+no+e-mail+checking+until+we+get+back%2C+so+please...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Cocoanetics now with Proper SSL Certificate</title>
		<link>http://www.cocoanetics.com/2011/08/cocoanetics-now-with-proper-ssl-certificate/</link>
		<comments>http://www.cocoanetics.com/2011/08/cocoanetics-now-with-proper-ssl-certificate/#comments</comments>
		<pubDate>Wed, 10 Aug 2011 06:12:55 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=5322</guid>
		<description><![CDATA[Last week I finally gave in and shelled out for a wildcard SSL certificate for *.cocoanetics.com. This means that any address you have been using on this domain via HTTPS has been changed. Previously you where using a self-signed certificate  which cause several problems, amongst those that you could not directly set up my Subversion repos you have access to in Xcode because you needed to first permanently accept the certificate even though it could not be verified. So you had to do the first checkout in terminal. Once accepted it would work in Xcode too. This is no longer the case. To check out code from any repository you no longer have to jump through this hoop. Just so that you know, your convenience is worth $600 to me. Please don&#8217;t smart-ass now how much cheaper a certificate for a single domain would have been, and YES I know that there are companies that give them away for free. I had a look at some, including StartSSL, but most of the free or cheap ones don&#8217;t do wildcards or subdomains Since I have several sites I want to have covered (all on the same web server) I had to go for the wildcard option. If you access a repository which was previously set up with the self-signed cert then you might have to approve the change once more. SVN repository for AntiCrack SVN repositories for all purchasable components To see the change in action just check out anything that you have access to like this, in terminal: svn checkout https://svn.cocoanetics.com/Component/trunk --username User You should see &#8230; that you don&#8217;t see anything. For a self-signed cert you would get a message that the certificate is not trusted asking if you want to accept it temporarily or permanently.]]></description>
				<content:encoded><![CDATA[<p>Last week I finally gave in and shelled out for a wildcard SSL certificate for *.cocoanetics.com. This means that any address you have been using on this domain via HTTPS has been changed.</p>
<p>Previously you where using a self-signed certificate  which cause several problems, amongst those that you could not directly set up my Subversion repos you have access to in Xcode because you needed to first permanently accept the certificate even though it could not be verified. So you had to do the first checkout in terminal. Once accepted it would work in Xcode too.</p>
<p><span id="more-5322"></span></p>
<div id="more-5322"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<p>This is no longer the case. To check out code from any repository you no longer have to jump through this hoop. Just so that you know, your convenience is worth $600 to me. <img src='http://i1.wp.com/www.cocoanetics.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' data-recalc-dims="1" />  Please don&#8217;t smart-ass now how much cheaper a certificate for a single domain would have been, and YES I know that there are companies that give them away for free. I had a look at some, including StartSSL, but most of the free or cheap ones don&#8217;t do wildcards or subdomains</p>
<p>Since I have several sites I want to have covered (all on the same web server) I had to go for the wildcard option. If you access a repository which was previously set up with the self-signed cert then you might have to approve the change once more.</p>
<ul>
<li>SVN repository for <a href="http://www.cocoanetics.com/anticrack">AntiCrack</a></li>
<li>SVN repositories for all <a href="http://www.cocoanetics.com/parts-store">purchasable components</a></li>
</ul>
<p>To see the change in action just check out anything that you have access to like this, in terminal:</p>

<div class="wp_codebox"><table><tr id="p532220"><td class="code" id="p5322code20"><pre class="sh" style="font-family:monospace;">svn checkout https://svn.cocoanetics.com/Component/trunk --username User</pre></td></tr></table></div>

<p>You should see &#8230; that you don&#8217;t see anything. For a self-signed cert you would get a message that the certificate is not trusted asking if you want to accept it temporarily or permanently.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=5322&amp;md5=c3aa56431125df12d87e5b36753f33a7" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2011/08/cocoanetics-now-with-proper-ssl-certificate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2011%2F08%2Fcocoanetics-now-with-proper-ssl-certificate%2F&amp;language=en_GB&amp;category=text&amp;title=Cocoanetics+now+with+Proper+SSL+Certificate&amp;description=Last+week+I+finally+gave+in+and+shelled+out+for+a+wildcard+SSL+certificate+for+%2A.cocoanetics.com.+This+means+that+any+address+you+have+been+using+on+this+domain+via+HTTPS...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>We&#8217;ll be back soon.</title>
		<link>http://www.cocoanetics.com/2011/07/well-be-back-soon/</link>
		<comments>http://www.cocoanetics.com/2011/07/well-be-back-soon/#comments</comments>
		<pubDate>Sun, 10 Jul 2011 07:13:27 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=5256</guid>
		<description><![CDATA[After working full throttle on the scribd app and struggling to keep two more deadlines the past few weeks where really taking their toll. So today begins a week of downtime for me. We &#8211; that&#8217;s me, my wife and our dog &#8211; have rented an apartment and I had to promise not to bring any devices&#8230;. except the iPhone. &#8220;Honey, what if we get lost? I need the maps app to steer us back to civilization!&#8221; You get the picture. See you on the other side.]]></description>
				<content:encoded><![CDATA[<p>After working full throttle on the <a href="http://www.scribd.com">scribd</a> app and struggling to keep two more deadlines the past few weeks where really taking their toll. So today begins a week of downtime for me. We &#8211; that&#8217;s me, my wife and our dog &#8211; have rented an apartment and I had to promise not to bring any devices&#8230;. except the iPhone.</p>
<p><a href="http://i0.wp.com/www.cocoanetics.com/files/backsoon.jpg"><img class="alignnone size-full wp-image-5257" title="back soon" src="http://i0.wp.com/www.cocoanetics.com/files/backsoon.jpg?resize=193%2C167" alt="" data-recalc-dims="1" /></a></p>
<p><em>&#8220;Honey, what if we get lost? I need the maps app to steer us back to civilization!&#8221;</em></p>
<p><em> </em>You get the picture. <img src='http://i1.wp.com/www.cocoanetics.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' data-recalc-dims="1" />  See you on the other side.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=5256&amp;md5=27b4383b976d6be981598d457cc7e62d" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2011/07/well-be-back-soon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2011%2F07%2Fwell-be-back-soon%2F&amp;language=en_GB&amp;category=text&amp;title=We%26%238217%3Bll+be+back+soon.&amp;description=After+working+full+throttle+on+the+scribd+app+and+struggling+to+keep+two+more+deadlines+the+past+few+weeks+where+really+taking+their+toll.+So+today+begins+a+week+of...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>CoreText Loading Performance</title>
		<link>http://www.cocoanetics.com/2011/04/coretext-loading-performance/</link>
		<comments>http://www.cocoanetics.com/2011/04/coretext-loading-performance/#comments</comments>
		<pubDate>Thu, 28 Apr 2011 06:40:17 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=4948</guid>
		<description><![CDATA[Somebody people told me that some function in my NSAttributedStrings+HTML would take forever but whenever I tested it, I could not see anything wrong. Then Stuart Carnie was able to send a snippet of code that, when pasted into appDidFinishLaunching, would exhibit the same problem, duplicatable. I was stumped at first. How could I have missed it? But at second glance Stuart did not reference any of my classes, but was only using standard SDK calls. Yet, those are almost identical to what I had wrapped into DTCoreTextFontDescriptor, my Objective-C wrapper. Then it dawned on me: this might be a lazy loading problem. Or maybe even a bug in CoreText.framework. So I modified Stuart&#8217;s snippet to perform the same test several times, with changing font sizes and font families. - &#40;void&#41;testWithSize:&#40;CGFloat&#41;size family:&#40;NSString *&#41;family &#123; NSLog&#40;@&#34;Start&#34;&#41;; NSMutableDictionary *attributes = &#91;NSMutableDictionary dictionary&#93;; &#91;attributes setObject:family forKey:&#40;id&#41;kCTFontFamilyNameAttribute&#93;; &#91;attributes setObject:&#91;NSNumber numberWithFloat:size&#93; forKey:&#40;id&#41;kCTFontSizeAttribute&#93;; CTFontDescriptorRef fontDesc = CTFontDescriptorCreateWithAttributes&#40;&#40;CFDictionaryRef&#41;attributes&#41;; CTFontRef matchingFont = CTFontCreateWithFontDescriptor&#40;fontDesc, size, NULL&#41;; CFRelease&#40;matchingFont&#41;; CFRelease&#40;fontDesc&#41;; NSLog&#40;@&#34;Finish&#34;&#41;; &#125; &#160; - &#40;BOOL&#41;application:&#40;UIApplication *&#41;application didFinishLaunchingWithOptions:&#40;NSDictionary *&#41;launchOptions &#123; &#91;self testWithSize:10 family:@&#34;Courier New&#34;&#93;; &#91;self testWithSize:20 family:@&#34;Georgia&#34;&#93;; &#91;self testWithSize:30 family:@&#34;Helvetica&#34;&#93;; // ... &#125; On my iPhone 4 the first test took 1284 ms, the second improved dramatically to 39 ms and the last one to only 13 ms. Clearly the very first time you are accessing a CTFontDescriptor function this causes the CoreText dynamic framework to be loaded and initialized. By extension this probably means that you would see the same problem for ANY CoreText function. Subsequent calls are as fast as you would expect them to be. Though Stuart comes to a slightly different conclusion than me: I am fairly confident it is not a dynamic lib loading issue, because the first API call to CoreText (CTFontDescriptorCreateWithAttributes) is not slow.  When I profiled into core text, it is a lot of code running in freetype library. This also explains why I was not seeing the problem myself. Because of the way the demo is structured this loading would occur during the first table view cell of the demo list was drawn. And since this was the first visible view in the demo app this would delay presentation of the UI. Stuart and me filed bug reports: 9350255 and 9350318 respectively. If you are affected by this problem too, then I encourage you to reference these two Radars in your own bug report. Now for a workaround Stuart proposes to use a background dispatch queue to force loading of the CoreText.framework without affecting either app startup or first use. dispatch_queue_t queue = dispatch_queue_create&#40;&#34;com.swatch.worker&#34;, NULL&#41;; dispatch_async&#40;queue, ^&#40;void&#41; &#123; NSMutableDictionary *attributes = &#91;NSMutableDictionary dictionary&#93;; &#91;attributes setObject:@&#34;Helvetica&#34; forKey:&#40;id&#41;kCTFontFamilyNameAttribute&#93;; &#91;attributes setObject:&#91;NSNumber numberWithFloat:36.0f&#93; forKey:&#40;id&#41;kCTFontSizeAttribute&#93;; CTFontDescriptorRef fontDesc = CTFontDescriptorCreateWithAttributes&#40;&#40;CFDictionaryRef&#41;attributes&#41;; CTFontRef matchingFont = CTFontCreateWithFontDescriptor&#40;fontDesc, 36.0f, NULL&#41;; CFRelease&#40;matchingFont&#41;; CFRelease&#40;fontDesc&#41;; &#125;&#41;; dispatch_release&#40;queue&#41;; This kind of collaboration with talented people like Stuart is exactly why I OpenSourced this project. Thanks to Stuart we were able to corner the problem! It&#8217;s always great to know that it&#8217;s not your code that is the issue, but a performance problem in a public framework is to blame.]]></description>
				<content:encoded><![CDATA[<p>Somebody people <a href="https://github.com/Cocoanetics/DTCoreText/issues/19">told me</a> that some function in my NSAttributedStrings+HTML would take forever but whenever I tested it, I could not see anything wrong. Then <a href="http://www.cocoapedia.org/wiki/Stuart_Carnie">Stuart Carnie</a> was able to send a snippet of code that, when pasted into appDidFinishLaunching, would exhibit the same problem, duplicatable.</p>
<p>I was stumped at first. How could I have missed it? But at second glance Stuart did not reference any of my classes, but was only using standard SDK calls. Yet, those are almost identical to what I had wrapped into DTCoreTextFontDescriptor, my Objective-C wrapper.</p>
<p>Then it dawned on me: this might be a lazy loading problem. Or maybe even a bug in CoreText.framework.</p>
<p><span id="more-4948"></span></p>
<div id="more-4948"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<p>So I modified Stuart&#8217;s snippet to perform the same test several times, with changing font sizes and font families.</p>

<div class="wp_codebox"><table><tr id="p494824"><td class="code" id="p4948code24"><pre class="objc" style="font-family:monospace;"><span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span>testWithSize<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>CGFloat<span style="color: #002200;">&#41;</span>size family<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/"><span style="color: #400080;">NSString</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>family
<span style="color: #002200;">&#123;</span>
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Start&quot;</span><span style="color: #002200;">&#41;</span>;
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/"><span style="color: #400080;">NSMutableDictionary</span></a> <span style="color: #002200;">*</span>attributes <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/"><span style="color: #400080;">NSMutableDictionary</span></a> dictionary<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>attributes setObject<span style="color: #002200;">:</span>family forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kCTFontFamilyNameAttribute<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>attributes setObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/"><span style="color: #400080;">NSNumber</span></a> numberWithFloat<span style="color: #002200;">:</span>size<span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kCTFontSizeAttribute<span style="color: #002200;">&#93;</span>;
    CTFontDescriptorRef fontDesc <span style="color: #002200;">=</span> CTFontDescriptorCreateWithAttributes<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CFDictionaryRef<span style="color: #002200;">&#41;</span>attributes<span style="color: #002200;">&#41;</span>;
    CTFontRef matchingFont <span style="color: #002200;">=</span> CTFontCreateWithFontDescriptor<span style="color: #002200;">&#40;</span>fontDesc, size, <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>;
    CFRelease<span style="color: #002200;">&#40;</span>matchingFont<span style="color: #002200;">&#41;</span>;
    CFRelease<span style="color: #002200;">&#40;</span>fontDesc<span style="color: #002200;">&#41;</span>;
    NSLog<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Finish&quot;</span><span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span>
&nbsp;
<span style="color: #002200;">-</span> <span style="color: #002200;">&#40;</span><span style="color: #a61390;">BOOL</span><span style="color: #002200;">&#41;</span>application<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span>UIApplication <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>application didFinishLaunchingWithOptions<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSDictionary_Class/"><span style="color: #400080;">NSDictionary</span></a> <span style="color: #002200;">*</span><span style="color: #002200;">&#41;</span>launchOptions
<span style="color: #002200;">&#123;</span>
    <span style="color: #002200;">&#91;</span>self testWithSize<span style="color: #002200;">:</span><span style="color: #2400d9;">10</span> family<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Courier New&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self testWithSize<span style="color: #002200;">:</span><span style="color: #2400d9;">20</span> family<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Georgia&quot;</span><span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>self testWithSize<span style="color: #002200;">:</span><span style="color: #2400d9;">30</span> family<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Helvetica&quot;</span><span style="color: #002200;">&#93;</span>;
<span style="color: #11740a; font-style: italic;">// ...</span>
<span style="color: #002200;">&#125;</span></pre></td></tr></table></div>

<p>On my iPhone 4 the first test took 1284 ms, the second improved dramatically to 39 ms and the last one to only 13 ms. Clearly the very first time you are accessing a CTFontDescriptor function this causes the CoreText dynamic framework to be loaded and initialized.</p>
<p>By extension this probably means that you would see the same problem for ANY CoreText function. Subsequent calls are as fast as you would expect them to be. Though Stuart comes to a slightly different conclusion than me:</p>
<blockquote><p>I am fairly confident it is not a dynamic lib loading issue,<br />
because the first API call to CoreText (CTFontDescriptorCreateWithAttributes)<br />
is not slow.  When I profiled into core text, it is a lot of code running in<br />
freetype library.</p></blockquote>
<p>This also explains why I was not seeing the problem myself. Because of the way the demo is structured this loading would occur during the first table view cell of the demo list was drawn. And since this was the first visible view in the demo app this would delay presentation of the UI.</p>
<p>Stuart and me filed bug reports: <a href="rdar://9350255">9350255</a> and <a href="rdar://9350318">9350318</a> respectively. If you are affected by this problem too, then I encourage you to reference these two Radars in your own bug report.</p>
<p>Now for a workaround Stuart <a href="https://gist.github.com/945862">proposes</a> to use a background dispatch queue to force loading of the CoreText.framework without affecting either app startup or first use.</p>

<div class="wp_codebox"><table><tr id="p494825"><td class="code" id="p4948code25"><pre class="objc" style="font-family:monospace;">dispatch_queue_t queue <span style="color: #002200;">=</span> dispatch_queue_create<span style="color: #002200;">&#40;</span><span style="color: #bf1d1a;">&quot;com.swatch.worker&quot;</span>, <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>;
dispatch_async<span style="color: #002200;">&#40;</span>queue, <span style="color: #002200;">^</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">void</span><span style="color: #002200;">&#41;</span> <span style="color: #002200;">&#123;</span>
    <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/"><span style="color: #400080;">NSMutableDictionary</span></a> <span style="color: #002200;">*</span>attributes <span style="color: #002200;">=</span> <span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/"><span style="color: #400080;">NSMutableDictionary</span></a> dictionary<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>attributes setObject<span style="color: #002200;">:</span><span style="color: #bf1d1a;">@</span><span style="color: #bf1d1a;">&quot;Helvetica&quot;</span> forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kCTFontFamilyNameAttribute<span style="color: #002200;">&#93;</span>;
    <span style="color: #002200;">&#91;</span>attributes setObject<span style="color: #002200;">:</span><span style="color: #002200;">&#91;</span><a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/"><span style="color: #400080;">NSNumber</span></a> numberWithFloat<span style="color: #002200;">:</span>36.0f<span style="color: #002200;">&#93;</span> forKey<span style="color: #002200;">:</span><span style="color: #002200;">&#40;</span><span style="color: #a61390;">id</span><span style="color: #002200;">&#41;</span>kCTFontSizeAttribute<span style="color: #002200;">&#93;</span>;
    CTFontDescriptorRef fontDesc <span style="color: #002200;">=</span> CTFontDescriptorCreateWithAttributes<span style="color: #002200;">&#40;</span><span style="color: #002200;">&#40;</span>CFDictionaryRef<span style="color: #002200;">&#41;</span>attributes<span style="color: #002200;">&#41;</span>;
    CTFontRef matchingFont <span style="color: #002200;">=</span> CTFontCreateWithFontDescriptor<span style="color: #002200;">&#40;</span>fontDesc, 36.0f, <span style="color: #a61390;">NULL</span><span style="color: #002200;">&#41;</span>;
    CFRelease<span style="color: #002200;">&#40;</span>matchingFont<span style="color: #002200;">&#41;</span>;
    CFRelease<span style="color: #002200;">&#40;</span>fontDesc<span style="color: #002200;">&#41;</span>;
<span style="color: #002200;">&#125;</span><span style="color: #002200;">&#41;</span>;
dispatch_release<span style="color: #002200;">&#40;</span>queue<span style="color: #002200;">&#41;</span>;</pre></td></tr></table></div>

<p>This kind of collaboration with talented people like Stuart is exactly why I OpenSourced this project. Thanks to Stuart we were able to corner the problem!</p>
<p>It&#8217;s always great to know that it&#8217;s not your code that is the issue, but a performance problem in a public framework is to blame.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=4948&amp;md5=e2402cab91c311e819b3f2e64375159c" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2011/04/coretext-loading-performance/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2011%2F04%2Fcoretext-loading-performance%2F&amp;language=en_GB&amp;category=text&amp;title=CoreText+Loading+Performance&amp;description=Somebody+people+told+me+that+some+function+in+my+NSAttributedStrings%2BHTML+would+take+forever+but+whenever+I+tested+it%2C+I+could+not+see+anything+wrong.+Then+Stuart+Carnie+was+able+to...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Cocoanetics Portal 2 Raffle</title>
		<link>http://www.cocoanetics.com/2011/04/cocoanetics-portal-2-raffle/</link>
		<comments>http://www.cocoanetics.com/2011/04/cocoanetics-portal-2-raffle/#comments</comments>
		<pubDate>Mon, 11 Apr 2011 06:20:11 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=4865</guid>
		<description><![CDATA[Fans of this blog and twitter followers alike will have a chance to get a free copy of Portal 2 on Steam. This highly anticipated game will be released on April 19th, round about the time when @Cocoanetics will surpass 2500 followers on Twitter. When I went to Steam to pre-order my copy I saw an offer to buy two copies and give one away. So I thought that this might be a nice way to say &#8220;thank you!&#8221; for you being a frequent visitor to my blog and for following me on twitter. To participate all you need to do is tweet the following text. On April 19th I will have tweetaways select a random winner from all the ones who tweeted the correct phrase. Portal 2 Giveaway by @cocoanetics (BTW a great source for iOS dev info): http://bit.ly/g5nsKG #raffle Good Luck!]]></description>
				<content:encoded><![CDATA[<p><img class="size-full wp-image-4866 alignright" title="Portal 2 Logo" src="http://i2.wp.com/www.cocoanetics.com/files/Screen-shot-2011-04-11-at-8.00.03-AM.png?resize=292%2C135" alt="" data-recalc-dims="1" />Fans of this blog and twitter followers alike will have a chance to get a free copy of <strong>Portal 2</strong> on Steam. This highly anticipated game will be released on April 19th, round about the time when <a href="http://twitter.com/cocoanetics">@Cocoanetics</a> will surpass 2500 followers on Twitter.</p>
<p>When I went to Steam to pre-order my copy I saw an offer to buy two copies and give one away. So I thought that this might be a nice way to say &#8220;thank you!&#8221; for you being a frequent visitor to my blog and for following me on twitter.</p>
<p>To participate all you need to do is tweet the following text. On April 19th I will have <a href="http://tweetaways.com/">tweetaways</a> select a random winner from all the ones who tweeted the correct phrase.</p>
<blockquote><p>Portal 2 Giveaway by @cocoanetics (BTW a great source for iOS dev info): http://bit.ly/g5nsKG #raffle</p></blockquote>
<p>Good Luck!</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=4865&amp;md5=fa37ab4fe8558e3899675b48aedeaeaa" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2011/04/cocoanetics-portal-2-raffle/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2011%2F04%2Fcocoanetics-portal-2-raffle%2F&amp;language=en_GB&amp;category=text&amp;title=Cocoanetics+Portal+2+Raffle&amp;description=Fans+of+this+blog+and+twitter+followers+alike+will+have+a+chance+to+get+a+free+copy+of+Portal+2+on+Steam.+This+highly+anticipated+game+will+be+released+on...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>San Francisco, here I come!</title>
		<link>http://www.cocoanetics.com/2011/03/san-francisco-here-i-come/</link>
		<comments>http://www.cocoanetics.com/2011/03/san-francisco-here-i-come/#comments</comments>
		<pubDate>Sat, 12 Mar 2011 05:11:21 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=4789</guid>
		<description><![CDATA[I&#8217;ve been hired by scribd to help jumpstart one of their iOS-related projects. That means I&#8217;ll soon grab my bags and hop onto a train that brings me to Vienna from where my plane leaves early morning Saturday, March 12th. I will be flying via London Heathrow to San Francisco where two busy work weeks are awaiting me. I am mentioning this for some reasons, obvious and less obvious ones. Of course I like to gloat a bit, but I am also mentioning my trip because it might cause extensive delays when responding to your e-mails. Just how does one land such a gig? I can only assume that my online activities and networking have played a role. This includes my educational articles from which people might deduct that I am serious about Cocoa. It also includes my open source projects, one might think that CoreText might be one of the technologies that scribd has a vested interest in. It&#8217;s the second time that I visit San Francisco, the first time that I am aware of Apple&#8217;s HQ being near. If you have some recommendations for a visiting iOS developer like myself, let me know. I will have free WiFi at the Hilton where I&#8217;m booked into. But I wonder: is there some kind of prepaid micro-SIM that one could get for a 2 week stay in the US that would give me a bit of voice and a bit of data. Just enough to use Google Maps or other connected apps while being out and about the town? Also, how would one approach visiting the mothership at Cupertino? It&#8217;s about an hour by car and like 3 hours by bus&#8230; should I maybe get a rental car? Or better to hook up with local talent? Speaking of which&#8230; is there any? I&#8217;ve been tweeting about my visit for several days now, but only one mentioned he is local to SF.]]></description>
				<content:encoded><![CDATA[<p>I&#8217;ve been hired by <a href="http://www.scribd.com/">scribd</a> to help jumpstart one of their iOS-related projects. That means I&#8217;ll soon grab my bags and hop onto a train that brings me to Vienna from where my plane leaves early morning Saturday, March 12th. I will be flying via London Heathrow to San Francisco where two busy work weeks are awaiting me.</p>
<p>I am mentioning this for some reasons, obvious and less obvious ones. Of course I like to gloat a bit, but I am also mentioning my trip because it might cause extensive delays when responding to your e-mails.</p>
<p>Just how does one land such a gig? I can only assume that my online activities and networking have played a role. This includes my educational articles from which people might deduct that I am serious about Cocoa. It also includes my open source projects, one might think that CoreText might be one of the technologies that scribd has a vested interest in.</p>
<p><span id="more-4789"></span></p>
<div id="more-4789"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<p>It&#8217;s the second time that I visit San Francisco, the first time that I am aware of Apple&#8217;s HQ being near. If you have some recommendations for a visiting iOS developer like myself, let me know.</p>
<p>I will have free WiFi at the Hilton where I&#8217;m booked into. But I wonder: is there some kind of prepaid micro-SIM that one could get for a 2 week stay in the US that would give me a bit of voice and a bit of data. Just enough to use Google Maps or other connected apps while being out and about the town?</p>
<p>Also, how would one approach visiting the mothership at Cupertino? It&#8217;s about an hour by car and like 3 hours by bus&#8230; should I maybe get a rental car? Or better to hook up with local talent? Speaking of which&#8230; is there any? I&#8217;ve been tweeting about my visit for several days now, but only one mentioned he is local to SF.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=4789&amp;md5=e14ab0b4873dd3282935da6d0a5bdb25" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2011/03/san-francisco-here-i-come/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2011%2F03%2Fsan-francisco-here-i-come%2F&amp;language=en_GB&amp;category=text&amp;title=San+Francisco%2C+here+I+come%21&amp;description=I%26%238217%3Bve+been+hired+by+scribd+to+help+jumpstart+one+of+their+iOS-related+projects.+That+means+I%26%238217%3Bll+soon+grab+my+bags+and+hop+onto+a+train+that+brings+me+to+Vienna...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>You Can Thank Me</title>
		<link>http://www.cocoanetics.com/2011/03/you-can-thank-me/</link>
		<comments>http://www.cocoanetics.com/2011/03/you-can-thank-me/#comments</comments>
		<pubDate>Fri, 04 Mar 2011 14:27:05 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=4743</guid>
		<description><![CDATA[You might have stumbled upon my site because of the variety of iOS development topics I am covering. I generally try to make any interesting thing I&#8217;m learning myself into an educational blog post. There are the things I stumble upon myself, those I document in the Recipes section. And whenever somebody sends me a question I try to answer it with code, examples and so that both our knowledge increases. Let me summarize the ways how you can express your gratitude. There is a variety of options you have and if you make use of them I will be happy. Which in turn causes me to write more. Win-Win. I understand that you probably don&#8217;t have an inclination to just send me money on PayPal. Here are 10 methods that you can use to build up some good karma. 1. Link to my articles If you find an article enlightening then you should link to it on your blog or tell your colleagues about it. Search traffic is in part based on the concept of authority. The more people link to a page the more authority Google thinks this page has. A site like my own lives from the traffic it gets. Yours as well as thousands of other developers who pop by every day. On February 22nd my unique visitors peaked at 1772, my article on In-App Subscriptions caused a bit of controversy. From this tendency of increasing traffic as well as comments made to my articles the consensus appears to be a favorable one. Interesting to see that people seem to prefer coming to me on weekdays. Checking the keywords that this &#8211; mostly organic &#8211; traffic is coming from we see a variety of topics that I wrote about, first and foremost how to make a Pull-To-Reload TableView. I also love to see how more and more people are referencing my posts when answering questions on Stack Overflow or the iPhone Dev SDK forums. 2. Follow me on Twitter The concept of authority can also seen at work on Twitter. Just recently I split my iOS development utterings @Cocoanetics from my German language personal tweets @OliverDrobnik. This way you won&#8217;t ever see me tweet about personal issues, but are guaranteed to see tweets and retweets that are relevant to the iOS and Mac universe. Of course I get spam followers, but generally I am followed by tweeps who are interested in iOS development. Take for example Christopher Oxley, a 26yr old iPhone app developer . Or Guy Couture, Vice-president of DCEsolutions. Or Marouen Ben Moussa who is iOS Software Engineer at Proxymit. Those are just three that mentioned their iOS passion in their twitter profile and followed me just now. By following me as well you will be part of a greater social network comprised of really smart company. And once you followed me be sure to recommend the same to your followers as well. Follow Friday was invented for this purpose. And of course my network is also available for you to crowd-source information or resources. If you tweet something funny or interesting nudge me to retweet it if I have not done so already. 3. Flattr me In the past some people sent me donations to my PayPal account (same as my e-mail address), but generally this is the exception. Being self-employed and really busy makes me sufficient money to live from. So you probably assume that I would not appreciate any small donation you might be able to make. That&#8217;s why Flattr was invented. Flattr is a play on the words Flatrate and &#8220;to flatter somebody&#8221;. It&#8217;s a small European company that makes it possible for you to do micropayments for a variety of things, mostly well written articles and blogs. The idea is that &#8211; if you like what you read &#8211; you find the nearest Flattr button and click on this. At the end of the month your &#8220;means&#8221; will be evenly divided (minus 10% fee for Flattr themselves) amongst all the articles you clicked on. The minimum amount for your monthly means is two Euros. You can add to your balance every time you like and set a slider to what monthly amount should be taken from your balance for these flattr&#8217;ing means. Also just recently Flattr introduced subscriptions which is automatic the process of flattr&#8217;ing multiple times over several months. If you click on a flattr button once it counts only for the current month. If you click a second time you can choose to have flattr repeat this click on the subsequent months. From this screenshot of my Flattr dashboard you see that so far I am earning between 2 and 4 Euros per month from people flattr&#8217;ing my articles. At the same time I have a subscription for the Cocoaheads [...]]]></description>
				<content:encoded><![CDATA[<p>You might have stumbled upon my site because of the variety of iOS development topics I am covering. I generally try to make any interesting thing I&#8217;m learning myself into an educational blog post. There are the things I stumble upon myself, those I document in the <a href="http://www.cocoanetics.com/category/recipes/">Recipes</a> section. And whenever somebody <a href="mailto:oliver@drobnik.com?subject=Question">sends me a question</a> I try to answer it with code, examples and so that both our knowledge increases.</p>
<p>Let me summarize the ways how you can express your gratitude. There is a variety of options you have and if you make use of them I will be happy. Which in turn causes me to write more. Win-Win.</p>
<p><span id="more-4743"></span></p>
<div id="more-4743"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<p>I understand that you probably don&#8217;t have an inclination to just send me money on PayPal. Here are 10 methods that you can use to build up some good karma.</p>
<h3>1. Link to my articles</h3>
<p>If you find an article enlightening then you should link to it on your blog or tell your colleagues about it.</p>
<p>Search traffic is in part based on the concept of authority. The more people link to a page the more authority Google thinks this page has.</p>
<p>A site like my own lives from the traffic it gets. Yours as well as thousands of other developers who pop by every day. On February 22nd my unique visitors peaked at 1772, my <a title="Apple Subscriptions" href="http://www.cocoanetics.com/2011/02/apple-subscriptions/">article on In-App Subscriptions</a> caused a bit of controversy.</p>
<p>From this tendency of increasing traffic as well as comments made to my articles the consensus appears to be a favorable one. Interesting to see that people seem to prefer coming to me on weekdays.</p>
<p><img title="Google Analytics Feb 2011" src="http://i1.wp.com/www.cocoanetics.com/files/Screen-shot-2011-03-04-at-11.45.18-AM.png?resize=663%2C119" alt="" data-recalc-dims="1" /></p>
<p>Checking the keywords that this &#8211; mostly organic &#8211; traffic is coming from we see a variety of topics that I wrote about, first and foremost how to make a <a title="How to make a Pull-To-Reload TableView just like Tweetie 2" href="http://www.cocoanetics.com/2009/12/how-to-make-a-pull-to-reload-tableview-just-like-tweetie-2/">Pull-To-Reload TableView</a>.</p>
<p>I also love to see how more and more people are referencing my posts when answering questions on Stack Overflow or the iPhone Dev SDK forums.</p>
<h3>2. Follow me on Twitter</h3>
<p>The concept of authority can also seen at work on Twitter. Just recently I split my iOS development utterings <a href="http://twitter.com/cocoanetics" target="_blank">@Cocoanetics</a> from my German language personal tweets <a href="http://twitter.com/OliverDrobnik" target="_blank">@OliverDrobnik</a>. This way you won&#8217;t ever see me tweet about personal issues, but are guaranteed to see tweets and retweets that are relevant to the iOS and Mac universe.</p>
<p>Of course I get spam followers, but generally I am followed by tweeps who are interested in iOS development. Take for example <a href="http://twitter.com/ThisIsChrisO" target="_blank">Christopher Oxley</a>, a 26yr old iPhone app developer . Or <a href="http://twitter.com/gcouture" target="_blank">Guy Couture</a>, Vice-president of DCEsolutions. Or <a href="http://twitter.com/marouen_bm" target="_blank">Marouen Ben Moussa</a> who is iOS Software Engineer at Proxymit. Those are just three that mentioned their iOS passion in their twitter profile and followed me just now.</p>
<p><img class="alignnone size-full wp-image-4746" title="Twitter Follower Stats" src="http://i2.wp.com/www.cocoanetics.com/files/Screen-shot-2011-03-04-at-1.33.06-PM.png?resize=714%2C260" alt="" data-recalc-dims="1" /></p>
<p>By following me as well you will be part of a greater social network comprised of really smart company. And once you followed me be sure to recommend the same to your followers as well. Follow Friday was invented for this purpose.</p>
<p>And of course my network is also available for you to crowd-source information or resources. If you tweet something funny or interesting nudge me to retweet it if I have not done so already.</p>
<h3>3. Flattr me</h3>
<p>In the past some people sent me donations to my PayPal account (same as my e-mail address), but generally this is the exception. Being self-employed and really busy makes me sufficient money to live from. So you probably assume that I would not appreciate any small donation you might be able to make. That&#8217;s why Flattr was invented.</p>
<p>Flattr is a play on the words Flatrate and &#8220;to flatter somebody&#8221;. It&#8217;s a small European company that makes it possible for you to do micropayments for a variety of things, mostly well written articles and blogs. The idea is that &#8211; if you like what you read &#8211; you find the nearest Flattr button and click on this.</p>
<p>At the end of the month your &#8220;means&#8221; will be evenly divided (minus 10% fee for Flattr themselves) amongst all the articles you clicked on. The minimum amount for your monthly means is two Euros. You can add to your balance every time you like and set a slider to what monthly amount should be taken from your balance for these flattr&#8217;ing means.</p>
<p>Also just recently Flattr introduced subscriptions which is automatic the process of flattr&#8217;ing multiple times over several months. If you click on a flattr button once it counts only for the current month. If you click a second time you can choose to have flattr repeat this click on the subsequent months.</p>
<p><a href="http://i1.wp.com/www.cocoanetics.com/files/Screen-shot-2011-03-04-at-1.53.24-PM.png"><img class="alignnone size-full wp-image-4747" title="Flattr Dashboard" src="http://i1.wp.com/www.cocoanetics.com/files/Screen-shot-2011-03-04-at-1.53.24-PM.png?resize=700%2C771" alt="" data-recalc-dims="1" /></a></p>
<p>From this screenshot of my Flattr dashboard you see that so far I am earning between 2 and 4 Euros per month from people flattr&#8217;ing my articles. At the same time I have a subscription for the <a href="http://www.cocoaheads.at" target="_blank">Cocoaheads Austria</a> homepage. So if I don&#8217;t click on any other Flattr buttons my entire 2 Euros will go to them automatically.</p>
<h3>4. Advertise on Cocoanetics.com</h3>
<p>I can never hope to achieve a significant income through ads alone. But I can use the ad revenue to offset the cost of my server, approximately 60 Euros per month. Those banners you see on the site from Google AdSense average around 8-10 Euros per month, so that&#8217;s why for January and February I experimented with finding sponsors willing to pay me a bit more than that.</p>
<p>Your choice of ad spots are:</p>
<p><strong>Location:</strong> Frontpage<br />
<strong>Stats:</strong> seen by 10% of overall visitors<br />
<strong>Size: </strong>Block 300 x 300<br />
<strong>Note:</strong> this replaced the entire block including the extra text on the lower right site</p>
<p><strong>Location: </strong>Blog Article List, 2 Slots after first and second article (part before MORE tag) repeated on each page<br />
<strong>Stats: </strong>seen by 5% of overall visitors<br />
<strong>Size: </strong>Banner  728 x 90</p>
<p><strong>Location: </strong>All Individual Articles, at the location where the MORE tag.<br />
<strong>Stats: </strong>depend on popularity of article, e.g. my multitasking article gets 5% of daily visitors<br />
<strong>Size:</strong> Banner 728 x 90<br />
<strong>Note: </strong>Currently these are inserted manually, they are spread around popular articles. Development is done to automate in about 1 week.</p>
<p><strong>Location:</strong> Specific Articles that you think match your offerings really well can be selected manually as well as the position in the article.<br />
<strong>Size:</strong> Banner 728 x 90</p>
<p>One such sponsor was the maker of the <a href="http://itunes.apple.com/at/app/cyberspace/id403114491?mt=8" target="_blank">Cyberspace web browser</a> for iPad/iPhone. With the help of Google Analytics we saw that his payment got him 67 click-throughs at 0.29 Euro each. Not bad for an app that costs $3. Now imagine what conversion rate you might get for YOUR service or product if it is in the least relevant for iOS developers.</p>
<p><img title="Cyberspace App Click-throughs" src="http://i2.wp.com/www.cocoanetics.com/files/Screen-shot-2011-03-04-at-2.05.02-PM.png?resize=809%2C127" alt="" data-recalc-dims="1" /></p>
<p>I have several spots available and the only wish I have is that together I can achieve to have my server paid for. I have not set sponsoring rate, just make me an offer. There&#8217;s not exactly a queue. If you see Google ads in a spot then that&#8217;s because nobody is in front of you.</p>
<h3>5. Let&#8217;s affiliate</h3>
<p>I&#8217;d love to have more affiliations. Generally if I am using somebody&#8217;s product or services I&#8217;d love to be sending them additional business. The easiest way for me to do that is if you have an affiliate link for me. Have a look at the footer of every page. Right now there&#8217;s an affiliate link for Dropbox and Mobfox, both services that I use white a bit. Thus the affiliation.</p>
<p>From <a href="http://db.tt/pUYczl6" target="_blank">Dropbox</a> I&#8217;m getting more free storage with every sign-up. I use that quite a bit to share project files with customers and also for certain kinds of backup scenarios. What&#8217;s also great is that via Dropbox I can get to my files on Mac, PC, MacBook, iPhone, iPad and even from Linux.</p>
<p><a href="http://bit.ly/mobfox" target="_blank">MobFox</a> on the other hand is a new Ad network based in Vienna, Austria which pays an order of magnitude more than AdMob. I built their SDK and that&#8217;s why I added support for it to DTBannerManager. If you sign up with MobFox via this link then I&#8217;ll get a small percentage of your ad earnings.</p>
<p>In both cases I consider it a thank you if you visit my affiliates via these links. That&#8217;s one way of thanking me.</p>
<p>The other would be to have a service that&#8217;s relevant for us iOS developers and make me your affiliate with similar benefits as these two examples.</p>
<h3>6. Review my apps</h3>
<p>I&#8217;ve given up on trying to get blogs to write about my work long time ago. So I have a big pile of promo codes for every app of mine and this pile is getting bigger with each new version I release.</p>
<p>If you have a blog &#8211; however small &#8211; then just ask me about a promo code and you will get one. If you don&#8217;t have a blog, then you can still have a promo code if you promise to post a review on iTunes. I have to rely on your honor in this case! Many people asked me for a code but never got around to actually stating their opinion on iTunes.</p>
<p>Hey, I won&#8217;t mind, even if you give me work less than 5 stars. If that&#8217;s the truth and my app sucks than I will see it as a nudge to go back to the drawing board and improve it. On the other hand, receiving a response like this is what makes me smile.</p>
<blockquote><p>My dad owns leaflet business and I occasionally help at weekends, I have been using the breadcrumbs section of the app to track what streets i have been down and have noticed it is very accurate in recording where I have been while doing this I can periodically upload my data to my google account with ease and retrieve this information<br />
The app is very well thought out and has been a big help to me and I will continue to use this app.<br />
- <a href="http://www.cocoapedia.org/wiki/Jonathan_Heald" target="_blank">Jonathan Heald</a></p></blockquote>
<p>This review is really cool because it shows an unexpected use of my utility app <a href="http://www.cocoanetics.com/apps/geocorder/" target="_blank">GeoCorder</a>. But it does not have to use as many words, check out this other review. You don&#8217;t have to understand Italian to know that this is something favorable:</p>
<blockquote><p>Ottima applicazione!!<br />
- Riccardo Rossi</p></blockquote>
<p>Here&#8217;s another example of a good review, for <a href="http://www.cocoanetics.com/apps/speakerclock/" target="_blank">SpeakerClock</a>.</p>
<blockquote><p>I use this a lot when I teach or speak. Helps me keep the time and looks great at the same time. Educator must-have.<br />
- Chris Marquardt</p></blockquote>
<p>Leaving reviews on iTunes is in a way similar to what I wrote about about authority in web pages and about linking to my articles. If something is liked then I know that I am the right track. If something is missing then I know what to put more value on once I have some time to further development on this app.</p>
<p>In general I just love to hear your comments, because it tells you that you care about my work. Here&#8217;s the most amazing testimonial, ever. Accompanied by a photo.</p>
<blockquote><p>So cool! We&#8217;re all playing with your app in the TED office. Here&#8217;s<br />
TED&#8217;s June Cohen and Chris Anderson.</p></blockquote>
<p><a href="http://i1.wp.com/www.cocoanetics.com/files/TED_using_SpeakerClock.jpg"><img src="http://i1.wp.com/www.cocoanetics.com/files/TED_using_SpeakerClock.jpg?resize=500%2C375" alt="" data-recalc-dims="1" /></a></p>
<p>If you didn&#8217;t know, <a href="http://en.wikipedia.org/wiki/Chris_Anderson_(TED)">Chris Anderson</a> is the curator of the TED Conference and <a href="http://en.wikipedia.org/wiki/June_Cohen">June Cohen</a> the Executive Producer of TED Media.</p>
<p>You don&#8217;t have to be famous, your opinion is valuable even if you are not.</p>
<h3>7. Comment</h3>
<p>Speaking about your opinions and insights&#8230; I am just human and I cannot know everything. For the most part I am just slightly ahead of you because I&#8217;ve been developing the iOS platform since the first SDK came out and full-time for slightly more than a year.</p>
<p>Feel free to let me know about omissions or factual errors in my posts and tweets. If you have something to contribute then do so below the article that it belongs to. The advantage for you is that your comment is seen by thousands of other developers and if it is a good one then this will add to your reputation just the same.</p>
<p>If you have a blog you can also comment there in the form of a new article referencing mine. Modern blog engines like WordPress will ping my blog and this ping will show as inbound link next to the comments.</p>
<h3>8. Cocoapedia.org</h3>
<p>This is a hobby of mine, sort of a Wikipedia for facts which are of interest to the Cocoa/Mac/iOS body of knowledge. I consider it a favor if you add yourself to the Wiki and give some interesting facts. I&#8217;m also looking for volunteers to patrol new entries and add stubs for people, companies, conferences and books that fit in there.</p>
<p>Lately there where a couple of spam entries which showed even more the need of a few more admins. If you have a bit of a journalistic tendency then join me in procuring Cocoa facts. The idea is to have a place for all the knowledge that is not sufficiently relevant for Wikipedia, but highly relevant for us Cocoa developers.</p>
<p>By volunteering on Cocoapedia you can definitely get on my good side. The simplest activities you can do are:</p>
<ul>
<li>make an article for yourself</li>
<li>look at the recent changes and remove files and articles that are spam</li>
<li>add stubs for other developers, or Cocoa facts</li>
<li>link to Cocoapedia articles in your own blog posts so that your readers can quickly get facts about people or companies you mention</li>
</ul>
<p>Cocoapedia is using the MediaWiki engine which also powers Wikipedia. So by learning your way around Cocoapedia you also learn how to create and edit Wikipedia articles. Not a bad thing to have on your CV, I think.</p>
<h3>9. Open Source Social Coding</h3>
<p>Most of my code I keep close to my heart, be it my apps or my components. But every once in a while I am open-sourcing something that I feel would be of benefit to the public. Generally I would do that for projects that I have no plan to make money with or where it would be hard to achieve a level of support that&#8217;s necessary for a professional component.</p>
<p>Just recently I open-sourced my mobile report downloading app <a title="OpenSource’ing MyAppSales" href="http://www.cocoanetics.com/2011/01/opensourceing-myappsales/">MyAppSales</a> and <a title="UIWebView must die" href="http://www.cocoanetics.com/2011/01/uiwebview-must-die/">NSAttributedString+HTML</a>. You can thank me by contributing to these projects by fixing bugs and implementing features that are on the issue lists there. Just now there is a problem with downloading financial reports in MyAppSales, that would be a good way to show off your skills by fixing that.</p>
<p><img class="alignnone size-full wp-image-4755" title="Screen shot 2011-03-04 at 3.17.41 PM" src="http://i2.wp.com/www.cocoanetics.com/files/Screen-shot-2011-03-04-at-3.17.41-PM.png?resize=637%2C131" alt="" data-recalc-dims="1" /></p>
<p>Even if you don&#8217;t feel up to the task of contributing yourself, you can reuse code you find in these projects as they are BSD-licensed. It&#8217;s only required that you mention me as original author of the code you borrow. You don&#8217;t have to feel ashamed if your work is in part based on mine. Rather I consider my mission a success if my work enabled you to produce successful apps. Just give credit where credit is due.</p>
<p>If you find issues then just add them to the list of issues on GitHub. This allows other more capable developers to go in and solve the problems you found. What&#8217;s also great on GitHub is that you can fork (i.e. create a copy) of my repositories and when you are done with your changes you can send me a pull request to enable me to pull your changes into the master repository.</p>
<h3>10. Let&#8217;s network</h3>
<p>Having thousands of visitors every day and thousands of followers on twitter does not mean that there are no opportunities for us to network. Above I mentioned a great deal of ways how you can get me to notice and appreciate you. This is a good base to also build a business relationship on.</p>
<p>I <a title="State of Code" href="http://www.cocoanetics.com/2011/02/state-of-code/">recently mentioned</a> that I tend to have too much work for myself alone. But honestly I have very few people that have made an effort to earn my trust. By picking one or more of the above options you can easily get into my &#8220;inner circle&#8221;. Being there will give you even more access and accelerate your own business and learning.</p>
<p>As the iOS market grows so does the amount of opportunities. I try to keep an open mind and I am interested in your novel ideas. Let&#8217;s discuss this on Skype, record it with AudioHijack and then call it a new podcast episode.</p>
<p>I designated 2011 &#8211; the second year of my full-time iOS work &#8211; to be my social year. I am making a conscious effort of meeting my peers in person, attending meetups like the monthly get-togethers of the Cocoaheads. I plan to attend as many conferences as economically possible and sensible. A bar camp in Graz is coming up. And this might also be the first year that I will be able to afford attending WWDC.</p>
<p>To cut a long story short, I would like to meet you, in person, if at all possible. Then you can thank me personally for anything smart that you once read on Cocoanetics.com.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=4743&amp;md5=a24cddddb044513bf0e04e729d40f65f" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2011/03/you-can-thank-me/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2011%2F03%2Fyou-can-thank-me%2F&amp;language=en_GB&amp;category=text&amp;title=You+Can+Thank+Me&amp;description=You+might+have+stumbled+upon+my+site+because+of+the+variety+of+iOS+development+topics+I+am+covering.+I+generally+try+to+make+any+interesting+thing+I%26%238217%3Bm+learning+myself+into...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>State of Code</title>
		<link>http://www.cocoanetics.com/2011/02/state-of-code/</link>
		<comments>http://www.cocoanetics.com/2011/02/state-of-code/#comments</comments>
		<pubDate>Sun, 20 Feb 2011 18:01:12 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=4704</guid>
		<description><![CDATA[I have to admit I am rather close to being stressed out at the moment. In this article I will try to summarize all that&#8217;s going on in my head to find a strategy or guideline as to how to deal with a good problem to have &#8220;too much work&#8221;. I made a promise to take one day off per week to recharge my batteries. Writing helps me do that and so I hope to share a few insights into my complicated brain while at the same time asking for your forgiveness if you have to queue to have me look at your code. But first, I want to show off my new battery I had put into my MacBook Pro. It&#8217;s one of the first ones that no longer has a &#8220;user serviceable battery&#8221;. I could have sent it in to an authorized Apple repair center, but instead I opted to call upon a friend of the Austrian Cocoaheads who happens to be an &#8220;authorized Apple screw-driver&#8221;. Fresh Batteries Pepi from MacLemon installed a new battery on my MacBook Pro (Summer 2009) after I kept seeing a &#8220;Service Battery&#8221; in the status bar for quite some time. The coconutBattery tool shows how fresh it is, it has even slightly more than the design capacity at the moment. I&#8217;m certain that it will soon dip below it. Getting the old battery out was a bit of a hassle because of the Pentalope system that Apple employs inside to prevent regular people from exchanging the battery themselves. Took the better part of two hours, 3/4 of which where spent on trying to remove the final screw. The final 1/4 of the time the MacBook did not want to boot. This was &#8220;fixed&#8221; by reseating the RAM modules several times. What about my mental batteries? This morning, when I getting ready to walk the dog, I found my iPhone without charge. So I walked for one hour without a podcast to distract my mind. And boy it would have needed distraction. It kept circling about all the fires I have to put out. In an effort to preserve my sanity I am trying to take off at least one day per week from coding. Recharging if you will. Writing blog articles does not count as coding, or so I am telling myself. Dear Diary, you are the friend I never had &#8230; I should be happy about my iOS-based self-employment, but there&#8217;s a feeling of indecision that&#8217;s gnawing away on me. Once you had a bit of success in any field you always come to the crossroads where several paths lead into opposing futures. Being a one-man-show means that you will always have a fight with your schedule. There will be important customers whom have something that is more important than everything else, say, because it needs to be done before a large trade show. Long term partners need some addition programmed. Friends who hope that you can make some time to help them build apps or spend time on their projects without compensations. There are large projects that you just would need to get started on, and then write monthly invoices. And then there are all these small bugs in your own apps that are the most painful. Every bad review hurts like hell but the apps are not making enough money to warrant spending time on them as long as there are so many other projects underway. And if only I had time to continue on my rich text editing component. I&#8217;ve had like half a dozen enquiries already about when that will be available. I&#8217;m in this situation myself at this very moment. Of all the work categories I mentioned above I have one or more examples burning at this very moment. The most important question on my mind is how to prioritize all of this. For lack of any better ideas I am using money and importance to decide on the order I am tacking the projects in. An attempt at prioritization How time-critical is the work? Is there some fixed deadline that if I where not to make it would irreparably damage my long-term relationship to a customer who is willing to pay an extra premium? Next in line are projects that are long-term and that provide a recurring income. Partnerships where you share the profits be it either directly from the app store or via enterprise customers of your partners. In my case the iCatalog apps fall into this category because there I own the framework and ICS is selling this solution to catalog companies. You probably have a couple of small apps, making in the order of 10-20 Dollars a day. Not enough to retire on, but still dear to your heart. Now it is [...]]]></description>
				<content:encoded><![CDATA[<p>I have to admit I am rather close to being stressed out at the moment. In this article I will try to summarize all that&#8217;s going on in my head to find a strategy or guideline as to how to deal with a good problem to have &#8220;too much work&#8221;.</p>
<p>I made a promise to take one day off per week to recharge my batteries. Writing helps me do that and so I hope to share a few insights into my complicated brain while at the same time asking for your forgiveness if you have to queue to have me look at your code.</p>
<p>But first, I want to show off my new battery I had put into my MacBook Pro. It&#8217;s one of the first ones that no longer has a &#8220;user serviceable battery&#8221;. I could have sent it in to an authorized Apple repair center, but instead I opted to call upon a friend of the <a href="http://www.cocoaheads.at">Austrian Cocoaheads</a> who happens to be an &#8220;authorized Apple screw-driver&#8221;.</p>
<p><span id="more-4704"></span></p>
<div id="more-4704"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<h3>Fresh Batteries</h3>
<p>Pepi from <a href="http://maclemon.at/">MacLemon</a> installed a new battery on my MacBook Pro (Summer 2009) after I kept seeing a &#8220;Service Battery&#8221; in the status bar for quite some time. The <a href="http://www.coconut-flavour.com/coconutbattery/">coconutBattery</a> tool shows how fresh it is, it has even slightly more than the design capacity at the moment. I&#8217;m certain that it will soon dip below it.</p>
<p><a href="http://i0.wp.com/www.cocoanetics.com/files/Screen-shot-2011-02-19-at-11.28.36.png"><img class="size-full wp-image-4705 alignnone" title="Coconut Battery new Battery" src="http://i0.wp.com/www.cocoanetics.com/files/Screen-shot-2011-02-19-at-11.28.36.png?resize=345%2C514" alt="" data-recalc-dims="1" /></a></p>
<p>Getting the old battery out was a bit of a hassle because of the Pentalope system that Apple employs inside to prevent regular people from exchanging the battery themselves. Took the better part of two hours, 3/4 of which where spent on trying to remove the final screw. The final 1/4 of the time the MacBook did not want to boot. This was &#8220;fixed&#8221; by reseating the RAM modules several times.</p>
<h3>What about my mental batteries?</h3>
<p>This morning, when I getting ready to walk the dog, I found my iPhone without charge. So I walked for one hour without a podcast to distract my mind. And boy it would have needed distraction. It kept circling about all the fires I have to put out.</p>
<p>In an effort to preserve my sanity I am trying to take off at least one day per week from coding. Recharging if you will. Writing blog articles does not count as coding, or so I am telling myself. Dear Diary, you are the friend I never had &#8230;</p>
<p>I should be happy about my iOS-based self-employment, but there&#8217;s a feeling of indecision that&#8217;s gnawing away on me. Once you had a bit of success in any field you always come to the crossroads where several paths lead into opposing futures.</p>
<p>Being a one-man-show means that you will always have a fight with your schedule. There will be important customers whom have something that is more important than everything else, say, because it needs to be done before a large trade show. Long term partners need some addition programmed. Friends who hope that you can make some time to help them build apps or spend time on their projects without compensations. There are large projects that you just would need to get started on, and then write monthly invoices.</p>
<p>And then there are all these small bugs in your own apps that are the most painful. Every bad review hurts like hell but the apps are not making enough money to warrant spending time on them as long as there are so many other projects underway. And if only I had time to continue on my rich text editing component. I&#8217;ve had like half a dozen enquiries already about when that will be available.</p>
<p>I&#8217;m in this situation myself at this very moment. Of all the work categories I mentioned above I have one or more examples burning at this very moment. The most important question on my mind is how to prioritize all of this. For lack of any better ideas I am using money and importance to decide on the order I am tacking the projects in.</p>
<h3>An attempt at prioritization</h3>
<p>How<strong> time-critical</strong> is the work? Is there some fixed deadline that if I where not to make it would irreparably damage my long-term relationship to a customer who is willing to pay an extra premium?</p>
<p>Next in line are projects that are long-term and that provide a <strong>recurring</strong> income. Partnerships where you share the profits be it either directly from the app store or via enterprise customers of your partners. In my case the iCatalog apps fall into this category because there I own the framework and ICS is selling this solution to catalog companies.</p>
<p>You probably have a couple of small apps, making in the order of 10-20 Dollars a day. Not enough to retire on, but still <strong>dear to your heart</strong>. Now it is time to spend a couple of hours polishing out the bugs that are a burden for your image. The apps in your portfolio might just be a playing ground to try out new technologies in. They cannot be much more if you cannot sustain yourself on them alone. But any bug that causes tons of negative reviews being written should be fixed because 1) it will ease your mind and 2) it is good for your image as a developer who cares for the quality of his code.</p>
<p>And then there&#8217;s always some work where you don&#8217;t make any money on at all. Open Source software that you are basing your commercial products on. Like the NSAttributedStrings+HTML project I open sourced while developing a rich text editor on top of it. I won&#8217;t ever make any money on the OSS part. Still this is important because projects like this and MyAppSales are benefitting my reputation. And truth be told, my customer ELO and my partner ICS found me because of them.</p>
<p><strong>Short-term contracts</strong> and consulting work might cause some invoices to be written, but you can only take on these projects if there the long-term stuff is satisfied. If I troubleshoot an app then this will provide a bit of cash in the short-term but I won&#8217;t make anything on the app if it sells well. In work overload times like I am experiencing right now you will have to not accept such work or tell them to call you in 2 weeks or a month. When you start to work in iOS development this kind of work will be your lion&#8217;s share. But down the road, in my case after just one year of doing this full time, you will have to see that your own business grows first and foremost.</p>
<p>Finally there are the mostly egotistical things like writing lengthy blog posts like this one. Be it something philosophical or about some new iOS programming API I found out how to use, I am writing those for my own benefit for the most part. Yes, I am making a couple of bucks on the side via paid ads and Flattr, but not nearly enough to be able to claim that I am making money with my <strong>writing</strong>. Still, this is the only reason why around 1100 unique people come to my site every day.</p>
<p><strong>So sorry&#8230;</strong></p>
<p>I have to ask quite a few people for forgiveness these days:</p>
<p>Dear purchasers of my apps, I am sorry for not having the time to instantly fix all bugs. I understand that you are angry if LuckyWheel does not work properly on iOS 4.x, but please understand this: it will be some time before I can fix bugs like this since my apps are but a minor part of my income.</p>
<p>Dear partners, I am sorry for having to ask you to give me a bit extra time due to something more important that I need to get off my plate before looking at our project. We&#8217;ve been partners for so long, I promise you, that you are next in line.</p>
<p>Dear readers, I wish I had the time to write all the articles I have on my mind. If only you flattr&#8217;ed more or sent me more money&#8230; just kidding, that would probably not change much, as I still need to work on the more important projects to keep my income alive. I promise that I will try to blog more interesting articles as soon as I have a bit of time.</p>
<p>Dear friends, I am sorry that I cannot help you with your stuff for free at the moment. I&#8217;d love to play with you in our iOS dev sandbox, but unfortunately there&#8217;s a long and serious queue in front of you. If you are a true friend, then you&#8217;ll understand my situation. Next chance I get I&#8217;ll make myself available for you once more.</p>
<p>Dear owners of troubled apps. I am saddened by the fact that I don&#8217;t find myself able to make you happy as well. I hate to be sending you away, but there are other able iOS developers out there who probably can do as good or better a job of fixing your memory leaks. If you cannot find one, then you can still appeal to my ego in one more or so. Maybe then I can sell you a couple hours of consulting time.</p>
<h3>The real crossroads</h3>
<p>Everybody needs to make a decision sooner or later in his life what kind of work suits his interest the most. I am not talking about deciding on whether or not to do iOS development, that&#8217;s a no-brainer. I am referring to the decision that most HR people are mentioning to prospective employees in companies around the globe: do you want to be <strong>expert or manager</strong>.</p>
<p>The <a href="http://en.wikipedia.org/wiki/Peter_Principle">Peter Principle</a> states that you will always rise to a level in an organization until further promotion would cause you to be incompetent. I suspect that organization in the context of self-employment does not need to mean that I can never be promoted. In fact I could always promote myself into a management position and instead let other experts to &#8220;the real work&#8221;.</p>
<p>But this is my real problem: I keep bouncing into this limitation of the maximum work that a single individual can accomplish. This prompts me to think that I would either require some employees to take on some of the workload. This would effectively promote me into a management position at which I would be highly incompetent. Peter Principle at work.</p>
<p>Would it make sense to stretch my limits? Other self-employed people (read: start-ups) are working way more than I am. It is rare that I can get in more than 8 hours of coding done in one day. If I sit down more than this, then my mood dramatically deteriorates, my eyes begin to burn and I find that I cannot clear my head at the end of the day. The suffering that this would impose on myself and &#8211; by extension &#8211; my wife and pets cannot be worth it.</p>
<p>This year I&#8217;ll be turning 37 and I suspect that the rule of thirds is around my natural physical and psychological limit. A third of the day is required for sleeping. A third should be spent concentrated on work. And a third should be non-work active time. Playing, spending time with family and everything else that is good for your soul.</p>
<p>I need to conserve my energies and brain power because I am not a teen or twen any more. My start-up train has sailed.</p>
<p>So I cannot work more. Or more precisely, I could work more, but the negatives would outweigh the benefits. And I cannot leverage other people&#8217;s work being my employees. Not just because I would be incompetent at leading them. Possibly I could develop these skills. But I simply cannot afford the risk of hiring somebody when the current income just barely fits my own needs. I have not just one mortgage to pay, I&#8217;ve got two.</p>
<p>Somebody on twitter suggested more partnerships. While those are at the core of several of my business endeavors already I don&#8217;t see it likely that somebody might turn up and tell me &#8220;hey Oliver, I want to work on your apps for free if you share 50% of the profits with me&#8221;. That would be something &#8230; who in his right mind would want to work on my apps for 100-200 Dollars per month. Not likely.</p>
<p>So what should I do about projects that people approach me with that I don&#8217;t have time for. Honestly I have trust issues. If I am forwarding a project to you, how can I know that you will be able to bring the project to a successful conclusion? I don&#8217;t know you personally. I don&#8217;t know what quality code you write. I don&#8217;t know about your skills dealing with difficult customers. Do you know this feeling? If you want something done right, you better do it yourself?</p>
<p>There&#8217;s also a language barrier. The majority of projects that landed on my desk recently is by German-language people and project descriptions are in German as well. That might be because German-speaking Central Europeans have little (positive) experience with outsourcing development work internationally. We see Eastern Europe as an enemy for our standard of living. Lot&#8217;s of cheap labour threatening to take our jobs away. Even cheaper is work in India, Israel and China, but these are seen less as a threat because they are so far away. In short the dilemma is this: if you speak German, you are probably too expensive. If not, then you&#8217;ll already fail at reading the project spec.</p>
<p>This is the reason why I am rejecting such projects at present and why I am not trying to make money on passing them on. If I were to take the approx. $1000 dollars in referral fee for a medium-sized project I fear that I would feel liable if it becomes a failure.</p>
<h3>Strategy forthcoming?</h3>
<p>Please forgive me if this article sounds like I am complaining or whining. I guess I am doing that a bit. But hey, I told you before that I am writing mostly for my own benefit. In this case to clear my head and try to come up with a creative solution to the &#8220;too much work&#8221; dilemma.</p>
<p>If there&#8217;s any conclusion to arrive at then only that I am keeping my eyes open for potential partnerships and deals where I have a long-term income from. At the same time I will continue to gradually raise my hourly rate as to reduce the demand for my consulting and contracting skills.</p>
<p>People say that this is a good problem to have. Here&#8217;s to hoping that they are right.</p>
<p>If you have any kind of smart ideas how you would deal with my situation let me know in the comments.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=4704&amp;md5=16c78239779a74809f7bba42e3435715" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2011/02/state-of-code/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2011%2F02%2Fstate-of-code%2F&amp;language=en_GB&amp;category=text&amp;title=State+of+Code&amp;description=I+have+to+admit+I+am+rather+close+to+being+stressed+out+at+the+moment.+In+this+article+I+will+try+to+summarize+all+that%26%238217%3Bs+going+on+in+my+head...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>Color Math</title>
		<link>http://www.cocoanetics.com/2011/02/color-math/</link>
		<comments>http://www.cocoanetics.com/2011/02/color-math/#comments</comments>
		<pubDate>Tue, 01 Feb 2011 13:48:29 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=4684</guid>
		<description><![CDATA[For my Rich Text Editing component I wanted selections to look like the Apple originals. So I made a screenshot of some editing action and inspected it in Photoshop to find out how they are drawn. Visually there are two options: either the selection boxes are drawn behind the text not affecting it, or they are layered on top of the text.  Because the selection also changes the color values of the black text it must be the latter. It&#8217;s on top. In this article I&#8217;ll try to figure out the math so that I can calculate the original blue and alpha value used. We will see that it is orders of magnitude easier to do if we know the result of blending this color over white and black than two arbitrary ones. Assuming that a normal blend mode is used the math to compose two pixels and their alpha is according to Wikipedia. So we basically diminish the pixel color by the inverse of the alpha and add the new color of the blended pixel. Ok, that&#8217;s not too difficult. Using the color dropper tool we find these values to be the the result of the blending: Color + Black = Rb: 0 (0.000), Gb: 17 (0.067), Bb: 34 (0.133) Color + White = Rw: 203 (0.796), Gw: 221 (0.867), Bw: 238 (0.933) Calculating Original Color I turned to twitter for help and Andy Durdin from Edinburgh responded with the appropriate equations while standing and waiting for a bus. Ro = Red of Original Color Rw = Red Value from blending Ro with White Rb = Red Value from blending Ro with Black A = Alpha Changing the formulas to look like the on quote above: Rw = (1 &#8211; A) * 1 + A * Ro Rb =  (1 &#8211; A) * 0 + A * Ro Now my algebra is quite weak, but with Andy&#8217;s help I figured out Rb = A * Ro Rw = 1 &#8211; A + Rb and then add A to and subtract Rw from both sides. A = 1 + Rb &#8211; Rw Ro = Rb / A So lets substitute the Red values and see what we get as a result: A = 1 + 0 &#8211; 0.796 = 0.204 Ro = 0 / 0.2 = 0 Go = 0.067 / 0.2 = 0.338 Bo = 0.133 / 0.2 = 0.652 Lo and behold, the color we get matches exactly! Being curious I asked Andy if this solving technique would work for any two arbitrary colors as well. Somehow I suspected that having black in there might make the whole way simpler because the multiplication with 0 reliminates a big chunk of one of the two equations. The answer is yes. If alpha is involved we always have two unknowns to solve for. You always require the same number of simultaneous equations as you have unknowns. Bonus: Arbitrary Colors Andy sat down and flexed his iron math muscles a bit more. A solid color C0 is blended with alpha A over two other colors C1, C2. The blend with C1 produces color C3, and the blend with C2 produces color C4. Considering only the red channels (r0 = red channel of c0), we have: R3 = A * R0 + (1 &#8211; A) * R1 R4 = A * R0 + (1 &#8211; A) * R2 If we only know C1, C2, C3, C4, we can solve for C0 and a. Again, considering just the red channels, a solution is: s = (R2 &#8211; R1) / (R4 &#8211; R2) R0 = (R2 * s &#8211; R1) / (s &#8211; 1) A = (R4 &#8211; R2) / (R0 &#8211; R2) s is used just to make the equation for r0 more readable. Andy&#8217;s conclusion: &#8220;This is a solution, and it works, but I&#8217;m not very happy with it. With some colors it is extremely sensitive to the rounding errors in the colour values.&#8221; So, yes, it&#8217;s possible, but not very feasible to try to get the original color and alpha when it&#8217;s blended with two arbitrary colors. So generally we&#8217;ll stick with white and black if we want to find out what original colors Apple is using for certain UI elements.]]></description>
				<content:encoded><![CDATA[<p>For my <a href="http://www.cocoanetics.com/2011/01/rich-text-editing-on-ios">Rich Text Editing component</a> I wanted selections to look like the Apple originals. So I made a screenshot of some editing action and inspected it in Photoshop to find out how they are drawn.</p>
<p><a href="http://i1.wp.com/www.cocoanetics.com/files/Selection.jpg"><img class="alignnone size-full wp-image-4685" title="Selection" src="http://i1.wp.com/www.cocoanetics.com/files/Selection.jpg?resize=190%2C96" alt="" data-recalc-dims="1" /></a></p>
<p>Visually there are two options: either the selection boxes are drawn behind the text not affecting it, or they are layered on top of the text.  Because the selection also changes the color values of the black text it must be the latter. It&#8217;s on top.</p>
<p>In this article I&#8217;ll try to figure out the math so that I can calculate the original blue and alpha value used. We will see that it is orders of magnitude easier to do if we know the result of blending this color over white and black than two arbitrary ones.</p>
<p><span id="more-4684"></span></p>
<div id="more-4684"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<p>Assuming that a normal blend mode is used the math to compose two pixels and their alpha is <a href="http://en.wikipedia.org/wiki/Alpha_compositing">according to Wikipedia</a>.</p>
<p><a href="http://i2.wp.com/www.cocoanetics.com/files/ee1a266894a3b625e4b6edeb4420f960.png"><img class="alignnone size-full wp-image-4686" title="Alpha Formula" src="http://i2.wp.com/www.cocoanetics.com/files/ee1a266894a3b625e4b6edeb4420f960.png?resize=288%2C21" alt="" data-recalc-dims="1" /></a></p>
<p>So we basically diminish the pixel color by the inverse of the alpha and add the new color of the blended pixel. Ok, that&#8217;s not too difficult.</p>
<p>Using the color dropper tool we find these values to be the the result of the blending:</p>
<p>Color + Black = Rb: 0 (0.000), Gb: 17 (0.067), Bb: 34 (0.133)<br />
Color + White = Rw: 203 (0.796), Gw: 221 (0.867), Bw: 238 (0.933)</p>
<h3>Calculating Original Color</h3>
<p>I turned to twitter for help and <a href="http://twitter.com/adurdin">Andy Durdin</a> from Edinburgh <a href="https://twitter.com/adurdin/status/32351212519030784">responded</a> with the appropriate equations while standing and waiting for a bus.</p>
<p>Ro = Red of Original Color<br />
Rw = Red Value from blending Ro with White<br />
Rb = Red Value from blending Ro with Black<br />
A = Alpha</p>
<p>Changing the formulas to look like the on quote above:</p>
<p>Rw = (1 &#8211; A) * 1 + A * Ro<br />
Rb =  (1 &#8211; A) * 0 + A * Ro</p>
<p>Now my algebra is quite weak, but with Andy&#8217;s help I figured out</p>
<p>Rb = A * Ro<br />
Rw = 1 &#8211; A + Rb</p>
<p>and then add A to and subtract Rw from both sides.</p>
<p>A = 1 + Rb &#8211; Rw<br />
Ro = Rb / A</p>
<p>So lets substitute the Red values and see what we get as a result:</p>
<p>A = 1 + 0 &#8211; 0.796 = 0.204<br />
Ro = 0 / 0.2 = 0<br />
Go = 0.067 / 0.2 = 0.338<br />
Bo = 0.133 / 0.2 = 0.652</p>
<p>Lo and behold, the color we get matches exactly!</p>
<p><a href="http://i0.wp.com/www.cocoanetics.com/files/Screen-shot-2011-02-01-at-11.17.50-AM.png"><img class="alignnone size-full wp-image-4687" title="Selection" src="http://i0.wp.com/www.cocoanetics.com/files/Screen-shot-2011-02-01-at-11.17.50-AM.png?resize=262%2C105" alt="" data-recalc-dims="1" /></a></p>
<p>Being curious I asked Andy if this solving technique would work for any two arbitrary colors as well. Somehow I suspected that having black in there might make the whole way simpler because the multiplication with 0 reliminates a big chunk of one of the two equations. The answer is yes. If alpha is involved we always have two unknowns to solve for. You always require the same number of <a href="http://en.wikipedia.org/wiki/Simultaneous_equations">simultaneous equations</a> as you have unknowns.</p>
<h3>Bonus: Arbitrary Colors</h3>
<p>Andy sat down and flexed his iron math muscles a bit more. <img src='http://i1.wp.com/www.cocoanetics.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' data-recalc-dims="1" /> </p>
<p>A solid color C0 is blended with alpha A over two other colors C1, C2. The blend with C1 produces color C3, and the blend with C2 produces color C4.</p>
<p>Considering only the red channels (r0 = red channel of c0), we have:</p>
<p>R3 = A * R0 + (1 &#8211; A) * R1<br />
R4 = A * R0 + (1 &#8211; A) * R2</p>
<p>If we only know C1, C2, C3, C4, we can solve for C0 and a. Again, considering just the red channels, a solution is:</p>
<p>s = (R2 &#8211; R1) / (R4 &#8211; R2)<br />
R0 = (R2 * s &#8211; R1) / (s &#8211; 1)<br />
A = (R4 &#8211; R2) / (R0 &#8211; R2)</p>
<p>s is used just to make the equation for r0 more readable.</p>
<p>Andy&#8217;s conclusion: <em>&#8220;This is a solution, and it works, but I&#8217;m not very happy with it. With some colors it is extremely sensitive to the rounding errors in the colour values.&#8221;</em></p>
<p>So, yes, it&#8217;s possible, but not very feasible to try to get the original color and alpha when it&#8217;s blended with two arbitrary colors. So generally we&#8217;ll stick with white and black if we want to find out what original colors Apple is using for certain UI elements.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=4684&amp;md5=2b8e6be602fd194c005d51a612fcc36b" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2011/02/color-math/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2011%2F02%2Fcolor-math%2F&amp;language=en_GB&amp;category=text&amp;title=Color+Math&amp;description=For+my+Rich+Text+Editing+component+I+wanted+selections+to+look+like+the+Apple+originals.+So+I+made+a+screenshot+of+some+editing+action+and+inspected+it+in+Photoshop+to...&amp;tags=blog" type="text/html" />
	</item>
		<item>
		<title>iTunes Connect Closed</title>
		<link>http://www.cocoanetics.com/2010/12/itunes-connect-closed/</link>
		<comments>http://www.cocoanetics.com/2010/12/itunes-connect-closed/#comments</comments>
		<pubDate>Mon, 27 Dec 2010 15:01:25 +0000</pubDate>
		<dc:creator>Drops</dc:creator>
				<category><![CDATA[Administrative]]></category>

		<guid isPermaLink="false">http://www.cocoanetics.com/?p=4525</guid>
		<description><![CDATA[iTunes Connect is closed until December 29th. This means: No new app submissions or update submissions No sales stats or reports No ranking info &#8230; from Apple or their sites. We&#8217;re taking a bit of a breather ourselves, the most coding I did personally was implement tracking support in GeoCorder for Google Latitude and Crossingways. A bit of a hobby of mine because I can test the tracking when I am moving around. But even joyous things like sending out invoices are on hold because I don&#8217;t enter my home office. But I promise I&#8217;ll send them out December 29th. When Apple reopens so will we to take the turn of the year in full swing with updates for iWoman and GeoCorder.]]></description>
				<content:encoded><![CDATA[<p>iTunes Connect is closed until December 29th.</p>
<p><img class="alignnone size-full wp-image-4526" title="holiday-closed" src="http://i2.wp.com/www.cocoanetics.com/files/holiday-closed.png?resize=166%2C118" alt="" data-recalc-dims="1" /></p>
<p>This means:</p>
<ul>
<li>No new app submissions or update submissions</li>
<li>No sales stats or reports</li>
<li>No ranking info</li>
</ul>
<p>&#8230; from Apple or their sites.</p>
<p><span id="more-4525"></span></p>
<div id="more-4525"></div>
<div class="inner_ad_block">
<div id="advman-7" class="widget Advman_Widget">
<h3 class="widgettitle"></h3>
<p><!-- BuySellAds.com Zone Code --></p>
<div id="bsap_1260346" class="bsarocks bsap_fc3166ea4a479e0fdb4251fbe92a1219"></div>
<p><!-- End BuySellAds.com Zone Code --></div>
</div>
<p>We&#8217;re taking a bit of a breather ourselves, the most coding I did personally was implement tracking support in GeoCorder for <a href="http://www.google.com/latitude">Google Latitude</a> and <a href="http://www.crossingways.com">Crossingways</a>. A bit of a hobby of mine because I can test the tracking when I am moving around.</p>
<p>But even joyous things like sending out invoices are on hold because I don&#8217;t enter my home office. But I promise I&#8217;ll send them out December 29th. When Apple reopens so will we to take the turn of the year in full swing with updates for iWoman and GeoCorder.</p>
 <p><a href="http://www.cocoanetics.com/?flattrss_redirect&amp;id=4525&amp;md5=9df55d171020f4ddfdf5918edd3d466c" title="Flattr" target="_blank"><img src="http://www.cocoanetics.com/wp-content/plugins/flattr/img/flattr-badge-large.png" alt="flattr this!"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.cocoanetics.com/2010/12/itunes-connect-closed/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<atom:link rel="payment" title="Flattr this!" href="https://flattr.com/submit/auto?user_id=dr_touch&amp;url=http%3A%2F%2Fwww.cocoanetics.com%2F2010%2F12%2Fitunes-connect-closed%2F&amp;language=en_GB&amp;category=text&amp;title=iTunes+Connect+Closed&amp;description=iTunes+Connect+is+closed+until+December+29th.+This+means%3A+No+new+app+submissions+or+update+submissions+No+sales+stats+or+reports+No+ranking+info+%26%238230%3B+from+Apple+or+their+sites....&amp;tags=blog" type="text/html" />
	</item>
	</channel>
</rss>
