tag:blogger.com,1999:blog-353232112024-03-07T00:46:02.766-08:00Bogdan's thoughtson technology and businessUnknownnoreply@blogger.comBlogger106125tag:blogger.com,1999:blog-35323211.post-17365997110818918432014-03-22T11:50:00.000-07:002014-03-22T11:50:21.699-07:00To prevent unpleasant surprises, check the initializers of the classes used in storyboards and NIBs.I love storyboards. I use them all the time. They act as blueprints of my apps. A glance at the storyboard is often is enough to get an idea of the workflow of an app, and where to look for things. I think it's a good idea to work at a higher abstraction level, and let the tool generate the code for you.<br />
<br />
They bring back fond memories, from when I was using Rational Rose RealTime and its predecessor, <a href="http://en.wikipedia.org/wiki/ObjecTime">ObjecTime</a>, while I was working for Motorola, <a href="http://user.mc.net/lawillis/resume/motogprs.htm">making history</a>.<br />
<br />
So, back on iOS land, I worked on this project where I had a class derived from <span style="color: #703daa; font-family: Monaco; font-size: 12px;">QLPreviewController</span> like so:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi58iGvdv9aFYysj2OHPQ9_oBq579IeKYYg14q1D_NSGfgNMInaPHv_yps6-ltBlPkmmm8C8rSLpCNcyDSxt_4wi0x3QEEheNTPmSPmfTk3RsYleKyz2mDgXy2FEdJOxSev1SggNg/s1600/-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi58iGvdv9aFYysj2OHPQ9_oBq579IeKYYg14q1D_NSGfgNMInaPHv_yps6-ltBlPkmmm8C8rSLpCNcyDSxt_4wi0x3QEEheNTPmSPmfTk3RsYleKyz2mDgXy2FEdJOxSev1SggNg/s1600/-1.png" height="78" width="320" /></a></div>
<br />
and I used the <span style="font-family: Monaco; font-size: 12px;">DocPreviewController</span> class in the storyboard, like so:<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4QfaLfRYtZ7QkrfdMWBocuGLdF-U82_GDq6tYkRwgqG0tP-d0yQNiSpwl-Wt820318TMjnL94e0l09fVAYBPquV0MNaXSWJFv09SIc-bPYkuSWlIgK3uqW4buiHSiKXinfsSp2A/s1600/0.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4QfaLfRYtZ7QkrfdMWBocuGLdF-U82_GDq6tYkRwgqG0tP-d0yQNiSpwl-Wt820318TMjnL94e0l09fVAYBPquV0MNaXSWJFv09SIc-bPYkuSWlIgK3uqW4buiHSiKXinfsSp2A/s1600/0.png" height="155" width="320" /></a></div>
<br />
My first attempt to run the app produced this crash:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM66VOYxj1dK3BYybHQvzs0-D7UNp0LnaJso25mxqjdArkJURzPr6sSJMff5Y7_pUHsGONfkbGBK0GMXoGPpb4MJq5GEYvun2FLACPpSuecoysvQQmVSRHUSCT4lYIaMUO6b4plg/s1600/1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM66VOYxj1dK3BYybHQvzs0-D7UNp0LnaJso25mxqjdArkJURzPr6sSJMff5Y7_pUHsGONfkbGBK0GMXoGPpb4MJq5GEYvun2FLACPpSuecoysvQQmVSRHUSCT4lYIaMUO6b4plg/s1600/1.png" height="44" width="320" /></a></div>
<br />
Taking a closer look reveals this abomination:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDZpK8B27kqKa69up4ZVTWq0ptAWhfg80VZt-BkyWIpt4EbYHG94gJYalCHG1922jXY0dALgIiYPyC1Rm55PlUsKAFTy7aNJgeBqTMmYVVPZUpdSxG2dft7_Gln5d34Tw9w4P4cw/s1600/2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDZpK8B27kqKa69up4ZVTWq0ptAWhfg80VZt-BkyWIpt4EbYHG94gJYalCHG1922jXY0dALgIiYPyC1Rm55PlUsKAFTy7aNJgeBqTMmYVVPZUpdSxG2dft7_Gln5d34Tw9w4P4cw/s1600/2.png" height="70" width="320" /></a></div>
<br />
Looks like <span style="font-family: Monaco; font-size: 12px;">docPreviewController</span> object might not have been properly constructed. To confirm the hypothesis, let's use Apple's sample code that doesn't use storyboards, instead it constructs the objects explicitly in code like so:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSXLiI2fVYovoFMgVP0lcUGVM86apAbDtVUhnzTQbz7e2uC_laMtqzdu7n363g0UHLQCMtxtliSKN530ZuLqs0Vu0W20AhhUoeE1av862t0IhVB0MtB5jyUEQg009C1wB8knIRxA/s1600/3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSXLiI2fVYovoFMgVP0lcUGVM86apAbDtVUhnzTQbz7e2uC_laMtqzdu7n363g0UHLQCMtxtliSKN530ZuLqs0Vu0W20AhhUoeE1av862t0IhVB0MtB5jyUEQg009C1wB8knIRxA/s1600/3.png" height="54" width="320" /></a></div>
<br />
Yup. That's how a properly constructed object should look like. Hypothesis confirmed.<br />
<br />
It's a <a href="https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW19">known fact</a> that when an object is loaded from a NIB or storyboard, its <code style="background-color: white; color: #666666; font-family: Courier, Consolas, monospace; font-size: 13px;">initWithCoder:</code> method is called. It seems that for <span style="color: #703daa; font-family: Monaco; font-size: 12px;">QLPreviewController</span>, a class from Apple, that method is not doing the right thing. Probably that's a bug on Apple's side. We could file a bug report, or we could take the matter in our own hands:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVTG7pkHd_-c8vyNlLkhYeth3nDwOUPTlOYOtb80AS0aGulfu9bUX72ntkjv2_BJTNI05n-Y41Hdn3prS3WzpooBfu4iSA_JTbll8kUhbdWlkXZVQ2CaDSWbLF4Nl8GJeDuVA_rA/s1600/4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVTG7pkHd_-c8vyNlLkhYeth3nDwOUPTlOYOtb80AS0aGulfu9bUX72ntkjv2_BJTNI05n-Y41Hdn3prS3WzpooBfu4iSA_JTbll8kUhbdWlkXZVQ2CaDSWbLF4Nl8GJeDuVA_rA/s1600/4.png" height="132" width="320" /></a></div>
<br />
and see it fixed:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQfZEtYXdYYIyVkCwEpkFBscbF70iLJtjSiu7D1b6wiS6SRZmGt_eWLzQRPZGPTdGBLPs2VySTjZG9gIE-_ynt2KrA5j9iln6uTi65oU-pKlXhw6mRDT0zMXixy1EynpkYZTJm-Q/s1600/5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQfZEtYXdYYIyVkCwEpkFBscbF70iLJtjSiu7D1b6wiS6SRZmGt_eWLzQRPZGPTdGBLPs2VySTjZG9gIE-_ynt2KrA5j9iln6uTi65oU-pKlXhw6mRDT0zMXixy1EynpkYZTJm-Q/s1600/5.png" height="77" width="320" /></a></div>
<br />
In conclusion, if you encounter problems with objects loaded from NIBs or storyboards check the <span style="background-color: white; color: #666666; font-family: Courier, Consolas, monospace; font-size: 13px;">initWithCoder: </span>and make sure that it's doing the right thing. For a subclass like mine, it means that it should call the designated initializer of its superclass. Since <span style="color: #703daa; font-family: Monaco; font-size: 12px;">QLPreviewController</span> doesn't define a designated initializer, it means that it inherits that of its parent, <span style="background-color: white; font-family: Courier, Consolas, monospace; font-size: 13px;">- (id)initWithNibName:(</span><a href="https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/doc/c_ref/NSString" style="background-color: white; color: #3366cc; font-family: Courier, Consolas, monospace; font-size: 13px; text-decoration: none;">NSString</a><span style="background-color: white; font-family: Courier, Consolas, monospace; font-size: 13px;"> *)</span><em style="background-color: white; font-family: 'Lucida Grande', 'Lucida Sans Unicode', Helvetica, Arial, Verdana, sans-serif; font-size: 13px;">nibName</em><span style="background-color: white; font-family: Courier, Consolas, monospace; font-size: 13px;"> bundle:(</span><a href="https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSBundle_Class/Reference/Reference.html#//apple_ref/doc/c_ref/NSBundle" style="background-color: white; color: #3366cc; font-family: Courier, Consolas, monospace; font-size: 13px; text-decoration: none;">NSBundle</a><span style="background-color: white; font-family: Courier, Consolas, monospace; font-size: 13px;"> *)</span><em style="background-color: white; font-family: 'Lucida Grande', 'Lucida Sans Unicode', Helvetica, Arial, Verdana, sans-serif; font-size: 13px;">nibBundle</em>. Normally I should have called that, passing nil as the value of both parameters, but I chose to use the same initializer used in Apple's sample code. It seems to achieve the same result.<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-40361448401358872962013-12-30T19:30:00.000-08:002014-01-10T12:51:29.006-08:00How to deal with "QuickBooks has encountered a problem and needs to close."It's 2 days before the end of the year, a time for bookkeeping and regulatory filing, albeit not a lot of time left to meet the end-of-year deadlines, when this happens when launching QuickBooks:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihv4HeGePMmNa3TLXVBQPaFfEjYx1iQ6eCXwDaDp1TWnlkh7_pCAFW18NvYZOC4vI-wKTksA_DhM3Obvu2UPElzpn2aGLAcLMynPbt_YEzf1Xmvf32eGW52LvFmPRQC4FLk6j1Lg/s1600/Screen+shot+2013-12-28+at+9.13.34+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihv4HeGePMmNa3TLXVBQPaFfEjYx1iQ6eCXwDaDp1TWnlkh7_pCAFW18NvYZOC4vI-wKTksA_DhM3Obvu2UPElzpn2aGLAcLMynPbt_YEzf1Xmvf32eGW52LvFmPRQC4FLk6j1Lg/s320/Screen+shot+2013-12-28+at+9.13.34+PM.png" height="210" width="320" /></a></div>
Trying again produces the same error, over and over again. Then panic sets in, did I just lost all my financial information ? Why is this happening ? Probably my company file got corrupted, and QuickBooks can't deal with it. More on this later. Let's fix it first.<br />
<br />
One way to recover from a corrupted company file is to restore it from a previously saved backup. If you don't have a recent backup ready, my method won't help you. First I need to locate the backup file. QuickBooks has the habit of moving the location of backups, as you upgrade to newer versions, so my best bet is to do a search for files with the extension ".QBB":<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFEAK0zHepB5f5Kg2T33Uc19v5NIYVQnNsuaMwWVNCmjJ2RRuxBJ4gdnGSAeUU8rvQtDJDjXhD6CulPa6UDBPRKtwbx_IF8z4SjQa6Ia-RWC0ZCvOIiFthKE2tLeKdVSkdCMS7Cw/s1600/Screen+shot+2013-12-31+at+2.26.49+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhFEAK0zHepB5f5Kg2T33Uc19v5NIYVQnNsuaMwWVNCmjJ2RRuxBJ4gdnGSAeUU8rvQtDJDjXhD6CulPa6UDBPRKtwbx_IF8z4SjQa6Ia-RWC0ZCvOIiFthKE2tLeKdVSkdCMS7Cw/s320/Screen+shot+2013-12-31+at+2.26.49+PM.png" height="239" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhosIELX3AGtWYp6BLbfFvBqcNg5c4zKo27Hj33tp8270dMQEI3Kg51w2ELCl6403MM6YKv-NW7UEoFCNeXkQqJ0GgYG7MpXT1hmS-zVAa_mvWD0UlSBKnz3icMXZ7Mv7r93Fiovg/s1600/Screen+shot+2013-12-31+at+2.27.33+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhosIELX3AGtWYp6BLbfFvBqcNg5c4zKo27Hj33tp8270dMQEI3Kg51w2ELCl6403MM6YKv-NW7UEoFCNeXkQqJ0GgYG7MpXT1hmS-zVAa_mvWD0UlSBKnz3icMXZ7Mv7r93Fiovg/s320/Screen+shot+2013-12-31+at+2.27.33+PM.png" height="240" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnxdMl9W9zpTV31D4ytGy_QlUEe4wxYRwBj7u1hYlz7q-7nWoteagp7BBhOpB_aLLcdNGTVtRVXcUvoMX4jIE4a1X23RaAhkPn9WvYThz2qBIHv6vmZN0x4I1uQdm5STYy1-bmGA/s1600/Screen+shot+2013-12-31+at+2.30.03+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnxdMl9W9zpTV31D4ytGy_QlUEe4wxYRwBj7u1hYlz7q-7nWoteagp7BBhOpB_aLLcdNGTVtRVXcUvoMX4jIE4a1X23RaAhkPn9WvYThz2qBIHv6vmZN0x4I1uQdm5STYy1-bmGA/s320/Screen+shot+2013-12-31+at+2.30.03+PM.png" height="239" width="320" /></a></div>
<br />
Alternatively, you may have a copy of the backup saved "in the cloud" - highly recommended in case something happens to your computer - not necessarily to use the online storage offered by Intuit. Any alternative will do.<br />
<br />
Trying to open a local backup by double-clicking the file produces this message:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaH6gC7GbO_F5yVMynXbs-yawKXi4To2thTX1YBDD8H71YY_AekUBM3MMXgnDYM60nAjeG9UeyWFN6fIKevO71QmYZ-UiWfqF2IiwZy_X2F9F0VhHPUA5qIg7lErSlP6ue2J6nTA/s1600/Screen+shot+2013-12-31+at+2.26.06+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaH6gC7GbO_F5yVMynXbs-yawKXi4To2thTX1YBDD8H71YY_AekUBM3MMXgnDYM60nAjeG9UeyWFN6fIKevO71QmYZ-UiWfqF2IiwZy_X2F9F0VhHPUA5qIg7lErSlP6ue2J6nTA/s320/Screen+shot+2013-12-31+at+2.26.06+PM.png" height="239" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Yeah, thats very helpful, Intuit. I'm having problems exactly with opening QuickBooks, which by default will always try to open the company file. If that's corrupted, I'll keep getting the "encountered a problem" error message (meaning that in fact the program has crashed). To get out of that dead-end we could first locate the company file (should have the extension *.QBW - if you don't know it's location you can search, as I did above for *QBB).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhP1d_Gqd4FviHEM6YpUZMqBoiN3hR8o8RVne8r0wtZkJPEmZLBt1gBf8jnnEHSJM-7ep5C78-SElOXj7iDNnBEDvxOQTe_hBDRbs41wVMfiwHcGdKbUx5tQxaQ8A7bNAJPoG_dFw/s1600/Screen+shot+2013-12-28+at+9.31.38+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhP1d_Gqd4FviHEM6YpUZMqBoiN3hR8o8RVne8r0wtZkJPEmZLBt1gBf8jnnEHSJM-7ep5C78-SElOXj7iDNnBEDvxOQTe_hBDRbs41wVMfiwHcGdKbUx5tQxaQ8A7bNAJPoG_dFw/s320/Screen+shot+2013-12-28+at+9.31.38+PM.png" height="240" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Then we can rename it to something else:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWTxumEbdnrv8_QBDLANnXhJrfKQ0ro9YKDl68M6teR6DNGw720tb0PhEtp9kZC8Po4pKcsLaxhr3jN5AP3dG8YpbytZijyWsvmwFbRlz_vFKXPQTQgWtfjhyX-Lm-y-tXjei2IA/s1600/Screen+shot+2013-12-28+at+9.32.18+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWTxumEbdnrv8_QBDLANnXhJrfKQ0ro9YKDl68M6teR6DNGw720tb0PhEtp9kZC8Po4pKcsLaxhr3jN5AP3dG8YpbytZijyWsvmwFbRlz_vFKXPQTQgWtfjhyX-Lm-y-tXjei2IA/s320/Screen+shot+2013-12-28+at+9.32.18+PM.png" height="238" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Now if I try to open QuickBooks I see:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCIWCv7bgIJ68f9wboEhTQbyw1wgnJrwhRJICuKKSFrCo0CVHugFcONUjbnwAl4m0AA5LdzhrPI0r8FC4G3ebD0th5ZsyDRqEd8oeFminHsC-wpLsOx2BPFjhWET6e6VVsYEQJjg/s1600/Screen+shot+2013-12-28+at+9.34.58+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCIWCv7bgIJ68f9wboEhTQbyw1wgnJrwhRJICuKKSFrCo0CVHugFcONUjbnwAl4m0AA5LdzhrPI0r8FC4G3ebD0th5ZsyDRqEd8oeFminHsC-wpLsOx2BPFjhWET6e6VVsYEQJjg/s320/Screen+shot+2013-12-28+at+9.34.58+PM.png" height="167" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Now we're getting somewhere. Click the "Open or restore an existing company" button:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbC2MUIZrFG64PBWP4688h1N6fzvlP3yFqJCDpSCBlrCKILBmQN7OHVosZkyn0cMDcmfRBwfvq49e8qw1Py1zpDlGsPruAa94ImuQZcyDXDwY1QxCxS-c82CzzPjOiLXR4ubodRQ/s1600/Screen+shot+2013-12-28+at+9.35.33+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbC2MUIZrFG64PBWP4688h1N6fzvlP3yFqJCDpSCBlrCKILBmQN7OHVosZkyn0cMDcmfRBwfvq49e8qw1Py1zpDlGsPruAa94ImuQZcyDXDwY1QxCxS-c82CzzPjOiLXR4ubodRQ/s320/Screen+shot+2013-12-28+at+9.35.33+PM.png" height="169" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
And choose the "Restore a backup copy":<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2Wuat9ApKT6j64dHRFWp6WuetCYtw3RQjPD1O-QzG9Eyl1jmgSBFvcqApajAqFn-udQPkAJON2BctgtK5b3lUZjzyoCZFV3BoswvZdyHSk0E8PpszkRgWHknBSoo7Flvad1dejg/s1600/Screen+shot+2013-12-28+at+9.36.08+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2Wuat9ApKT6j64dHRFWp6WuetCYtw3RQjPD1O-QzG9Eyl1jmgSBFvcqApajAqFn-udQPkAJON2BctgtK5b3lUZjzyoCZFV3BoswvZdyHSk0E8PpszkRgWHknBSoo7Flvad1dejg/s320/Screen+shot+2013-12-28+at+9.36.08+PM.png" height="169" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
In my case I'll use a local backup:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia3G9pq2n37RdChQp1x2nmRwgm7jdg_-RsD8-QRaisipuF3w0eIHUmfGVoUl3Q3Y_RzL0lkSbb0QjvikPn7BDy7LGxRYvpargv1EL0sz_ZTyGwiW3daDYd400JOm8LXI2gBubVjg/s1600/Screen+shot+2013-12-28+at+9.36.29+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEia3G9pq2n37RdChQp1x2nmRwgm7jdg_-RsD8-QRaisipuF3w0eIHUmfGVoUl3Q3Y_RzL0lkSbb0QjvikPn7BDy7LGxRYvpargv1EL0sz_ZTyGwiW3daDYd400JOm8LXI2gBubVjg/s320/Screen+shot+2013-12-28+at+9.36.29+PM.png" height="168" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Here QuickBooks will try to hold my hand:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEie2a0V31QtxO492wQd0I2cGEwo7ZaEZ4BB8QDx-WrjJDHZjM0HQoVQ8Kwh1w2OA3-HXqGPlVKoLnz9OL3BCaaP6fLK_6Fgs102sCuwcilufr14z34hslqYkLdamq9YO_B8w6UZVw/s1600/Screen+shot+2013-12-28+at+9.37.04+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEie2a0V31QtxO492wQd0I2cGEwo7ZaEZ4BB8QDx-WrjJDHZjM0HQoVQ8Kwh1w2OA3-HXqGPlVKoLnz9OL3BCaaP6fLK_6Fgs102sCuwcilufr14z34hslqYkLdamq9YO_B8w6UZVw/s320/Screen+shot+2013-12-28+at+9.37.04+PM.png" height="168" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
But the original (corrupted) company file would have been already renamed, so I'll just use its original name:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoh1M9YIWALZ0prmQgC7yz6xNUpzBWYRFkgsDjvqmsTE4-Nu7KW7-24mTjXKDkV4enl4hKBGyYqDtA4FQlNi-at0nvHnuUd3lzmlnY54x_3_vFtVqB-HGAveZHjH2YDSAR_3FvBw/s1600/Screen+shot+2013-12-28+at+9.37.29+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjoh1M9YIWALZ0prmQgC7yz6xNUpzBWYRFkgsDjvqmsTE4-Nu7KW7-24mTjXKDkV4enl4hKBGyYqDtA4FQlNi-at0nvHnuUd3lzmlnY54x_3_vFtVqB-HGAveZHjH2YDSAR_3FvBw/s320/Screen+shot+2013-12-28+at+9.37.29+PM.png" height="168" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Next, sweet victory:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWTuc4OUc6ID8fhHIiG_Dhdkkgb5VxV-a32mq_TX9moI2qEyVKL3H3MVvTmXcIoKJFXU7CJ9NcpyCySbwTuXANEQRIvxRXwNZZ_8Yk0ULIWI2wdSHKQqdbATBonvDxjDqURD8ofg/s1600/Screen+shot+2013-12-28+at+9.38.04+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWTuc4OUc6ID8fhHIiG_Dhdkkgb5VxV-a32mq_TX9moI2qEyVKL3H3MVvTmXcIoKJFXU7CJ9NcpyCySbwTuXANEQRIvxRXwNZZ_8Yk0ULIWI2wdSHKQqdbATBonvDxjDqURD8ofg/s320/Screen+shot+2013-12-28+at+9.38.04+PM.png" height="168" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhR8EXkg42J_HHi6H9LdJL1UFOiRMbM2CPQBdJxIBGy6K62Garl2Ja9rv5BvOLbT5QskTH6PJtvJ1vmq6_K7BsQszIyresSbouUzBM4RocNf9oW_ClC4oDgdKugaF8OTDnZAjyd9w/s1600/Screen+shot+2013-12-28+at+9.38.48+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhR8EXkg42J_HHi6H9LdJL1UFOiRMbM2CPQBdJxIBGy6K62Garl2Ja9rv5BvOLbT5QskTH6PJtvJ1vmq6_K7BsQszIyresSbouUzBM4RocNf9oW_ClC4oDgdKugaF8OTDnZAjyd9w/s320/Screen+shot+2013-12-28+at+9.38.48+PM.png" height="168" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
We're back in business. Just remember, because this was recovered from a backup, some of the most recent transactions, since that backup was made, will be missing. You'll need to enter those again. That's why it's good practice to perform backups often.<br />
<br />
Now let's talk about why this happens, and how Intuit could have dealt with it in a better way and not have us jump through all those hoops. I'm a software developer. It's right up my ally.<br />
<br />
In my case the problem happened because I inadvertently launched QuickBooks twice. My computer had just rebooted after Microsoft installed a bunch of updates, and now was acting pretty sluggish (thanks Microsoft !). My initial attempt to open QuickBooks seemed to go nowhere, so I tried to open it up again. Upon closer inspection, using the task manager, I was able to see 2 instances of the QuickBooks app running. Uh-oh. Shortly after came the error message about the crash.<br />
<br />
So the first failure of Intuit was to handle this common scenario, of trying to open the program multiple times. Obviously, when QuickBooks opens it must be writing something in the company file, and having multiple instances open causes them to step on each other's toes and results in corrupting that file. There are plenty of ways to ensure exclusive access to a file by a single process - pretty basic stuff - which Intuit failed to implement.<br />
<br />
There are other ways in which the company file may get corrupted, for example if something happens with the application/operating system/computer while the file is in the process of being written. There are ways of dealing with those scenarios too, and indeed a well engineered app should try to prevent errors and data corruption. But those may happen anyway, despite our best intentions. So the next step would be automatic error recovery. Here Intuit fails again. They pretty much try to open the same corrupted file each time the app launches, resulting in crashing over and over.<br />
<br />
A better way would be to catch that error and not let the app crash, or at least on subsequent launches detect that the app had previously crashed, and enter a recovery mode. The recovery could be made from a redundant copy of the company file or from a backup, as I manually did above.<br />
<br />
These are 2 principles worth observing when doing software development. First do your best to prevent errors. Then assume that some errors will happen anyway and ensure that you can recover from them graciously.Unknownnoreply@blogger.com13tag:blogger.com,1999:blog-35323211.post-91357749515821546652013-05-25T09:00:00.000-07:002013-05-25T09:00:01.665-07:00How to fix PDFs that appear with colors too dark or too bright when viewed on iPad or iPhone.In some of my iOS projects I had to display PDFs of documents originally intended for print format. Some of those PDFs would appear horribly on iOS devices, with colors messed up. It was a pretty surprising behaviour, which I initially attributed to bugs in Apple's PDF rendering code.<br />
<br />
My first approach to getting around such problems was to use a server-side component powered by Ghostscript to convert each PDF page into an image, that would show up in the right colors, and display that. The advantage of this approach is that it can be fully automated. The disadvantage is that images may show up poorly (pixelated) when zoomed in, depending on their pixel density.<br />
<br />
Upon investigating this problem further I discovered <a href="http://www.makeyourmobileapp.com/How-to-fix-dark-or-bright-PDFs-viewed-on-iPad.html">a way to fix this problem</a> at its root, that is the source PDF document. Unfortunately it can't be automated easily because it involves running Adobe's Acrobat tool. In the absence of a public API to run that conversion programatically one has the option of using workflow-recording tools like Apple's Automator to drive the Acrobat automatically. While that approach may work, it would be hard to scale in a cost-effective manner.<br />
<br />
Another option to handle this may be to use iText to automatically convert CYMK profiles to RGB, or if that's not possible, to at least detect the presence of CYMK profiles and alert the user about the need to convert the PDF manually using Acrobat.<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-34581722909320293662013-05-14T06:17:00.001-07:002013-05-14T06:17:49.093-07:00So we had the www for a while. What's next ?The dawn of the web introduced us to URLs starting with "http://www". For those old enough to remember those days of <a href="https://en.wikipedia.org/wiki/Lynx_(web_browser)">Lynx</a>, <a href="http://en.wikipedia.org/wiki/Mosaic_(web_browser)">Mosaic</a>, and <a href="http://en.wikipedia.org/wiki/Netscape_Navigator">Netscape</a>, "www" was true to its meaning of "world-wide web". Suddenly anyone connected to the Internet was able to reach out to any remote place in the world, also connected to the net, and browse the information published there. Powerful.<br />
<br />
Since then a lot has changed. The devices we use to access the net had moved from our desks to our palms, and soon to our glasses, and with the mobility they afford, the Internet access got a new dimension - that of context, or location. So in addition to what's out there (www) now what's over here becomes an interesting question. Perhaps some new URLs, like "http://here" and "http://now", start to make sense. Seems that I'm not the only one thinking so. Nokia appears to be doing something like that with <a href="http://here.com/">http://here.com</a>. If face recognition becomes a feature of Google Glass, then a "http://you" makes sense too. I'm probably stating the obvious here, but what I'd like to see is more of these 2 things:<br />
<br />
1. The ability of users to freely add and annotate the content presented. Think of "Augmented Reality Wikipedia". Like "digital graffiti" curated through a vote-based meritocracy, or by applying a filtering based on what your contacts on social networks think of that content.<br />
<br />
2. More mash-ups. With the growing number of web services (<a href="http://blog.programmableweb.com/2013/04/30/9000-apis-mobile-gets-serious/" rel="nofollow">over 9000 APIs as of now</a>), and the continued move toward a more semantic web, the ability to mash things up should continue to grow.<br />
<br />
It'd be interesting to see how all this will unfold, and maybe even contribute to this vision. Such projects, once they pass a critical mass of adoption, they tend to snowball fast.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-51685651576737250782013-05-10T06:50:00.000-07:002013-05-10T06:58:16.944-07:00Rendering office documents in HTML - an idea whose time has comeA while ago I was working on <a href="http://www.tartor.com/portfolio/?permaLink=mwapp">a project</a> that needed rendering PDFs on iOS. There are several ways to do that. On iOS, that is. My client wanted a solution for Android too, and was complaining about the lack of similar capabilities there. Since Android wasn't one of my areas of competence at the time I wasn't involved with that effort directly. However I kept hearing about the need to use some 3rd party, rather expensive, libraries.<br />
<br />
So naturally it dawned on me this idea: why don't the "owners" of the PDF format, Adobe, provide a cross-platform viewer. The natural solution would be an HTML based approach, since virtually all popular platforms provide a way to display HTML. At the time I was thinking that the capabilities provided by HTML 5 and CSS 3 should be enough to accomplish the "print-quality" level of rendering offered by Adobe's Acrobat Reader or Apple's Preview. Since Adobe wasn't doing much about it, it seemed a pretty good opportunity. Turns out that wasn't such a bad idea. In fact folks at <a href="https://crocodoc.com/" rel="nofollow">Crocodoc</a> were banging at it since 2006. Today was the <a href="http://blog.crocodoc.com/post/50019810661/crocodoc-joins-box-to-reimagine-documents-in-the-cloud" rel="nofollow">payback</a>. Good for them.<br />
<br />
I only heard about them today. A brief glance at their API shows that right now it fetches the documents from some servers, where they're processed and converted from PDF to HTML. With this dependency on a server-side component it doesn't seem to have support for offline viewing. I guess one could hack around and save the generated HTML and all the referenced components (images, CSS, and what not), but that may be a brittle solution. With their new owner I'm sure they'll keep improving their technology and this may well become a compelling cross-platform document rendering solution.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-8260998241083069962013-05-04T10:45:00.000-07:002013-05-04T10:45:00.182-07:00Caveats of using MPMoviePlayerControllerFor a recent iOS project I had to play some videos, embedded in a subview of a larger view. One way to achieve that is to employ the <a href="http://developer.apple.com/library/ios/#documentation/MediaPlayer/Reference/MPMoviePlayerController_Class/Reference/Reference.html" rel="nofollow">MPMoviePlayerController</a>. At first glance that component seems easy enough to use. Folks at Apple are trying to help by providing the following code snippet, right there in the official docs:<br />
<br />
<div style="color: #666666; font-family: Courier; font-size: 12px;">
MPMoviePlayerController *player =</div>
<div style="color: #666666; font-family: Courier; font-size: 12px;">
[[MPMoviePlayerController alloc] initWithContentURL: myURL];</div>
<div style="color: #666666; font-family: Courier; font-size: 12px; min-height: 14px;">
<br /></div>
<div style="color: #666666; font-family: Courier; font-size: 12px;">
[player prepareToPlay];</div>
<div style="color: #666666; font-family: Courier; font-size: 12px; min-height: 14px;">
<br /></div>
<div style="color: #666666; font-family: Courier; font-size: 12px;">
[player.view setFrame: myView.bounds]; // player's frame must match parent's</div>
<div style="color: #666666; font-family: Courier; font-size: 12px; min-height: 14px;">
<br /></div>
<div style="color: #666666; font-family: Courier; font-size: 12px;">
[myView addSubview: player.view];</div>
<div style="color: #666666; font-family: Courier; font-size: 12px; min-height: 14px;">
<br /></div>
<div style="color: #666666; font-family: Courier; font-size: 12px;">
// ...</div>
<div style="color: #666666; font-family: Courier; font-size: 12px; min-height: 14px;">
<br /></div>
<div style="color: #666666; font-family: Courier; font-size: 12px;">
[player play];</div>
<br />
Right on. I'm adding this stuff to my app, and ... nothing happens. Nothing plays, just a black rectangle where the video player was supposed to show up. My first reaction was to look if they have a complete sample project that I could play with, and learn how to use the API. They do. I open it and it's using manual memory management (pre-ARC). Yuck ! Still I look there and see that they're using notifications to observe the state of the player. That sounds like a good way to debug what's going on. I do the same in my code. None of the notifications get called. What the ... ?<br />
<br />
On a 2nd look at the code above, it becomes clear that in an ARC project, like mine was, the <span style="background-color: #f1f5f9; color: #666666; font-family: Courier, Consolas, monospace; font-size: 12px; line-height: 13px; white-space: pre-wrap;">player</span> local variable will be gone at the end of its enclosing scope. No wonder that nothing happens. The player must be kept alive through a strong ivar, or property. Doing that fixed my problem. So Apple's code snippet is pretty bad. It would have worked in the pre-ARC projects, albeit by leaking memory, but obviously this stuff was never updated for ARC.<br />
<br />
Luckily I have plenty of experience doing manual memory management, and I can handle old code bases, like so many of Apple's code samples are. For now I'll inform their docs team of the problem.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-18611174555565688622013-04-27T10:03:00.000-07:002013-04-27T10:03:00.500-07:00Keeping the code clean of warnings helps your productivityIn some Fortune 500 companies I worked we had an official policy of 0 compilation warnings allowed in the code. That was a good practice that saved us of many troubles. Since then I try to follow that practice in my projects.<br />
<br />
Let's see an example:<br />
<br />
<div style="color: #d12f1b; font-family: Monaco; font-size: 12px;">
<span style="color: black;"> </span><span style="color: #3d1d81;">NSLog</span><span style="color: black;">(</span>@"Hello, World!"<span style="color: black;">);</span></div>
<div style="font-family: Monaco; font-size: 12px; min-height: 16px;">
</div>
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #bb2ca2;">int</span> i = <span style="color: #272ad8;">1</span>;</div>
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #bb2ca2;">switch</span> (i) {</div>
<div style="font-family: Monaco; font-size: 12px;">
case1:</div>
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #3d1d81;">NSLog</span>(<span style="color: #d12f1b;">@"OK"</span>);</div>
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #bb2ca2;">break</span>;</div>
<div style="font-family: Monaco; font-size: 12px;">
}</div>
<br />
If I placed this code in a project with the default settings created by Xcode, the result wouldn't output the "OK" string, due to the "<span style="font-family: Monaco; font-size: 12px;">case1:</span>" typo which transformed the "<span style="font-family: Monaco; font-size: 12px;">case 1:</span>" case statement into an unused label. The compilation wouldn't produce any warning. Neither would the static analyzer.<br />
<br />
You can however catch such problems at compile time, by changing the default settings like so:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiV0JlT4WABbyXzYFa4TehmkWXxLlgLpvcW8tlqXTHT2RP0BPSD-fS2V6kUyr-_-ccYvtOxHIPKt_qcbE0QnQOgN4XwWmyv1MyD3bVpaQ-jz145D923v5ui5P1Vf3ubfZVqVLAmLw/s1600/Screen+Shot+2013-04-20+at+7.50.22+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiV0JlT4WABbyXzYFa4TehmkWXxLlgLpvcW8tlqXTHT2RP0BPSD-fS2V6kUyr-_-ccYvtOxHIPKt_qcbE0QnQOgN4XwWmyv1MyD3bVpaQ-jz145D923v5ui5P1Vf3ubfZVqVLAmLw/s320/Screen+Shot+2013-04-20+at+7.50.22+PM.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
This enables all warnings. The following setting treats all warning as errors:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQcfc72BnLWW2Uc1iP1pfA2h7Dij__lIp7vVGlWFK_ei8ZUGnBr37m4hOwLiLwd24vQtJNKvVC41X80Lqn0vkn9ruMFMJoMktCzuKDHXYyxtl-Jdvn_mx-0PVZACbG4vOu6hMT-Q/s1600/Screen+Shot+2013-04-20+at+8.13.57+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQcfc72BnLWW2Uc1iP1pfA2h7Dij__lIp7vVGlWFK_ei8ZUGnBr37m4hOwLiLwd24vQtJNKvVC41X80Lqn0vkn9ruMFMJoMktCzuKDHXYyxtl-Jdvn_mx-0PVZACbG4vOu6hMT-Q/s320/Screen+Shot+2013-04-20+at+8.13.57+PM.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
If I now try to compile I get this error:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT3_yJm3knRg3WAHLY4K9COg9SOmF-qJhyqaNMouq4vdbay_8zFDSzgwzDn-PeYoOBiI4KdlWNJJKC-ZMyFLVaGaXgSIRC3UuI0Wb6jUm_QWlkPGGTku7By79Vk6xkXT39bEk24A/s1600/Screen+Shot+2013-04-20+at+8.15.45+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT3_yJm3knRg3WAHLY4K9COg9SOmF-qJhyqaNMouq4vdbay_8zFDSzgwzDn-PeYoOBiI4KdlWNJJKC-ZMyFLVaGaXgSIRC3UuI0Wb6jUm_QWlkPGGTku7By79Vk6xkXT39bEk24A/s1600/Screen+Shot+2013-04-20+at+8.15.45+PM.png" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Catching this bug at compile time is much better than later when the app may have been released.<br />
<br />
Another useful setting to have is this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0BcyzYXlD2a_QLwtyQ-bDHRt1PsQFEduYbrKi_YTMbcpbNtVSrJfNI73EUj-EoaqwpxbdtPc0HuFQS0XcSmmEfk5evSROGeSqDLdL_YyO_VYkjt4ObEOd0WHoCfHDn72vJmVwcQ/s1600/Screen+Shot+2013-04-20+at+7.51.39+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0BcyzYXlD2a_QLwtyQ-bDHRt1PsQFEduYbrKi_YTMbcpbNtVSrJfNI73EUj-EoaqwpxbdtPc0HuFQS0XcSmmEfk5evSROGeSqDLdL_YyO_VYkjt4ObEOd0WHoCfHDn72vJmVwcQ/s320/Screen+Shot+2013-04-20+at+7.51.39+PM.png" width="320" /></a></div>
which runs the static analyzer on every compilation. I found this combination of settings very useful to smoke out bugs shortly after they have been introduced.<br />
<br />
<br />
<br />
<br />
<br />
Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-75492244501054916382013-04-20T08:58:00.000-07:002013-04-20T09:00:29.337-07:00Unexpected side effect of fast enumeration in Objective-CFast enumeration is a relatively new capability in Objective-C. For a thorough survey of all the ways one can enumerate through a collection, you can see <a href="http://www.mikeash.com/pyblog/friday-qa-2010-04-09-comparison-of-objective-c-enumeration-techniques.html" rel="nofollow">this post</a>.<br />
<br />
In a recent project I had a code sequence like this (modified here for illustration):<br />
<br />
<br />
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #703daa;">NSArray</span> *array = <span style="color: #272ad8;">@[@1</span>, <span style="color: #272ad8;">@2]</span>;</div>
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #703daa;">NSNumber</span> *number = <span style="color: #bb2ca2;">nil</span>;</div>
<div style="font-family: Monaco; font-size: 12px; min-height: 16px;">
<br /></div>
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #bb2ca2;">for</span> (number <span style="color: #bb2ca2;">in</span> array) {</div>
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #3d1d81;">NSLog</span>(<span style="color: #d12f1b;">@"number: %@"</span>, number);</div>
<div style="font-family: Monaco; font-size: 12px;">
}</div>
<div style="font-family: Monaco; font-size: 12px; min-height: 16px;">
</div>
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #3d1d81;">NSLog</span>(<span style="color: #d12f1b;">@"Last number: %@"</span>, number);</div>
<div>
<br /></div>
<br />
My expectation was that at the end of the for loop the <span style="font-family: Monaco; font-size: 12px;">number</span> variable would hold the last value of the <span style="font-family: Monaco; font-size: 12px;">array</span>. Here's what I get instead:<br />
<br />
<br />
<div style="font-family: Menlo; font-size: 11px;">
<b>2013-04-19 17:13:06.223 FastEnumBug[49016:303] number: 1</b></div>
<div style="font-family: Menlo; font-size: 11px;">
<b>2013-04-19 17:13:06.240 FastEnumBug[49016:303] number: 2</b></div>
<div style="font-family: Menlo; font-size: 11px;">
<b>2013-04-19 17:13:06.241 FastEnumBug[49016:303] Last number: (null)</b></div>
<div>
<br /></div>
<br />
Strangely the value comes back as <span style="color: #bb2ca2; font-family: Monaco; font-size: 12px;">nil</span>. Which is what it was initialized to before entering the loop. Could that be the case ? Let's try this instead:<br />
<br />
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #703daa;">NSArray</span> *array = <span style="color: #272ad8;">@[@1</span>, <span style="color: #272ad8;">@2]</span>;</div>
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #703daa;">NSNumber</span> *number = <span style="color: #272ad8;">@100</span>;</div>
<div style="font-family: Monaco; font-size: 12px; min-height: 16px;">
<br /></div>
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #bb2ca2;">for</span> (number <span style="color: #bb2ca2;">in</span> array) {</div>
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #3d1d81;">NSLog</span>(<span style="color: #d12f1b;">@"number: %@"</span>, number);</div>
<div style="font-family: Monaco; font-size: 12px;">
}</div>
<div style="font-family: Monaco; font-size: 12px; min-height: 16px;">
</div>
<div style="font-family: Monaco; font-size: 12px;">
<span style="color: #3d1d81;">NSLog</span>(<span style="color: #d12f1b;">@"Last number: %@"</span>, number);</div>
<br />
which produces:<br />
<br />
<br />
<div style="font-family: Menlo; font-size: 11px;">
<b>2013-04-20 18:47:34.209 FastEnumBug[62468:303] number: 1</b></div>
<div style="font-family: Menlo; font-size: 11px;">
<b>2013-04-20 18:47:34.212 FastEnumBug[62468:303] number: 2</b></div>
<div style="font-family: Menlo; font-size: 11px;">
<b>2013-04-20 18:47:34.212 FastEnumBug[62468:303] Last number: (null)</b></div>
<div>
<b><br /></b></div>
<br />
Nope, I still get <span style="color: #bb2ca2; font-family: Monaco; font-size: 12px;">nil</span>, not the <span style="color: #272ad8; font-family: Monaco; font-size: 12px;">@100 </span>value at the entry of the loop. So it seems that fast enumeration blocks reset the value of the iteration pointer in the outer context back to <span style="color: #bb2ca2; font-family: Monaco; font-size: 12px;">nil</span>. This is, at least to me, unexpected. Maybe it's a bug. I'll see what Apple has to say.<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-69974404426463318472013-03-23T09:30:00.000-07:002013-04-19T23:37:30.061-07:00Charging for wireless services by auctionI've been thinking about this for a while now. All mobile network operators have a rigid price structure, in some markets, like Canada, with <a href="http://www.fido.ca/web/page/portal/Fido/MonthlyPlans" rel="nofollow">outrageous costs</a>. Yet when certain areas of the network are idle, due to low traffic, the network equipment remains unused, and is producing no revenue. It strikes me as a very inefficient way to allocate and manage resources. I believe an auction-based model, where available capacity is up for bidding would be more efficient.<br />
<br />
Once the costs of laying out a network have been sunk, the ongoing cost of operations should dwarf the initial investment, and should allow for a wide range of pricing to make economic sense. That is, the cost of allowing access to a spare channel of communication between a mobile device and the network shouldn't be much higher than the cost of keeping that channel unused, on stand-by. I'd venture to guess that most of the additional cost is for the energy used to power the transmission.<br />
<br />
Hence the opportunity, if I'm a customer in the right place at the right time, and the cell covering that location has plenty of spare capacity at that particular time, I should be given the opportunity to get access to the network at a rate lower than the going rate. Whereas I would <i>almost</i> <i>never</i> pay the $10/GB going rate, I would be willing to pay a lower price. Because of the rigid pricing, however, this opportunity goes wasted. I don't get to use the service, the service provider doesn't get paid. Lose-lose scenario. Flexible pricing would turn it in a win-win.<br />
<br />
Conversely, sometimes you might find yourself in an area that's highly congested, with no physical ability to accommodate everyone, even at the going rate. Some calls will need to be dropped. Flexible pricing would be a way to guarantee a connection for the higher bidders. So <i>sometime</i> I would be willing to pay above the $10/GB rate.<br />
<br />
Such flexibility would benefit all parties. Sure there would be some complexity added to metering and billing, and some signalling mechanisms should be devised for dealing with the bidding process, but the gains may far outweigh the costs. Why nobody implemented something like this, especially for pre-paid or pay-per-use plans, remains a mystery.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-58463885863593350242013-02-16T07:54:00.000-08:002013-06-16T06:15:43.763-07:00UIView gotchas in iOSIn iOS the UI consists of a hierarchy of views and view controllers, linked through containment relationships. That's following the common composite design pattern, which should be familiar to most programmers. In addition there is a specific system-imposed lifecycle, which governs how all those pieces come into existence, and various callbacks that the system (Cocoa Touch) calls at specific points in this lifecycle. All this is fairly well documented, but with experience comes additional insights, and lessons learned the hard way. Here's what I discovered:<br />
<br />
If your code relies on the coordinates of a view's frame, then your best bet is reading the frame in:<br />
<br />
<div style="font-family: Monaco; font-size: 12px;">
- (<span style="color: #bb2ca2;">void</span>)viewWillAppear:(<span style="color: #bb2ca2;">BOOL</span>)animated</div>
<br />
You may be tempted to use <span style="font-family: Monaco; font-size: 12px;">- (</span><span style="color: #bb2ca2; font-family: Monaco; font-size: 12px;">void</span><span style="font-family: Monaco; font-size: 12px;">)viewDidLoad</span> for the same purpose, which gets called earlier in the lifecycle, however at that time <a href="http://stackoverflow.com/questions/6757018/why-am-i-having-to-manually-set-my-views-frame-in-viewdidload" rel="nofollow">the frame may not have its value set accurately</a>. I find this happening often especially for iPad. Most times I use the storyboard (and IB in the past) to implement my UIs. I usually lay it out in portrait mode only, and rely on the autoresizing mask, or layout constraints, to position everything properly. Because on iPad you can launch an app in landscape mode directly, the frame in <span style="font-family: Monaco; font-size: 12px;">viewDidLoad </span>will appear as defined in the storyboard, with the size for portrait. If those values are relied upon later, that would result in problems.<br />
<br />
This problem may also occur in obscure contexts, where one is not directly using the frame. For example <a href="http://bhapca.blogspot.ro/2013/01/unexpected-behaviour-when-calling.html">in a previous post</a> I was mentioning some weird behaviour when setting the value of a progress bar, like so:<br />
<br />
<span style="background-color: #eeeeee; color: #333333; font-family: Monaco; font-size: 12px; line-height: 20px; text-align: left;">[</span><span style="background-color: #eeeeee; color: #bb2ca2; font-family: Monaco; font-size: 12px; line-height: 20px; text-align: left;">self</span><span style="background-color: #eeeeee; color: #333333; font-family: Monaco; font-size: 12px; line-height: 20px; text-align: left;">.</span><span style="background-color: #eeeeee; color: #4f8187; font-family: Monaco; font-size: 12px; line-height: 20px; text-align: left;">progressBar</span><span style="background-color: #eeeeee; color: #333333; font-family: Monaco; font-size: 12px; line-height: 20px; text-align: left;"> </span><span style="background-color: #eeeeee; color: #3d1d81; font-family: Monaco; font-size: 12px; line-height: 20px; text-align: left;">setProgress</span><span style="background-color: #eeeeee; color: #333333; font-family: Monaco; font-size: 12px; line-height: 20px; text-align: left;">:</span><span style="background-color: #eeeeee; color: #272ad8; font-family: Monaco; font-size: 12px; line-height: 20px; text-align: left;">0.5</span><span style="background-color: #eeeeee; color: #333333; font-family: Monaco; font-size: 12px; line-height: 20px; text-align: left;"> </span><span style="background-color: #eeeeee; color: #3d1d81; font-family: Monaco; font-size: 12px; line-height: 20px; text-align: left;">animated</span><span style="background-color: #eeeeee; color: #333333; font-family: Monaco; font-size: 12px; line-height: 20px; text-align: left;">:</span><span style="background-color: #eeeeee; color: #bb2ca2; font-family: Monaco; font-size: 12px; line-height: 20px; text-align: left;">YES</span><span style="background-color: #eeeeee; color: #333333; font-family: Monaco; font-size: 12px; line-height: 20px; text-align: left;">];</span><br />
<br />
Apple took a look at it and informed me that "<span style="font-family: inherit;">The view animates from an undefined state. Doing such things in the viewDidLoad can only lead to problems.</span>".<br />
<br />
<b>Update:</b><br />
<b><br /></b>
While watching the slides from <a href="https://itunes.apple.com/us/course/coding-together-developing/id593208016" rel="nofollow">Stanford's iOS Programming course</a> I discovered that in case that autolayout is used, instead of using <span style="font-family: Monaco; font-size: 12px;">viewWillAppear</span> to get the view's geometry, one must use<br />
<br />
<span style="background-color: white; font-family: Courier, Consolas, monospace; font-size: 13px;">- (void)viewDidLayoutSubviews</span><br />
<br />
Apparently the latter is guaranteed to be called each time the bounds of the view change, and by the time that happens all the autolayout constrains would have been processed and the geometry would have been established.Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-45843102792323989362013-01-26T10:52:00.000-08:002013-04-15T10:16:45.474-07:00Unexpected behaviour when calling setProgress:animated: twice in the same run loopI found some bugs in <span style="background-color: white; font-family: Courier, Consolas, monospace; font-size: 13px;">setProgress:</span><span style="background-color: white; font-family: Courier, Consolas, monospace; font-size: 13px;">animated:</span> method of <span style="background-color: white; color: #666666; font-family: Courier, Consolas, monospace; font-size: 13px;">UIProgressView</span>. It seems that calling it several times within the same run loop ignores all but the last call.<br />
<br />
For instance, I have a bar set up in the storyboard with the progress all the way to the max (i.e. 1.0). If later in the code I do this:<br />
<br />
<br />
<div style="color: #3d1d81; font-family: Monaco; font-size: 12px;">
</div>
- (<span style="color: #bb2ca2;">IBAction</span>)showBug {<br />
<span style="color: black;"> [</span><span style="color: #bb2ca2;">self</span><span style="color: black;">.</span><span style="color: #4f8187;">progressBar</span><span style="color: black;"> </span>setProgress<span style="color: black;">:</span><span style="color: #272ad8;">0.0</span><span style="color: black;"> </span>animated<span style="color: black;">:</span><span style="color: #bb2ca2;">NO</span><span style="color: black;">];</span><br />
<span style="color: black;"> [</span><span style="color: #bb2ca2;">self</span><span style="color: black;">.</span><span style="color: #4f8187;">progressBar</span><span style="color: black;"> </span>setProgress<span style="color: black;">:</span><span style="color: #272ad8;">0.5</span><span style="color: black;"> </span>animated<span style="color: black;">:</span><span style="color: #bb2ca2;">YES</span><span style="color: black;">];</span><br />
}<br />
<div>
<br /></div>
<br />
<br />
I would expect the bar to jump to 0 and then animate to 0.5. What happens instead, the bar animates from 1.0 to 0.5.<br />
<br />
One workaround, of course, is to place the 2nd call on a separate run loop, like so:<br />
<br />
<br />
<div style="font-family: Monaco; font-size: 12px;">
- (<span style="color: #bb2ca2;">void</span>)hack</div>
<div style="font-family: Monaco; font-size: 12px;">
{</div>
<div style="color: #3d1d81; font-family: Monaco; font-size: 12px;">
<span style="color: black;"> [</span><span style="color: #bb2ca2;">self</span><span style="color: black;">.</span><span style="color: #4f8187;">progressBar</span><span style="color: black;"> </span>setProgress<span style="color: black;">:</span><span style="color: #272ad8;">0.5</span><span style="color: black;"> </span>animated<span style="color: black;">:</span><span style="color: #bb2ca2;">YES</span><span style="color: black;">];</span></div>
<div style="font-family: Monaco; font-size: 12px;">
}</div>
<div style="font-family: Monaco; font-size: 12px; min-height: 16px;">
<br /></div>
<div style="font-family: Monaco; font-size: 12px;">
- (<span style="color: #bb2ca2;">IBAction</span>)fixIt {</div>
<div style="color: #3d1d81; font-family: Monaco; font-size: 12px;">
<span style="color: black;"> [</span><span style="color: #bb2ca2;">self</span><span style="color: black;">.</span><span style="color: #4f8187;">progressBar</span><span style="color: black;"> </span>setProgress<span style="color: black;">:</span><span style="color: #272ad8;">0.0</span><span style="color: black;"> </span>animated<span style="color: black;">:</span><span style="color: #bb2ca2;">NO</span><span style="color: black;">];</span></div>
<div style="color: #3d1d81; font-family: Monaco; font-size: 12px;">
<span style="color: black;"> [</span><span style="color: #bb2ca2;">self</span><span style="color: black;"> </span>performSelector<span style="color: black;">:</span><span style="color: #bb2ca2;">@selector</span><span style="color: black;">(hack) </span>withObject<span style="color: black;">:</span><span style="color: #bb2ca2;">nil</span><span style="color: black;"> </span>afterDelay<span style="color: black;">:</span><span style="color: #272ad8;">0</span><span style="color: black;">];</span></div>
<div style="font-family: Monaco; font-size: 12px;">
}</div>
<div>
<br /></div>
<br />
Ahh, the trusted 0 timer. How many times it saved my skin. For instance, when mutating collections while iterating. And not only in Objective-C, I remember using it in JavaScript to work around all kinds of browser bugs. That's the advantage of having exposure to multiple platforms and languages. You learn all kinds of tricks.<br />
<br />
Incidentally, when I was preparing the bug report for Apple, I discovered yet another, unrelated bug. Placing this line:<br />
<br />
<span style="font-family: Monaco; font-size: 12px;">[</span><span style="color: #bb2ca2; font-family: Monaco; font-size: 12px;">self</span><span style="font-family: Monaco; font-size: 12px;">.</span><span style="color: #4f8187; font-family: Monaco; font-size: 12px;">progressBar</span><span style="font-family: Monaco; font-size: 12px;"> </span><span style="color: #3d1d81; font-family: Monaco; font-size: 12px;">setProgress</span><span style="font-family: Monaco; font-size: 12px;">:</span><span style="color: #272ad8; font-family: Monaco; font-size: 12px;">0.5</span><span style="font-family: Monaco; font-size: 12px;"> </span><span style="color: #3d1d81; font-family: Monaco; font-size: 12px;">animated</span><span style="font-family: Monaco; font-size: 12px;">:</span><span style="color: #bb2ca2; font-family: Monaco; font-size: 12px;">YES</span><span style="font-family: Monaco; font-size: 12px;">];</span><br />
<br />
in the <span style="font-family: Monaco; font-size: 12px;">- (</span><span style="color: #bb2ca2; font-family: Monaco; font-size: 12px;">void</span><span style="font-family: Monaco; font-size: 12px;">)viewDidLoad</span> method of the view controller makes another mess. Now the bar, which was placed statically in the storyboard, (in my example I had it centred) it animates when the app starts, through a "genie" animation from the top-left. Nice, but definitely not what I intended.<br />
<br />
<b>Update:</b> Regarding the latter bug, Apple informed me that <span style="background-color: #eeeeee; color: #333333; font-family: 'Trebuchet MS', Verdana, Arial, sans-serif; font-size: 14px; line-height: 20px; text-align: left;"> "</span><span style="background-color: #eeeeee; color: #333333; font-family: inherit; font-size: 14px; line-height: 20px; text-align: left;">The view animates from an undefined state. Doing such things in the viewDidLoad can only lead to problems.</span><span style="background-color: #eeeeee; color: #333333; font-family: 'Trebuchet MS', Verdana, Arial, sans-serif; font-size: 14px; line-height: 20px; text-align: left;">"</span>. See <a href="http://bhapca.blogspot.ro/2013/02/view-gotchas-in-ios.html">this post</a> for a discussion of the perils of reading/writing the frame of a view in <span style="font-family: Monaco; font-size: 12px;">viewDidLoad</span>.<br />
<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-60126912473246527792012-12-22T09:00:00.000-08:002013-02-06T00:25:57.578-08:00View gets inset by 20 points when instantiated through instantiateViewControllerWithIdentifierIn a recent project I had a custom container view controller in which I wanted to embed another custom content controller, as a child controller. Since the content controller already resided in the storyboard I thought I'd use a sequence of code like so:<br />
<br />
<br />
<div style="color: #3d1d81; font-family: Monaco; font-size: 12px;">
<span style="color: black;"> </span><span style="color: #4f8187;">PdfViewController</span><span style="color: black;"> *pvc = [</span><span style="color: #bb2ca2;">self</span><span style="color: black;">.</span><span style="color: #703daa;">storyboard</span><span style="color: black;"> </span>instantiateViewControllerWithIdentifier<span style="color: black;">:</span><span style="color: #d12f1b;">@"PdfViewController"</span><span style="color: black;">];</span></div>
<div style="color: #3d1d81; font-family: Monaco; font-size: 12px;">
<span style="color: black;"> [</span><span style="color: #bb2ca2;">self</span><span style="color: black;"> </span>addChildViewController<span style="color: black;">:pvc];</span></div>
<div style="font-family: Monaco; font-size: 12px;">
[<span style="color: #bb2ca2;">self</span>.<span style="color: #703daa;">view</span> <span style="color: #3d1d81;">addSubview</span>:pvc.<span style="color: #703daa;">view</span>];</div>
<div style="color: #3d1d81; font-family: Monaco; font-size: 12px;">
<span style="color: black;"> [pvc </span>didMoveToParentViewController<span style="color: black;">:</span><span style="color: #bb2ca2;">self</span><span style="color: black;">];</span></div>
<div>
<span style="color: black;"><br /></span></div>
<br />
Giving it a try produced this result:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn7HvO3CvSwwX4sZEpWM_FCBEPq-5oXw0JPu0g2uuZmRJmT-Yep5iavXSO3-XgD2QfU3-X6V58O-j37om1qeertpfLezFAa3IssT7WDOXsZdmzYweLkf_d949lMswtOYF32jxP0w/s1600/Screen+Shot+2012-12-20+at+5.42.32+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn7HvO3CvSwwX4sZEpWM_FCBEPq-5oXw0JPu0g2uuZmRJmT-Yep5iavXSO3-XgD2QfU3-X6V58O-j37om1qeertpfLezFAa3IssT7WDOXsZdmzYweLkf_d949lMswtOYF32jxP0w/s320/Screen+Shot+2012-12-20+at+5.42.32+PM.png" width="265" /></a></div>
<br />
<br />
You can see an unsightly white band at the top of the screen. By the looks of it it seems about the same size as the status bar. It's as if the view of the embedded view controller loaded by <span style="color: #3d1d81; font-family: Monaco; font-size: 12px;">instantiateViewControllerWithIdentifier</span> is inset to make room for the status bar. A little debugging confirmed that indeed that's the case:<br />
<br />
<br />
<div style="font-family: Menlo; font-size: 11px;">
<span style="color: #6389ff;"><b>(lldb) </b></span><b>p (CGRect)[[pvc view] frame]</b></div>
<div style="font-family: Menlo; font-size: 11px;">
(CGRect) $1 = origin=(x=0, y=<span style="background-color: #ffdad8; text-decoration: underline;">20</span>) size=(width=320, height=460)</div>
<div style="color: #6389ff; font-family: Menlo; font-size: 11px;">
<b>(lldb) </b></div>
<div>
<b><br /></b></div>
<br />
My first thought was that it may be caused by the default "Status Bar" setting under the "Simulated Metrics" section in the utility pane. That "simulated" qualifier still raised some questions. AFAIK those simulated metrics <a href="http://www.raywenderlich.com/5138/beginning-storyboards-in-ios-5-part-1" rel="nofollow">are only used as an aid in designing the UI</a>, without any effect at runtime. A more promising clue should be given by the size inspector of that view in IB:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAe0mHZMPg7kCvyrV23WkivnZFNwrV9gc3VH32HSvzdjbhektrwAaYiFt0TddDPb096Bo9QX-gDh94l6wWQAz05eEESnRm4SmyVY_-L97724ppCjaDDJneb1WV4ShEnPYW4lHqzQ/s1600/Screen+Shot+2012-12-20+at+8.38.26+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="205" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiAe0mHZMPg7kCvyrV23WkivnZFNwrV9gc3VH32HSvzdjbhektrwAaYiFt0TddDPb096Bo9QX-gDh94l6wWQAz05eEESnRm4SmyVY_-L97724ppCjaDDJneb1WV4ShEnPYW4lHqzQ/s320/Screen+Shot+2012-12-20+at+8.38.26+PM.png" width="320" /></a></div>
<br />
Hmm, looks like that 20 points offset might be the culprit. Yet that's a grayed-out value. How to change that ? Let's fiddle with the simulated metrics, just for kicks:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisFP_6YJLkI4yJbIzEsnI3JjqcDss8XSevXYFiq9yTpOA7acjHOum7Fse4o5z9a5cIxMGFjo1TPe3qdeGmvjbpNOst8uzYknfokaLr1yPs2mN643-2OpAOPqidyB_1HdConM_u0g/s1600/Screen+Shot+2012-12-20+at+5.59.11+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisFP_6YJLkI4yJbIzEsnI3JjqcDss8XSevXYFiq9yTpOA7acjHOum7Fse4o5z9a5cIxMGFjo1TPe3qdeGmvjbpNOst8uzYknfokaLr1yPs2mN643-2OpAOPqidyB_1HdConM_u0g/s320/Screen+Shot+2012-12-20+at+5.59.11+PM.png" width="320" /></a></div>
<br />
and check out what we get as a result:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgb_f0_MJBwPuK5kkGHNJnaLTPk4CTw6_Zf7ekeOL01io1PJ1ZIGyKFkdY6Dvpq9gBxXNAQOmau9Vbr3ZxF_q_5lZ5smgWtBIOpgJCdrbdr8_SX4Y6qo9z3HJTPf3Cy4dYAPwVaiQ/s1600/Screen+Shot+2012-12-20+at+8.37.29+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="207" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgb_f0_MJBwPuK5kkGHNJnaLTPk4CTw6_Zf7ekeOL01io1PJ1ZIGyKFkdY6Dvpq9gBxXNAQOmau9Vbr3ZxF_q_5lZ5smgWtBIOpgJCdrbdr8_SX4Y6qo9z3HJTPf3Cy4dYAPwVaiQ/s320/Screen+Shot+2012-12-20+at+8.37.29+PM.png" width="320" /></a></div>
<br />
You'd think this would fix the problem. Alas it doesn't. I think this may be a bug in Xcode. I believe the change in the simulated metrics shouldn't affect the value of the view's frame. In any case, I find the interplay between the "Simulated Metrics" of the view controller and the "Size Inspector" of its view pretty confusing. For example, sometime you can't change the struts and springs in "Size Inspector" unless you set the "Size" in "Simulated Metrics" to freeform.<br />
<br />
So it looks like we need to fix this in code, by pinning the frame of the embedded view in the top-left corner of its superview, like so:<br />
<br />
<div style="color: #3d1d81; font-family: Monaco; font-size: 12px;">
<span style="color: black;"> </span><span style="color: #4f8187;">PdfViewController</span><span style="color: black;"> *pvc = [</span><span style="color: #bb2ca2;">self</span><span style="color: black;">.</span><span style="color: #703daa;">storyboard</span><span style="color: black;"> </span>instantiateViewControllerWithIdentifier<span style="color: black;">:</span><span style="color: #d12f1b;">@"PdfViewController"</span><span style="color: black;">];</span></div>
<div style="color: #3d1d81; font-family: Monaco; font-size: 12px;">
<span style="color: black;"> [</span><span style="color: #bb2ca2;">self</span><span style="color: black;"> </span>addChildViewController<span style="color: black;">:pvc];</span></div>
<div style="color: #703daa; font-family: Monaco; font-size: 12px;">
<span style="color: black;"> pvc.</span>view<span style="color: black;">.</span>frame<span style="color: black;"> = </span><span style="color: #3d1d81;">CGRectMake</span><span style="color: black;">(</span><span style="color: #272ad8;">0</span><span style="color: black;">, </span><span style="color: #272ad8;">0</span><span style="color: black;">, pvc.</span>view<span style="color: black;">.</span>frame<span style="color: black;">.</span>size<span style="color: black;">.</span>width<span style="color: black;">, pvc.</span>view<span style="color: black;">.</span>frame<span style="color: black;">.</span>size<span style="color: black;">.</span>height<span style="color: black;">); </span><span style="color: #008400;">// fix</span></div>
<div style="font-family: Monaco; font-size: 12px;">
[<span style="color: #bb2ca2;">self</span>.<span style="color: #703daa;">view</span> <span style="color: #3d1d81;">addSubview</span>:pvc.<span style="color: #703daa;">view</span>];</div>
<div style="color: #3d1d81; font-family: Monaco; font-size: 12px;">
<span style="color: black;"> [pvc </span>didMoveToParentViewController<span style="color: black;">:</span><span style="color: #bb2ca2;">self</span><span style="color: black;">];</span></div>
<div>
<span style="color: black;"><br /></span></div>
This takes care of the problem. Hopefully Apple will keep improving their Interface Builder, and add more <a href="http://en.wikipedia.org/wiki/Computer-aided_software_engineering">CASE</a> capabilities to Xcode. I fondly remember using <a href="http://en.wikipedia.org/wiki/ObjecTime">ObjecTime</a> and enjoying the productivity gains that afforded. After all the best code is no code. Easiest to write, read and maintain :).<br />
<br />
<br />
UPDATE:<br />
<br />
I found a better fix for this issue. It started as a solution for another problem. It turns out that if you have a view controller defined in the storyboard, with a non-standard size, when loaded by default would show up at full screen size. It turns out all we need is to deselect the "Resize View From NIB" checkbox. This also eliminates that 20 points inset at the top.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFRvouXzTC4hydiPbdKiQgTu9URhPaXtyhLL15-e5_4aqzczikbk_cAy0OTjb38lDyc-bPlOjQZnNDq7lev4XsCfeZjmL3_amoqtkp2O1o9JquAIyoUEuUElCjbMOERbimyS6ZLw/s1600/Screen+Shot+2013-01-29+at+3.38.36+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFRvouXzTC4hydiPbdKiQgTu9URhPaXtyhLL15-e5_4aqzczikbk_cAy0OTjb38lDyc-bPlOjQZnNDq7lev4XsCfeZjmL3_amoqtkp2O1o9JquAIyoUEuUElCjbMOERbimyS6ZLw/s320/Screen+Shot+2013-01-29+at+3.38.36+PM.png" width="169" /></a></div>
<br />
<br />
<br />Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-35323211.post-15175746778047078732012-11-17T10:47:00.000-08:002012-11-21T12:59:23.940-08:00Using the iOS simulator for debuggingIf you spend some time with the iOS simulator you'll notice the "Debug" menu, which contains some capabilities that come handy when investigating problems with apps under development.<br />
<br />
Such a potential problem could be flickery or jerky animations. Since the duration of the animation on normal use can be pretty short, it may be difficult to see what's going on. Using the "Toggle Slow Animations" option, the first under the "Debug" menu, slows it down enough to allow getting an insight on what may be the problem. For an example of such problem, and the difference that slower animations makes, see the video below:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dwECBUo5Dlma1qBd9TG3lZRTu3OI_Szk7Yra2pVqWXzzNcA1ZO-jPBNfFsHKTysgMH2ebYhfILHCQc' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
Once we have visibility on the problem, we can try various fixes and use the slow-mo animations to see if the fix produces a better outcome:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen='allowfullscreen' webkitallowfullscreen='webkitallowfullscreen' mozallowfullscreen='mozallowfullscreen' width='320' height='266' src='https://www.blogger.com/video.g?token=AD6v5dywvBZZSIePj2BKhv3n-rS9_8NF0Kx8R0fC7-Jn9KrX5SeAoti8wCf_TQq5jB2lMkVD_-HeK7VhLVk' class='b-hbp-video b-uploaded' frameborder='0'></iframe></div>
<br />
Another group of debugging functionality has the "Color Blended Layers", "Color Copied Images", "Color Misaligned Images" and "Color Offscreen-Rendered" options. All these options can be used to expose inefficient composite drawing, and they're also available through Instruments.<br />
<br />
Yet another group of functionality appears under the "Location", which allows simulating changing the location for apps that use location services.<br />
<br />
I'm amazed by the quality of development tools that Apple provides, far exceeding other platforms.<br />
<br />
If you have an app developed, perhaps by an outsourcing developer like me, and notice some problems with animation, you may ask your developer to toggle those options and produce a screen recording of the app running in the simulator, like I did above, to prove that any issues have been addressed.<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-46892280245132245752012-11-03T12:09:00.000-07:002012-11-03T12:09:44.533-07:00How to access backing ivars for inherited properties in Objective-CI had a superclass that declared and synthesized a read only property, meant to be set in its subclasses. The code was something like this:<br />
<br />
<br />
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
@interface<span style="color: black;"> A : </span><span style="color: #7340a3;">NSObject</span></div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #bf2e9d;">@property</span> (nonatomic, readonly) <span style="color: #7340a3;">NSUInteger</span> prop;</div>
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
@end</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 16.0px;">
<br /></div>
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
@implementation<span style="color: black;"> A</span></div>
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
@synthesize<span style="color: black;"> prop = </span><span style="color: #4b8186;">_prop</span><span style="color: black;">;</span></div>
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
@end</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 16.0px;">
<br /></div>
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
@interface<span style="color: black;"> B : </span><span style="color: #4b8186;">A</span></div>
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
@end</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 16.0px;">
<br /></div>
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
@implementation<span style="color: black;"> B</span></div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 16.0px;">
<br /></div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
- (<span style="color: #bf2e9d;">void</span>)establishValueForProp</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
{</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #4b8186;">_prop</span> = <span style="color: #2832cf;">1</span>; <span class="Apple-style-span" style="color: #008326;">// PROBLEM !!!</span></div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
}</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px; min-height: 16.0px;">
<br /></div>
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
@end</div>
<div>
<br /></div>
<br />
The instance variable backing the property seemed to be invisible in the subclass. The error was pretty unclear when compiling an iOS app: "Use of undeclared identifier '_prop'". To get around the error I did the following:<br />
<br />
<br />
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
@interface<span style="color: black;"> A : </span><span style="color: #7340a3;">NSObject</span><span style="color: black;"> <b>{</b></span></div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<b> <span style="color: #7340a3;">NSUInteger</span> _prop;</b></div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<b>}</b></div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #bf2e9d;">@property</span> (nonatomic, readonly) <span style="color: #7340a3;">NSUInteger</span> prop;</div>
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
@end</div>
<br />
<br />
That is, I explicitly declared the backing variable in the declaration of the superclass.<br />
<br />
Interestingly, when I was preparing this blog post I compiled the code above as a "Command Line Tool" type of project, not an iOS app. The error was different, dare I say better, more telling of the root cause: "Instance variable '_prop' is private". So it's a matter of the visibility of the ivar, so perhaps a better fix would be:<br />
<br />
<br />
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
@interface<span style="color: black;"> A : </span><span style="color: #7340a3;">NSObject</span><span style="color: black;"> {</span></div>
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: black;"> </span><b>@protected</b></div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #7340a3;">NSUInteger</span> _prop;</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
}</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #bf2e9d;">@property</span> (nonatomic, readonly) <span style="color: #7340a3;">NSUInteger</span> prop;</div>
<div style="color: #bf2e9d; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
@end</div>
<br />
<br />
Kind of interesting though that properties are synthesized by default as private ivars. Learned something new.Unknownnoreply@blogger.com1tag:blogger.com,1999:blog-35323211.post-54673379219803337182012-10-26T08:42:00.000-07:002012-10-27T09:36:41.533-07:00Dealing with exit code 5 when running Ghostscript under MAMP<br />
I had been using Ghostscript for a project, calling it from a PHP script running in a MAMP environment on Snow Leopard. Several months later, on a different computer, running a newer version of MAMP (2.1.1), on Lion, I kept getting some weird errors.<br />
<br />
When GS was called through passthru, like so:<br />
<div>
<br /></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">passthru('gs -version', $retval);</span></div>
</div>
<div>
<br /></div>
<div>
<span class="Apple-style-span">I wouldn't get the expected output, indicating the version of GS, instead the command would be completely silent and </span><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">$retval</span><span class="Apple-style-span"> would be set to <b>5</b>, indicating an error (on success it should have been 0).</span></div>
<div>
<br /></div>
<div>
Running the same command in a regular terminal window would produce the expected result:</div>
<div>
<br /></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">$ gs -v</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">GPL Ghostscript 9.06 (2012-08-08)</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Copyright (C) 2012 Artifex Software, Inc. All rights reserved.</span></div>
</div>
<div>
<br /></div>
<div>
My intuition told me that it may be a problem of the environment used by PHP interpreter running under MAMP. Taking a look it shows this:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqMOgMPjiVjpD_-b7hiYdADYSTHDIGqVHBW5L0gv1HT-xtDS7jU8vH_S8P_rB9f_fr-zZuuYNTAqhVv2zI_0IrGONaqVs3Il2VJAg49HXN3Jx0vkAfukfGKO9My8OLjCHIhgTa9g/s1600/Screen+Shot+2012-10-19+at+8.44.41+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgqMOgMPjiVjpD_-b7hiYdADYSTHDIGqVHBW5L0gv1HT-xtDS7jU8vH_S8P_rB9f_fr-zZuuYNTAqhVv2zI_0IrGONaqVs3Il2VJAg49HXN3Jx0vkAfukfGKO9My8OLjCHIhgTa9g/s320/Screen+Shot+2012-10-19+at+8.44.41+PM.png" width="320" /></a></div>
<div>
<br /></div>
<div>
Next step was to reproduce the same environment on the terminal, and surely the result confirmed my guess:</div>
<div>
<br /></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">$ ./gs -version </span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">dyld: Symbol not found: _iconv</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> Referenced from: /usr/lib/libcups.2.dylib</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> Expected in: /Applications/MAMP/Library/lib/libiconv.2.dylib</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"> in /usr/lib/libcups.2.dylib</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">Trace/BPT trap: <b>5</b></span></div>
</div>
<div>
<br /></div>
<div>
Later I discovered that the same error also shows up in the Apache error log under MAMP, albeit without explicitly showing the error <b>5</b>.<br />
<br />
<br />
The problem seems to be caused by the dylibs under /Applications/MAMP/Library/lib/. MAMP seems to be prompted to look there by the DYLD_LIBRARY_PATH environment variable that comes with the default config (set by /Applications/MAMP/Library/bin/envvars).<br />
<div>
<br /></div>
<div>
It seems that the dylibs used by MAMP are different than those used by a default terminal session. A regular shell session, ran from terminal, loads dylibs from /usr/lib. If I do this:</div>
</div>
<div>
<br /></div>
<div>
<br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">$ nm /usr/lib/libiconv.2.dylib | grep _iconv</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">00000000000f1af0 S ___iconv_2VersionNumber</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">00000000000f1b90 S ___iconv_2VersionString</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">000000000000a1e1 T _iconv</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">000000000000a5a0 T _iconv_canonicalize</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">0000000000013164 T _iconv_close</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">0000000000013171 T _iconv_open</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">000000000000a72c T _iconvctl</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">000000000000a20f T _iconvlist</span><br />
<div>
<br /></div>
</div>
<div>
<br />
it shows the _iconv symbol present in that version of the lib.<br />
<br />
However, if I look in the version used by MAMP, it's missing:<br />
<div>
<br /></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">$ nm /Applications/MAMP/Library/lib/libiconv.2.dylib | grep _iconv</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">0000000000029c50 T _iconv_canonicalize</span></div>
</div>
<div>
<br /></div>
<div>
<div>
Instead those symbols seem to have an extra "lib" prefix:</div>
</div>
<div>
<br /></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">$ nm /Applications/MAMP/Library/lib/libiconv.2.dylib | grep iconv</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">000000000010d748 D __libiconv_version</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">0000000000029c50 T _iconv_canonicalize</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">0000000000028a90 T _libiconv</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">0000000000028b40 T _libiconv_close</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">00000000000280c0 T _libiconv_open</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">0000000000028b80 T _libiconv_open_into</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">000000000002a7c0 t _libiconv_relocate</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">000000000002a310 T _libiconv_set_relocation_prefix</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">0000000000029500 T _libiconvctl</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">0000000000029870 T _libiconvlist</span></div>
</div>
<div>
<br /></div>
<div>
It seems that MAMP loads libcups.2.dylib from /usr/lib/ and its libiconv.2.dylib dependency from /Applications/MAMP/Library/lib. That's, I believe, the root of the problem. Those 2 libraries have incompatible versions. That's confirmed by:</div>
<div>
<br /></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">$ otool -L /usr/lib/libcups.2.dylib/usr/lib/libcups.2.dylib:</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/usr/lib/libcups.2.dylib (compatibility version 2.0.0, current version 2.9.0)</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos (compatibility version 5.0.0, current version 6.0.0)</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/System/Library/Frameworks/GSS.framework/Versions/A/GSS (compatibility version 1.0.0, current version 1.0.0)</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 635.21.0)</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration (compatibility version 1.0.0, current version 395.11.0)</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 46.1.0)</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 55148.1.0)</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/usr/lib/libiconv.2.dylib (compatibility version<b> 7.0.0</b>, current version 7.0.0)</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)</span></div>
</div>
<div>
<br /></div>
<div>
and:</div>
<div>
<br /></div>
<div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">$ otool -L /Applications/MAMP/Library/lib/libiconv.2.dylib</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">/Applications/MAMP/Library/lib/libiconv.2.dylib:</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/Applications/MAMP/Library/lib/libiconv.2.dylib (compatibility version <b>8.0.0</b>, current version 8.1.0)</span></div>
<div>
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.11)</span></div>
</div>
<div>
<br /></div>
</div>
<div>
A workaround may be as easy as easy as re-building <span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">libcups.2.dylib </span>from sources, and configure it to pick the libs from <span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">/Applications/MAMP/Library/lib/.</span></div>
<div>
<br /></div>
<div>
<br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">$ cd cups-1.6.1</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">$ ./configure CC=clang CXX=clang++ LDFLAGS=-L/Applications/MAMP/Library/lib </span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">$ make</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">$ cp ./cups/libcups.2.dylib /Applications/MAMP/Library/lib/</span><br />
<div>
<br /></div>
</div>
<div>
Seems to fix the problem with my script, so I can move on with my work. The question is how sane this rebuilt <span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">libcups.2.dylib </span>is.</div>
<div>
<br />
Doing<br />
<br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">$ otool -L ./cups/libcups.2.dylib</span><br />
<br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">./cups/libcups.2.dylib:</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/usr/lib/libcups.2.dylib (compatibility version 2.0.0, current version 2.10.0)</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos (compatibility version 5.0.0, current version 6.0.0)</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/System/Library/Frameworks/GSS.framework/Versions/A/GSS (compatibility version 1.0.0, current version 1.0.0)</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 635.21.0)</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration (compatibility version 1.0.0, current version 395.11.0)</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 46.1.0)</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/System/Library/Frameworks/Security.framework/Versions/A/Security (compatibility version 1.0.0, current version 55148.1.0)</span><br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;"><span class="Apple-tab-span" style="white-space: pre;"> </span>/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.5)</span><br />
<div>
<br /></div>
<br />
shows the dependency on <span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">/usr/lib/libiconv.2.dylib</span> gone. A bit surprising.<br />
<br />
<br />
A quick sanity check done like this:<br />
<span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">$ make check </span><br />
<br />
<br />
has most of the tests pass, except internationalization API tests, which is not that surprising, since I suppose <span class="Apple-style-span" style="font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;">libiconv.2.dylib</span> would play an important role there.<br />
<div>
<br /></div>
<div>
All in all, that's how I was able to get around this problem with MAMP. I posted this issue on <a href="http://forum.mamp.info/viewtopic.php?f=6&t=10846" rel="nofollow">their forum</a>, but almost 24 hr later it hasn't even cleared the moderator, let alone gotten a better solution.</div>
<br />
<br />
<br />
<br /></div>
Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-35323211.post-60315402138371497432012-10-06T12:34:00.000-07:002012-11-22T01:51:38.472-08:00Caveats of calling subviews in a UIScrollView, and how to customize the scrollbars.In a recent project I had a scroll view defined in a storyboard, together with 2 subviews. I was looking for a way to access them in the <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>layoutSubviews</b></span> method of the scroll view.<br />
<br />
The first approach I took was to create 2 outlets in the scroll view, pointing to the to the said subviews. Even though I had it working fine, I had to twist Xcode's arm in doing that, since the normal drag-to-create-outlet maneouvre in the Assistant editor seems to work only when the target of the drag is the code pane of a view controller, not a view.<br />
<br />
So, as an alternative, I figured, hey, we have this <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>subviews</b></span> property available, why not fast-iterate through it and call it a day. When testing that approach weird things started to happen. A little debugging showed this:<br />
<br />
<div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
<div class="p1">
<span class="s1"><b>(lldb) </b></span><b>po [self subviews]</b></div>
<div class="p1">
(id) $1 = 0x06b805b0 <__NSArrayM 0x6b805b0>(</div>
<div class="p1">
<span class="Apple-style-span"><</span>SomePageView<span class="Apple-style-span">: 0x68968b0; frame = (0 0; 320 452.507); transform = [0.450704, 0, 0, 0.450704, 0, 0]; opaque = NO; autoresize = W+H; layer = <CALayer: 0x68965f0>>,</span></div>
<div class="p1">
<AnotherPageView: 0x6896e40; frame = (0 0; 320 460); autoresize = W+H; layer = <CATiledLayer: 0x6896e90>>,</div>
<div class="p1">
<UIImageView: 0x6897330; <b>frame</b> = (313 453; 7 7); alpha = 0; opaque = NO; <b>autoresize</b> = LM; <b>userInteractionEnabled</b> = NO; layer = <CALayer: 0x68973a0>>,</div>
<div class="p1">
<UIImageView: 0x6897290; <b>frame</b> = (313 453; 7 7); alpha = 0; opaque = NO; <b>autoresize</b> = TM; <b>userInteractionEnabled</b> = NO; layer = <CALayer: 0x6897300>></div>
<div class="p1">
)</div>
</div>
</div>
<br />
What ? I thought I had 2 subviews - this shows 4. Looking at the frames, autoresize mask and the fact that they ignore touches it's a strong indication that those 2 extra subviews may be the scrollbars - LOL.<br />
<br />
Inspecting the UIScrollView confirms that. See the _horizontalScrollIndicator and _verticalScrollIndicator ivars:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSUWfZmE6t7Feue736nqtDnUE1Tjjt0UMjmo-zhDfsF3Vq3MNKaTnP3LdwEyAku86YDOg7HyA65BxMnPDd2ie5yeRoYEo8iQptmtkmKRrHUD-zFAYsMxEwkvBmNwhyphenhypheniAdOlR7q3A/s1600/Screen+Shot+2012-10-08+at+11.56.36+AM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhSUWfZmE6t7Feue736nqtDnUE1Tjjt0UMjmo-zhDfsF3Vq3MNKaTnP3LdwEyAku86YDOg7HyA65BxMnPDd2ie5yeRoYEo8iQptmtkmKRrHUD-zFAYsMxEwkvBmNwhyphenhypheniAdOlR7q3A/s320/Screen+Shot+2012-10-08+at+11.56.36+AM.png" width="320" /></a></div>
<br />
<br />
This has one clear implication - if you're nuts enough you can customize the appearance of the scrollbars in a UIScrollView. They seem to be simple <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>UIImageView</b></span><span class="Apple-style-span" style="font-family: inherit;">s. However rummaging through UIKit internals like this is not condoned by Apple, since future updates may break your assumptions.</span><br />
<br />
Incidentally, another approach I could have taken to access my own subviews would have been to tag them in the storyboard and use the <span class="Apple-style-span" style="font-size: 13px;"><span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"><b>viewWithTag</b></span></span> method to get to them.<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-91526063236233218402012-09-09T13:49:00.002-07:002012-09-09T13:53:35.612-07:00How to read multiple lines from the standard input stream in JavaI was facing this problem, of reading lines of text from the console input, as I was under some intense time-pressure, while I was taking an online test. I was convinced that it must be something simple like:<br />
<br />
<br />
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<br />
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
String line = System.<span style="color: #032fc3;">in</span>.<span style="text-decoration: underline;"><span class="Apple-style-span" style="color: red;">readln</span></span>();</div>
</div>
<br />
<br />
Not such luck. This seemingly simple task in Java ain't that simple. Googling for this revealed (in multiple places) something along these lines:<br />
<br />
<br />
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #961a65;">import</span> java.io;</div>
<div style="color: #961a65; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
try<span style="color: black;"> {</span></div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>BufferedReader in = <span style="color: #961a65;">new</span> BufferedReader(<span style="color: #961a65;">new</span> InputStreamReader(System.<span style="color: #032fc3;">in</span>));</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="color: #961a65;">return</span> in.readLine();</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
} <span style="color: #961a65;">catch</span> (IOException e) {</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>System.<span style="color: #032fc3;">err</span>.println(e);</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
}</div>
<div>
<br /></div>
<br />
which seems straightforward, until you try running this sequence repeatedly, perhaps in a loop.<br />
<br />
If you feed this a multi-line input, pasted in the console, like so:<br />
<br />
<span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><b>one</b></span><br />
<span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><b>two</b></span><br />
<span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><b>three</b></span><br />
<br />
then you'd notice that the first gets read fine, then the subsequent reads block, without catching the lines:<br />
<br />
<span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><b>two</b></span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">
<span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif; font-size: x-small;"><b>three</b></span></div>
<div>
<br /></div>
Bad times. There's a fatal flaw in the code above, cited on so many sites, from one of which I copied it too. The readers hooked up to <span class="Apple-style-span" style="font-family: Monaco; font-size: 12px;">System.</span><span class="Apple-style-span" style="font-family: Monaco; font-size: 12px;"><span style="color: #032fc3;">in</span></span> don't get closed, and if that sequence of code is run in a loop we'd end up with multiple readers for the same single standard input stream. Now one could argue that an exception should be thrown in such case, where multiple readers are trying to slurp data from the same source. Alas it doesn't, and instead the behaviour is truly puzzling.<br />
<br />
My faulty code had this function called repeatedly:<br />
<br />
<br />
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #961a65;">public</span> <span style="color: #961a65;">static</span> String readline() {</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="color: #961a65;">try</span> {</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>BufferedReader in = <span style="color: #961a65;">new</span> BufferedReader(<span style="color: #961a65;">new</span> InputStreamReader(System.<span style="color: #032fc3;">in</span>));</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="color: #961a65;">return</span> in.readLine();</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>} <span style="color: #961a65;">catch</span> (IOException e) {</div>
<div style="color: #961a65; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: black;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span>return<span style="color: black;"> </span>null<span style="color: black;">;</span></div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>}</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
}<span class="Apple-tab-span" style="white-space: pre;"> </span></div>
<div>
<br /></div>
<br />
The fix consisted in doing this instead:<br />
<br />
<br />
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #961a65;">static</span> BufferedReader <span style="color: #032fc3;">in</span> = <span style="color: #961a65;">new</span> BufferedReader(<span style="color: #961a65;">new</span> InputStreamReader(System.<span style="color: #032fc3;">in</span>));</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #961a65;">public</span> <span style="color: #961a65;">static</span> String readline() {</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="color: #961a65;">try</span> {<span class="Apple-tab-span" style="white-space: pre;"> </span></div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="color: #961a65;">return</span> <span style="color: #032fc3;">in</span>.readLine();</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>} <span style="color: #961a65;">catch</span> (IOException e) {</div>
<div style="color: #961a65; font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: black;"><span class="Apple-tab-span" style="white-space: pre;"> </span></span>return<span style="color: black;"> </span>null<span style="color: black;">;</span></div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span>}</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
}</div>
<div>
<br /></div>
<br />
The static variable gets initialized only once, and now calling readLine() repeatedly works fine.<br />
<br />
Alternatively in Java 1.6 one could also use:<br />
<br />
<br />
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #961a65;">public</span> <span style="color: #961a65;">static</span> String readline() {</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
<span class="Apple-tab-span" style="white-space: pre;"> </span><span style="color: #961a65;">return</span> System.console().readLine();</div>
<div style="font: 12.0px Monaco; margin: 0.0px 0.0px 0.0px 0.0px;">
}</div>
<div>
<br /></div>
<br />
with the caveat that this approach using console() doesn't work by default <a href="http://stackoverflow.com/questions/104254/java-io-console-support-in-eclipse-ide" rel="nofollow">when running in Eclipse</a>.<br />
<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-83303104257583863342012-08-11T08:26:00.000-07:002012-08-11T08:26:00.378-07:00How to deal with inconsistent display of characters with diacritics on the webA friend asked me to build a web site, targeted to Romanian visitors. Romanian language has some characters with diacritics, as documented in Wikipedia:<br />
<blockquote class="tr_bq">
<span class="Apple-style-span" style="font-family: sans-serif; font-size: 13px; line-height: 19px;"><a href="http://en.wikipedia.org/wiki/Romanian_alphabet" style="background-attachment: initial; background-clip: initial; background-color: initial; background-image: none; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: #0645ad; text-decoration: none;" title="Romanian alphabet">Romanian</a> uses a <a href="http://en.wikipedia.org/wiki/Breve" style="background-attachment: initial; background-clip: initial; background-color: initial; background-image: none; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: #0645ad; text-decoration: none;" title="Breve">breve</a> on the letter <i>a</i> (<i><a href="http://en.wikipedia.org/wiki/%C4%82" style="background-attachment: initial; background-clip: initial; background-color: initial; background-image: none; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: #0645ad; text-decoration: none;" title="Ă">ă</a></i>) to indicate the sound <a href="http://en.wikipedia.org/wiki/Schwa" style="background-attachment: initial; background-clip: initial; background-color: initial; background-image: none; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: #0645ad; text-decoration: none;" title="Schwa">schwa</a> <span class="IPA" title="Representation in the International Phonetic Alphabet (IPA)">/ə/</span>, as well as a circumflex over the letters <i>a</i> (<i><a href="http://en.wikipedia.org/wiki/%C3%82" style="background-attachment: initial; background-clip: initial; background-color: initial; background-image: none; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: #0645ad; text-decoration: none;" title="Â">â</a></i>) and <i>i</i> (<i><a href="http://en.wikipedia.org/wiki/%C3%8E" style="background-attachment: initial; background-clip: initial; background-color: initial; background-image: none; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: #0645ad; text-decoration: none;" title="Î">î</a></i>) for the sound <span class="IPA" title="Representation in the International Phonetic Alphabet (IPA)">/ɨ/</span>. Romanian also writes a <a href="http://en.wikipedia.org/wiki/Comma" style="background-attachment: initial; background-clip: initial; background-color: initial; background-image: none; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: #0645ad; text-decoration: none;" title="Comma">comma</a> below the letters <i>s</i> (<i><span class="Unicode"><a class="mw-redirect" href="http://en.wikipedia.org/wiki/%C8%98" style="background-attachment: initial; background-clip: initial; background-color: initial; background-image: none; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: #0645ad; text-decoration: none;" title="Ș">ș</a></span></i>) and <i>t</i> (<i><span class="Unicode"><a class="mw-redirect" href="http://en.wikipedia.org/wiki/%C8%9A" style="background-attachment: initial; background-clip: initial; background-color: initial; background-image: none; background-origin: initial; background-position: initial initial; background-repeat: initial initial; color: #0645ad; text-decoration: none;" title="Ț">ț</a></span></i>) to represent the sounds <span class="IPA" title="Representation in the International Phonetic Alphabet (IPA)">/ʃ/</span> and <span class="IPA" title="Representation in the International Phonetic Alphabet (IPA)">/t͡s/</span>, respectively.</span></blockquote>
So I thought I'd use a UTF-8 encoding for the HTML, together with some fonts that support those characters and this should be easy enough. To my surprise the results were pretty bad:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcyaOQMT7zrd26IWA0-r97_GphlamLSk5HaGSGXP0Ze8so3hEJQSB6kKv3SERnNdzjy752Eswi02ovZhYxqUicJKfwoQvXJRiQM4JjYQivmfOzJeaWCFwA-UvMjEHxhdxp8yaAFg/s1600/Screen+shot+2012-08-10+at+4.42.20+PM+-+bad+paragraphs.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjcyaOQMT7zrd26IWA0-r97_GphlamLSk5HaGSGXP0Ze8so3hEJQSB6kKv3SERnNdzjy752Eswi02ovZhYxqUicJKfwoQvXJRiQM4JjYQivmfOzJeaWCFwA-UvMjEHxhdxp8yaAFg/s320/Screen+shot+2012-08-10+at+4.42.20+PM+-+bad+paragraphs.png" width="320" /></a></div>
<br />
Here I have 5 paragraphs, showing the same text, each with a different font. First 2 are fonts downloaded on demand from Google ('Arvo' and 'Noticia Text'). The following 3 are stock fonts ('serif', 'sans-serif' and 'Verdana'). You can see that the stock fonts are failing badly, as marked with red. Those characters are either over or under-sized, relative to the others (they should have the same <a href="http://en.wikipedia.org/wiki/Baseline_(typography)">x-hight</a>). The first 2 fonts aren't much better, since they fail in other contexts, depending on the size of the font chosen. So this yields the first insight - changing the font size may smooth out such issues. To check this I focus on the paragraph in the blue box and I tinker with the 'font-size' CSS selector. Seems to work:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI4d2oxb9xMJTtdT0OniGP21aDdYqCK-O2SIqAQbm3Gwgbc5f6Zny7uf2rt9wV7UmWRUr3G2SoZpTfub4bj54x86VA1L2zlS4kR2RRgljijM4sYKFHqtftqX7Y5EXtfhm6RAquiA/s1600/Screen+shot+2012-08-10+at+4.40.29+PM+-+OK.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjI4d2oxb9xMJTtdT0OniGP21aDdYqCK-O2SIqAQbm3Gwgbc5f6Zny7uf2rt9wV7UmWRUr3G2SoZpTfub4bj54x86VA1L2zlS4kR2RRgljijM4sYKFHqtftqX7Y5EXtfhm6RAquiA/s320/Screen+shot+2012-08-10+at+4.40.29+PM+-+OK.png" width="320" /></a></div>
<br />
The 4th paragraph looks better now. Applying the same trick in another context fails miserably:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYSGcGwxBkqwsJlqIKeSJPtsEiafRug4fRbXISCeC5532H-IxuNV8yT-iAsIBR2ai55evRdwp0EKridm0Y6EfmP8MlOJcO7eAMSY7HMAGeWTLdEIHmxeGO13UTRfr2fIKyWsPyRQ/s1600/Screen+shot+2012-08-10+at+5.04.29+PM-FAIL.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYSGcGwxBkqwsJlqIKeSJPtsEiafRug4fRbXISCeC5532H-IxuNV8yT-iAsIBR2ai55evRdwp0EKridm0Y6EfmP8MlOJcO7eAMSY7HMAGeWTLdEIHmxeGO13UTRfr2fIKyWsPyRQ/s320/Screen+shot+2012-08-10+at+5.04.29+PM-FAIL.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
That's using the 'serif' font, and on Mozilla it would fail regardless of the chosen size (at least on Windows XP). Incidentally, the same combination works perfectly on Safari on OS X, at any size:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkc8HKlUZGxYzCgHnqFnIal61Io7-vQtDa7VHjz_OhvYaWycRVgAqVtthcE4iNrf1LWIu6uOGC0JlcgdpZlKEtiVEJZ_Ld2APXupZdkfTJkzwyAqUYg5PhpsK7TqwputsxBR9H0Q/s1600/Screen+shot+2012-08-10+at+7.19.26+PM+-+SAFARI.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhkc8HKlUZGxYzCgHnqFnIal61Io7-vQtDa7VHjz_OhvYaWycRVgAqVtthcE4iNrf1LWIu6uOGC0JlcgdpZlKEtiVEJZ_Ld2APXupZdkfTJkzwyAqUYg5PhpsK7TqwputsxBR9H0Q/s320/Screen+shot+2012-08-10+at+7.19.26+PM+-+SAFARI.png" width="320" /></a></div>
<br />
Going back to Mozilla, if I change the 'font-family' to 'Arvo' it works fine (while that same combination would break in Safari):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz7BxlmjxHs4CKhs7HBS7VQ9RBLsEarxXrsn3Gl0e1-GWwxCc4QYC1YekmADPBV1Y8pQnEl8tMjAT2GFDk9BsG0ZjxUUQESzHBTzz-WjT1TEUi1eeHS43uy1qLPxfwzlktLlcOzA/s1600/Screen+shot+2012-08-10+at+7.27.38+PM+-+MOZOK.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgz7BxlmjxHs4CKhs7HBS7VQ9RBLsEarxXrsn3Gl0e1-GWwxCc4QYC1YekmADPBV1Y8pQnEl8tMjAT2GFDk9BsG0ZjxUUQESzHBTzz-WjT1TEUi1eeHS43uy1qLPxfwzlktLlcOzA/s320/Screen+shot+2012-08-10+at+7.27.38+PM+-+MOZOK.png" width="320" /></a></div>
<br />
To make matter worse, the initial set-up that would fail on Mozilla on Windows XP works fine on Mozilla on OS X:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfP_Ocek-5-UORs4-Cr-KMgo6ccKZ0QMw8OU9tejOvc6TvoQlmtZVN3063Kppqr2xIusm1cpgjeSdCItNNpICHojhC6aLxrLthYULptF6bDVNKKKuJFV71SZ542IHIbwdZq1TDFg/s1600/Screen+shot+2012-08-10+at+7.36.02+PM+-+MOZOSX.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfP_Ocek-5-UORs4-Cr-KMgo6ccKZ0QMw8OU9tejOvc6TvoQlmtZVN3063Kppqr2xIusm1cpgjeSdCItNNpICHojhC6aLxrLthYULptF6bDVNKKKuJFV71SZ542IHIbwdZq1TDFg/s320/Screen+shot+2012-08-10+at+7.36.02+PM+-+MOZOSX.png" width="320" /></a></div>
<br />
Yet the same change in font-family that made it work on Mozilla on Windows XP brakes it on Mozilla on OS X (you can't make this up):<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiGqQe1A0j91VfdL3JbfQb6c5Kp33_vqeKf-3O7-bv-R83rTkdyobphRt8azuf-KcJQcG17HCTQc1Pga8a1DyHo5W0FIjBUt8S4DOnE0MAEac9lf7QKtDJpM9fBQBuS2nUUJXa0g/s1600/Screen+shot+2012-08-10+at+7.41.40+PM-MOZOSX_FAIL.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgiGqQe1A0j91VfdL3JbfQb6c5Kp33_vqeKf-3O7-bv-R83rTkdyobphRt8azuf-KcJQcG17HCTQc1Pga8a1DyHo5W0FIjBUt8S4DOnE0MAEac9lf7QKtDJpM9fBQBuS2nUUJXa0g/s320/Screen+shot+2012-08-10+at+7.41.40+PM-MOZOSX_FAIL.png" width="320" /></a></div>
<br />
<br />
To get this right you need to test different combinations of 'font-family', 'font-size', browser and OS. I guess the biggest surprise for me was that for the 2nd paragraph, even if I used 'Noticia Text', included though <a href="http://www.html5rocks.com/en/tutorials/webfonts/quick/">@font-face</a> from <a href="http://www.google.com/webfonts/">Google web fonts</a>, which contains all glyphs with diacritics that I was looking for, it still failed to display properly on Windows. Doesn't that defeat the whole purpose of @font-face ?<br />
<br />
So there you have it, another type of cross-browser inconsistencies that we must be aware of, together with the usual workarounds involving serving browser-specific CSS, consolidated in included files that can be applied to the whole site.<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-76314252794299411902012-08-04T09:03:00.000-07:002012-08-08T02:03:13.532-07:00Spare your users the high cost of data roamingYou may have heard reports from the media, regarding the high cost of roaming charges that <a href="http://ipod.about.com/u/ua/internationaliphone/iphone-roaming.htm" rel="nofollow">some people</a> incurred. It's really no surprise, as some network carriers are practicing <a href="http://www.fido.ca/web/content/coverageroaming/roaming_intl_datapasses?lang=en" rel="nofollow">predatory pricing</a> every time you leave the borders of their home country.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_zRr0vbJnd9WW6C3sdsKBcJfVBcSDEYEsIiPJGjnEUwWa4ZkMgWmxqykVlKLmXWH7tVuur1DuZqXR9T9Zn0JB4DQQNyAvSgL9ZsUFPAsJv52Y6BUMszR64Q8E64qAW1Z0IY43aA/s1600/bill_shock.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_zRr0vbJnd9WW6C3sdsKBcJfVBcSDEYEsIiPJGjnEUwWa4ZkMgWmxqykVlKLmXWH7tVuur1DuZqXR9T9Zn0JB4DQQNyAvSgL9ZsUFPAsJv52Y6BUMszR64Q8E64qAW1Z0IY43aA/s1600/bill_shock.png" /></a></div>
<br />
<br />
Although the end users are ultimately responsible for those charges, we, as developers, should strive to warn them when they're about to do some data transfers while using the apps we developed, if they're likely to be roaming at the time. That would help people that haven't turned off data roaming, through the settings provided by iOS.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN197Tgiq70j7hDbcZmOy4PGjiJRJdNwZF2tCC4tHrA5vXvQ3Bj3Z_kb6JwsNVBG6wcH0ohlRDhyphenhyphendta8_kQB1u94k6pSLBDbaiLros44uBvhHR_BTnDEtUjKbjPeyyPJa4atgQvw/s1600/iphone_turn_off_data_roaming.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgN197Tgiq70j7hDbcZmOy4PGjiJRJdNwZF2tCC4tHrA5vXvQ3Bj3Z_kb6JwsNVBG6wcH0ohlRDhyphenhyphendta8_kQB1u94k6pSLBDbaiLros44uBvhHR_BTnDEtUjKbjPeyyPJa4atgQvw/s320/iphone_turn_off_data_roaming.png" width="213" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
The problem is that AFAIK there's no API exposed by iOS to determine if the user is roaming. So we'll need to get creative. First off, we have the <span class="Apple-style-span" style="color: #666666; font-family: Courier, Consolas, monospace; font-size: 13px;">SystemConfiguration.framework</span>, which allows us to determine whether a Wi-Fi or cellular connection is in use. If it's the former, we have a non-issue. There won't be any roaming charges for Wi-Fi connections. If it's the latter we need to dig deeper. We could use the <span class="Apple-style-span" style="color: #666666; font-family: Courier, Consolas, monospace; font-size: 13px;">CoreLocation.framework </span>to determine the current location of the device.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv787JGUD-b-aYxLfNC0p0wkAZVvpq2Qw1Eu2e2fMXv0ZaNLm1v6PGMZ2NJhYWfI1iSACCEuuus_PDF3TuGLHnyFiFOiC2LAnDLfvY6PnZCJfiWz7Zb9usSaVwQG9YgVdyZ8Lm8g/s1600/photo.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjv787JGUD-b-aYxLfNC0p0wkAZVvpq2Qw1Eu2e2fMXv0ZaNLm1v6PGMZ2NJhYWfI1iSACCEuuus_PDF3TuGLHnyFiFOiC2LAnDLfvY6PnZCJfiWz7Zb9usSaVwQG9YgVdyZ8Lm8g/s320/photo.PNG" width="213" /></a></div>
<br />
<br />
Then we could use <span class="Apple-style-span" style="color: #666666; font-family: Courier, Consolas, monospace; font-size: 13px;">NSLocale</span> and its ability to determine the county code of the current locale (likely established when the device is first set up).<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ-maCnX8Qe8MlqpqWizvst03npaU6wuHJoedlrsPBavpbC51xBWXXmOLNXJn4NtcwirjagSBULp5xft30h8PWrLbwwOQF7Es-eSXdxDzB9nZxCs3emfVP4t_eTUXllxxFdOlzmw/s1600/locale.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjQ-maCnX8Qe8MlqpqWizvst03npaU6wuHJoedlrsPBavpbC51xBWXXmOLNXJn4NtcwirjagSBULp5xft30h8PWrLbwwOQF7Es-eSXdxDzB9nZxCs3emfVP4t_eTUXllxxFdOlzmw/s320/locale.PNG" width="213" /></a></div>
<br />
<br />
If the country of the locale differs from the country of the current location, there's a high probability that the user is roaming, so we could warn them about potential charges before any data transfer is initiated by the app.<br />
<br />
This heuristic is not fool-proof, but it's better than nothing, and it can go a long way towards preventing some unwanted charges. An alternative is to track changes in the country reported by the core location framework and use that as a hint of possible roaming. A possible complication may be caused by the user not authorizing the app for location lookups. There's a way around that, which I'll explore in a future blog post.<br />
<br />
The best approach would be to have an API to tell precisely when a user is roaming, and better yet, the data rates for that particular destination, but that will be the topic for another blog post.<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-84868965493213441962012-07-28T12:12:00.001-07:002012-08-06T02:35:06.028-07:00Notify your users about updates to your iOS appsMost apps undergo updates, to fix problems, or to add new features. It's a fact of life. As is the fact that most updates go unnoticed by the end user. That's because by default Apple simply shows a badge on the icon of the "App Store" app, like so:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4S6CYgWBTsaEscVasNmWBcHkm5C9wIGncGps7O4P6TlwvE8SdbvdcwIVXaEzafQTdoo-i8pXaTJaZWfL1hEiYzIjvHtuWjp0tTxE2MLrHNJa3bkNPB-85DrhWBeiWyTFe4LsBbw/s1600/photo1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4S6CYgWBTsaEscVasNmWBcHkm5C9wIGncGps7O4P6TlwvE8SdbvdcwIVXaEzafQTdoo-i8pXaTJaZWfL1hEiYzIjvHtuWjp0tTxE2MLrHNJa3bkNPB-85DrhWBeiWyTFe4LsBbw/s320/photo1.PNG" width="240" /></a></div>
<br />
If you have a lot of apps installed, which are likely to produce lots of updates, I think most people would develop selective blindness towards those badge notifications, and would postpone the updates.<br />
<br />
Another way to notify the users about an update available for a given app is to send a more vocal push notification (text alert, maybe with sound), assuming that the user agreed to receive such notifications. That may however be perceived as too pushy (or desperate), and that may be why people developed a more elegant way of notifying about updates, in a more appropriate context, which increases the chance of people acting on them. That's by simply showing the notifications when people are launching the old app, like so:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-RDM_Q_SWWYNO_IUSPEjEJgfmWqK_ecwxLJPDFQu87HqYgyzFTHsTWMYSmp89JuRM4XhRG0BIDkEsyLsPAS56Z5gD9cJpWt-KaA_meR2ZXffgxSjtsIaJSBaa8pHMpeiCYabBgQ/s1600/photo2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-RDM_Q_SWWYNO_IUSPEjEJgfmWqK_ecwxLJPDFQu87HqYgyzFTHsTWMYSmp89JuRM4XhRG0BIDkEsyLsPAS56Z5gD9cJpWt-KaA_meR2ZXffgxSjtsIaJSBaa8pHMpeiCYabBgQ/s320/photo2.PNG" width="240" /></a></div>
<br />
That makes sense, because now the end users are in a context where they demonstrate engagement with the app (they just started it) and the notifications have less chance to be perceived as off-putting. So this is a design idiom that makes sense to be followed.<br />
<br />
In some instances the notifications must go further in providing more details about the upcoming update, and possibly assist the user with the upgrade. One such scenario is, for example, if the user moves an app that was initially a stand-alone app, with its own icon on the home screen, to the Newsstand. In that case the icon on the home screen would disappear and a cover corresponding to that app would appear in the Newsstand, like so:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4vdCNXWhyphenhyphenvmDiAdd0DCGkOpYN1qzVYQa3j0szhCjp94sWhsOm9yVRToQmX-N4GKHeYa3I7u4hDdItio2H7gECdAcU1Ln6oykPVGjoAOvBBtiWxk6CMr5zcthQb71g2Asxu1uNEw/s1600/photo3.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4vdCNXWhyphenhyphenvmDiAdd0DCGkOpYN1qzVYQa3j0szhCjp94sWhsOm9yVRToQmX-N4GKHeYa3I7u4hDdItio2H7gECdAcU1Ln6oykPVGjoAOvBBtiWxk6CMr5zcthQb71g2Asxu1uNEw/s320/photo3.PNG" width="240" /></a></div>
<br />
That move has the potential to confuse people, and a notice shown by the old app before the upgrade could clarify the new location.<br />
<br />
Another move scenario is moving an app to another developers' account. This tends to happen when a bespoke app is first developed as an experiment, with few expectations, and it's published under the developer's account. If the app is a success, the contracting clients often want to have the app moved to their own account. This is challenging because from Apple's perspective the app in the new account becomes a brand new app, completely independent from the old one. The upgrade prompt should set clear expectations about the old app being discontinued, with all future development and support slated to go in the new one.<br />
<br />
If the app has in-app purchasing content, care must be taken to migrate purchases made in the old app to the new one. The usual purchase restoration mechanism provided by Apple is of no use here, because Apple has no notion about the 2 apps being related. So you'll need to roll out your own purchase migration mechanism. For example, when the old app is launched, you could make a snapshot of the past purchases, upload them to a server, and produce a redeemable code that could be used in the new app to restore the purchases. If you already have another way of identifying the users, perhaps through some user account/login scheme, you can use that instead to assist the migration. In iOS 5 and later this is facilitated by the newly introduced Account framework, that allows tying separate apps to the same users through their credentials on social networks like Twitter.<br />
<br />
Another consideration would be the transfer of the name of the app. Since there can't be 2 apps with the same name, you'll need to allocate a temporary new name, then delete or rename the old app, to free up the old name, and later apply it to the new app.<br />
<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-71003812975521754622012-07-05T00:36:00.001-07:002012-07-10T03:08:01.486-07:00How to install MySQLdb on Mac OS X LionAfter Apple rendered all my development tools (MacBook, iPad and iPod touch) obsolete and incompatible with iOS 6, I purchased a new MacBook Pro, running Lion. So I tried installing the software I've been using on the old MacBook to the new one.<br />
<br />
One of that software is MySQLdb. Yet I didn't remember how I installed it in the first place. So I had to start from scratch. I'm a proponent of the principle "if it ain't broken don't fix it". Since Lion comes with Python 2.7 pre-installed, I figured I'd use that.<br />
<br />
Next missing piece was MySQL. I used a .dmg from <a href="http://dev.mysql.com/downloads/mysql/">http://dev.mysql.com/downloads/mysql/</a>, specifically mysql-5.1.63-osx10.6-x86_64.dmg. As the name indicates that's for a 64 bits architecture.<br />
<br />
One important insight gathered from <a href="http://learninglamp.wordpress.com/2010/02/21/mysqldb-python-mysql-and-os-x-a-match-made-in-satans-bum/">this site</a> was that the architecture of Python, MySQL and the MySQLdb I've been trying to build should match. To check where I was standing I started the Python interpreter, made sure that MySQL server was running and used Activity Monitor to look at their processes like so:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsAhCgFAXRwgG-Aa7_wnrFBPLqVrfqr2v-khzsOq8G97kpM2d51Ov1HeB4lch9r3zwKxqNcaXS98ujcVfVcQDNKlyN8txwCjD2gE2BcxtA48oLS2f1BtGL4uHF_RSFNVOb-IrGJg/s1600/Screen+Shot+2012-07-03+at+7.55.53+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="238" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsAhCgFAXRwgG-Aa7_wnrFBPLqVrfqr2v-khzsOq8G97kpM2d51Ov1HeB4lch9r3zwKxqNcaXS98ujcVfVcQDNKlyN8txwCjD2gE2BcxtA48oLS2f1BtGL4uHF_RSFNVOb-IrGJg/s320/Screen+Shot+2012-07-03+at+7.55.53+PM.png" width="320" /></a></div>
<br />
So I clearly needed to build the 64 bits variant of MySQLdb. After downloading the sources from <a href="http://sourceforge.net/projects/mysql-python/">http://sourceforge.net/projects/mysql-python/</a> I followed the instructions from the README file with the following amendments:<br />
<br />
1. Did a <b><span class="Apple-style-span" style="color: #741b47;">which mysql_config</span></b> to see its location and updated the site.cfg to point there like so: <b><span class="Apple-style-span" style="color: #660000;">mysql_config = /usr/local/mysql/bin/mysql_config</span></b><br />
<br />
2. Instead <b><span class="Apple-style-span" style="color: #660000;">python setup.py build</span></b> did a <b><span class="Apple-style-span" style="color: #660000;">ARCHFLAGS="-arch x86_64" python setup.py build</span></b>.<br />
<br />
3. Instead <b><span class="Apple-style-span" style="color: #660000;">sudo python setup.py install</span></b> I did <b><span class="Apple-style-span" style="color: #660000;">sudo ARCHFLAGS="-arch x86_64" python setup.py install</span></b><br />
<br />
To check the result I did <b><span class="Apple-style-span" style="color: #660000;">import MySQLdb</span></b> at the Python prompt and checked that no errors occur.<br />
<br />
Note that following the step #2 you'll see a bunch of '<span class="Apple-style-span" style="font-family: Helvetica; font-size: 12px;">implicit conversion shortens 64-bit value into a 32-bit value</span>' warnings. Those could probably be ignored, though there's a chance that some data loss may occur during those implicit conversions if the values on the right hand side of those assignments are large enough (probably unlikely). I tried a fix, to eliminate them, by using platform independent types like size_t instead of int and by matching the types of the variables in LHS return types of the functions in RHS of the assignments on the problematic lines. I placed a patch that attempts to fix those warnings at <a href="http://sourceforge.net/tracker/?func=detail&aid=3541063&group_id=22307&atid=374934">http://sourceforge.net/tracker/?func=detail&aid=3541063&group_id=22307&atid=374934</a>.<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-51123667398289143722012-03-25T20:58:00.000-07:002012-03-26T15:46:35.490-07:00Connecting external devices to iPhoneRecently I heard about some opportunities involving creating apps running on iPhone, meant to talk to specialized hardware devices, so that got me thinking about ways in which the iPhone can connect and talk to external devices.<br />
<br />
First category is wired connections. Here the choices are simple, since there's only a single connection port, the docking port (also used to charge the device). In order to be able to communicate through that port to the external device you'd need to be enrolled in <a href="https://developer.apple.com/programs/mfi/">Apple's MFi program</a>. However there's another option, that doesn't require participation in this program, and uses the audio jack available on iPhone. That jack outlet provides connectivity to both headsets and microphone, so that gives you access to an input/output channel. Your external device should be capable to generate the required voltage that applied on the microphone pin would be detected in the iOS app as a sound, and should be able to understand the audio output received on the headset pins, as generated by the app. This is nothing new, as some people have already implemented it as either dedicated solutions like Square, or more general-purpose solutions like <a href="http://arstechnica.com/apple/news/2011/01/project-hijack-uses-iphone-audio-jack-to-make-cheap-sensors.ars">HiJack</a>. For low data rates you may be able to get by with a simple detection technique, whereas for higher data rates you may need to implement a full-blown modem.<br />
<br />
The other category is wireless connections. Here your best bet may be using the network connectivity (either WiFi or 3G) to connect to a server over TCP/IP or higher protocols. That's probably the approach that involves the least effort. Another appealing avenue is to use Bluetooth, however the public SDK only allows you to talk to another iOS on Mac device, via Game Center, or Bonjour. If you wanted to talk to your specialized external device over bluetooth, you would also <a href="http://developer.apple.com/library/ios/#qa/qa1657/_index.html">need to be enrolled in the MFi program</a>, and use the <a href="http://developer.apple.com/library/ios/#documentation/ExternalAccessory/Reference/ExternalAccessoryFrameworkReference/_index.html">External Accessory Framework</a> to talk to the device.<br />
<br />
Another wireless channel, albeit one-way, is to use the camera to interpret either a pattern like QR code or barcode, or a pulsating light. Another one-way channel in the opposite direction is the screen of the iPhone. You could have your app display a sequence of patterns that could be interpreted by an external devices. Some of you greybeards may remember a version of Windows transferring data to a Timex watch in that manner.<br />
<br />
The accelerometer falls in a category of its own, since it's not quite wired, neither wireless. It's obviously an input channel into the app, whereby the app can detect movement, if the iPhone is physically attached to an external device. That could be used for a monitoring/tracking the movement of physical goods, either intentional or due to theft or mishandling.<br />
<br />
That pretty much sums it up. If you can imagine other ways of communication between the iPhone and external devices, please comment.<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-20321884992594932192012-03-14T20:05:00.000-07:002012-03-25T21:03:36.364-07:00Using gdb to debug Objective-C codeI've been using gdb for many years, initially for debugging code for embedded software, written in C/C++ and running on specialized hardware, and more recently for software meant to run on iOS devices, written in Objective-C. Knowing the way to use it for C/C++ served me well, as most of that stuff is applicable to Objective-C too, including the most commonly used commands. I was aware of, and had been using some commands specific to Objective-C, like <b>print-object</b>, but not much beyond that.<br />
<br />
At some point I came across a presentation that informed me about the ability to evaluate and print the value of complex expressions, including method calls. Of course you have to be mindful of possible side-effects, but that's a pretty powerful capability to have in the middle of a debug session.<br />
<br />
So recently I had to inspect the number of entries in a dictionary. Even though I could have used the Xcode's ability to hover over variable's name and "inspect" some of its content, which for NSDictionary works really well, in that it shows how many key/value pairs it contains (in my case 10), I thought I should use the command-line gdb to find that out. So I did:<br />
<br />
<br />
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #5f78ff;"><b>(gdb) </b></span><b>po [existentMetadataForPrefix count]</b></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
0xa does not appear to point to a valid object.</div>
<div>
<br /></div>
<br />
<span class="Apple-style-span">Hmm, not what I expected. The 0xa mentioned there in hex is 10 in decimal, so the value appears OK. It looks like </span><span class="Apple-style-span" style="font-family: Menlo; font-size: 11px;"><b>po</b></span><span class="Apple-style-span"> (shorthand for print-object) tries to send a message to the object pointed by 0x10. In fact that message is "description", so what I get is fair enough. Obviously I shouldn't be using print-object on an integer value (NSUInteger) returned by count.</span><br />
<br />
To print primitive values in C/C++ one would use straight <b>print</b>. Doing so yields:<br />
<br />
<br />
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #5f78ff;"><b>(gdb) </b></span><b>p [existentMetadataForPrefix count]</b></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
Unable to call function "objc_msgSend" at 0x1b1e08c: no return type information available.</div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
To call this function anyway, you can cast the return type explicitly (e.g. 'print (float) fabs (3.0)')</div>
<div>
<br /></div>
<div>
What the ... ? This doesn't make any sense. That <span class="Apple-style-span" style="font-family: Menlo; font-size: 11px;">0x1b1e08c</span> address is not the address of <span class="Apple-style-span" style="font-family: Menlo; font-size: 11px;"><b>existentMetadataForPrefix</b></span>, as shown by:</div>
<div>
<br /></div>
<div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #5f78ff;"><b>(gdb) </b></span><b>p existentMetadataForPrefix</b></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
$2 = (NSMutableDictionary *) 0xf520c10</div>
</div>
<div>
<br /></div>
<div>
Then, what's at that address ? Can find out, like so:</div>
<div>
<br /></div>
<div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #5f78ff;"><b>(gdb) </b></span><b>x 0x1b1e08c</b></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
0x1b1e08c <objc_msgsend>:<span class="Apple-tab-span" style="white-space: pre;"> </span>0x08244c8b</objc_msgsend></div>
</div>
<div>
<br /></div>
<div>
Huh, looks like that might be the actual address of the function <span class="Apple-style-span" style="font-family: Menlo; font-size: 11px;">objc_msgSend</span>. Can that be ? Let's double-check:</div>
<div>
<br /></div>
<div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #5f78ff;"><b>(gdb) </b></span><b>x objc_msgSend</b></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
0x1b1e08c <objc_msgsend>:<span class="Apple-tab-span" style="white-space: pre;"> </span>0x08244c8b</objc_msgsend></div>
</div>
<div>
<br /></div>
<div>
It is indeed, so what's going on here ? AFAIK that <span class="Apple-style-span" style="font-family: Menlo; font-size: 11px;">objc_msgSend</span> function is called when a message like <span class="Apple-style-span" style="font-family: Menlo; font-size: 11px;"><b>count</b></span> is sent to an object like <span class="Apple-style-span" style="font-family: Menlo; font-size: 11px;"><b>existentMetadataForPrefix</b></span>. Let's set a breakpoint:</div>
<div>
<br /></div>
<div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #5f78ff;"><b>(gdb) </b></span><b>b objc_msgSend</b></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
Breakpoint 3 at 0x1b1e08c</div>
</div>
<div>
<br /></div>
<div>
And try again:</div>
<div>
<br /></div>
<div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #5f78ff;"><b>(gdb) </b></span><b>p [existentMetadataForPrefix count]</b></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
Unable to call function "objc_msgSend" at 0x1b1e08c: no return type information available.</div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
To call this function anyway, you can cast the return type explicitly (e.g. 'print (float) fabs (3.0)')</div>
</div>
<div>
<br /></div>
<div>
Nope, the breakpoint doesn't get hit. Ok, at this point it's pretty clear that I need to learn more about how to use gdb with Objective-C. In doing so I discovered this <a href="http://mikeash.com/pyblog/friday-qa-2011-06-17-gdb-tips-and-tricks.html">excellent blog post</a> that explains that:</div>
<blockquote class="tr_bq">
We can also print the result of messages which return primitive values. However, <code style="color: #222266; font-size: 1.15em; text-rendering: auto;">gdb</code> is not smart enough to figure out the return type in this case, so we have to tell it by adding a cast to the expression:</blockquote>
So all I had to do was this:<br />
<br />
<br />
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
<span style="color: #5f78ff;"><b>(gdb) </b></span><b>p (int)[existentMetadataForPrefix count]</b></div>
<div style="font: 11.0px Menlo; margin: 0.0px 0.0px 0.0px 0.0px;">
$1 = 10</div>
<div>
<br /></div>
<br />
Which, in all fairness was in fact suggested by gdb, but was shrouded in confusion, at least for me, by the mention of <span class="Apple-style-span" style="font-family: Menlo; font-size: 11px;">objc_msgSend</span>.<br />
<br />
I hope this would help you in case you run into a similar problem, and I can definitely recommend checking out that blog post. It's full of very interesting gotchas on this topic.<br />
<br />
<br />Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-35323211.post-48766831138692446442012-03-06T16:37:00.000-08:002012-03-06T16:37:38.845-08:00Following through the examples in the "Agile Web Application Development with Yii 1.1 and PHP5" book<br />
I just started reading the <a href="http://www.amazon.com/Agile-Web-Application-Development-PHP5/dp/1847199585/">Agile Web Application Development with Yii 1.1 and PHP5 book</a>. Chapter 3 explains the virtues of TDD (test-driven development) and tries to walk us through setting up a development environment that supports automated testing through PHPUnit and Selenium.<br />
<br />
At the same time, right at the beginning of the chapter 2 there's this note:<br />
<br />
<blockquote class="tr_bq">
"There are several versions of Yii from which to choose when downloading the framework. We will be using version 1.1.2 for the purposes of this book, which is the latest stable version as of the time of writing. Though most of the sample code should work with any 1.1.x version of Yii, there may be some subtle differences if you are using a different version. Please use 1.1.2 if you are following along with the examples."</blockquote>
<br />
This clearly makes sense - it's better to use the same version of the tools, as the author, if we're expecting to see the same results as shown in the book. The realty is that by the time some readers, like myself, get to read a book some of the software tools, and their dependencies, have evolved to the point where what they produce does not even remotely match what the version that the author used produced.<br />
<br />
So I followed the advice, got Yii version 1.1.2, and I tried to follow along. It wasn't a smooth ride. I'll try to walk you through some of the pitfalls that I experienced, and the ways I overcame them, hopefully helping you if you're experiencing similar problems.<br />
<br />
First problem appeared when I tried:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo pear install phpunit/PHPUnit </span><br />
<br />
shown on page 45<br />
<br />
I got an error telling me that the version of pear I've been using was too old (had been using a MAMP setup common on Macs, which may have grown old, at version 1.*). Even though I don't have the exact message, based on my googling history it said something along these lines: "requires PEAR Installer (version >= 1.9.4)".<br />
<br />
The solution for that was to upgrade pear, like so:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo pear upgrade pear</span><br />
<br />
and do a<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">pear --version </span><br />
to check that the version went up.<br />
<br />
However, if we follow what the book says, literally, when it tells us to install phpunit/PHPUnit, like so:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo pear install phpunit/PHPUnit</span><br />
<br />
we'll get the latest version of PHPUnit, which, of course, doesn't match the older version of the Yii framework, which we were advised to install. This opens a whole can of worms.<br />
<br />
First off, when you try to run the functional test cases, by doing:<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">phpunit functional/SiteTest.php </span><br />
you'll be informed that:<br />
<br />
<span class="Apple-style-span" style="color: purple; font-family: inherit;">PHP Warning: require_once(PHPUnit/Extensions/SeleniumTestCase.php): failed to open stream: No such file or directory</span><br />
<br />
If you check the location of PHPUnit install, which on my system is at /Applications/MAMP/bin/php5/lib/php/PHPUnit, you'll see that indeed that file is missing. How so ? Turns out that most recent versions of PHPUnit and Selenium now get that file installed by doing:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo pear install phpunit/phpunit_selenium</span><br />
<br />
but don't do that, because you'd just be wasting your time ! The thing is, you don't want to use the most recent PHPUnit, because if you do, as you would be if you followed the instructions in the book, you'll next hit this error:<br />
<br />
<span class="Apple-style-span" style="color: purple;">Warning: require_once(PHPUnit/Framework.php): failed to open stream: No such file or directory in .../framework/test/CTestCase.php on line 11</span><br />
<br />
Yeah, Yii version 1.1.2 requires PHPUnit/Framework.php, which is not present in the most recent versions of the PHPUnit.<br />
<br />
So, "yes it is" - a complete mess, that is. To save your sanity, uninstall the newer versions of the tools:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo pear uninstall phpunit/PHPUnit_selenium</span> (if you installed it already)<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo pear uninstall phpunit/PHPUnit</span><br />
<br />
Then install the version that matches the one used in the book:<br />
<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">sudo pear install --alldeps phpunit/PHPUnit-3.3.17</span><br />
<br />
This should bring you to clear sailing through chapter 3.<br />
<br />Unknownnoreply@blogger.com2tag:blogger.com,1999:blog-35323211.post-87113606075662774722012-02-14T16:27:00.000-08:002012-03-14T20:13:33.420-07:00how to find the app version from the iOS crash reportsIf you have an app that has a longer history, with several versions of the app having been released along its lifetime, you may find yourself getting a crash report from an end user and not knowing for sure to which potential version of the app it corresponds.<br />
<div>
<br /></div>
<div>
This is a pretty glaring oversight from Apple, because they don't include any information about the bundle version of the app in the crash reports they produce. You'll often see a "<span class="Apple-style-span" style="font-family: Monaco; font-size: 10px;">Version: ??? (???)</span>" string that's pretty useless in determining the actual version of the app that produced the crash.</div>
<div>
<br /></div>
<div>
Luckily other people did come up with <a href="http://stackoverflow.com/questions/1112683/iphone-crash-logs-say-version">a solution for this</a>. I'm writing this mostly as a note for myself, after spending more than an hour trying to dig up this info. Hopefully this blog post will help funnel other searches towards the solution.</div>
<div>
<br /></div>
<div>
The key to solving the problem is to use the <b>dwarfdump</b> command line tool to determine the UDID of the app, for different versions of the app that you published, and look up those UDID in the crash report, until you find a match.</div>
<div>
<br /></div>
<div>
So for each version of the app you have in your "Archives" view of the Xcode organizer,</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3cPG0Ws9LHp5-BgSov6oyn09FKDUhe31ZfodTY3ly9z8S4jZDe9EOUO8lt3lCFEdkt_w30sJOjlo_SLKP8z5YGrWNG65FnhhHVpYCV_SSiTBOj_Af5ksvqT-2EfCJzXVtiHS91w/s1600/Screen+shot+2012-02-14+at+3.41.48+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj3cPG0Ws9LHp5-BgSov6oyn09FKDUhe31ZfodTY3ly9z8S4jZDe9EOUO8lt3lCFEdkt_w30sJOjlo_SLKP8z5YGrWNG65FnhhHVpYCV_SSiTBOj_Af5ksvqT-2EfCJzXVtiHS91w/s320/Screen+shot+2012-02-14+at+3.41.48+PM.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
you'd try to find the actual binary of the app. You may need to use the "Show Package Contents" option of the Finder several times to dig down through archives, towards the binary file.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0bOTe87LmNqzFP6UB5PdRGng6k53hvyw146dmv1Mvz7m3i3Kdmf4Mig-GmBf5T7AGQVE59aba67M5e99OIV-DngICAljedvf6PwwdtoPEkuWzIrb8iuXO9gxH0d2k_VZDg6vOkg/s1600/Screen+shot+2012-02-14+at+3.42.43+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="181" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj0bOTe87LmNqzFP6UB5PdRGng6k53hvyw146dmv1Mvz7m3i3Kdmf4Mig-GmBf5T7AGQVE59aba67M5e99OIV-DngICAljedvf6PwwdtoPEkuWzIrb8iuXO9gxH0d2k_VZDg6vOkg/s320/Screen+shot+2012-02-14+at+3.42.43+PM.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi672-2AzZVeIekYQP7tzv2pfkIE4u3UR1LJRfN1U800zhtVBTUsuhFEd2aOcU1fBNKPWEfwrazFEa9wGc4YBX-I8EKYICJh1do582FO2TcCT_0feCuqwWOs5B1zUiiJPR6Gzll5Q/s1600/Screen+shot+2012-02-14+at+3.43.34+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="181" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi672-2AzZVeIekYQP7tzv2pfkIE4u3UR1LJRfN1U800zhtVBTUsuhFEd2aOcU1fBNKPWEfwrazFEa9wGc4YBX-I8EKYICJh1do582FO2TcCT_0feCuqwWOs5B1zUiiJPR6Gzll5Q/s320/Screen+shot+2012-02-14+at+3.43.34+PM.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Then you'd drag that binary over a Terminal window, to complete the call to dwarfdump, and you'd make a note of the UDIDs that are output by the tool:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgobDYTGDo-AwSBAzkvUepnvORHvdf6OoaEesSBygFega8y8P2FFnJ5VciH3jD03_wFqn490BV0RA4Wr0fBdpfNPEy73kbBbyD36yvhA3ZNweUVQM2vAZQtu-Lblf9eXAgqGqMmAg/s1600/Screen+shot+2012-02-14+at+3.46.03+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="41" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgobDYTGDo-AwSBAzkvUepnvORHvdf6OoaEesSBygFega8y8P2FFnJ5VciH3jD03_wFqn490BV0RA4Wr0fBdpfNPEy73kbBbyD36yvhA3ZNweUVQM2vAZQtu-Lblf9eXAgqGqMmAg/s320/Screen+shot+2012-02-14+at+3.46.03+PM.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: left;">
Then you'd simply look up those UDIDs in the crash report, while ignoring the dashes in the format of UDIDs that are produced by dwarfdump but are not present in the crash report:</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGSol7Qj_Tyzo8627bZVdb4_10YmHRPuj5lnfEepuE6hxH1ocl3jOxAXQzlRcssBmjlYFzlrDQe9jTZ4ebIIRukJf3WHszGvqDGctiYtZE-wNdauEQn2smeOutDYo-XyiHo3Z52g/s1600/Screen+shot+2012-02-14+at+3.47.22+PM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="112" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGSol7Qj_Tyzo8627bZVdb4_10YmHRPuj5lnfEepuE6hxH1ocl3jOxAXQzlRcssBmjlYFzlrDQe9jTZ4ebIIRukJf3WHszGvqDGctiYtZE-wNdauEQn2smeOutDYo-XyiHo3Z52g/s320/Screen+shot+2012-02-14+at+3.47.22+PM.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div>
If you get a match, like I do here for the armv7 architecture, it means that the version of the app you have selected in the Organizer corresponds to the crash report being analyzed.</div>
<div>
<br /></div>Unknownnoreply@blogger.com0