PageRenderTime 28ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

HTML | 131 lines | 85 code | 35 blank | 11 comment | 0 complexity | 0dd7227531d69dc4b4ed56ea2bbd8dce MD5 | raw file
  1. <!doctype html>
  2. <!-- START OF _layouts/default.html -->
  3. <html lang="en">
  4. <head>
  5. <meta charset="utf-8">
  6. <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible" >
  7. <meta content="width=device-width,initial-scale=1" name="viewport">
  8. <meta content="" name="description">
  9. <meta content="just a dude abiding" name="author">
  10. <title>Thoughts on Appcelerator Titanium &mdash; just a dude abiding</title>
  11. <!-- Styles -->
  12. <link href="/stylesheets/main.css" rel="stylesheet">
  13. <!-- Google webfonts -->
  14. <link rel="stylesheet" type="text/css" href="">
  15. <link rel="stylesheet" type="text/css" href="">
  16. <!-- jQuery and plugins -->
  17. <script src="//"></script>
  18. <script src="/js/jquery.zclip.min.js"></script>
  19. <!-- Syntax highlighter -->
  20. <link href="/stylesheets/prettify-hemisu.css" type="text/css" rel="stylesheet" />
  21. <script type="text/javascript" src="/js/prettify.js"></script>
  22. <!--<link href="" rel="alternate" title="just a dude abiding" type="application/rss+xml" />-->
  23. </head>
  24. <body onload="prettyPrint()">
  25. <div class="wrap">
  26. <header>
  27. <div class="title">just a dude abiding</div>
  28. <div class="navi">
  29. <ul>
  30. <li><a href="/">Blog</a></li>
  31. <li><a href="/about.html">About</a></li>
  32. <li><a href="/blog/archives">Archives</a></li>
  33. </ul>
  34. </div> <!-- // .navi -->
  35. </header>
  36. <!-- START OF _layouts/post.html -->
  37. <!-- START OF _includes/article.html -->
  38. <article>
  39. <header>
  40. <h1><a href="/blog/2011/04/03/Thoughts-on-Appcelerator-Titanium/">Thoughts on Appcelerator Titanium</a></h1>
  41. <time>03 April 2011</time>
  42. </header>
  43. <div class="content">
  44. <p><a href="">Appcelerator Titanium</a> is a product that bills itself as the easy way to create cross-platform, native, mobile applications. It&#8217;s a lofty goal. After several months of development on a decent sized application, I can say that currently the platform falls short of meeting that goal, way short.</p>
  45. <h2>A promising start..</h2>
  46. <p>I was drawn to Appcelerator because of the idea of being able to write straightforward JS and get native widgets. This would allow me to focus on the logic of my application, and not making sure I hadn&#8217;t forgot to track the retain/release counts on my objects correctly. Initially I was able to make tremendous progress in mocking up the UI. Sure I don&#8217;t get the great Interface Builder, but with minor tweaks I can deploy to Android! What had taken me weeks to sketch out in Obj-c was taking me hours or days instead. Multi-level navigation heirarchies with back buttons? Easy! But shortly after I reached the end of mocking up my UI flow, I began running into trouble. The documentation for the platform was sparse, but seemed to be improving. If you got really stuck, you could look at the &#8220;KitchenSink&#8221; sample app to see how various components worked. This isn&#8217;t too bad, but progress is slowing&#8230;</p>
  47. <h2>It does what?</h2>
  48. <p>So the first clear sign of troubl was that I had to use a separate application (Titanium Developer) to build/launch/monitor my applications. There wasn&#8217;t (and still isn&#8217;t) a visible method to run an app from the command line, or even to just generate code to run from within XCode. Sure, Titanium Developer is a bit slow, a little clumsy, and not terribly stable, but the code is going so much faster it&#8217;s bound to be worth it. Surely it is. I was wrong. Titanium Developer rapidly became the bane of my existence. It&#8217;s only syntax/static checking is done via JSLint with a pretty arcane set of rules. Want to write one line if statements? That&#8217;s a warning. A for loop without checking for property existence? That&#8217;s a warning. Appcelerator&#8217;s own sample app generates hundreds of JSLint warnings. What use are warnings if they are too verbose to find real problems? Get used to missing a comma, or a semi-colon, and it going unnoticed in the sea of other warnings.</p>
  49. <p>Once I settled into the fact that the Titanium Developer app itself is pretty brutal to work with, I moved onto the next set of troubles. The documentation is terrible. It&#8217;s a simple <span class="caps">API</span> doc, with almost no supporting code, and nearly useless descriptions for many properties. If you really want to know how a particular <span class="caps">API</span> or widget reacts, you have to look at the KitchenSink and hope your use case is covered. If it is covered, then you have to figure out how to work with the spaghetti nature of the sample app, and shoe-horn it into your app. If it&#8217;s not, then you&#8217;re off to the next giant pain, the community forum.</p>
  50. <p>The idea behind the community forum is great, a place for users to ask and hopefully answer each others questions. Instead what you find are questions that are 6 or 7 months old, unanswered, full of &#8220;any update?&#8221; responses. The most common official responses are &#8220;please provide Titanium and platform <span class="caps">SDK</span> versions&#8221;, with no follow up. When there are solutions, or work arounds, they may no longer be applicable to the newer versions.</p>
  51. <p>Minor platform versions routinely caused regressions in functionality (like grouped table views scrolling whenever the keyboard is present) while adding more ways for Appcelerator to make a dime (paid Modules), but without fixing persistent, core problems. Don&#8217;t get me wrong, they deserve to make some money off of their product, but leaving broken functionality in place for months with no expected resolution dates just doesn&#8217;t cut it. Some recent examples of major platform bugs: &#8216;swipe&#8217; gestures not being handled correctly or consistently including in their own custom horizontal scrolling view, platform specific overrides not working on devices (but working fine in the simulator) on iOS. And more that I&#8217;ve probably blocked out for my own sanity.</p>
  52. <h2>Almost there&#8230;</h2>
  53. <p>I managed to suffer through all of this, I&#8217;d put too much time and effort into the app to give up yet. I&#8217;m too close to the finish line. I&#8217;d become used to the undocumented idiosyncracies (like event propogation failing if you add subviews after the parent view has been added, or image views that cannot be scaled in a logical fashion, strange positiong issues if setting both lef/right or top/bottom). It was time for some last minute bug squashing, and pushing the data off to beta testers! Thanks to the fantastic <a href="">TestFlight</a> we were able to gather a group of testers, and get our permissioning setup to be able to send them an ad-hoc build. Now all I have to do is get a clean, release build ready.</p>
  54. <p>Great, Titanium Developer crashes everytime I try and create a release package. The builds take 5 or 6 minutes, have no stop button, and often hang the Titanium Developer UI. The only way to kill a build that&#8217;s already begun is to `killall xcodebuild`, which is certainly not documented. After waiting for the full rebuild (it doesn&#8217;t appear to cache <span class="caps">ANY</span> compilation steps), I am greeted with a large build log error. Usually about a failure to copy some file. The good news is that at this point Titanium Developer has generated a functional(ish) XCode project. Open it in XCode to find&#8230;it hasn&#8217;t set my distribution profile at all, it doesn&#8217;t seem to be targetting the correct platform, and in fact seems to be defaulting to a debug build. In fact some of the generated code seems to still be set to debug mode, must be a custom script that runs outside of XCode to fix that&#8230;</p>
  55. <p>An hour of learning what isn&#8217;t set correctly in the generated XCode project and I&#8217;m finally building again. Replace a few missing files (default icon, and Default.png don&#8217;t seem to copy correctly), fight with provisioning profiles some more, and a build is finally made. Now I load the fresh beta release onto my device, and immediately find a bug that didn&#8217;t seem to appear in the simulator, curse loudly, and call it a night.</p>
  56. <h2>Lessons learned?</h2>
  57. <p>Middleware platforms are a great idea, in theory. In practice it means working through a vendor who is struggling to keep up with the underlying platforms, stuggling to support their paid customers (speculating here), and completely failing to support their free user base. There is practically no external community for the Appcelerator platform, no solid bare bones starter applications, gotcha lists, or much of anything else. It&#8217;s a community of people all fighting to get their project done, and get the hell out of the way. I&#8217;m sure they mean well, but things don&#8217;t look good.</p>
  58. <p>I&#8217;m monumentally disappointed in the current state of the Appcelerator platform, community, and toolset, and have no plans on doing further development on the platform after completing my current project. I&#8217;m just going to cut my losses and either go back to direct native development, or forget native development alltogether and get with &quot;PhoneGap&quot;</p>
  59. </div>
  60. <footer>
  61. </footer>
  62. </article>
  63. <!-- END OF _includes/article.html -->
  64. <!-- END OF _/layouts/post.html -->
  65. <footer>
  66. Copyright &copy; 2015
  67. Tanner Burson
  68. </footer>
  69. </div> <!-- // .wrap -->
  70. </body>
  71. <script>
  72. $(document).ready(function() {
  73. // Make images center
  74. $('p:has(img)').css('text-align', 'center');
  75. // Add the image's title attribute as a caption
  76. $('p:has(img)').append(function () {
  77. return '<div class="caption">' + ($('img', this).attr('title') || "") + '</div>';
  78. });
  79. // Prettify code
  80. $('code').addClass('prettyprint');
  81. $('pre code').addClass('linenums');
  82. // Copy to clipboard with button
  83. $('pre:has(code)').prepend(function(){
  84. return '<div class="clip-btn">copy to clipboard</div>';
  85. });
  86. $('.clip-btn').zclip({
  87. path:'/js/ZeroClipboard.swf',
  88. copy: $(this).next('code').text(),
  89. afterCopy: function(){
  90. $(this).replaceWith('<div class="clip-btn">copied!');
  91. }
  92. });
  93. });
  94. </script>
  95. </html>
  96. <!-- END OF _layouts/default.html -->