├── .gitignore ├── .gitmodules ├── ClojureScript ├── deps.edn ├── externs.js ├── project.clj ├── repl.sh └── src │ └── shrimp │ ├── core.cljs │ ├── database.cljs │ ├── detail_view_controller.cljs │ └── master_view_controller.cljs ├── LICENSE ├── README.md ├── devenv.png └── iOS ├── Podfile ├── Shrimp.xcodeproj └── project.pbxproj ├── Shrimp ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── BaseDatabaseManager.h ├── BaseDatabaseManager.m ├── DatabaseManager.h ├── DatabaseManager.m ├── DetailViewController.h ├── DetailViewController.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── MasterViewController.h ├── MasterViewController.m ├── Shrimp.h ├── Shrimp.m ├── Shrimp.xcdatamodeld │ ├── .xccurrentversion │ └── Shrimp.xcdatamodel │ │ └── contents └── main.m └── ShrimpTests ├── Info.plist └── ShrimpTests.m /.gitignore: -------------------------------------------------------------------------------- 1 | # Clojure 2 | ClojureScript/target 3 | ClojureScript/js 4 | ClojureScript/out 5 | ClojureScript/repl 6 | ClojureScript/.repl 7 | .nrepl-port 8 | .lein-repl-history 9 | 10 | # Xcode 11 | xcuserdata 12 | shrimp.iml 13 | *.xccheckout 14 | Podfile.lock 15 | iOS/Pods 16 | iOS/Shrimp.xcworkspace 17 | ClojureScript/.idea 18 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mfikes/shrimp/83f7a5c63ff340511bfdc1370d26d30f5a3f7202/.gitmodules -------------------------------------------------------------------------------- /ClojureScript/deps.edn: -------------------------------------------------------------------------------- 1 | {:deps 2 | {org.clojure/clojurescript {:mvn/version "1.10.339"} 3 | org.clojure/core.async {:mvn/version "0.4.474"} 4 | goby {:mvn/version "1.1.0"} 5 | ambly {:mvn/version "1.8.0"}}} 6 | -------------------------------------------------------------------------------- /ClojureScript/externs.js: -------------------------------------------------------------------------------- 1 | var DatabaseManager = {}; 2 | DatabaseManager.createShrimpFetchedResultsController = function() {}; 3 | DatabaseManager.saveContext = function() {}; 4 | DatabaseManager.deleteEntity = function() {}; 5 | DatabaseManager.createEntityWithName = function() {}; 6 | 7 | var Shrimp = {}; 8 | Shrimp.name = function() {}; 9 | Shrimp.desc = function() {}; 10 | Shrimp.edibleFlag = function() {}; 11 | -------------------------------------------------------------------------------- /ClojureScript/project.clj: -------------------------------------------------------------------------------- 1 | (defproject shrimp "0.1.0-SNAPSHOT" 2 | :description "Demo project for Goby." 3 | :dependencies [[org.clojure/clojure "1.9.0"] 4 | [org.clojure/clojurescript "1.10.339"] 5 | [org.clojure/core.async "0.3.443"] 6 | [goby "1.1.0"] 7 | [ambly "1.8.0"]] 8 | :plugins [[lein-cljsbuild "1.1.6"]] 9 | :source-paths ["src"] 10 | :clean-targets ["target" "out"] 11 | :cljsbuild {:builds {:dev 12 | {:source-paths ["src"] 13 | :compiler {:output-to "target/out/main.js" 14 | :output-dir "target/out" 15 | :optimizations :none}} 16 | :rel 17 | {:source-paths ["src"] 18 | :compiler {:output-to "target/out/main.js" 19 | :optimizations :advanced 20 | :externs ["externs.js"] 21 | :pretty-print false 22 | :pseudo-names false}}}}) 23 | -------------------------------------------------------------------------------- /ClojureScript/repl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [ ! -d out ] 6 | then 7 | echo "Building shrimp.core..." 8 | clojure -m cljs.main -t none -c shrimp.core 9 | fi 10 | 11 | clj -m cljs.main -co '{:analyze-path ["src"]}' -re ambly -r 12 | 13 | -------------------------------------------------------------------------------- /ClojureScript/src/shrimp/core.cljs: -------------------------------------------------------------------------------- 1 | (ns shrimp.core 2 | (:require [goby.core :refer [env]] 3 | [shrimp.database] 4 | [shrimp.master-view-controller] 5 | [shrimp.detail-view-controller])) 6 | 7 | (defn map-keys [f m] 8 | (reduce-kv (fn [r k v] (assoc r (f k) v)) {} m)) 9 | 10 | (defn ^:export init! 11 | [js-env] 12 | 13 | (reset! env (map-keys keyword (cljs.core/js->clj js-env))) 14 | 15 | (enable-console-print!) 16 | (println "ClojureScript initialized: " @env) 17 | 18 | (when (:debug-build @env) 19 | (set! *print-newline* true))) 20 | -------------------------------------------------------------------------------- /ClojureScript/src/shrimp/database.cljs: -------------------------------------------------------------------------------- 1 | (ns shrimp.database) 2 | 3 | (def database-manager (atom nil)) 4 | 5 | (defn ^:export set-database-manager! [database-manager] 6 | (reset! shrimp.database/database-manager database-manager)) 7 | -------------------------------------------------------------------------------- /ClojureScript/src/shrimp/detail_view_controller.cljs: -------------------------------------------------------------------------------- 1 | (ns shrimp.detail-view-controller 2 | (:require [shrimp.database :refer [database-manager]]) 3 | (:require-macros [goby.macros :refer [defui]])) 4 | 5 | (defui name-text-field description-text-field edible-switch) 6 | 7 | (def shrimp (atom nil)) 8 | 9 | (defn do-name-changed! [new-name] 10 | (set! (.-name @shrimp) new-name) 11 | (.saveContext @database-manager)) 12 | 13 | (defn do-description-changed! [new-description] 14 | (set! (.-desc @shrimp) new-description) 15 | (.saveContext @database-manager)) 16 | 17 | (defn do-edible-changed! [new-value] 18 | (set! (.-edibleFlag @shrimp) new-value) 19 | (.saveContext @database-manager)) 20 | 21 | (defn- handle-view-did-load! [] 22 | (set! (.-text @name-text-field) (.-name @shrimp)) 23 | (set! (.-text @description-text-field) (.-desc @shrimp)) 24 | (set! (.-on @edible-switch) (.-edibleFlag @shrimp)) 25 | (.setEditingChangedCallback @name-text-field do-name-changed!) 26 | (.setEditingChangedCallback @description-text-field do-description-changed!) 27 | (.setValueChangedCallback @edible-switch do-edible-changed!)) 28 | -------------------------------------------------------------------------------- /ClojureScript/src/shrimp/master_view_controller.cljs: -------------------------------------------------------------------------------- 1 | (ns shrimp.master-view-controller 2 | (:require [goby.core :refer [reify-fetched-results-controller-delegate TableViewDataSource 3 | table-view-cell-editing-styles TableViewDelegate]] 4 | [shrimp.detail-view-controller] 5 | [shrimp.database :refer [database-manager]]) 6 | (:require-macros [goby.macros :refer [defui reify]])) 7 | 8 | (defui table-view) 9 | 10 | (def fetched-results-controller (atom nil)) 11 | 12 | (defn setup-fetched-results-controller-delegate [] 13 | (set! (.-cljsDelegate @fetched-results-controller) 14 | (reify-fetched-results-controller-delegate table-view))) 15 | 16 | (defn setup-table-view-data-source [] 17 | (set! (.-dataSource @table-view) 18 | (reify TableViewDataSource 19 | 20 | (number-of-rows-in-section [_ section] 21 | (.numberOfObjectsInSection @fetched-results-controller section)) 22 | 23 | (init-cell-for-row-at-index-path [_ cell section row] 24 | (let [shrimp (.objectAtSectionRow @fetched-results-controller section row)] 25 | (set! (-> cell .-textLabel .-text) (.-name shrimp)))) 26 | 27 | (number-of-sections [_] 28 | (.sectionCount @fetched-results-controller))))) 29 | 30 | (defn setup-table-view-delegate [] 31 | (set! (.-delegate @table-view) 32 | (reify TableViewDelegate 33 | (did-select-row-at-index-path [_ section row] 34 | (reset! shrimp.detail-view-controller/shrimp (.objectAtSectionRow @fetched-results-controller section row)))))) 35 | 36 | (defn- handle-view-did-load! [] 37 | (when @fetched-results-controller 38 | (set! (.-cljsDelegate @fetched-results-controller) nil)) 39 | (reset! fetched-results-controller (.createShrimpFetchedResultsController @database-manager)) 40 | (setup-fetched-results-controller-delegate) 41 | (.performFetch @fetched-results-controller) 42 | 43 | (setup-table-view-data-source) 44 | (setup-table-view-delegate)) -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Eclipse Public License - v 1.0 2 | 3 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC 4 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM 5 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. 6 | 7 | 1. DEFINITIONS 8 | 9 | "Contribution" means: 10 | 11 | a) in the case of the initial Contributor, the initial code and documentation 12 | distributed under this Agreement, and 13 | b) in the case of each subsequent Contributor: 14 | i) changes to the Program, and 15 | ii) additions to the Program; 16 | 17 | where such changes and/or additions to the Program originate from and are 18 | distributed by that particular Contributor. A Contribution 'originates' 19 | from a Contributor if it was added to the Program by such Contributor 20 | itself or anyone acting on such Contributor's behalf. Contributions do not 21 | include additions to the Program which: (i) are separate modules of 22 | software distributed in conjunction with the Program under their own 23 | license agreement, and (ii) are not derivative works of the Program. 24 | 25 | "Contributor" means any person or entity that distributes the Program. 26 | 27 | "Licensed Patents" mean patent claims licensable by a Contributor which are 28 | necessarily infringed by the use or sale of its Contribution alone or when 29 | combined with the Program. 30 | 31 | "Program" means the Contributions distributed in accordance with this 32 | Agreement. 33 | 34 | "Recipient" means anyone who receives the Program under this Agreement, 35 | including all Contributors. 36 | 37 | 2. GRANT OF RIGHTS 38 | a) Subject to the terms of this Agreement, each Contributor hereby grants 39 | Recipient a non-exclusive, worldwide, royalty-free copyright license to 40 | reproduce, prepare derivative works of, publicly display, publicly 41 | perform, distribute and sublicense the Contribution of such Contributor, 42 | if any, and such derivative works, in source code and object code form. 43 | b) Subject to the terms of this Agreement, each Contributor hereby grants 44 | Recipient a non-exclusive, worldwide, royalty-free patent license under 45 | Licensed Patents to make, use, sell, offer to sell, import and otherwise 46 | transfer the Contribution of such Contributor, if any, in source code and 47 | object code form. This patent license shall apply to the combination of 48 | the Contribution and the Program if, at the time the Contribution is 49 | added by the Contributor, such addition of the Contribution causes such 50 | combination to be covered by the Licensed Patents. The patent license 51 | shall not apply to any other combinations which include the Contribution. 52 | No hardware per se is licensed hereunder. 53 | c) Recipient understands that although each Contributor grants the licenses 54 | to its Contributions set forth herein, no assurances are provided by any 55 | Contributor that the Program does not infringe the patent or other 56 | intellectual property rights of any other entity. Each Contributor 57 | disclaims any liability to Recipient for claims brought by any other 58 | entity based on infringement of intellectual property rights or 59 | otherwise. As a condition to exercising the rights and licenses granted 60 | hereunder, each Recipient hereby assumes sole responsibility to secure 61 | any other intellectual property rights needed, if any. For example, if a 62 | third party patent license is required to allow Recipient to distribute 63 | the Program, it is Recipient's responsibility to acquire that license 64 | before distributing the Program. 65 | d) Each Contributor represents that to its knowledge it has sufficient 66 | copyright rights in its Contribution, if any, to grant the copyright 67 | license set forth in this Agreement. 68 | 69 | 3. REQUIREMENTS 70 | 71 | A Contributor may choose to distribute the Program in object code form under 72 | its own license agreement, provided that: 73 | 74 | a) it complies with the terms and conditions of this Agreement; and 75 | b) its license agreement: 76 | i) effectively disclaims on behalf of all Contributors all warranties 77 | and conditions, express and implied, including warranties or 78 | conditions of title and non-infringement, and implied warranties or 79 | conditions of merchantability and fitness for a particular purpose; 80 | ii) effectively excludes on behalf of all Contributors all liability for 81 | damages, including direct, indirect, special, incidental and 82 | consequential damages, such as lost profits; 83 | iii) states that any provisions which differ from this Agreement are 84 | offered by that Contributor alone and not by any other party; and 85 | iv) states that source code for the Program is available from such 86 | Contributor, and informs licensees how to obtain it in a reasonable 87 | manner on or through a medium customarily used for software exchange. 88 | 89 | When the Program is made available in source code form: 90 | 91 | a) it must be made available under this Agreement; and 92 | b) a copy of this Agreement must be included with each copy of the Program. 93 | Contributors may not remove or alter any copyright notices contained 94 | within the Program. 95 | 96 | Each Contributor must identify itself as the originator of its Contribution, 97 | if 98 | any, in a manner that reasonably allows subsequent Recipients to identify the 99 | originator of the Contribution. 100 | 101 | 4. COMMERCIAL DISTRIBUTION 102 | 103 | Commercial distributors of software may accept certain responsibilities with 104 | respect to end users, business partners and the like. While this license is 105 | intended to facilitate the commercial use of the Program, the Contributor who 106 | includes the Program in a commercial product offering should do so in a manner 107 | which does not create potential liability for other Contributors. Therefore, 108 | if a Contributor includes the Program in a commercial product offering, such 109 | Contributor ("Commercial Contributor") hereby agrees to defend and indemnify 110 | every other Contributor ("Indemnified Contributor") against any losses, 111 | damages and costs (collectively "Losses") arising from claims, lawsuits and 112 | other legal actions brought by a third party against the Indemnified 113 | Contributor to the extent caused by the acts or omissions of such Commercial 114 | Contributor in connection with its distribution of the Program in a commercial 115 | product offering. The obligations in this section do not apply to any claims 116 | or Losses relating to any actual or alleged intellectual property 117 | infringement. In order to qualify, an Indemnified Contributor must: 118 | a) promptly notify the Commercial Contributor in writing of such claim, and 119 | b) allow the Commercial Contributor to control, and cooperate with the 120 | Commercial Contributor in, the defense and any related settlement 121 | negotiations. The Indemnified Contributor may participate in any such claim at 122 | its own expense. 123 | 124 | For example, a Contributor might include the Program in a commercial product 125 | offering, Product X. That Contributor is then a Commercial Contributor. If 126 | that Commercial Contributor then makes performance claims, or offers 127 | warranties related to Product X, those performance claims and warranties are 128 | such Commercial Contributor's responsibility alone. Under this section, the 129 | Commercial Contributor would have to defend claims against the other 130 | Contributors related to those performance claims and warranties, and if a 131 | court requires any other Contributor to pay any damages as a result, the 132 | Commercial Contributor must pay those damages. 133 | 134 | 5. NO WARRANTY 135 | 136 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN 137 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR 138 | IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, 139 | NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each 140 | Recipient is solely responsible for determining the appropriateness of using 141 | and distributing the Program and assumes all risks associated with its 142 | exercise of rights under this Agreement , including but not limited to the 143 | risks and costs of program errors, compliance with applicable laws, damage to 144 | or loss of data, programs or equipment, and unavailability or interruption of 145 | operations. 146 | 147 | 6. DISCLAIMER OF LIABILITY 148 | 149 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY 150 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, 151 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION 152 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 153 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 154 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE 155 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY 156 | OF SUCH DAMAGES. 157 | 158 | 7. GENERAL 159 | 160 | If any provision of this Agreement is invalid or unenforceable under 161 | applicable law, it shall not affect the validity or enforceability of the 162 | remainder of the terms of this Agreement, and without further action by the 163 | parties hereto, such provision shall be reformed to the minimum extent 164 | necessary to make such provision valid and enforceable. 165 | 166 | If Recipient institutes patent litigation against any entity (including a 167 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself 168 | (excluding combinations of the Program with other software or hardware) 169 | infringes such Recipient's patent(s), then such Recipient's rights granted 170 | under Section 2(b) shall terminate as of the date such litigation is filed. 171 | 172 | All Recipient's rights under this Agreement shall terminate if it fails to 173 | comply with any of the material terms or conditions of this Agreement and does 174 | not cure such failure in a reasonable period of time after becoming aware of 175 | such noncompliance. If all Recipient's rights under this Agreement terminate, 176 | Recipient agrees to cease use and distribution of the Program as soon as 177 | reasonably practicable. However, Recipient's obligations under this Agreement 178 | and any licenses granted by Recipient relating to the Program shall continue 179 | and survive. 180 | 181 | Everyone is permitted to copy and distribute copies of this Agreement, but in 182 | order to avoid inconsistency the Agreement is copyrighted and may only be 183 | modified in the following manner. The Agreement Steward reserves the right to 184 | publish new versions (including revisions) of this Agreement from time to 185 | time. No one other than the Agreement Steward has the right to modify this 186 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The 187 | Eclipse Foundation may assign the responsibility to serve as the Agreement 188 | Steward to a suitable separate entity. Each new version of the Agreement will 189 | be given a distinguishing version number. The Program (including 190 | Contributions) may always be distributed subject to the version of the 191 | Agreement under which it was received. In addition, after a new version of the 192 | Agreement is published, Contributor may elect to distribute the Program 193 | (including its Contributions) under the new version. Except as expressly 194 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or 195 | licenses to the intellectual property of any Contributor under this Agreement, 196 | whether expressly, by implication, estoppel or otherwise. All rights in the 197 | Program not expressly granted under this Agreement are reserved. 198 | 199 | This Agreement is governed by the laws of the State of New York and the 200 | intellectual property laws of the United States of America. No party to this 201 | Agreement will bring a legal action under this Agreement more than one year 202 | after the cause of action arose. Each party waives its rights to a jury trial in 203 | any resulting litigation. 204 | 205 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Shrimp 2 | ====== 3 | 4 | Example project using [Goby](https://github.com/mfikes/goby). 5 | 6 | Overview 7 | ======== 8 | 9 | This is a sample project illustrating the use of Goby, which is some glue code facilitating the creation of iOS apps in ClojureScript. 10 | 11 | This repo is really two projects in one: 12 | 13 | 1. An iOS app which contains the Storyboards and which loads the compiled JavaScript. 14 | 2. A ClojureScript project which contains implementations for the view controllers. 15 | 16 | This project illustrates how UIKit elements are injected into ClojureScript and how Objective-C protocols such as `UITableViewDataSource` are implemented. It also shows how CoreData can be used, injecting (mutable) CoreData objects into ClojureScript. 17 | 18 | [This blog post](http://blog.fikesfarm.com/posts/2015-03-05-ambly-app-bootstrapping.html) delves into more of the detail on how the Ambly REPL is integrated into Shrimp. 19 | 20 | Running 21 | ======= 22 | 23 | To set up the Shrimp Xcode project, go into `shrimp/iOS` and do `pod install`. 24 | 25 | To run Shrimp, first go into the `ClojureScript` directory and run 26 | ``` 27 | clojure -m cljs.main -t none -c shrimp.core 28 | ``` 29 | This will produce the `main.js` file and `out` directory referenced in the iOS project workspace. 30 | 31 | Then open `iOS/Shrimp.xcworkspace` in Xcode and run the project in an iPhone simulator. You should see the main UI come up with a list view showing a list of shrimp names. Tap on any of these to see editable details. 32 | 33 | 34 | 35 | REPL 36 | ==== 37 | 38 | To interact with the app via the Ambly REPL: 39 | 40 | 1. Run `./repl.sh` in the `ClojureScript` directory 41 | 2. Choose `[1] Shrimp on iPhone Simulator ()`. 42 | 3. In the REPL, do `(in-ns 'shrimp.detail-view-controller)`. 43 | 4. In the app, tap on one of the shrimp names to go to a detail view. 44 | 5. Try updating the text in one of the fields with `(set! (.-text @name-text-field) "Hello")`. 45 | 46 | You can also establish a REPL with a test device; simply follow the same steps but run the app on a device and choose the device when starting the REPL. 47 | 48 | Here is what this all looks like in [Cursive](https://cursiveclojure.com) (using a previous copy that worked with Weasel): 49 | 50 | ![](https://raw.githubusercontent.com/mfikes/shrimp/master/devenv.png) 51 | 52 | License 53 | ======= 54 | 55 | Copyright © 2015-2020 Mike Fikes and Contributors 56 | 57 | Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version. 58 | -------------------------------------------------------------------------------- /devenv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mfikes/shrimp/83f7a5c63ff340511bfdc1370d26d30f5a3f7202/devenv.png -------------------------------------------------------------------------------- /iOS/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | platform :ios, '8.0' 3 | 4 | target 'Shrimp' do 5 | pod 'Goby', '~> 1.1.0' 6 | pod 'Ambly', '~> 1.8.0' 7 | end 8 | -------------------------------------------------------------------------------- /iOS/Shrimp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B43A84765925EA972D376A8A /* libPods-Shrimp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 448132A27FAE77A8B48DED26 /* libPods-Shrimp.a */; }; 11 | ED0E172F19F58F29004345D9 /* MasterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ED0E172E19F58F29004345D9 /* MasterViewController.m */; }; 12 | ED0E173219F58F41004345D9 /* DetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ED0E173119F58F41004345D9 /* DetailViewController.m */; }; 13 | ED15C8A02038B43900160C69 /* out in Resources */ = {isa = PBXBuildFile; fileRef = ED15C89F2038B43900160C69 /* out */; }; 14 | ED26DEAD19F5861800822BB4 /* DatabaseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = ED26DEAC19F5861800822BB4 /* DatabaseManager.m */; }; 15 | ED26DEB019F5869700822BB4 /* BaseDatabaseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = ED26DEAF19F5869700822BB4 /* BaseDatabaseManager.m */; }; 16 | ED26DEB319F5886900822BB4 /* Shrimp.m in Sources */ = {isa = PBXBuildFile; fileRef = ED26DEB219F5886900822BB4 /* Shrimp.m */; }; 17 | EDF7942219F571CF005E8532 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EDF7942119F571CF005E8532 /* main.m */; }; 18 | EDF7942519F571CF005E8532 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = EDF7942419F571CF005E8532 /* AppDelegate.m */; }; 19 | EDF7942819F571CF005E8532 /* Shrimp.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = EDF7942619F571CF005E8532 /* Shrimp.xcdatamodeld */; }; 20 | EDF7942E19F571CF005E8532 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = EDF7942C19F571CF005E8532 /* Main.storyboard */; }; 21 | EDF7943019F571CF005E8532 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = EDF7942F19F571CF005E8532 /* Images.xcassets */; }; 22 | EDF7943319F571CF005E8532 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = EDF7943119F571CF005E8532 /* LaunchScreen.xib */; }; 23 | EDF7943F19F571CF005E8532 /* ShrimpTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EDF7943E19F571CF005E8532 /* ShrimpTests.m */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXContainerItemProxy section */ 27 | EDF7943919F571CF005E8532 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = EDF7941419F571CF005E8532 /* Project object */; 30 | proxyType = 1; 31 | remoteGlobalIDString = EDF7941B19F571CF005E8532; 32 | remoteInfo = Shrimp; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | 448132A27FAE77A8B48DED26 /* libPods-Shrimp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Shrimp.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 5150508E7AAE6D778E2536B4 /* Pods-Shrimp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Shrimp.release.xcconfig"; path = "Pods/Target Support Files/Pods-Shrimp/Pods-Shrimp.release.xcconfig"; sourceTree = ""; }; 39 | B8BB98D315FBEF416DAA27F9 /* Pods-Shrimp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Shrimp.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Shrimp/Pods-Shrimp.debug.xcconfig"; sourceTree = ""; }; 40 | ED0E172D19F58F29004345D9 /* MasterViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MasterViewController.h; sourceTree = ""; }; 41 | ED0E172E19F58F29004345D9 /* MasterViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MasterViewController.m; sourceTree = ""; }; 42 | ED0E173019F58F41004345D9 /* DetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DetailViewController.h; sourceTree = ""; }; 43 | ED0E173119F58F41004345D9 /* DetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DetailViewController.m; sourceTree = ""; }; 44 | ED15C89F2038B43900160C69 /* out */ = {isa = PBXFileReference; lastKnownFileType = folder; name = out; path = ../ClojureScript/out; sourceTree = ""; }; 45 | ED26DEAB19F5861800822BB4 /* DatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseManager.h; sourceTree = ""; }; 46 | ED26DEAC19F5861800822BB4 /* DatabaseManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DatabaseManager.m; sourceTree = ""; }; 47 | ED26DEAE19F5869700822BB4 /* BaseDatabaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BaseDatabaseManager.h; sourceTree = ""; }; 48 | ED26DEAF19F5869700822BB4 /* BaseDatabaseManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BaseDatabaseManager.m; sourceTree = ""; }; 49 | ED26DEB119F5886900822BB4 /* Shrimp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Shrimp.h; sourceTree = ""; }; 50 | ED26DEB219F5886900822BB4 /* Shrimp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Shrimp.m; sourceTree = ""; }; 51 | EDF7941C19F571CF005E8532 /* Shrimp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Shrimp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 52 | EDF7942019F571CF005E8532 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | EDF7942119F571CF005E8532 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 54 | EDF7942319F571CF005E8532 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 55 | EDF7942419F571CF005E8532 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 56 | EDF7942719F571CF005E8532 /* Shrimp.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Shrimp.xcdatamodel; sourceTree = ""; }; 57 | EDF7942D19F571CF005E8532 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 58 | EDF7942F19F571CF005E8532 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 59 | EDF7943219F571CF005E8532 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 60 | EDF7943819F571CF005E8532 /* ShrimpTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ShrimpTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | EDF7943D19F571CF005E8532 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 62 | EDF7943E19F571CF005E8532 /* ShrimpTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ShrimpTests.m; sourceTree = ""; }; 63 | /* End PBXFileReference section */ 64 | 65 | /* Begin PBXFrameworksBuildPhase section */ 66 | EDF7941919F571CF005E8532 /* Frameworks */ = { 67 | isa = PBXFrameworksBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | B43A84765925EA972D376A8A /* libPods-Shrimp.a in Frameworks */, 71 | ); 72 | runOnlyForDeploymentPostprocessing = 0; 73 | }; 74 | EDF7943519F571CF005E8532 /* Frameworks */ = { 75 | isa = PBXFrameworksBuildPhase; 76 | buildActionMask = 2147483647; 77 | files = ( 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | /* End PBXFrameworksBuildPhase section */ 82 | 83 | /* Begin PBXGroup section */ 84 | 0016AD5F9125A067591C6FC1 /* Pods */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | B8BB98D315FBEF416DAA27F9 /* Pods-Shrimp.debug.xcconfig */, 88 | 5150508E7AAE6D778E2536B4 /* Pods-Shrimp.release.xcconfig */, 89 | ); 90 | name = Pods; 91 | sourceTree = ""; 92 | }; 93 | 1368C8179B3A8BC43FF9F2FF /* Frameworks */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 448132A27FAE77A8B48DED26 /* libPods-Shrimp.a */, 97 | ); 98 | name = Frameworks; 99 | sourceTree = ""; 100 | }; 101 | EDF7941319F571CF005E8532 = { 102 | isa = PBXGroup; 103 | children = ( 104 | ED15C89F2038B43900160C69 /* out */, 105 | EDF7941E19F571CF005E8532 /* Shrimp */, 106 | EDF7943B19F571CF005E8532 /* ShrimpTests */, 107 | EDF7941D19F571CF005E8532 /* Products */, 108 | 0016AD5F9125A067591C6FC1 /* Pods */, 109 | 1368C8179B3A8BC43FF9F2FF /* Frameworks */, 110 | ); 111 | sourceTree = ""; 112 | }; 113 | EDF7941D19F571CF005E8532 /* Products */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | EDF7941C19F571CF005E8532 /* Shrimp.app */, 117 | EDF7943819F571CF005E8532 /* ShrimpTests.xctest */, 118 | ); 119 | name = Products; 120 | sourceTree = ""; 121 | }; 122 | EDF7941E19F571CF005E8532 /* Shrimp */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | EDF7942319F571CF005E8532 /* AppDelegate.h */, 126 | EDF7942419F571CF005E8532 /* AppDelegate.m */, 127 | ED0E172D19F58F29004345D9 /* MasterViewController.h */, 128 | ED0E172E19F58F29004345D9 /* MasterViewController.m */, 129 | ED0E173019F58F41004345D9 /* DetailViewController.h */, 130 | ED0E173119F58F41004345D9 /* DetailViewController.m */, 131 | ED26DEAE19F5869700822BB4 /* BaseDatabaseManager.h */, 132 | ED26DEAF19F5869700822BB4 /* BaseDatabaseManager.m */, 133 | ED26DEAB19F5861800822BB4 /* DatabaseManager.h */, 134 | ED26DEAC19F5861800822BB4 /* DatabaseManager.m */, 135 | EDF7942C19F571CF005E8532 /* Main.storyboard */, 136 | EDF7942F19F571CF005E8532 /* Images.xcassets */, 137 | EDF7943119F571CF005E8532 /* LaunchScreen.xib */, 138 | EDF7942619F571CF005E8532 /* Shrimp.xcdatamodeld */, 139 | ED26DEB119F5886900822BB4 /* Shrimp.h */, 140 | ED26DEB219F5886900822BB4 /* Shrimp.m */, 141 | EDF7941F19F571CF005E8532 /* Supporting Files */, 142 | ); 143 | path = Shrimp; 144 | sourceTree = ""; 145 | }; 146 | EDF7941F19F571CF005E8532 /* Supporting Files */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | EDF7942019F571CF005E8532 /* Info.plist */, 150 | EDF7942119F571CF005E8532 /* main.m */, 151 | ); 152 | name = "Supporting Files"; 153 | sourceTree = ""; 154 | }; 155 | EDF7943B19F571CF005E8532 /* ShrimpTests */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | EDF7943E19F571CF005E8532 /* ShrimpTests.m */, 159 | EDF7943C19F571CF005E8532 /* Supporting Files */, 160 | ); 161 | path = ShrimpTests; 162 | sourceTree = ""; 163 | }; 164 | EDF7943C19F571CF005E8532 /* Supporting Files */ = { 165 | isa = PBXGroup; 166 | children = ( 167 | EDF7943D19F571CF005E8532 /* Info.plist */, 168 | ); 169 | name = "Supporting Files"; 170 | sourceTree = ""; 171 | }; 172 | /* End PBXGroup section */ 173 | 174 | /* Begin PBXNativeTarget section */ 175 | EDF7941B19F571CF005E8532 /* Shrimp */ = { 176 | isa = PBXNativeTarget; 177 | buildConfigurationList = EDF7944219F571CF005E8532 /* Build configuration list for PBXNativeTarget "Shrimp" */; 178 | buildPhases = ( 179 | AF8848A0C0FCE718B78EBED0 /* [CP] Check Pods Manifest.lock */, 180 | EDF7941819F571CF005E8532 /* Sources */, 181 | EDF7941919F571CF005E8532 /* Frameworks */, 182 | EDF7941A19F571CF005E8532 /* Resources */, 183 | ); 184 | buildRules = ( 185 | ); 186 | dependencies = ( 187 | ); 188 | name = Shrimp; 189 | productName = Shrimp; 190 | productReference = EDF7941C19F571CF005E8532 /* Shrimp.app */; 191 | productType = "com.apple.product-type.application"; 192 | }; 193 | EDF7943719F571CF005E8532 /* ShrimpTests */ = { 194 | isa = PBXNativeTarget; 195 | buildConfigurationList = EDF7944519F571CF005E8532 /* Build configuration list for PBXNativeTarget "ShrimpTests" */; 196 | buildPhases = ( 197 | EDF7943419F571CF005E8532 /* Sources */, 198 | EDF7943519F571CF005E8532 /* Frameworks */, 199 | EDF7943619F571CF005E8532 /* Resources */, 200 | ); 201 | buildRules = ( 202 | ); 203 | dependencies = ( 204 | EDF7943A19F571CF005E8532 /* PBXTargetDependency */, 205 | ); 206 | name = ShrimpTests; 207 | productName = ShrimpTests; 208 | productReference = EDF7943819F571CF005E8532 /* ShrimpTests.xctest */; 209 | productType = "com.apple.product-type.bundle.unit-test"; 210 | }; 211 | /* End PBXNativeTarget section */ 212 | 213 | /* Begin PBXProject section */ 214 | EDF7941419F571CF005E8532 /* Project object */ = { 215 | isa = PBXProject; 216 | attributes = { 217 | LastUpgradeCheck = 0600; 218 | ORGANIZATIONNAME = Goby; 219 | TargetAttributes = { 220 | EDF7941B19F571CF005E8532 = { 221 | CreatedOnToolsVersion = 6.0.1; 222 | }; 223 | EDF7943719F571CF005E8532 = { 224 | CreatedOnToolsVersion = 6.0.1; 225 | TestTargetID = EDF7941B19F571CF005E8532; 226 | }; 227 | }; 228 | }; 229 | buildConfigurationList = EDF7941719F571CF005E8532 /* Build configuration list for PBXProject "Shrimp" */; 230 | compatibilityVersion = "Xcode 3.2"; 231 | developmentRegion = English; 232 | hasScannedForEncodings = 0; 233 | knownRegions = ( 234 | en, 235 | Base, 236 | ); 237 | mainGroup = EDF7941319F571CF005E8532; 238 | productRefGroup = EDF7941D19F571CF005E8532 /* Products */; 239 | projectDirPath = ""; 240 | projectRoot = ""; 241 | targets = ( 242 | EDF7941B19F571CF005E8532 /* Shrimp */, 243 | EDF7943719F571CF005E8532 /* ShrimpTests */, 244 | ); 245 | }; 246 | /* End PBXProject section */ 247 | 248 | /* Begin PBXResourcesBuildPhase section */ 249 | EDF7941A19F571CF005E8532 /* Resources */ = { 250 | isa = PBXResourcesBuildPhase; 251 | buildActionMask = 2147483647; 252 | files = ( 253 | EDF7942E19F571CF005E8532 /* Main.storyboard in Resources */, 254 | EDF7943319F571CF005E8532 /* LaunchScreen.xib in Resources */, 255 | EDF7943019F571CF005E8532 /* Images.xcassets in Resources */, 256 | ED15C8A02038B43900160C69 /* out in Resources */, 257 | ); 258 | runOnlyForDeploymentPostprocessing = 0; 259 | }; 260 | EDF7943619F571CF005E8532 /* Resources */ = { 261 | isa = PBXResourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | ); 265 | runOnlyForDeploymentPostprocessing = 0; 266 | }; 267 | /* End PBXResourcesBuildPhase section */ 268 | 269 | /* Begin PBXShellScriptBuildPhase section */ 270 | AF8848A0C0FCE718B78EBED0 /* [CP] Check Pods Manifest.lock */ = { 271 | isa = PBXShellScriptBuildPhase; 272 | buildActionMask = 2147483647; 273 | files = ( 274 | ); 275 | inputPaths = ( 276 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 277 | "${PODS_ROOT}/Manifest.lock", 278 | ); 279 | name = "[CP] Check Pods Manifest.lock"; 280 | outputPaths = ( 281 | "$(DERIVED_FILE_DIR)/Pods-Shrimp-checkManifestLockResult.txt", 282 | ); 283 | runOnlyForDeploymentPostprocessing = 0; 284 | shellPath = /bin/sh; 285 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 286 | showEnvVarsInLog = 0; 287 | }; 288 | /* End PBXShellScriptBuildPhase section */ 289 | 290 | /* Begin PBXSourcesBuildPhase section */ 291 | EDF7941819F571CF005E8532 /* Sources */ = { 292 | isa = PBXSourcesBuildPhase; 293 | buildActionMask = 2147483647; 294 | files = ( 295 | EDF7942519F571CF005E8532 /* AppDelegate.m in Sources */, 296 | EDF7942819F571CF005E8532 /* Shrimp.xcdatamodeld in Sources */, 297 | ED26DEAD19F5861800822BB4 /* DatabaseManager.m in Sources */, 298 | ED0E173219F58F41004345D9 /* DetailViewController.m in Sources */, 299 | ED0E172F19F58F29004345D9 /* MasterViewController.m in Sources */, 300 | ED26DEB019F5869700822BB4 /* BaseDatabaseManager.m in Sources */, 301 | EDF7942219F571CF005E8532 /* main.m in Sources */, 302 | ED26DEB319F5886900822BB4 /* Shrimp.m in Sources */, 303 | ); 304 | runOnlyForDeploymentPostprocessing = 0; 305 | }; 306 | EDF7943419F571CF005E8532 /* Sources */ = { 307 | isa = PBXSourcesBuildPhase; 308 | buildActionMask = 2147483647; 309 | files = ( 310 | EDF7943F19F571CF005E8532 /* ShrimpTests.m in Sources */, 311 | ); 312 | runOnlyForDeploymentPostprocessing = 0; 313 | }; 314 | /* End PBXSourcesBuildPhase section */ 315 | 316 | /* Begin PBXTargetDependency section */ 317 | EDF7943A19F571CF005E8532 /* PBXTargetDependency */ = { 318 | isa = PBXTargetDependency; 319 | target = EDF7941B19F571CF005E8532 /* Shrimp */; 320 | targetProxy = EDF7943919F571CF005E8532 /* PBXContainerItemProxy */; 321 | }; 322 | /* End PBXTargetDependency section */ 323 | 324 | /* Begin PBXVariantGroup section */ 325 | EDF7942C19F571CF005E8532 /* Main.storyboard */ = { 326 | isa = PBXVariantGroup; 327 | children = ( 328 | EDF7942D19F571CF005E8532 /* Base */, 329 | ); 330 | name = Main.storyboard; 331 | sourceTree = ""; 332 | }; 333 | EDF7943119F571CF005E8532 /* LaunchScreen.xib */ = { 334 | isa = PBXVariantGroup; 335 | children = ( 336 | EDF7943219F571CF005E8532 /* Base */, 337 | ); 338 | name = LaunchScreen.xib; 339 | sourceTree = ""; 340 | }; 341 | /* End PBXVariantGroup section */ 342 | 343 | /* Begin XCBuildConfiguration section */ 344 | EDF7944019F571CF005E8532 /* Debug */ = { 345 | isa = XCBuildConfiguration; 346 | buildSettings = { 347 | ALWAYS_SEARCH_USER_PATHS = NO; 348 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 349 | CLANG_CXX_LIBRARY = "libc++"; 350 | CLANG_ENABLE_MODULES = YES; 351 | CLANG_ENABLE_OBJC_ARC = YES; 352 | CLANG_WARN_BOOL_CONVERSION = YES; 353 | CLANG_WARN_CONSTANT_CONVERSION = YES; 354 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 355 | CLANG_WARN_EMPTY_BODY = YES; 356 | CLANG_WARN_ENUM_CONVERSION = YES; 357 | CLANG_WARN_INT_CONVERSION = YES; 358 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 359 | CLANG_WARN_UNREACHABLE_CODE = YES; 360 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 361 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 362 | COPY_PHASE_STRIP = NO; 363 | ENABLE_STRICT_OBJC_MSGSEND = YES; 364 | GCC_C_LANGUAGE_STANDARD = gnu99; 365 | GCC_DYNAMIC_NO_PIC = NO; 366 | GCC_OPTIMIZATION_LEVEL = 0; 367 | GCC_PREPROCESSOR_DEFINITIONS = ( 368 | "DEBUG=1", 369 | "$(inherited)", 370 | ); 371 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 372 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 373 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 374 | GCC_WARN_UNDECLARED_SELECTOR = YES; 375 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 376 | GCC_WARN_UNUSED_FUNCTION = YES; 377 | GCC_WARN_UNUSED_VARIABLE = YES; 378 | IPHONEOS_DEPLOYMENT_TARGET = 8.2; 379 | MTL_ENABLE_DEBUG_INFO = YES; 380 | ONLY_ACTIVE_ARCH = YES; 381 | SDKROOT = iphoneos; 382 | TARGETED_DEVICE_FAMILY = "1,2"; 383 | }; 384 | name = Debug; 385 | }; 386 | EDF7944119F571CF005E8532 /* Release */ = { 387 | isa = XCBuildConfiguration; 388 | buildSettings = { 389 | ALWAYS_SEARCH_USER_PATHS = NO; 390 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 391 | CLANG_CXX_LIBRARY = "libc++"; 392 | CLANG_ENABLE_MODULES = YES; 393 | CLANG_ENABLE_OBJC_ARC = YES; 394 | CLANG_WARN_BOOL_CONVERSION = YES; 395 | CLANG_WARN_CONSTANT_CONVERSION = YES; 396 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 397 | CLANG_WARN_EMPTY_BODY = YES; 398 | CLANG_WARN_ENUM_CONVERSION = YES; 399 | CLANG_WARN_INT_CONVERSION = YES; 400 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 401 | CLANG_WARN_UNREACHABLE_CODE = YES; 402 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 403 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 404 | COPY_PHASE_STRIP = YES; 405 | ENABLE_NS_ASSERTIONS = NO; 406 | ENABLE_STRICT_OBJC_MSGSEND = YES; 407 | GCC_C_LANGUAGE_STANDARD = gnu99; 408 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 409 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 410 | GCC_WARN_UNDECLARED_SELECTOR = YES; 411 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 412 | GCC_WARN_UNUSED_FUNCTION = YES; 413 | GCC_WARN_UNUSED_VARIABLE = YES; 414 | IPHONEOS_DEPLOYMENT_TARGET = 8.2; 415 | MTL_ENABLE_DEBUG_INFO = NO; 416 | SDKROOT = iphoneos; 417 | TARGETED_DEVICE_FAMILY = "1,2"; 418 | VALIDATE_PRODUCT = YES; 419 | }; 420 | name = Release; 421 | }; 422 | EDF7944319F571CF005E8532 /* Debug */ = { 423 | isa = XCBuildConfiguration; 424 | baseConfigurationReference = B8BB98D315FBEF416DAA27F9 /* Pods-Shrimp.debug.xcconfig */; 425 | buildSettings = { 426 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 427 | INFOPLIST_FILE = Shrimp/Info.plist; 428 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 429 | PRODUCT_NAME = "$(TARGET_NAME)"; 430 | TARGETED_DEVICE_FAMILY = 1; 431 | }; 432 | name = Debug; 433 | }; 434 | EDF7944419F571CF005E8532 /* Release */ = { 435 | isa = XCBuildConfiguration; 436 | baseConfigurationReference = 5150508E7AAE6D778E2536B4 /* Pods-Shrimp.release.xcconfig */; 437 | buildSettings = { 438 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 439 | INFOPLIST_FILE = Shrimp/Info.plist; 440 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 441 | PRODUCT_NAME = "$(TARGET_NAME)"; 442 | TARGETED_DEVICE_FAMILY = 1; 443 | }; 444 | name = Release; 445 | }; 446 | EDF7944619F571CF005E8532 /* Debug */ = { 447 | isa = XCBuildConfiguration; 448 | buildSettings = { 449 | BUNDLE_LOADER = "$(TEST_HOST)"; 450 | FRAMEWORK_SEARCH_PATHS = ( 451 | "$(SDKROOT)/Developer/Library/Frameworks", 452 | "$(inherited)", 453 | ); 454 | GCC_PREPROCESSOR_DEFINITIONS = ( 455 | "DEBUG=1", 456 | "$(inherited)", 457 | ); 458 | INFOPLIST_FILE = ShrimpTests/Info.plist; 459 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 460 | PRODUCT_NAME = "$(TARGET_NAME)"; 461 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Shrimp.app/Shrimp"; 462 | }; 463 | name = Debug; 464 | }; 465 | EDF7944719F571CF005E8532 /* Release */ = { 466 | isa = XCBuildConfiguration; 467 | buildSettings = { 468 | BUNDLE_LOADER = "$(TEST_HOST)"; 469 | FRAMEWORK_SEARCH_PATHS = ( 470 | "$(SDKROOT)/Developer/Library/Frameworks", 471 | "$(inherited)", 472 | ); 473 | INFOPLIST_FILE = ShrimpTests/Info.plist; 474 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 475 | PRODUCT_NAME = "$(TARGET_NAME)"; 476 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Shrimp.app/Shrimp"; 477 | }; 478 | name = Release; 479 | }; 480 | /* End XCBuildConfiguration section */ 481 | 482 | /* Begin XCConfigurationList section */ 483 | EDF7941719F571CF005E8532 /* Build configuration list for PBXProject "Shrimp" */ = { 484 | isa = XCConfigurationList; 485 | buildConfigurations = ( 486 | EDF7944019F571CF005E8532 /* Debug */, 487 | EDF7944119F571CF005E8532 /* Release */, 488 | ); 489 | defaultConfigurationIsVisible = 0; 490 | defaultConfigurationName = Release; 491 | }; 492 | EDF7944219F571CF005E8532 /* Build configuration list for PBXNativeTarget "Shrimp" */ = { 493 | isa = XCConfigurationList; 494 | buildConfigurations = ( 495 | EDF7944319F571CF005E8532 /* Debug */, 496 | EDF7944419F571CF005E8532 /* Release */, 497 | ); 498 | defaultConfigurationIsVisible = 0; 499 | defaultConfigurationName = Release; 500 | }; 501 | EDF7944519F571CF005E8532 /* Build configuration list for PBXNativeTarget "ShrimpTests" */ = { 502 | isa = XCConfigurationList; 503 | buildConfigurations = ( 504 | EDF7944619F571CF005E8532 /* Debug */, 505 | EDF7944719F571CF005E8532 /* Release */, 506 | ); 507 | defaultConfigurationIsVisible = 0; 508 | defaultConfigurationName = Release; 509 | }; 510 | /* End XCConfigurationList section */ 511 | 512 | /* Begin XCVersionGroup section */ 513 | EDF7942619F571CF005E8532 /* Shrimp.xcdatamodeld */ = { 514 | isa = XCVersionGroup; 515 | children = ( 516 | EDF7942719F571CF005E8532 /* Shrimp.xcdatamodel */, 517 | ); 518 | currentVersion = EDF7942719F571CF005E8532 /* Shrimp.xcdatamodel */; 519 | path = Shrimp.xcdatamodeld; 520 | sourceTree = ""; 521 | versionGroupType = wrapper.xcdatamodel; 522 | }; 523 | /* End XCVersionGroup section */ 524 | }; 525 | rootObject = EDF7941419F571CF005E8532 /* Project object */; 526 | } 527 | -------------------------------------------------------------------------------- /iOS/Shrimp/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @class DatabaseManager; 5 | @class GBYManager; 6 | 7 | @interface AppDelegate : UIResponder 8 | 9 | @property (strong, nonatomic) UIWindow *window; 10 | 11 | @property (strong, nonatomic) DatabaseManager* databaseManager; 12 | @property (strong, nonatomic) GBYManager* cljsManager; 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /iOS/Shrimp/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import "DatabaseManager.h" 4 | #import "GBYManager.h" 5 | 6 | #ifdef DEBUG 7 | #import "ABYContextManager.h" 8 | #import "ABYServer.h" 9 | 10 | @interface AppDelegate () 11 | 12 | @property (strong, nonatomic) ABYContextManager* contextManager; 13 | @property (strong, nonatomic) ABYServer* replServer; 14 | 15 | @end 16 | #endif 17 | 18 | void uncaughtExceptionHandler(NSException *exception) { 19 | NSLog(@"CRASH: %@", exception); 20 | NSLog(@"Stack Trace: %@", [exception callStackSymbols]); 21 | } 22 | 23 | @implementation AppDelegate 24 | 25 | #ifdef DEBUG 26 | -(void)requireAppNamespaces:(JSContext*)context 27 | { 28 | [context evaluateScript:@"goog.require('shrimp.core');"]; 29 | 30 | // Need to require these as they are not referenced by shrimp.core (munging also needed) 31 | [context evaluateScript:@"goog.require('shrimp.master_view_controller');"]; 32 | [context evaluateScript:@"goog.require('shrimp.detail_view_controller');"]; 33 | } 34 | #endif 35 | 36 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 37 | 38 | NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler); 39 | 40 | // Shut down the idle timer so that you can easily experiment 41 | // with the demo app from a device that is not connected to a Mac 42 | // running Xcode. Since this demo app isn't being released we 43 | // can do this unconditionally. 44 | [UIApplication sharedApplication].idleTimerDisabled = YES; 45 | 46 | #ifdef DEBUG 47 | // Set up the compiler output directory 48 | NSURL* compilerOutputDirectory = [[self privateDocumentsDirectory] URLByAppendingPathComponent:@"cljs-out"]; 49 | 50 | // Ensure private documents directory exists 51 | [self createDirectoriesUpTo:[self privateDocumentsDirectory]]; 52 | 53 | // Copy resources from bundle "out" to compilerOutputDirectory 54 | 55 | NSFileManager* fileManager = [NSFileManager defaultManager]; 56 | fileManager.delegate = self; 57 | 58 | // First blow away old compiler output directory 59 | [fileManager removeItemAtPath:compilerOutputDirectory.path error:nil]; 60 | 61 | // Copy files from bundle to compiler output driectory 62 | NSString *outPath = [[NSBundle mainBundle] pathForResource:@"out" ofType:nil]; 63 | [fileManager copyItemAtPath:outPath toPath:compilerOutputDirectory.path error:nil]; 64 | 65 | NSLog(@"Initializing ClojureScript"); 66 | self.contextManager = [[ABYContextManager alloc] initWithContext:JSGlobalContextCreate(NULL) 67 | compilerOutputDirectory:compilerOutputDirectory]; 68 | [self.contextManager setupGlobalContext]; 69 | [self.contextManager setUpConsoleLog]; 70 | [self.contextManager setUpTimerFunctionality]; 71 | [self.contextManager setUpAmblyImportScript]; 72 | 73 | NSURL* googDirectory = [compilerOutputDirectory URLByAppendingPathComponent:@"goog"]; 74 | 75 | [self.contextManager bootstrapWithDepsFilePath:[[compilerOutputDirectory URLByAppendingPathComponent:@"main" isDirectory:NO] URLByAppendingPathExtension:@"js"].path 76 | googBasePath:[[googDirectory URLByAppendingPathComponent:@"base" isDirectory:NO] URLByAppendingPathExtension:@"js"].path]; 77 | 78 | JSContext* jsContext = [JSContext contextWithJSGlobalContextRef:self.contextManager.context]; 79 | [self requireAppNamespaces:jsContext]; 80 | 81 | self.cljsManager = [[GBYManager alloc] initWithInitFnName:@"init!" 82 | inNamespace:@"shrimp.core" 83 | withContext:jsContext 84 | loadingJavaScript:nil]; 85 | #else 86 | self.cljsManager = [[GBYManager alloc] initWithInitFnName:@"init!" 87 | inNamespace:@"shrimp.core" 88 | loadingJavaScript:[[NSBundle mainBundle] pathForResource:@"out/main" ofType:@"js"]]; 89 | #endif 90 | 91 | NSLog(@"Initializing database"); 92 | self.databaseManager = [[DatabaseManager alloc] init]; 93 | 94 | JSValue* setDatabaseManagerFn = [self.cljsManager getValue:@"set-database-manager!" inNamespace:@"shrimp.database"]; 95 | [setDatabaseManagerFn callWithArguments:@[self.databaseManager]]; 96 | 97 | #ifdef DEBUG 98 | // Start up the REPL server 99 | self.replServer = [[ABYServer alloc] initWithContext:self.contextManager.context 100 | compilerOutputDirectory:compilerOutputDirectory]; 101 | BOOL success = [self.replServer startListening]; 102 | if (!success) { 103 | NSLog(@"Failed to start REPL server."); 104 | } 105 | #endif 106 | 107 | return YES; 108 | } 109 | 110 | - (BOOL)fileManager:(NSFileManager *)fileManager shouldProceedAfterError:(NSError *)error copyingItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath{ 111 | if ([error code] == 516) //error code for: The operation couldn’t be completed. File exists 112 | return YES; 113 | else 114 | return NO; 115 | } 116 | 117 | - (void)applicationWillResignActive:(UIApplication *)application { 118 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 119 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 120 | } 121 | 122 | - (void)applicationDidEnterBackground:(UIApplication *)application { 123 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 124 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 125 | } 126 | 127 | - (void)applicationWillEnterForeground:(UIApplication *)application { 128 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 129 | } 130 | 131 | - (void)applicationDidBecomeActive:(UIApplication *)application { 132 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 133 | } 134 | 135 | - (void)applicationWillTerminate:(UIApplication *)application { 136 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 137 | // Saves changes in the application's managed object context before the application terminates. 138 | } 139 | 140 | - (NSURL *)privateDocumentsDirectory 141 | { 142 | NSURL *libraryDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject]; 143 | 144 | return [libraryDirectory URLByAppendingPathComponent:@"Private Documents"]; 145 | } 146 | 147 | - (void)createDirectoriesUpTo:(NSURL*)directory 148 | { 149 | if (![[NSFileManager defaultManager] fileExistsAtPath:[directory path]]) { 150 | NSError *error = nil; 151 | 152 | if (![[NSFileManager defaultManager] createDirectoryAtPath:[directory path] 153 | withIntermediateDirectories:YES 154 | attributes:nil 155 | error:&error]) { 156 | NSLog(@"Can't create directory %@ [%@]", [directory path], error); 157 | abort(); 158 | } 159 | } 160 | } 161 | 162 | @end 163 | -------------------------------------------------------------------------------- /iOS/Shrimp/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /iOS/Shrimp/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 88 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /iOS/Shrimp/BaseDatabaseManager.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | @class FCJFetchedResultsController; 6 | 7 | @protocol BaseDatabaseManager 8 | 9 | - (NSManagedObject*)createEntityWithName:(NSString*)name; 10 | - (void)deleteEntity:(NSManagedObject*)object; 11 | - (void)saveContext; 12 | 13 | @end 14 | 15 | @interface BaseDatabaseManager : NSObject 16 | 17 | @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; 18 | @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; 19 | @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; 20 | 21 | -(NSString*)momdName; 22 | -(NSString*)dbFilename; 23 | 24 | -(NSArray*)getEntitiesWithName:(NSString*)entityName satisfyingPredicate:(NSPredicate*)predicate; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /iOS/Shrimp/BaseDatabaseManager.m: -------------------------------------------------------------------------------- 1 | #import "BaseDatabaseManager.h" 2 | #import 3 | 4 | @implementation BaseDatabaseManager 5 | 6 | @synthesize managedObjectContext = _managedObjectContext; 7 | @synthesize managedObjectModel = _managedObjectModel; 8 | @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 9 | 10 | -(NSString*)momdName 11 | { 12 | NSAssert(NO, @"Override"); 13 | return nil; 14 | } 15 | 16 | -(NSString*)dbFilename 17 | { 18 | NSAssert(NO, @"Override"); 19 | return nil; 20 | } 21 | 22 | - (void)saveContext 23 | { 24 | NSError *error = nil; 25 | NSManagedObjectContext *managedObjectContext = self.managedObjectContext; 26 | if (managedObjectContext != nil) { 27 | if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { 28 | // Replace this implementation with code to handle the error appropriately. 29 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 30 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 31 | abort(); 32 | } 33 | } 34 | } 35 | 36 | // Returns the managed object context for the application. 37 | // If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application. 38 | - (NSManagedObjectContext *)managedObjectContext 39 | { 40 | if (_managedObjectContext != nil) { 41 | return _managedObjectContext; 42 | } 43 | 44 | NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 45 | if (coordinator != nil) { 46 | _managedObjectContext = [[NSManagedObjectContext alloc] init]; 47 | [_managedObjectContext setPersistentStoreCoordinator:coordinator]; 48 | } 49 | return _managedObjectContext; 50 | } 51 | 52 | // Returns the managed object model for the application. 53 | // If the model doesn't already exist, it is created from the application's model. 54 | - (NSManagedObjectModel *)managedObjectModel 55 | { 56 | if (_managedObjectModel != nil) { 57 | return _managedObjectModel; 58 | } 59 | NSURL *modelURL = [[NSBundle mainBundle] URLForResource:[self momdName] withExtension:@"momd"]; 60 | _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 61 | return _managedObjectModel; 62 | } 63 | 64 | // Returns the persistent store coordinator for the application. 65 | // If the coordinator doesn't already exist, it is created and the application's store added to it. 66 | - (NSPersistentStoreCoordinator *)persistentStoreCoordinator 67 | { 68 | if (_persistentStoreCoordinator != nil) { 69 | return _persistentStoreCoordinator; 70 | } 71 | 72 | [self createPrivateDocumentsDirectoryIf]; 73 | 74 | NSURL *storeURL = [[self applicationPrivateDocumentsDirectory] URLByAppendingPathComponent:[self dbFilename]]; 75 | 76 | NSError *error = nil; 77 | _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 78 | 79 | if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType 80 | configuration:nil 81 | URL:storeURL 82 | options:@{NSMigratePersistentStoresAutomaticallyOption: @YES, NSInferMappingModelAutomaticallyOption: @YES} 83 | error:&error]) { 84 | /* 85 | Replace this implementation with code to handle the error appropriately. 86 | 87 | abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 88 | 89 | Typical reasons for an error here include: 90 | * The persistent store is not accessible; 91 | * The schema for the persistent store is incompatible with current managed object model. 92 | Check the error message to determine what the actual problem was. 93 | 94 | 95 | If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory. 96 | 97 | If you encounter schema incompatibility errors during development, you can reduce their frequency by: 98 | * Simply deleting the existing store: 99 | [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil] 100 | 101 | * Performing automatic lightweight migration by passing the following dictionary as the options parameter: 102 | @{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES} 103 | 104 | Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details. 105 | 106 | */ 107 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 108 | abort(); 109 | } 110 | 111 | return _persistentStoreCoordinator; 112 | } 113 | 114 | - (NSURL *)applicationPrivateDocumentsDirectory 115 | { 116 | NSURL *libraryDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSLibraryDirectory inDomains:NSUserDomainMask] lastObject]; 117 | 118 | return [libraryDirectory URLByAppendingPathComponent:@"Private Documents"]; 119 | } 120 | 121 | - (void)createPrivateDocumentsDirectoryIf 122 | { 123 | NSURL *privateDocuments = [self applicationPrivateDocumentsDirectory]; 124 | 125 | if (![[NSFileManager defaultManager] fileExistsAtPath:[privateDocuments path]]) { 126 | NSError *error = nil; 127 | 128 | if (![[NSFileManager defaultManager] createDirectoryAtPath:[privateDocuments path] withIntermediateDirectories:YES attributes:nil error:&error]) { 129 | NSLog(@"Can't create directory %@ [%@]", [privateDocuments path], error); 130 | abort(); 131 | } 132 | } 133 | } 134 | 135 | // Predicate can be nil 136 | -(NSArray*)getEntitiesWithName:(NSString*)entityName satisfyingPredicate:(NSPredicate*)predicate 137 | { 138 | NSEntityDescription *entityDescription = [NSEntityDescription entityForName:entityName inManagedObjectContext:self.managedObjectContext]; 139 | NSFetchRequest *request = [[NSFetchRequest alloc] init]; 140 | 141 | [request setEntity:entityDescription]; 142 | 143 | if (predicate) { 144 | [request setPredicate:predicate]; 145 | } 146 | 147 | NSError *error = nil; 148 | NSArray *array = [self.managedObjectContext executeFetchRequest:request error:&error]; 149 | 150 | return array; 151 | } 152 | 153 | -(NSManagedObject*)createEntityWithName:(NSString*)name 154 | { 155 | return [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:self.managedObjectContext]; 156 | } 157 | 158 | - (void)deleteEntity:(NSManagedObject*)object 159 | { 160 | [self.managedObjectContext deleteObject:object]; 161 | } 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /iOS/Shrimp/DatabaseManager.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import 4 | #import "BaseDatabaseManager.h" 5 | 6 | @class GBYFetchedResultsController; 7 | 8 | @protocol DatabaseManager 9 | 10 | -(NSArray*)getShrimp; 11 | 12 | - (GBYFetchedResultsController*)createShrimpFetchedResultsController; 13 | 14 | @end 15 | 16 | 17 | @interface DatabaseManager : BaseDatabaseManager 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /iOS/Shrimp/DatabaseManager.m: -------------------------------------------------------------------------------- 1 | #import "DatabaseManager.h" 2 | #import 3 | 4 | #import "GBYFetchedResultsController.h" 5 | 6 | #import "Shrimp.h" 7 | 8 | @implementation DatabaseManager 9 | 10 | -(void)createShrimpWithName:(NSString*)name desc:(NSString*)desc edible:(BOOL)edible 11 | { 12 | Shrimp* shrimp = [NSEntityDescription insertNewObjectForEntityForName:@"Shrimp" inManagedObjectContext:self.managedObjectContext]; 13 | shrimp.name = name; 14 | shrimp.edible = @(edible); 15 | shrimp.desc = desc; 16 | } 17 | 18 | -(id)init 19 | { 20 | if (self = [super init]) { 21 | 22 | if (!self.getShrimp.count) { 23 | [self createShrimpWithName:@"Penaeus monodon" desc:@"The giant tiger prawn or Asian tiger shrimp." edible:YES]; 24 | [self createShrimpWithName:@"Pandalus borealis" desc:@"A species of caridean shrimp found in cold parts of the Atlantic and Pacific Oceans." edible:YES]; 25 | [self createShrimpWithName:@"Procarididea" desc:@"An infraorder of decapods, comprising only eleven species." edible:NO]; 26 | [self createShrimpWithName:@"Stenopodidea" desc:@"A small group of decapod crustaceans." edible:NO]; 27 | [self createShrimpWithName:@"Artemia" desc:@"A genus of aquatic crustaceans known as brine shrimp." edible:NO]; 28 | [self createShrimpWithName:@"Conchostraca" desc:@"Clam shrimp are a taxon of bivalved branchiopod crustaceans that resemble the unrelated bivalved molluscs." edible:NO]; 29 | [self createShrimpWithName:@"Anostraca" desc:@"One of the four orders of crustaceans in the class Branchiopoda." edible:NO]; 30 | [self createShrimpWithName:@"Notostraca" desc:@"The single family Triopsidae, containing the tadpole shrimp or shield shrimp." edible:NO]; 31 | [self createShrimpWithName:@"Lophogastrida" desc:@"An order of malacostracan crustaceans in the superorder Peracarida." edible:NO]; 32 | [self createShrimpWithName:@"Stomatopods" desc:@"Marine crustaceans, the members of the order Stomatopoda." edible:NO]; 33 | [self createShrimpWithName:@"Mysida" desc:@"An order of small, shrimp-like crustaceans in the malacostracan superorder Peracarida." edible:NO]; 34 | [self createShrimpWithName:@"Caprellidae" desc:@"A family of amphipods commonly known as skeleton shrimps." edible:NO]; 35 | [self createShrimpWithName:@"Ostracod" desc:@"A class of the Crustacea (class Ostracoda), sometimes known as seed shrimp." edible:NO]; 36 | 37 | [self saveContext]; 38 | } 39 | 40 | } 41 | return self; 42 | } 43 | 44 | -(NSString*)momdName 45 | { 46 | return @"Shrimp"; 47 | } 48 | 49 | -(NSString*)dbFilename 50 | { 51 | return @"Shrimp.sqlite"; 52 | } 53 | 54 | -(NSArray*)getShrimp 55 | { 56 | return [self getEntitiesWithName:@"Shrimp" satisfyingPredicate:nil]; 57 | } 58 | 59 | - (NSArray *)shrimpSortDescriptors 60 | { 61 | NSSortDescriptor *sortDescriptor0 = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; 62 | 63 | return [NSArray arrayWithObjects:sortDescriptor0, nil]; 64 | } 65 | 66 | - (GBYFetchedResultsController*)createShrimpFetchedResultsController 67 | { 68 | // Create the fetch request for the entity. 69 | NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 70 | NSEntityDescription *entity = [NSEntityDescription entityForName:@"Shrimp" inManagedObjectContext:self.managedObjectContext]; 71 | [fetchRequest setEntity:entity]; 72 | 73 | // Set the batch size to a suitable number. 74 | [fetchRequest setFetchBatchSize:20]; 75 | 76 | [fetchRequest setSortDescriptors:[self shrimpSortDescriptors]]; 77 | 78 | // Edit the section name key path and cache name if appropriate. 79 | // nil for section name key path means "no sections". 80 | GBYFetchedResultsController *aFetchedResultsController = [[GBYFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:nil]; 81 | 82 | return aFetchedResultsController; 83 | } 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /iOS/Shrimp/DetailViewController.h: -------------------------------------------------------------------------------- 1 | #import "GBYViewController.h" 2 | 3 | @interface DetailViewController : GBYViewController 4 | 5 | @property (weak, nonatomic) IBOutlet UITextField *nameTextField; 6 | @property (weak, nonatomic) IBOutlet UITextField *descriptionTextField; 7 | @property (weak, nonatomic) IBOutlet UISwitch *edibleSwitch; 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /iOS/Shrimp/DetailViewController.m: -------------------------------------------------------------------------------- 1 | #import "DetailViewController.h" 2 | 3 | #import "GBYTextField.h" 4 | #import "GBYSwitch.h" 5 | 6 | @interface DetailViewController () 7 | 8 | @end 9 | 10 | @implementation DetailViewController 11 | 12 | 13 | - (void)handleViewDidLoad { 14 | 15 | [[self getFunction:@"view-did-load!"] 16 | callWithArguments:@[self, 17 | [GBYTextField wrap:self.nameTextField], 18 | [GBYTextField wrap:self.descriptionTextField], 19 | [GBYSwitch wrap:self.edibleSwitch]]]; 20 | } 21 | 22 | - (NSString*)getNamespace 23 | { 24 | return @"shrimp.detail-view-controller"; 25 | } 26 | 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /iOS/Shrimp/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /iOS/Shrimp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.goby.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSBonjourServices 26 | 27 | _http._tcp 28 | 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | Main 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UISupportedInterfaceOrientations 38 | 39 | UIInterfaceOrientationPortrait 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /iOS/Shrimp/MasterViewController.h: -------------------------------------------------------------------------------- 1 | #import "GBYViewController.h" 2 | 3 | @interface MasterViewController : GBYViewController 4 | 5 | @property (weak, nonatomic) IBOutlet UITableView *tableView; 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /iOS/Shrimp/MasterViewController.m: -------------------------------------------------------------------------------- 1 | #import "MasterViewController.h" 2 | 3 | #import "GBYTableView.h" 4 | 5 | @interface MasterViewController () 6 | 7 | @end 8 | 9 | @implementation MasterViewController 10 | 11 | - (void)handleViewDidLoad { 12 | 13 | [[self getFunction:@"view-did-load!"] 14 | callWithArguments:@[self, 15 | [GBYTableView wrap:self.tableView]]]; 16 | } 17 | 18 | - (NSString*)getNamespace 19 | { 20 | return @"shrimp.master-view-controller"; 21 | } 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /iOS/Shrimp/Shrimp.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | @class Shrimp; 6 | 7 | @protocol Shrimp 8 | 9 | @property (nonatomic, retain) NSString * name; 10 | @property (nonatomic, retain) JSValue * edibleFlag; 11 | @property (nonatomic, retain) NSString *desc; 12 | 13 | @end 14 | 15 | 16 | @interface Shrimp : NSManagedObject 17 | 18 | @property (nonatomic, retain) NSNumber * edible; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /iOS/Shrimp/Shrimp.m: -------------------------------------------------------------------------------- 1 | #import "Shrimp.h" 2 | 3 | 4 | @implementation Shrimp 5 | 6 | @dynamic name; 7 | @dynamic edible; 8 | @dynamic desc; 9 | 10 | - (void)setEdibleFlag:(JSValue *)edibleFlag 11 | { 12 | self.edible = [edibleFlag toNumber]; 13 | } 14 | 15 | - (JSValue*)edibleFlag { 16 | return [JSValue valueWithBool:self.edible.boolValue inContext:[JSContext currentContext]]; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /iOS/Shrimp/Shrimp.xcdatamodeld/.xccurrentversion: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | _XCCurrentVersionName 6 | Shrimp.xcdatamodel 7 | 8 | 9 | -------------------------------------------------------------------------------- /iOS/Shrimp/Shrimp.xcdatamodeld/Shrimp.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /iOS/Shrimp/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import "AppDelegate.h" 3 | 4 | int main(int argc, char * argv[]) { 5 | @autoreleasepool { 6 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /iOS/ShrimpTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.goby.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /iOS/ShrimpTests/ShrimpTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface ShrimpTests : XCTestCase 5 | 6 | @end 7 | 8 | @implementation ShrimpTests 9 | 10 | - (void)setUp { 11 | [super setUp]; 12 | // Put setup code here. This method is called before the invocation of each test method in the class. 13 | } 14 | 15 | - (void)tearDown { 16 | // Put teardown code here. This method is called after the invocation of each test method in the class. 17 | [super tearDown]; 18 | } 19 | 20 | - (void)testExample { 21 | // This is an example of a functional test case. 22 | XCTAssert(YES, @"Pass"); 23 | } 24 | 25 | - (void)testPerformanceExample { 26 | // This is an example of a performance test case. 27 | [self measureBlock:^{ 28 | // Put the code you want to measure the time of here. 29 | }]; 30 | } 31 | 32 | @end 33 | --------------------------------------------------------------------------------