Browse files

Add slides and supporting files

  • Loading branch information...
1 parent bcae416 commit bf8bfd11872524ab98294407772324a5ef35d123 @msv committed Aug 28, 2012
Showing with 23,024 additions and 0 deletions.
  1. +1 −0 .gitignore
  2. BIN images/f_logo.png
  3. BIN images/stackmob_logo.png
  4. BIN images/twitter_logo.png
  5. +1,264 −0 ios/360iDev.html
  6. +1,187 −0 ios/appsterdam.html
  7. +592 −0 ios/iOSFundamentals.html
  8. +65 −0 ios/stackmob-debug.js
  9. +19 −0 reveal.js/LICENSE
  10. +178 −0 reveal.js/README.md
  11. +2 −0 reveal.js/assets/fonts/leaguegothic/LICENSE
  12. BIN reveal.js/assets/fonts/leaguegothic/league_gothic-webfont.ttf
  13. +955 −0 reveal.js/css/main.css
  14. +164 −0 reveal.js/css/print.css
  15. +57 −0 reveal.js/css/reset.css
  16. +308 −0 reveal.js/index.html
  17. +793 −0 reveal.js/js/reveal.js
  18. +51 −0 reveal.js/js/reveal.min.js
  19. +2 −0 reveal.js/lib/classList.js
  20. +5 −0 reveal.js/lib/highlight.js
  21. +115 −0 reveal.js/lib/zenburn.css
  22. +165 −0 syntaxhighlighter/LGPL-LICENSE
  23. +20 −0 syntaxhighlighter/MIT-LICENSE
  24. +120 −0 syntaxhighlighter/compass/_theme_template.scss
  25. +14 −0 syntaxhighlighter/compass/config.rb
  26. +216 −0 syntaxhighlighter/compass/shCore.scss
  27. +2 −0 syntaxhighlighter/compass/shCoreDefault.scss
  28. +2 −0 syntaxhighlighter/compass/shCoreDjango.scss
  29. +2 −0 syntaxhighlighter/compass/shCoreEclipse.scss
  30. +2 −0 syntaxhighlighter/compass/shCoreEmacs.scss
  31. +2 −0 syntaxhighlighter/compass/shCoreFadeToGrey.scss
  32. +2 −0 syntaxhighlighter/compass/shCoreMDUltra.scss
  33. +2 −0 syntaxhighlighter/compass/shCoreMidnight.scss
  34. +2 −0 syntaxhighlighter/compass/shCoreRDark.scss
  35. +7 −0 syntaxhighlighter/compass/shThemeDefault.scss
  36. +36 −0 syntaxhighlighter/compass/shThemeDjango.scss
  37. +48 −0 syntaxhighlighter/compass/shThemeEclipse.scss
  38. +32 −0 syntaxhighlighter/compass/shThemeEmacs.scss
  39. +36 −0 syntaxhighlighter/compass/shThemeFadeToGrey.scss
  40. +32 −0 syntaxhighlighter/compass/shThemeMDUltra.scss
  41. +32 −0 syntaxhighlighter/compass/shThemeMidnight.scss
  42. +32 −0 syntaxhighlighter/compass/shThemeRDark.scss
  43. +22 −0 syntaxhighlighter/index.html
  44. +17 −0 syntaxhighlighter/scripts/shAutoloader.js
  45. +59 −0 syntaxhighlighter/scripts/shBrushAS3.js
  46. +75 −0 syntaxhighlighter/scripts/shBrushAppleScript.js
  47. +59 −0 syntaxhighlighter/scripts/shBrushBash.js
  48. +65 −0 syntaxhighlighter/scripts/shBrushCSharp.js
  49. +100 −0 syntaxhighlighter/scripts/shBrushColdFusion.js
  50. +97 −0 syntaxhighlighter/scripts/shBrushCpp.js
  51. +91 −0 syntaxhighlighter/scripts/shBrushCss.js
  52. +55 −0 syntaxhighlighter/scripts/shBrushDelphi.js
  53. +41 −0 syntaxhighlighter/scripts/shBrushDiff.js
  54. +52 −0 syntaxhighlighter/scripts/shBrushErlang.js
  55. +67 −0 syntaxhighlighter/scripts/shBrushGroovy.js
  56. +52 −0 syntaxhighlighter/scripts/shBrushJScript.js
  57. +57 −0 syntaxhighlighter/scripts/shBrushJava.js
  58. +58 −0 syntaxhighlighter/scripts/shBrushJavaFX.js
  59. +72 −0 syntaxhighlighter/scripts/shBrushPerl.js
  60. +88 −0 syntaxhighlighter/scripts/shBrushPhp.js
  61. +33 −0 syntaxhighlighter/scripts/shBrushPlain.js
  62. +74 −0 syntaxhighlighter/scripts/shBrushPowerShell.js
  63. +64 −0 syntaxhighlighter/scripts/shBrushPython.js
  64. +55 −0 syntaxhighlighter/scripts/shBrushRuby.js
  65. +94 −0 syntaxhighlighter/scripts/shBrushSass.js
  66. +51 −0 syntaxhighlighter/scripts/shBrushScala.js
  67. +66 −0 syntaxhighlighter/scripts/shBrushSql.js
  68. +56 −0 syntaxhighlighter/scripts/shBrushVb.js
  69. +69 −0 syntaxhighlighter/scripts/shBrushXml.js
  70. +17 −0 syntaxhighlighter/scripts/shCore.js
  71. +17 −0 syntaxhighlighter/scripts/shLegacy.js
  72. +130 −0 syntaxhighlighter/src/shAutoloader.js
  73. +1,721 −0 syntaxhighlighter/src/shCore.js
  74. +157 −0 syntaxhighlighter/src/shLegacy.js
  75. +226 −0 syntaxhighlighter/styles/shCore.css
  76. +328 −0 syntaxhighlighter/styles/shCoreDefault.css
  77. +331 −0 syntaxhighlighter/styles/shCoreDjango.css
  78. +339 −0 syntaxhighlighter/styles/shCoreEclipse.css
  79. +324 −0 syntaxhighlighter/styles/shCoreEmacs.css
  80. +328 −0 syntaxhighlighter/styles/shCoreFadeToGrey.css
  81. +324 −0 syntaxhighlighter/styles/shCoreMDUltra.css
  82. +324 −0 syntaxhighlighter/styles/shCoreMidnight.css
  83. +324 −0 syntaxhighlighter/styles/shCoreRDark.css
  84. +117 −0 syntaxhighlighter/styles/shThemeDefault.css
  85. +120 −0 syntaxhighlighter/styles/shThemeDjango.css
  86. +128 −0 syntaxhighlighter/styles/shThemeEclipse.css
  87. +113 −0 syntaxhighlighter/styles/shThemeEmacs.css
  88. +117 −0 syntaxhighlighter/styles/shThemeFadeToGrey.css
  89. +113 −0 syntaxhighlighter/styles/shThemeMDUltra.css
  90. +113 −0 syntaxhighlighter/styles/shThemeMidnight.css
  91. +113 −0 syntaxhighlighter/styles/shThemeRDark.css
  92. +1 −0 syntaxhighlighter/tests/.rvmrc
  93. +204 −0 syntaxhighlighter/tests/brushes/sass.html
  94. +136 −0 syntaxhighlighter/tests/brushes_tests.html
  95. +42 −0 syntaxhighlighter/tests/cases/001_basic.html
  96. +50 −0 syntaxhighlighter/tests/cases/002_brushes.html
  97. +42 −0 syntaxhighlighter/tests/cases/003_script_tag.html
  98. +43 −0 syntaxhighlighter/tests/cases/004_url_parsing.html
  99. +33 −0 syntaxhighlighter/tests/cases/005_no_gutter.html
  100. +39 −0 syntaxhighlighter/tests/cases/006_pad_line_numbers.html
  101. +60 −0 syntaxhighlighter/tests/cases/007_collapse.html
  102. +44 −0 syntaxhighlighter/tests/cases/007_collapse_interaction.html
  103. +29 −0 syntaxhighlighter/tests/cases/008_first_line.html
  104. +32 −0 syntaxhighlighter/tests/cases/009_class_name.html
  105. +70 −0 syntaxhighlighter/tests/cases/010_highlight.html
  106. +98 −0 syntaxhighlighter/tests/cases/011_smart_tabs.html
  107. +35 −0 syntaxhighlighter/tests/cases/012_server_side.html
  108. +34 −0 syntaxhighlighter/tests/cases/013_html_script.html
  109. +70 −0 syntaxhighlighter/tests/cases/014_legacy.html
  110. +52 −0 syntaxhighlighter/tests/commonjs_tests.js
  111. +6,240 −0 syntaxhighlighter/tests/js/jquery-1.4.2.js
  112. +135 −0 syntaxhighlighter/tests/js/qunit.css
  113. +1,069 −0 syntaxhighlighter/tests/js/qunit.js
  114. +242 −0 syntaxhighlighter/tests/syntaxhighlighter_tests.html
  115. +134 −0 syntaxhighlighter/tests/theme_tests.html
  116. +11 −0 syntaxhighlighter/tests/webrick.rb
  117. +2 −0 syntaxhighlighter/tests/webrick.sh
View
1 .gitignore
@@ -0,0 +1 @@
+.DS_Store
View
BIN images/f_logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN images/stackmob_logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN images/twitter_logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
1,264 ios/360iDev.html
@@ -0,0 +1,1264 @@
+<html>
+ <head>
+ <title>Case Study: Implementing an Incremental Store</title>
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
+ <script type="text/javascript" src="http://static.stackmob.com/js/json2-min.js"></script>
+ <script type="text/javascript" src="http://static.stackmob.com/js/underscore-1.3.3-min.js"></script>
+ <script type="text/javascript" src="http://static.stackmob.com/js/backbone-0.9.2-min.js"></script>
+ <script type="text/javascript" src="http://static.stackmob.com/js/stackmob-js-0.2.1-min.js"></script>
+ <script type="text/javascript" src="http://static.stackmob.com/resources/js/jsonFormatter-0.1.0-min.js"></script>
+ <script type="text/javascript" src="stackmob-debug.js"></script>
+
+ <!-- Include required JS files -->
+ <script type="text/javascript" src="../syntaxhighlighter/scripts/shCore.js"></script>
+
+ <script type="text/javascript" src="../syntaxhighlighter/scripts/shBrushJScript.js"></script>
+ <script type="text/javascript" src="../syntaxhighlighter/scripts/shBrushXml.js"></script>
+ <script type="text/javascript" src="../syntaxhighlighter/scripts/shBrushJava.js"></script>
+ <script type="text/javascript" src="../syntaxhighlighter/scripts/shBrushCpp.js"></script>
+
+ <link href="../syntaxhighlighter/styles/shCoreMidnight.css" rel="stylesheet" type="text/css" />
+ <link href="../syntaxhighlighter/styles/shThemeMidnight.css" rel="stylesheet" type="text/css" />
+
+ <style type="text/css">
+ .syntaxhighlighter {
+ margin: 0px !important; padding-top: 15px; padding-bottom: 15px;
+ border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px;
+
+ }
+ </style>
+
+ <script type="text/javascript">
+ StackMob.init({
+ appName: 'javascript',
+ clientSubdomain: 'stackmob',
+ apiVersion: 0
+ });
+
+ var Todo = StackMob.Model.extend({
+ schemaName: 'todo'
+ });
+
+ var Todos = StackMob.Collection.extend({
+ model: Todo
+ });
+
+ $(document).ready(function() {
+ SyntaxHighlighter.config.tagName = 'code';
+ SyntaxHighlighter.config.toolbar = false;
+ SyntaxHighlighter.all();
+
+ Reveal.addEventListener('stampede', function() {
+ $('#stampede').attr('src', 'http://dl.dropbox.com/u/77348001/stampede.gif');
+ });
+ });
+ </script>
+
+ <link rel="stylesheet" href="../reveal.js/css/reset.css">
+ <link rel="stylesheet" href="../reveal.js/css/main.css">
+ <style type="text/css" media="screen">
+ .button, .button a
+{
+ background: #98be47;
+ background: linear-gradient(top, #a8cf43, #98be47);
+ background: -moz-linear-gradient(top, #a8cf43, #98be47);
+ background: -ms-linear-gradient(top, #a8cf43, #98be47);
+ background: -o-linear-gradient(top, #a8cf43, #98be47);
+ background: -webkit-linear-gradient(top, #a8cf43, #98be47);
+ border: 1px solid #8cac42;
+ border-bottom-color: #7b9b36;
+ border-radius: 4px;
+ border-top-color: #94b146;
+ box-shadow: 0 2px 2px rgba(0, 0, 0, .2), inset 0 1px 0 rgba(255, 255, 255, .5);
+ color: #fff !important;
+ cursor: pointer;
+ font-family: "Helvetica Neue", Arial, sans-serif;
+ font-size: 26px;
+ font-weight: bold;
+ moz-border-radius: 4px;
+ moz-box-shadow: 0 2px 2px rgba(0, 0, 0, .2), inset 0 1px 0 rgba(255, 255, 255, .5);
+ ms-border-radius: 4px;
+ ms-box-shadow: 0 2px 2px rgba(0, 0, 0, .2), inset 0 1px 0 rgba(255, 255, 255, .5);
+ o-border-radius: 4px;
+ o-box-shadow: 0 2px 2px rgba(0, 0, 0, .2), inset 0 1px 0 rgba(255, 255, 255, .5);
+ padding: 6px 14px;
+ text-decoration: none;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, .4);
+ webkit-border-radius: 4px;
+ webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, .2), inset 0 1px 0 rgba(255, 255, 255, .5);
+}
+.button:hover, .button a:hover
+{
+ background: #67a215;
+ background: linear-gradient(top, #9dbf46, #67a215);
+ background: -moz-linear-gradient(top, #9dbf46, #67a215);
+ background: -ms-linear-gradient(top, #9dbf46, #67a215);
+ background: -o-linear-gradient(top, #9dbf46, #67a215);
+ background: -webkit-linear-gradient(top, #9dbf46, #67a215);
+ border: 1px solid #699631;
+ border-bottom-color: #457119;
+ border-top-color: #6d9e34;
+ color: rgba(250, 250, 250, .96);
+ text-decoration: none;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, .8);
+}
+.button:active, .button a:active
+{
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
+ moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
+ ms-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
+ o-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
+ padding: 4px 14px 7px;
+ webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
+}
+.button.blue, .button.blue a
+{
+ background: #6bbad7;
+ background: linear-gradient(top, #76cced, #6bbad7);
+ background: -moz-linear-gradient(top, #76cced, #6bbad7);
+ background: -ms-linear-gradient(top, #76cced, #6bbad7);
+ background: -o-linear-gradient(top, #76cced, #6bbad7);
+ background: -webkit-linear-gradient(top, #76cced, #6bbad7);
+ border: 1px solid #4ca8ca;
+ border-bottom-color: #4c9bb9;
+ border-top-color: #4cb2da;
+}
+.button.blue:hover, .button.blue a:hover
+{
+ background: #2c9cc6;
+ background: linear-gradient(top, #3cb7e5, #2c9cc6);
+ background: -moz-linear-gradient(top, #3cb7e5, #2c9cc6);
+ background: -ms-linear-gradient(top, #3cb7e5, #2c9cc6);
+ background: -o-linear-gradient(top, #3cb7e5, #2c9cc6);
+ background: -webkit-linear-gradient(top, #3cb7e5, #2c9cc6);
+ border: 1px solid #0083b4;
+ border-bottom-color: #00709b;
+ border-top-color: #0092ca;
+}
+
+#stackmoblogo {
+ position: fixed;
+ top: 20px;
+ left: 20px;
+}
+ </style>
+
+ </head>
+ <body>
+ <div id="stackmoblogo"><img src="../images/stackmob_logo.png"/></div>
+ <div id="reveal">
+ <div class="state-background"></div>
+
+ <div class="slides">
+ <section>
+ <h2>Case Study: Implementing an Incremental Store</h2>
+ <!-- <h3 class="inverted">StackMob &amp; Objective-C</h3> -->
+ <!-- <p><span style="font-size: 24px;">(uses Backbone.js)</span></p> -->
+ <p style="margin-top: 100px;">
+ <!-- <p><a href="http://www.stackmob.com" target="_blank">stackmob.com</a> | <a href="http://www.twitter.com/stackmob">@stackmob</a> | #stackmob</p> -->
+ <p>Matt Vaznaian | <a href="http://www.twitter.com/mvaznaian" target="_blank">@_mattvaz</a></p>
+ </p>
+ </section>
+ <section>
+ <h2>Matt Vaznaian</h2>
+ <h3>matt@stackmob.com</h3>
+ <h3>@_mattvaz</h3>
+ <p><a href="http://www.stackmob.com"><img src="../images/stackmob_logo.png"/></a></p>
+ </section>
+
+ <section>
+ <h2>What problem are we trying to solve?</h2>
+
+ <ul>
+ <li>Want to improve the experience of using a mobile development platform</li>
+ <li>What existing iOS knowledge can we leverage?</li>
+ <li>Core Data</li>
+ <li>sqlite --> StackMob</li>
+ <li>Incremental Store</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Core Data Overview</h2>
+
+ <ul>
+ <li>What is it used for?</li>
+ <li>How does it work</li>
+ <li>NSManagedObjectContext</li>
+ <li>NSPersistentStoreCoordinator</li>
+ <li>NSManagedObjectModel</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>NSIncrementalStore Introduction</h2>
+
+ <ul>
+ <li>What is it used for?</li>
+ <li>How does it work</li>
+ <li>How does it differ from an atomic store</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Methods to override</h2>
+
+ <ul>
+ <li>loadMetadata:</li>
+ <li>executeRequest:WithContext:error</li>
+ <li>newValuesForObjectWithID:withContext:error</li>
+ <li>newValuesForRelationship:forObjectWithID:withContext:error</li>
+ <li>obtainPermanentIDsForObjects:error</li>
+ <li>There is no need to override the methods that you must otherwise override for a subclass of NSPersistentStore.</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Details of implementation</h2>
+ </section>
+
+ <section>
+ <h2>Hurdles/Obstacles</h2>
+
+ <ul>
+ <li>The serialization process: Core Data <--> StackMob</li>
+ <li>Bugs --> autoreleasing error</li>
+ <li>Decreasing Limitations --> matching up StackMob ids with Core Data NSManagedObjectID</li>
+ </ul>
+
+ </section>
+
+ <section>
+ <h2>What's next?</h2>
+
+ <ul>
+ <li>Offline Sync - What's the plan</li>
+ <li>Constant iteration</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Try it out!</h2>
+
+ <p>Give the resources for stackmob ios sdk</p>
+ </section>
+
+ <section>
+ <h2>DONE</h2>
+
+ <section>
+ </section>
+
+ <section>
+ <h3>Database</h3>
+ <img src="https://dl.dropbox.com/u/79464649/oracle.jpg" />
+ <img src="https://dl.dropbox.com/u/79464649/mysql-big.gif" />
+ </section>
+
+ <section>
+ <h3>Hardware</h3>
+ <img src="https://dl.dropbox.com/u/79464649/300px-Dell_Logo.svg_1.png" />
+ <img src="https://dl.dropbox.com/u/79464649/intel-logo-300x198.jpg" />
+ </section>
+
+ <section>
+ <h3>Cloud Store</h3>
+ <img src="https://dl.dropbox.com/u/79464649/amazon.png" />
+ <img src="https://dl.dropbox.com/u/79464649/iCloud.png" />
+ </section>
+
+ <section>
+ <h3>Software Layer</h3>
+ <img src="https://dl.dropbox.com/u/79464649/heroku.jpg" />
+ <img src="https://dl.dropbox.com/u/79464649/appengine-logo.png" />
+ </section>
+
+
+ </section>
+
+ <section>
+ <h2>NSIncrementalStore</h2>
+
+ <ul>
+ <li>Mobile Backend Platform</li>
+ <li>Lowering barrier of entry</li>
+ <li>Focus on your user experience.</li>
+ <li>Access to "big company" backend power.</li>
+ <li>Develop. Scale. Analytics. Revisioning.</li>
+ </ul>
+
+ </section>
+
+ <section>
+ <h2>SMIncrementalStore</h2>
+
+ <p>We've powered apps:</p>
+ <ul>
+ <li>Featured in the AppStore</li>
+ <li>Top 20 in the AppStore</li>
+ <li>TechCrunch Disrupt</li>
+ <li>SXSW</li>
+ <li>Won Startup Weekend</li>
+ <li>Atari</li>
+ </ul>
+ <p>Games, Enterprise Apps, Social... </p>
+ <p>iOS, Android, JavaScript, Ruby, PHP, Python, Java</p>
+ </section>
+
+ <section>
+ <h2>The First App You Ever Built</h2>
+ <p>
+ <img src="https://dl.dropbox.com/u/79464649/helloWorld.png"/>
+ </p>
+ </section>
+
+ <section>
+ <h2>NSUserDefaults</h2>
+ <p>
+ <img src="https://dl.dropbox.com/u/79464649/helloMatt.png" />
+ </p>
+ </section>
+
+ <section>
+ <h2>The Next Level</h2>
+
+ <ul>
+ <li>Access Data From Multiple Devices.</li>
+ <li>Lots of Features == Lots of Data.</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>I could do it myself</h2>
+
+ <img src="https://dl.dropbox.com/u/79464649/headInHands.jpg" />
+ </section>
+
+ <section>
+ <h2>Focus on your user experience!</h2>
+
+ <img src="https://dl.dropbox.com/u/79464649/awesome_note.png" />
+ </section>
+
+ <section>
+ <h2>Configure StackMob iOS SDK</h2>
+
+ <h3>StackMobConfiguration.h</h3>
+ <pre><code class="brush: xml">
+ #define STACKMOB_PUBLIC_KEY @"YOUR_PUBLIC_KEY"
+ #define STACKMOB_PRIVATE_KEY @"YOUR_PRIVATE_KEY"
+ #define STACKMOB_APP_NAME @"YOUR_APP_NAME"
+ #define STACKMOB_UDID_SALT @"UDID"
+ #define STACKMOB_APP_DOMAIN @"stackmob.com"
+ #define STACKMOB_APP_MOB @"mob1"
+ #define STACKMOB_USER_OBJECT_NAME @"user"
+ #define STACKMOB_API_VERSION 0
+ </code></pre>
+
+ <h3>AppDelegate.h (or any other file)</h3>
+ <pre><code class="brush: xml">
+ #import "StackMob.h"
+ </code></pre>
+ </section>
+
+
+ <section>
+ <h2>Initialize</h2>
+
+ <pre><code class="brush: javascript; highlight: [5]">
+ - (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+ {
+
+ [[StackMob stackmob] startSession];
+
+ [self.window makeKeyAndVisible];
+ return YES;
+
+
+ }
+ </code></pre>
+
+ <pre><code class="brush: javascript; highlight: [3]">
+ - (void)applicationWillTerminate:(UIApplication *)application
+ {
+ [[StackMob stackmob] endSession];
+ }
+ </code></pre>
+
+ </section>
+
+
+ <section>
+ <h2>Server-Side Persistence: Create</h2>
+ <section>
+ <a href="javascript:void(0);">Syntax:</a>
+ <pre><code class="brush: javascript;">
+
+ // define schema
+ NSString *schemaName = @"blogentry"
+
+ // define field/value pairs and contain in a dictionary
+ NSDictionary *args = [[NSDictionary alloc] initWithObjectsAndKeys:
+ @"rich text", @"content", nil];
+
+ [[StackMob stackmob] post:schemaName withArguments:args
+ andCallback:MyCallback];
+
+ </code></pre>
+
+ </section>
+
+ <section>
+ <h2>Let's try it out!</h2>
+ </section>
+
+ <section>
+ <a href="javascript:void(0);">Syntax:</a>
+ <pre><code class="brush: javascript; highlight: [2]">
+
+ // define schema
+ NSString *schemaName = @"blogentry"
+
+ // define field/value pairs and contain in a dictionary
+ NSDictionary *args = [[NSDictionary alloc] initWithObjectsAndKeys:
+ @"rich text", @"content", nil];
+
+ [[StackMob stackmob] post:schemaName withArguments:args
+ andCallback:MyCallback];
+
+ </code></pre>
+
+ </section>
+
+ <section>
+ <a href="javascript:void(0);">Syntax:</a>
+ <pre><code class="brush: javascript; highlight: [5, 6]">
+
+ // define schema
+ NSString *schemaName = @"blogentry"
+
+ // define field/value pairs and contain in a dictionary
+ NSDictionary *args = [[NSDictionary alloc] initWithObjectsAndKeys:
+ @"rich text", @"content", nil];
+
+ [[StackMob stackmob] post:schemaName withArguments:args
+ andCallback:MyCallback];
+
+ </code></pre>
+
+ </section>
+
+ <section>
+ <a href="javascript:void(0);">Syntax:</a>
+ <pre><code class="brush: javascript; highlight: [8, 9]">
+
+ // define schema
+ NSString *schemaName = @"blogentry"
+
+ // define field/value pairs and contain in a dictionary
+ NSDictionary *args = [[NSDictionary alloc] initWithObjectsAndKeys:
+ @"rich text", @"content", nil];
+
+ [[StackMob stackmob] post:schemaName withArguments:args
+ andCallback:MyCallback];
+
+ </code></pre>
+
+ </section>
+
+ <section>
+ <a href="javascript:void(0);">Callback:</a>
+ <pre><code class="brush: javascript;">
+ [[StackMob stackmob] post:schemaName withArguments:args
+ andCallback:^(BOOL success, id result){
+ if(success){
+
+ // We can get the response body of the newly created object
+ // in NSDictionary form
+ NSDictionary *resultDict = (NSDictionary *)result;
+ [self updateUI:resultDict];
+
+ } else {
+ // Action after a call results in error
+ }
+ }];
+ </code></pre>
+
+ </section>
+
+
+ <section>
+ <h2>Aw yeah! Backend Created!</h2>
+
+ <p>
+ <img src="http://dl.dropbox.com/u/9289507/joy.gif" alt=""/>
+ </p>
+ </section>
+
+ </section>
+
+
+ <section>
+
+ <h2>Read from DB</h2>
+ <a href="javascript:void(0);">Read Item</a>
+ <pre><code class="brush: javascript;">
+ NSString *schemaName = @"blogentry";
+ NSString objectId = @"1234";
+
+ [[StackMob stackmob] get:[NSString stringWithFormat:@"%@/%@",
+ schemaName, objectID] withCallback:myCallBack];
+ </code></pre>
+
+ </section>
+
+ <section>
+
+ <h2>Update DB</h2>
+ <a href="javascript:void(0);">Update Item</a>
+ <pre><code class="brush: javascript;">
+ NSString *schemaName = @"blogentry"
+ NSString objectId = @"1234";
+
+ // define field/value pairs and contain in a dictionary
+ NSDictionary *args = [[NSDictionary alloc]
+ initWithObjectsAndValues:@"some other stuff", @"content"];
+
+ [[StackMob stackmob] put:schemaName withID:objectId andArguments:args
+ andCallback:myCallback];
+</code></pre>
+
+ </section>
+
+ <section>
+ <h2>Delete from DB</h2>
+ <a href="javascript:void(0);">Delete Item</a>
+ <pre><code class="brush: javascript;">
+ NSString *schemaName = @"blogentry"
+
+ // define field/value pairs and contain in a dictionary
+ NSDictionary *args = [[NSDictionary alloc]
+ initWithObjectsAndKeys:@"1234", @"blogentry_id"];
+
+ [[StackMob stackmob] destroy:schemaName withArguments:args
+ andCallback:myCallback];
+</code></pre>
+
+ </section>
+
+ <section>
+ <h2>WOOHOO for CRUD!</h2>
+ <img src="https://dl.dropbox.com/u/79464649/homer_woohoo.jpg" />
+ </section>
+
+ <section>
+ <h2>But I want more than just a datastore in the cloud!</h2>
+
+ <ul>
+ <li>Queries</li>
+ <li>Relate this object to that object</li>
+ <li>User Authentication</li>
+ <li>Push Notifications</li>
+ <li><img src="../images/f_logo.png"/>
+ <img src="../images/twitter_logo.png"/>
+ </li>
+ </ul>
+ </section>
+
+
+ <section>
+ <h2>Queries</h2>
+
+ <section>
+ <img src="https://dl.dropbox.com/u/79464649/massiveData_dr-evil.jpg" />
+
+ </section>
+
+ <section>
+ <h3>Field Selection</h3>
+ <pre><code class="brush: javascript;">
+ StackMobQuery *q = [StackMobQuery query];
+ [q setSelectionToFields:[NSArray arrayWithObjects:@"username", @"age", nil]];
+
+ // perform the query and handle the results
+ [[StackMob stackmob] get:@"user" withQuery:q andCallback:myQueryCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>Equality</h3>
+ <pre><code class="brush: javascript;">
+ StackMobQuery *q = [StackMobQuery query];
+ [q field:@"age" mustEqualValue:25];
+
+ [[StackMob stackmob] get:@"user" withQuery:q andCallback:myQueryCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>Order By</h3>
+ <pre><code class="brush: javascript;">
+ StackMobQuery *q = [StackMobQuery query];
+ [q orderByField:@"createddate" withDirection:SMOrderDescending];
+ [q orderByField:@"age" withDirection:SMOrderAscending];
+
+
+ [[StackMob stackmob] get:@"user" withQuery:q andCallback:myQueryCallback];
+ </code></pre>
+ </section>
+
+
+ </section>
+
+ <section>
+ <h2>Relationships</h2>
+ <section>
+ <img src="https://dl.dropbox.com/u/79464649/holdingHands.jpg" />
+
+ </section>
+
+ <section>
+ <pre><code class="brush: javascript;">
+ {
+ user: john
+ todos: [1, 2]
+ }
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>POST - Creating</h3>
+ <pre><code class="brush: javascript; highlight: [1, 2]">
+ NSDictionary *item1 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 1", @"action", @"high", @"priority", nil];
+ NSDictionary *item2 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 2", @"action", @"low", @"priority", nil];
+ NSArray *items = [NSArray arrayWithObjects:item1, item2, nil];
+
+ [[StackMob stackmob] post:@"user" withId:@"john" andField:@"todos"
+ andBulkArguments:items andCallback:myCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>POST - Creating</h3>
+ <pre><code class="brush: javascript; highlight: [3, 4]">
+ NSDictionary *item1 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 1", @"action", @"high", @"priority", nil];
+ NSDictionary *item2 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 2", @"action", @"low", @"priority", nil];
+ NSArray *items = [NSArray arrayWithObjects:item1, item2, nil];
+
+ [[StackMob stackmob] post:@"user" withId:@"john" andField:@"todos"
+ andBulkArguments:items andCallback:myCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>POST - Creating</h3>
+ <pre><code class="brush: javascript; highlight: [5]">
+ NSDictionary *item1 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 1", @"action", @"high", @"priority", nil];
+ NSDictionary *item2 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 2", @"action", @"low", @"priority", nil];
+ NSArray *items = [NSArray arrayWithObjects:item1, item2, nil];
+
+ [[StackMob stackmob] post:@"user" withId:@"john" andField:@"todos"
+ andBulkArguments:items andCallback:myCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>POST - Creating</h3>
+ <pre><code class="brush: javascript; highlight: [7, 8]">
+ NSDictionary *item1 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 1", @"action", @"high", @"priority", nil];
+ NSDictionary *item2 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 2", @"action", @"low", @"priority", nil];
+ NSArray *items = [NSArray arrayWithObjects:item1, item2, nil];
+
+ [[StackMob stackmob] post:@"user" withId:@"john" andField:@"todos"
+ andBulkArguments:items andCallback:myCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <p>Result from a GET on user/john</p>
+ <pre><code class="brush: javascript;">
+ {
+ user: john
+ todos: [1, 2]
+ }
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>GET - Expansion</h3>
+ <pre><code class="brush: javascript;">
+ StackMobQuery *q = [StackMobQuery query];
+ [q setExpandDepth:1];
+
+ [[StackMob stackmob] get:@"user/john" withQuery:q andCallback:myCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <pre><code class="brush: javascript;">
+ {
+ user: john
+ todos: [
+ {
+ todo_id: 1
+ action: "my todo 1"
+ priority: "high"
+ }
+ {
+ todo_id: 2
+ action: "my todo 2"
+ priority: "low"
+ }
+ ]
+ }
+ </code></pre>
+ </section>
+
+ </section>
+
+ <section>
+ <h2>User Authentication</h2>
+ <section>
+ <img src="http://dl.dropbox.com/u/77348001/calving_hobbes_password.gif" alt=""/>
+ </section>
+
+ <section>
+ <h3>Create User & Login</h2>
+ <pre><code class="brush: javascript;">
+ NSString *username = @"[USERNAME]"
+ NSString *password = @"[PASSWORD]"
+ NSDictionary *args = [NSDictionary dictionaryWithObjectsAndKeys:
+ username, @"username", password, @"password", nil];
+
+ [[StackMob stackmob] loginWithArguments:args andCallback:loginCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>Password Management</h3>
+ <ul>
+ <li>Forgotten Passwords</li>
+ <li>Reset Password</li>
+ </ul>
+
+ </section>
+ </section>
+ <!--
+ <section>
+ <h2>Security &rarr; OAuth 2.0</h2>
+
+ <ul>
+ <li>Industry Standard: OAuth 1.0/2.0</li>
+ <li>Public/Private Keys identify your app's requests</li>
+ <li>FB/Twitter: OAuth 2.0. Username/Password</li>
+ <li>In current JS SDK for pre-trials</li>
+ </ul>
+
+ </section>
+ -->
+ <section>
+ <h2>Access Controls</h2>
+ <ul>
+ <li>Share objects to certain users</li>
+ <li>Limit visibility</li>
+ <li>Coming very very soon</li>
+ </ul>
+ </section>
+
+
+ <section>
+
+ <section>
+ <h2>Even more flexibility: Custom Code</h2>
+ <ul>
+ <li>Java/Scala Server Side SDK</li>
+ <li>Write Code - StackMob REST-ifies it</li>
+ <li>iOS can execute server code via REST API!</li>
+ <li>iOS receives your custom JSON response too</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Call Custom Code from iOS App!</h2>
+ <pre><code class="brush: javascript;">
+ [[StackMob stackmob] get:@"hello_world" withCallback:^(BOOL success, id result) {
+ if (success) {
+ // result is the JSON as an NSDictionary of "msg" vs. "Hello, world!"
+ } else {
+ }
+ }];
+ </code></pre>
+ </section>
+
+ <section>
+ <h2>Custom Code Example</h2>
+
+<pre><code class="brush: java">
+//Java
+public class HelloWorldExample implements CustomCodeMethod {
+
+ @Override
+ public String getMethodName() {
+ return "hello_world";
+ }
+
+ @Override
+ public ResponseToProcess execute(...) {
+
+ //Do fancy server side things
+
+ Map&lt;String, String&gt; json =
+ new HashMap&lt;String, String&gt;();
+ json.put("msg", "hello world!");
+ return new ResponseToProcess(..., json);
+ }
+}
+</code></pre>
+ </section>
+
+ <section>
+ <h2>Defines your REST endpoint</h2>
+ <p><code>http://api.mob1.stackmob.com/hello_world</code></p>
+<pre><code class="brush: java; highlight: [6]">
+//Java
+public class HelloWorldExample implements CustomCodeMethod {
+
+ @Override
+ public String getMethodName() {
+ return "hello_world";
+ }
+
+ ...
+}
+</code></pre>
+ </section>
+
+ <section>
+ <h2>Defines your return JSON</h2>
+ <p><code>{ msg: "hello world!" }</code></p>
+<pre><code class="brush: java; highlight: [11]">
+//Java
+public class HelloWorldExample implements CustomCodeMethod {
+ ...
+ @Override
+ public ResponseToProcess execute(...) {
+
+ //Do fancy server side things
+
+ Map&lt;String, String&gt; json =
+ new HashMap&lt;String, String&gt;();
+ json.put("msg", "hello world!");
+ return new ResponseToProcess(..., json);
+ }
+}
+</code></pre>
+ </section>
+
+ </section>
+
+ <section>
+ <h2>Development &amp; Production Environments</h2>
+ <ul>
+ <li>Different databases</li>
+ <li>Only deploy when you're ready!</li>
+ <li><a href="https://www.stackmob.com/platform/deploy/" target="_blank">Easy rollout/rollback</a></li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>API Versions</h2>
+ <ul>
+ <li>Backwards support old clients</li>
+ <li>Concurrently run different versions of your custom code/schemas</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Time to Re-Market</h2>
+ <ul>
+ <li>Change configurations through the Dashboard</li>
+ <li>Instantly reflected in your application</li>
+ <li>No need to resubmit to the App Store</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Open Sourced SDKs</h2>
+
+ <ul>
+ <li>iOS</li>
+ <li>Android</li>
+ <li>Javascript</li>
+ <li>Download them today!</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Adding a backend with StackMob</h2>
+ <ul>
+ <li>Simple</li>
+ <li>Seamless</li>
+ <li>Flexible</li>
+ <li>Powerful</li>
+ <li>Free &rarr; Grow</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Backend Services</h2>
+ <ul>
+ <li>User Authentication</li>
+ <li>Datastore</li>
+ <li>Security</li>
+ <li>GeoSpatial</li>
+ <li>Push</li>
+ <li>Hosting</li>
+ <li>Social Integration</li>
+ <li>Custom Server Side Code</li>
+ <li>Analytics</li>
+ <li>...</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>The future of the iOS SDK</h2>
+ <img src="https://dl.dropbox.com/u/79464649/future.jpg" />
+
+ </section>
+
+ <section>
+ <h2>Thank you!</h2>
+ <p><img width="400px" src="../images/stackmob_logo.png"/></p>
+
+ </section>
+
+ <section>
+ <h2>Resources</h2>
+ <ul>
+ <li><a href="https://www.stackmob.com/signup" target="_blank">Get a Free Account</a></li>
+ <li><a href="http://www.stackmob.com/devcenter/docs/Datastore-API#|js" target="_blank">iOS SDK Docs</a></li>
+ <li><a href="http://dev.iossdktest.stackmob.stackmobapp.com/ios/appsterdam.html#/" target="_blank">Slides: http://dev.iossdktest.stackmob.stackmobapp.com/ios/appsterdam.html#/</a></li>
+ </ul>
+
+ </section>
+
+ <section>
+ <h2>Credits</h2>
+ <ul>
+ <li>Reveal.js and Styles - Hakim El Hattab </li>
+ <li>MySQL, Oracle, AWS, Dell, Intel, Google App Engine, Heroku - Google Images</li>
+ <li>Head In Hands, Awesome Note, Dr. Evil, Holding Hands, Future - Google Images</li>
+ <li>Cookie Monster - Sesame Street</li>
+ <li>Calvin &amp; Hobbes - Bill Watterson</li>
+
+ </ul>
+ </section>
+
+ </div>
+
+ <!-- The navigational controls UI -->
+ <aside class="controls">
+ <a class="left" href="#">&#x25C4;</a>
+ <a class="right" href="#">&#x25BA;</a>
+ <a class="up" href="#">&#x25B2;</a>
+ <a class="down" href="#">&#x25BC;</a>
+ </aside>
+
+ <!-- Displays presentation progress, max value changes via JS to reflect # of slides -->
+ <div class="progress"><span></span></div>
+
+ </div>
+ <script type="text/javascript" src="../reveal.js/js/reveal.js"></script>
+ <script type="text/javascript">
+ Reveal.initialize({
+ // Display controls in the bottom right corner
+ controls: true,
+
+ // Display a presentation progress bar
+ progress: true,
+
+ // If true; each slide will be pushed to the browser history
+ history: true,
+
+ // Loops the presentation, defaults to false
+ loop: false,
+
+ // Flags if mouse wheel navigation should be enabled
+ mouseWheel: false,
+
+ // UI style
+ theme: 'default', // default/neon
+
+ rollingLinks: false,
+
+ // Transition style
+ transition: 'default' // default/cube/page/concave/linear(2d)
+ });
+ </script>
+
+ </body>
+</html>
+
+
+
+<!--
+
+
+
+
+
+
+ <section>
+ <h2>This. But for you.</h2>
+
+ <p>This isn't just for Facebook, Twitter, or the big guys.</p>
+
+ <p>This is for you.</p>
+
+ <p><img width="400px" src="../images/stackmob_logo.png"/></p>
+
+ </section>
+
+
+
+ <section>
+ <section>
+ <h2>Collections</h2>
+ <pre><code class="brush: javascript; highlight: [9,10,13]">
+ //From earlier..
+ var Todo = StackMob.Model.extend({
+ schemaName: 'todo'
+ });
+
+ ...
+
+ //Same as Backbone..
+ var Todos = StackMob.Collection.extend({
+ model: Todo
+ });
+
+ var todos = new Todos();
+ todos.fetch();
+ </code></pre>
+
+ </section>
+ <section>
+ <h2>Fetch your Todos!</h2>
+ <p>var todos = new Todos();</p>
+ <p>todos.fetch();</p>
+
+ <p><input id="fetchcollection" type="button" class="button" value="Fetch your Todos"/></p>
+
+ <textarea id="fetchtodos"></textarea>
+
+ <script type="text/javascript">
+ $(document).ready(function() {
+ $('#fetchcollection').click(function() {
+ var todos = new Todos();
+ todos.fetch(SMDebug.callbacks('Fetch Todos', 'fetchtodos'));
+ });
+ });
+ </script>
+ </section>
+ </section>
+
+ <section>
+ <section>
+ <h2>Queries: Fetching specific models</h2>
+
+ <p>Getting Finished Todos</p>
+ <pre><code class="brush: javascript; highlight: [1, 5]">
+ var q = new StackMob.Collection.Query();
+ q.equals('done', true);
+
+ var todos = new Todos();
+ todos.query(q, callbacks);
+ </code></pre>
+ </section>
+ <section>
+ <h2>Get Finished Todos</h2>
+<pre><code class="brush: javascript;">
+var q = new StackMob.Collection.Query();
+q.equals('done', true);
+
+var todos = new Todos();
+todos.query(q, callbacks);
+</code></pre>
+ <p><input type="button" class="button" id="querycollection" value="Get Finished Todos"/></p>
+
+ <textarea id="fetchfinishedtodos"></textarea>
+
+ <script type="text/javascript">
+ $(document).ready(function() {
+ $('#querycollection').click(function() {
+ var q = new StackMob.Collection.Query();
+ q.equals('done', true);
+
+ var todos = new Todos();
+ todos.query(q, SMDebug.callbacks('Query Finished Todos', 'fetchfinishedtodos'));
+ });
+ });
+ </script>
+ </section>
+
+ <section>
+ <h2>Filter Queries</h2>
+<pre><code class="brush: javascript;">
+var q = new StackMob.Collection.Query();
+q.lt('age', 21); //less than
+q.gt('followers', 30); //greater than
+q.notEquals('age', 5); //not equals
+
+var people = new People(); //StackMob.Collection
+people.query(q, callbacks);
+</code></pre>
+ </section>
+ <section>
+ <h2>Ordering/Pagination</h2>
+
+<pre><code class="brush: javascript;">
+var q = new StackMob.Collection.Query();
+q.orderAsc('age'); //order by ascending
+q.setRange(0,4); //pagination first 5 results
+
+var people = new People(); //StackMob.Collection
+people.query(q, callbacks);
+
+</code></pre>
+ </section>
+ <section>
+ <h2>Select Fields (Smaller Payload)</h2>
+<pre><code class="brush: javascript;">
+var q = new StackMob.Collection.Query();
+//select certain fields
+q.select('username').select('age');
+
+var people = new People(); //StackMob.Collection
+people.query(q, callbacks);
+
+</code></pre>
+
+ </section>
+
+ <section>
+ <h2>Select Fields Example</h2>
+<pre><code class="brush: javascript;">
+//q.select('username').select('age');
+
+[{
+ username: 'bob',
+ age: 10
+}, {
+ username: 'jane',
+ age: 15
+}, {
+ username: 'matt',
+ age: 20
+}]
+
+</code></pre>
+ </section>
+
+ </section>
+
+ <section>
+ <section>
+ <h2>Relationships</h2>
+ <img src="http://dl.dropbox.com/u/77348001/userTotodos.png" alt=""/>
+ </section>
+
+ <section>
+ <h2>Relationship: User &rarr; Todos</h2>
+ <ul>
+ <li><a href="https://www.stackmob.com/platform/api/schemas/edit/user" target="blank">Edit User Schema</a></li>
+ <li>Add one-to-many "todos" relationship</li>
+ </ul>
+ <img src="http://dl.dropbox.com/u/77348001/to-do-list-nothing.jpg" alt=""/>
+ </section>
+
+ <section>
+ <h2>Give Todo Items to User</h2>
+ <img src="http://dl.dropbox.com/u/77348001/calvin_and_hobbes_calvin.png" alt=""/>
+<pre><code class="brush: javascript;">
+var todo1 = new Todo({ action: 'take out the trash' });
+var todo2 = new Todo({ action: 'do the laundry' });
+var todo3 = new Todo({ action: 'prepare my slides!' });
+
+var user = new StackMob.User({ username: 'calvin' });
+user.addRelationship('todos', [todo1, todo2, todo3], callbacks);
+</code></pre>
+ </section>
+
+ <section>
+ <h2>Let's try it. But first..</h2>
+ <p>Let's see what "ericktai" looks like:</p>
+ <textarea id="readuser"></textarea>
+ <p><input type="button" id="fetchuser" class="button" value="Fetch User"/></p>
+ <script type="text/javascript">
+ $(document).ready(function() {
+ $('#fetchuser').click(function() {
+ var user = new StackMob.User({ username: 'ericktai' });
+ user.fetch(SMDebug.callbacks('Fetch User', 'readuser'));
+ });
+ });
+ </script>
+ </section>
+
+ <section>
+ <h2>Add Todos to User</h2>
+
+ <textarea id="addtodos"></textarea>
+ <p><input type="button" id="addtodoitems" class="button" value="Add Todos to User"/></p>
+ <script type="text/javascript">
+ $(document).ready(function() {
+ $('#addtodoitems').click(function() {
+ var todo1 = new Todo({ action: 'take out the trash' });
+ var todo2 = new Todo({ action: 'do the laundry' });
+ var todo3 = new Todo({ action: 'prepare my slides!' });
+
+ var user = new StackMob.User({ username: 'ericktai' });
+ user.addRelationship('todos', [todo1, todo2, todo3], SMDebug.callbacks('Add Todos to User', 'addtodos'));
+ });
+ });
+ </script>
+ </section>
+ <section>
+ <h2>Expand: Get Full Related Objects</h2>
+<pre><code class="brush: javascript;">
+//Use StackMob.Model#fetchExpanded
+
+var user = new StackMob.User({ username: 'ericktai' });
+user.fetchExpanded(1, callbacks);
+</code></pre>
+ <textarea id="readuserexpanded"></textarea>
+ <p><input type="button" id="fetchuserexpanded" class="button" value="Fetch Expanded User"/></p>
+ <script type="text/javascript">
+ $(document).ready(function() {
+ $('#fetchuserexpanded').click(function() {
+ var user = new StackMob.User({ username: 'ericktai' });
+ user.fetchExpanded(1, SMDebug.callbacks('Fetch Expanded User', 'readuserexpanded'));
+ });
+ });
+ </script>
+ </section>
+ </section>
+
+ <section>
+ <section>
+ <h2>User Authentication</h2>
+
+ <img src="http://dl.dropbox.com/u/77348001/calving_hobbes_password.gif" alt=""/>
+ </section>
+
+
+
+-->
View
1,187 ios/appsterdam.html
<
@@ -0,0 +1,1187 @@
+<html>
+ <head>
+ <title>StackMob - Adding a Backend to your iOS App</title>
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
+ <script type="text/javascript" src="http://static.stackmob.com/js/json2-min.js"></script>
+ <script type="text/javascript" src="http://static.stackmob.com/js/underscore-1.3.3-min.js"></script>
+ <script type="text/javascript" src="http://static.stackmob.com/js/backbone-0.9.2-min.js"></script>
+ <script type="text/javascript" src="http://static.stackmob.com/js/stackmob-js-0.2.1-min.js"></script>
+ <script type="text/javascript" src="http://static.stackmob.com/resources/js/jsonFormatter-0.1.0-min.js"></script>
+ <script type="text/javascript" src="stackmob-debug.js"></script>
+
+ <!-- Include required JS files -->
+ <script type="text/javascript" src="../syntaxhighlighter/scripts/shCore.js"></script>
+
+ <script type="text/javascript" src="../syntaxhighlighter/scripts/shBrushJScript.js"></script>
+ <script type="text/javascript" src="../syntaxhighlighter/scripts/shBrushXml.js"></script>
+ <script type="text/javascript" src="../syntaxhighlighter/scripts/shBrushJava.js"></script>
+ <script type="text/javascript" src="../syntaxhighlighter/scripts/shBrushCpp.js"></script>
+
+ <link href="../syntaxhighlighter/styles/shCoreMidnight.css" rel="stylesheet" type="text/css" />
+ <link href="../syntaxhighlighter/styles/shThemeMidnight.css" rel="stylesheet" type="text/css" />
+
+ <style type="text/css">
+ .syntaxhighlighter {
+ margin: 0px !important; padding-top: 15px; padding-bottom: 15px;
+ border-radius: 10px; -moz-border-radius: 10px; -webkit-border-radius: 10px;
+
+ }
+ </style>
+
+ <script type="text/javascript">
+ StackMob.init({
+ appName: 'javascript',
+ clientSubdomain: 'stackmob',
+ apiVersion: 0
+ });
+
+ var Todo = StackMob.Model.extend({
+ schemaName: 'todo'
+ });
+
+ var Todos = StackMob.Collection.extend({
+ model: Todo
+ });
+
+ $(document).ready(function() {
+ SyntaxHighlighter.config.tagName = 'code';
+ SyntaxHighlighter.config.toolbar = false;
+ SyntaxHighlighter.all();
+
+ Reveal.addEventListener('stampede', function() {
+ $('#stampede').attr('src', 'http://dl.dropbox.com/u/77348001/stampede.gif');
+ });
+ });
+ </script>
+
+ <link rel="stylesheet" href="../reveal.js/css/reset.css">
+ <link rel="stylesheet" href="../reveal.js/css/main.css">
+ <style type="text/css" media="screen">
+ .button, .button a
+{
+ background: #98be47;
+ background: linear-gradient(top, #a8cf43, #98be47);
+ background: -moz-linear-gradient(top, #a8cf43, #98be47);
+ background: -ms-linear-gradient(top, #a8cf43, #98be47);
+ background: -o-linear-gradient(top, #a8cf43, #98be47);
+ background: -webkit-linear-gradient(top, #a8cf43, #98be47);
+ border: 1px solid #8cac42;
+ border-bottom-color: #7b9b36;
+ border-radius: 4px;
+ border-top-color: #94b146;
+ box-shadow: 0 2px 2px rgba(0, 0, 0, .2), inset 0 1px 0 rgba(255, 255, 255, .5);
+ color: #fff !important;
+ cursor: pointer;
+ font-family: "Helvetica Neue", Arial, sans-serif;
+ font-size: 26px;
+ font-weight: bold;
+ moz-border-radius: 4px;
+ moz-box-shadow: 0 2px 2px rgba(0, 0, 0, .2), inset 0 1px 0 rgba(255, 255, 255, .5);
+ ms-border-radius: 4px;
+ ms-box-shadow: 0 2px 2px rgba(0, 0, 0, .2), inset 0 1px 0 rgba(255, 255, 255, .5);
+ o-border-radius: 4px;
+ o-box-shadow: 0 2px 2px rgba(0, 0, 0, .2), inset 0 1px 0 rgba(255, 255, 255, .5);
+ padding: 6px 14px;
+ text-decoration: none;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, .4);
+ webkit-border-radius: 4px;
+ webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, .2), inset 0 1px 0 rgba(255, 255, 255, .5);
+}
+.button:hover, .button a:hover
+{
+ background: #67a215;
+ background: linear-gradient(top, #9dbf46, #67a215);
+ background: -moz-linear-gradient(top, #9dbf46, #67a215);
+ background: -ms-linear-gradient(top, #9dbf46, #67a215);
+ background: -o-linear-gradient(top, #9dbf46, #67a215);
+ background: -webkit-linear-gradient(top, #9dbf46, #67a215);
+ border: 1px solid #699631;
+ border-bottom-color: #457119;
+ border-top-color: #6d9e34;
+ color: rgba(250, 250, 250, .96);
+ text-decoration: none;
+ text-shadow: 0 -1px 0 rgba(0, 0, 0, .8);
+}
+.button:active, .button a:active
+{
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
+ moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
+ ms-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
+ o-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
+ padding: 4px 14px 7px;
+ webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5);
+}
+.button.blue, .button.blue a
+{
+ background: #6bbad7;
+ background: linear-gradient(top, #76cced, #6bbad7);
+ background: -moz-linear-gradient(top, #76cced, #6bbad7);
+ background: -ms-linear-gradient(top, #76cced, #6bbad7);
+ background: -o-linear-gradient(top, #76cced, #6bbad7);
+ background: -webkit-linear-gradient(top, #76cced, #6bbad7);
+ border: 1px solid #4ca8ca;
+ border-bottom-color: #4c9bb9;
+ border-top-color: #4cb2da;
+}
+.button.blue:hover, .button.blue a:hover
+{
+ background: #2c9cc6;
+ background: linear-gradient(top, #3cb7e5, #2c9cc6);
+ background: -moz-linear-gradient(top, #3cb7e5, #2c9cc6);
+ background: -ms-linear-gradient(top, #3cb7e5, #2c9cc6);
+ background: -o-linear-gradient(top, #3cb7e5, #2c9cc6);
+ background: -webkit-linear-gradient(top, #3cb7e5, #2c9cc6);
+ border: 1px solid #0083b4;
+ border-bottom-color: #00709b;
+ border-top-color: #0092ca;
+}
+
+#stackmoblogo {
+ position: fixed;
+ top: 20px;
+ left: 20px;
+}
+ </style>
+
+ </head>
+ <body>
+ <div id="stackmoblogo"><img src="../images/stackmob_logo.png"/></div>
+ <div id="reveal">
+ <div class="state-background"></div>
+
+ <div class="slides">
+ <section>
+ <h2>Adding a Server-Side Backend to your iOS Application</h2>
+ <!-- <h3 class="inverted">StackMob &amp; Objective-C</h3> -->
+ <!-- <p><span style="font-size: 24px;">(uses Backbone.js)</span></p> -->
+ <p style="margin-top: 100px;">
+ <p><a href="http://www.stackmob.com" target="_blank">stackmob.com</a> | <a href="http://www.twitter.com/stackmob">@stackmob</a> | #stackmob</p>
+ <p>Matt Vaznaian | <a href="http://www.twitter.com/mvaznaian" target="_blank">@_mattvaz</a></p>
+ </p>
+ </section>
+ <section>
+ <h2>Matt Vaznaian</h2>
+ <h3>matt@stackmob.com</h3>
+ <h3>@_mattvaz</h3>
+ <p><a href="http://www.stackmob.com"><img src="../images/stackmob_logo.png"/></a></p>
+ </section>
+
+ <section>
+ <h2>A Brief History of Building your backend</h2>
+
+ <section>
+ </section>
+
+ <section>
+ <h3>Database</h3>
+ <img src="https://dl.dropbox.com/u/79464649/oracle.jpg" />
+ <img src="https://dl.dropbox.com/u/79464649/mysql-big.gif" />
+ </section>
+
+ <section>
+ <h3>Hardware</h3>
+ <img src="https://dl.dropbox.com/u/79464649/300px-Dell_Logo.svg_1.png" />
+ <img src="https://dl.dropbox.com/u/79464649/intel-logo-300x198.jpg" />
+ </section>
+
+ <section>
+ <h3>Cloud Store</h3>
+ <img src="https://dl.dropbox.com/u/79464649/amazon.png" />
+ <img src="https://dl.dropbox.com/u/79464649/iCloud.png" />
+ </section>
+
+ <section>
+ <h3>Software Layer</h3>
+ <img src="https://dl.dropbox.com/u/79464649/heroku.jpg" />
+ <img src="https://dl.dropbox.com/u/79464649/appengine-logo.png" />
+ </section>
+
+
+ </section>
+
+ <section>
+ <h2>StackMob: Who are we?</h2>
+
+ <ul>
+ <li>Mobile Backend Platform</li>
+ <li>Lowering barrier of entry</li>
+ <li>Focus on your user experience.</li>
+ <li>Access to "big company" backend power.</li>
+ <li>Develop. Scale. Analytics. Revisioning.</li>
+ </ul>
+
+ </section>
+
+ <section>
+ <h2>StackMob: Who uses us?</h2>
+
+ <p>We've powered apps:</p>
+ <ul>
+ <li>Featured in the AppStore</li>
+ <li>Top 20 in the AppStore</li>
+ <li>TechCrunch Disrupt</li>
+ <li>SXSW</li>
+ <li>Won Startup Weekend</li>
+ <li>Atari</li>
+ </ul>
+ <p>Games, Enterprise Apps, Social... </p>
+ <p>iOS, Android, JavaScript, Ruby, PHP, Python, Java</p>
+ </section>
+
+ <section>
+ <h2>The First App You Ever Built</h2>
+ <p>
+ <img src="https://dl.dropbox.com/u/79464649/helloWorld.png"/>
+ </p>
+ </section>
+
+ <section>
+ <h2>NSUserDefaults</h2>
+ <p>
+ <img src="https://dl.dropbox.com/u/79464649/helloMatt.png" />
+ </p>
+ </section>
+
+ <section>
+ <h2>The Next Level</h2>
+
+ <ul>
+ <li>Access Data From Multiple Devices.</li>
+ <li>Lots of Features == Lots of Data.</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>I could do it myself</h2>
+
+ <img src="https://dl.dropbox.com/u/79464649/headInHands.jpg" />
+ </section>
+
+ <section>
+ <h2>Focus on your user experience!</h2>
+
+ <img src="https://dl.dropbox.com/u/79464649/awesome_note.png" />
+ </section>
+
+ <section>
+ <h2>Configure StackMob iOS SDK</h2>
+
+ <h3>StackMobConfiguration.h</h3>
+ <pre><code class="brush: xml">
+ #define STACKMOB_PUBLIC_KEY @"YOUR_PUBLIC_KEY"
+ #define STACKMOB_PRIVATE_KEY @"YOUR_PRIVATE_KEY"
+ #define STACKMOB_APP_NAME @"YOUR_APP_NAME"
+ #define STACKMOB_UDID_SALT @"UDID"
+ #define STACKMOB_APP_DOMAIN @"stackmob.com"
+ #define STACKMOB_APP_MOB @"mob1"
+ #define STACKMOB_USER_OBJECT_NAME @"user"
+ #define STACKMOB_API_VERSION 0
+ </code></pre>
+
+ <h3>AppDelegate.h (or any other file)</h3>
+ <pre><code class="brush: xml">
+ #import "StackMob.h"
+ </code></pre>
+ </section>
+
+
+ <section>
+ <h2>Initialize</h2>
+
+ <pre><code class="brush: javascript; highlight: [5]">
+ - (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+ {
+
+ [[StackMob stackmob] startSession];
+
+ [self.window makeKeyAndVisible];
+ return YES;
+
+
+ }
+ </code></pre>
+
+ <pre><code class="brush: javascript; highlight: [3]">
+ - (void)applicationWillTerminate:(UIApplication *)application
+ {
+ [[StackMob stackmob] endSession];
+ }
+ </code></pre>
+
+ </section>
+
+
+ <section>
+ <h2>Server-Side Persistence: Create</h2>
+ <section>
+ <a href="javascript:void(0);">Syntax:</a>
+ <pre><code class="brush: javascript;">
+
+ // define schema
+ NSString *schemaName = @"blogentry"
+
+ // define field/value pairs and contain in a dictionary
+ NSDictionary *args = [[NSDictionary alloc] initWithObjectsAndKeys:
+ @"rich text", @"content", nil];
+
+ [[StackMob stackmob] post:schemaName withArguments:args
+ andCallback:MyCallback];
+
+ </code></pre>
+
+ </section>
+
+ <section>
+ <h2>Let's try it out!</h2>
+ </section>
+
+ <section>
+ <a href="javascript:void(0);">Syntax:</a>
+ <pre><code class="brush: javascript; highlight: [2]">
+
+ // define schema
+ NSString *schemaName = @"blogentry"
+
+ // define field/value pairs and contain in a dictionary
+ NSDictionary *args = [[NSDictionary alloc] initWithObjectsAndKeys:
+ @"rich text", @"content", nil];
+
+ [[StackMob stackmob] post:schemaName withArguments:args
+ andCallback:MyCallback];
+
+ </code></pre>
+
+ </section>
+
+ <section>
+ <a href="javascript:void(0);">Syntax:</a>
+ <pre><code class="brush: javascript; highlight: [5, 6]">
+
+ // define schema
+ NSString *schemaName = @"blogentry"
+
+ // define field/value pairs and contain in a dictionary
+ NSDictionary *args = [[NSDictionary alloc] initWithObjectsAndKeys:
+ @"rich text", @"content", nil];
+
+ [[StackMob stackmob] post:schemaName withArguments:args
+ andCallback:MyCallback];
+
+ </code></pre>
+
+ </section>
+
+ <section>
+ <a href="javascript:void(0);">Syntax:</a>
+ <pre><code class="brush: javascript; highlight: [8, 9]">
+
+ // define schema
+ NSString *schemaName = @"blogentry"
+
+ // define field/value pairs and contain in a dictionary
+ NSDictionary *args = [[NSDictionary alloc] initWithObjectsAndKeys:
+ @"rich text", @"content", nil];
+
+ [[StackMob stackmob] post:schemaName withArguments:args
+ andCallback:MyCallback];
+
+ </code></pre>
+
+ </section>
+
+ <section>
+ <a href="javascript:void(0);">Callback:</a>
+ <pre><code class="brush: javascript;">
+ [[StackMob stackmob] post:schemaName withArguments:args
+ andCallback:^(BOOL success, id result){
+ if(success){
+
+ // We can get the response body of the newly created object
+ // in NSDictionary form
+ NSDictionary *resultDict = (NSDictionary *)result;
+ [self updateUI:resultDict];
+
+ } else {
+ // Action after a call results in error
+ }
+ }];
+ </code></pre>
+
+ </section>
+
+
+ <section>
+ <h2>Aw yeah! Backend Created!</h2>
+
+ <p>
+ <img src="http://dl.dropbox.com/u/9289507/joy.gif" alt=""/>
+ </p>
+ </section>
+
+ </section>
+
+
+ <section>
+
+ <h2>Read from DB</h2>
+ <a href="javascript:void(0);">Read Item</a>
+ <pre><code class="brush: javascript;">
+ NSString *schemaName = @"blogentry";
+ NSString objectId = @"1234";
+
+ [[StackMob stackmob] get:[NSString stringWithFormat:@"%@/%@",
+ schemaName, objectID] withCallback:myCallBack];
+ </code></pre>
+
+ </section>
+
+ <section>
+
+ <h2>Update DB</h2>
+ <a href="javascript:void(0);">Update Item</a>
+ <pre><code class="brush: javascript;">
+ NSString *schemaName = @"blogentry"
+ NSString objectId = @"1234";
+
+ // define field/value pairs and contain in a dictionary
+ NSDictionary *args = [[NSDictionary alloc]
+ initWithObjectsAndValues:@"some other stuff", @"content"];
+
+ [[StackMob stackmob] put:schemaName withID:objectId andArguments:args
+ andCallback:myCallback];
+</code></pre>
+
+ </section>
+
+ <section>
+ <h2>Delete from DB</h2>
+ <a href="javascript:void(0);">Delete Item</a>
+ <pre><code class="brush: javascript;">
+ NSString *schemaName = @"blogentry"
+
+ // define field/value pairs and contain in a dictionary
+ NSDictionary *args = [[NSDictionary alloc]
+ initWithObjectsAndKeys:@"1234", @"blogentry_id"];
+
+ [[StackMob stackmob] destroy:schemaName withArguments:args
+ andCallback:myCallback];
+</code></pre>
+
+ </section>
+
+ <section>
+ <h2>WOOHOO for CRUD!</h2>
+ <img src="https://dl.dropbox.com/u/79464649/homer_woohoo.jpg" />
+ </section>
+
+ <section>
+ <h2>But I want more than just a datastore in the cloud!</h2>
+
+ <ul>
+ <li>Queries</li>
+ <li>Relate this object to that object</li>
+ <li>User Authentication</li>
+ <li>Push Notifications</li>
+ <li><img src="../images/f_logo.png"/>
+ <img src="../images/twitter_logo.png"/>
+ </li>
+ </ul>
+ </section>
+
+
+ <section>
+ <h2>Queries</h2>
+
+ <section>
+ <img src="https://dl.dropbox.com/u/79464649/massiveData_dr-evil.jpg" />
+
+ </section>
+
+ <section>
+ <h3>Field Selection</h3>
+ <pre><code class="brush: javascript;">
+ StackMobQuery *q = [StackMobQuery query];
+ [q setSelectionToFields:[NSArray arrayWithObjects:@"username", @"age", nil]];
+
+ // perform the query and handle the results
+ [[StackMob stackmob] get:@"user" withQuery:q andCallback:myQueryCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>Equality</h3>
+ <pre><code class="brush: javascript;">
+ StackMobQuery *q = [StackMobQuery query];
+ [q field:@"age" mustEqualValue:25];
+
+ [[StackMob stackmob] get:@"user" withQuery:q andCallback:myQueryCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>Order By</h3>
+ <pre><code class="brush: javascript;">
+ StackMobQuery *q = [StackMobQuery query];
+ [q orderByField:@"createddate" withDirection:SMOrderDescending];
+ [q orderByField:@"age" withDirection:SMOrderAscending];
+
+
+ [[StackMob stackmob] get:@"user" withQuery:q andCallback:myQueryCallback];
+ </code></pre>
+ </section>
+
+
+ </section>
+
+ <section>
+ <h2>Relationships</h2>
+ <section>
+ <img src="https://dl.dropbox.com/u/79464649/holdingHands.jpg" />
+
+ </section>
+
+ <section>
+ <pre><code class="brush: javascript;">
+ {
+ user: john
+ todos: [1, 2]
+ }
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>POST - Creating</h3>
+ <pre><code class="brush: javascript; highlight: [1, 2]">
+ NSDictionary *item1 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 1", @"action", @"high", @"priority", nil];
+ NSDictionary *item2 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 2", @"action", @"low", @"priority", nil];
+ NSArray *items = [NSArray arrayWithObjects:item1, item2, nil];
+
+ [[StackMob stackmob] post:@"user" withId:@"john" andField:@"todos"
+ andBulkArguments:items andCallback:myCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>POST - Creating</h3>
+ <pre><code class="brush: javascript; highlight: [3, 4]">
+ NSDictionary *item1 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 1", @"action", @"high", @"priority", nil];
+ NSDictionary *item2 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 2", @"action", @"low", @"priority", nil];
+ NSArray *items = [NSArray arrayWithObjects:item1, item2, nil];
+
+ [[StackMob stackmob] post:@"user" withId:@"john" andField:@"todos"
+ andBulkArguments:items andCallback:myCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>POST - Creating</h3>
+ <pre><code class="brush: javascript; highlight: [5]">
+ NSDictionary *item1 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 1", @"action", @"high", @"priority", nil];
+ NSDictionary *item2 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 2", @"action", @"low", @"priority", nil];
+ NSArray *items = [NSArray arrayWithObjects:item1, item2, nil];
+
+ [[StackMob stackmob] post:@"user" withId:@"john" andField:@"todos"
+ andBulkArguments:items andCallback:myCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>POST - Creating</h3>
+ <pre><code class="brush: javascript; highlight: [7, 8]">
+ NSDictionary *item1 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 1", @"action", @"high", @"priority", nil];
+ NSDictionary *item2 = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"my todo 2", @"action", @"low", @"priority", nil];
+ NSArray *items = [NSArray arrayWithObjects:item1, item2, nil];
+
+ [[StackMob stackmob] post:@"user" withId:@"john" andField:@"todos"
+ andBulkArguments:items andCallback:myCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <p>Result from a GET on user/john</p>
+ <pre><code class="brush: javascript;">
+ {
+ user: john
+ todos: [1, 2]
+ }
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>GET - Expansion</h3>
+ <pre><code class="brush: javascript;">
+ StackMobQuery *q = [StackMobQuery query];
+ [q setExpandDepth:1];
+
+ [[StackMob stackmob] get:@"user/john" withQuery:q andCallback:myCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <pre><code class="brush: javascript;">
+ {
+ user: john
+ todos: [
+ {
+ todo_id: 1
+ action: "my todo 1"
+ priority: "high"
+ }
+ {
+ todo_id: 2
+ action: "my todo 2"
+ priority: "low"
+ }
+ ]
+ }
+ </code></pre>
+ </section>
+
+ </section>
+
+ <section>
+ <h2>User Authentication</h2>
+ <section>
+ <img src="http://dl.dropbox.com/u/77348001/calving_hobbes_password.gif" alt=""/>
+ </section>
+
+ <section>
+ <h3>Create User & Login</h2>
+ <pre><code class="brush: javascript;">
+ NSString *username = @"[USERNAME]"
+ NSString *password = @"[PASSWORD]"
+ NSDictionary *args = [NSDictionary dictionaryWithObjectsAndKeys:
+ username, @"username", password, @"password", nil];
+
+ [[StackMob stackmob] loginWithArguments:args andCallback:loginCallback];
+ </code></pre>
+ </section>
+
+ <section>
+ <h3>Password Management</h3>
+ <ul>
+ <li>Forgotten Passwords</li>
+ <li>Reset Password</li>
+ </ul>
+
+ </section>
+ </section>
+ <!--
+ <section>
+ <h2>Security &rarr; OAuth 2.0</h2>
+
+ <ul>
+ <li>Industry Standard: OAuth 1.0/2.0</li>
+ <li>Public/Private Keys identify your app's requests</li>
+ <li>FB/Twitter: OAuth 2.0. Username/Password</li>
+ <li>In current JS SDK for pre-trials</li>
+ </ul>
+
+ </section>
+ -->
+ <section>
+ <h2>Access Controls</h2>
+ <ul>
+ <li>Share objects to certain users</li>
+ <li>Limit visibility</li>
+ <li>Coming very very soon</li>
+ </ul>
+ </section>
+
+
+ <section>
+
+ <section>
+ <h2>Even more flexibility: Custom Code</h2>
+ <ul>
+ <li>Java/Scala Server Side SDK</li>
+ <li>Write Code - StackMob REST-ifies it</li>
+ <li>iOS can execute server code via REST API!</li>
+ <li>iOS receives your custom JSON response too</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Call Custom Code from iOS App!</h2>
+ <pre><code class="brush: javascript;">
+ [[StackMob stackmob] get:@"hello_world" withCallback:^(BOOL success, id result) {
+ if (success) {
+ // result is the JSON as an NSDictionary of "msg" vs. "Hello, world!"
+ } else {
+ }
+ }];
+ </code></pre>
+ </section>
+
+ <section>
+ <h2>Custom Code Example</h2>
+
+<pre><code class="brush: java">
+//Java
+public class HelloWorldExample implements CustomCodeMethod {
+
+ @Override
+ public String getMethodName() {
+ return "hello_world";
+ }
+
+ @Override
+ public ResponseToProcess execute(...) {
+
+ //Do fancy server side things
+
+ Map&lt;String, String&gt; json =
+ new HashMap&lt;String, String&gt;();
+ json.put("msg", "hello world!");
+ return new ResponseToProcess(..., json);
+ }
+}
+</code></pre>
+ </section>
+
+ <section>
+ <h2>Defines your REST endpoint</h2>
+ <p><code>http://api.mob1.stackmob.com/hello_world</code></p>
+<pre><code class="brush: java; highlight: [6]">
+//Java
+public class HelloWorldExample implements CustomCodeMethod {
+
+ @Override
+ public String getMethodName() {
+ return "hello_world";
+ }
+
+ ...
+}
+</code></pre>
+ </section>
+
+ <section>
+ <h2>Defines your return JSON</h2>
+ <p><code>{ msg: "hello world!" }</code></p>
+<pre><code class="brush: java; highlight: [11]">
+//Java
+public class HelloWorldExample implements CustomCodeMethod {
+ ...
+ @Override
+ public ResponseToProcess execute(...) {
+
+ //Do fancy server side things
+
+ Map&lt;String, String&gt; json =
+ new HashMap&lt;String, String&gt;();
+ json.put("msg", "hello world!");
+ return new ResponseToProcess(..., json);
+ }
+}
+</code></pre>
+ </section>
+
+ </section>
+
+ <section>
+ <h2>Development &amp; Production Environments</h2>
+ <ul>
+ <li>Different databases</li>
+ <li>Only deploy when you're ready!</li>
+ <li><a href="https://www.stackmob.com/platform/deploy/" target="_blank">Easy rollout/rollback</a></li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>API Versions</h2>
+ <ul>
+ <li>Backwards support old clients</li>
+ <li>Concurrently run different versions of your custom code/schemas</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Time to Re-Market</h2>
+ <ul>
+ <li>Change configurations through the Dashboard</li>
+ <li>Instantly reflected in your application</li>
+ <li>No need to resubmit to the App Store</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Open Sourced SDKs</h2>
+
+ <ul>
+ <li>iOS</li>
+ <li>Android</li>
+ <li>Javascript</li>
+ <li>Download them today!</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Adding a backend with StackMob</h2>
+ <ul>
+ <li>Simple</li>
+ <li>Seamless</li>
+ <li>Flexible</li>
+ <li>Powerful</li>
+ <li>Free &rarr; Grow</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>Backend Services</h2>
+ <ul>
+ <li>User Authentication</li>
+ <li>Datastore</li>
+ <li>Security</li>
+ <li>GeoSpatial</li>
+ <li>Push</li>
+ <li>Hosting</li>
+ <li>Social Integration</li>
+ <li>Custom Server Side Code</li>
+ <li>Analytics</li>
+ <li>...</li>
+ </ul>
+ </section>
+
+ <section>
+ <h2>The future of the iOS SDK</h2>
+ <img src="https://dl.dropbox.com/u/79464649/future.jpg" />
+
+ </section>
+
+ <section>
+ <h2>Thank you!</h2>
+ <p><img width="400px" src="../images/stackmob_logo.png"/></p>
+
+ </section>
+
+ <section>
+ <h2>Resources</h2>
+ <ul>
+ <li><a href="https://www.stackmob.com/signup" target="_blank">Get a Free Account</a></li>
+ <li><a href="http://www.stackmob.com/devcenter/docs/Datastore-API#|js" target="_blank">iOS SDK Docs</a></li>
+ <li><a href="http://dev.iossdktest.stackmob.stackmobapp.com/ios/appsterdam.html#/" target="_blank">Slides: http://dev.iossdktest.stackmob.stackmobapp.com/ios/appsterdam.html#/</a></li>
+ </ul>
+
+ </section>
+
+ <section>
+ <h2>Credits</h2>
+ <ul>
+ <li>Reveal.js and Styles - Hakim El Hattab </li>
+ <li>MySQL, Oracle, AWS, Dell, Intel, Google App Engine, Heroku - Google Images</li>
+ <li>Head In Hands, Awesome Note, Dr. Evil, Holding Hands, Future - Google Images</li>
+ <li>Cookie Monster - Sesame Street</li>
+ <li>Calvin &amp; Hobbes - Bill Watterson</li>
+
+ </ul>
+ </section>
+
+ </div>
+
+ <!-- The navigational controls UI -->
+ <aside class="controls">
+ <a class="left" href="#">&#x25C4;</a>
+ <a class="right" href="#">&#x25BA;</a>
+ <a class="up" href="#">&#x25B2;</a>
+ <a class="down" href="#">&#x25BC;</a>
+ </aside>
+
+ <!-- Displays presentation progress, max value changes via JS to reflect # of slides -->
+ <div class="progress"><span></span></div>
+
+ </div>
+ <script type="text/javascript" src="../reveal.js/js/reveal.js"></script>
+ <script type="text/javascript">
+ Reveal.initialize({
+ // Display controls in the bottom right corner
+ controls: true,
+