├── .gitignore ├── Conductor ├── conductor.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── jontelang.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── jontelang.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── conductor │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── icon-hat128.png │ │ ├── icon-hat128@2x.png │ │ ├── icon-hat16.png │ │ ├── icon-hat16@2x.png │ │ ├── icon-hat256.png │ │ ├── icon-hat256@2x.png │ │ ├── icon-hat32.png │ │ └── icon-hat32@2x.png │ ├── Base.lproj │ └── Main.storyboard │ ├── Info.plist │ ├── Preferences View │ ├── PreferencesViewController.h │ └── PreferencesViewController.m │ ├── Simuator List │ ├── Data Source │ │ ├── SimulatorDataSource.h │ │ └── SimulatorDataSource.m │ ├── Helpers │ │ ├── TestLogScanner.h │ │ └── TestLogScanner.m │ ├── Simulator.h │ ├── Simulator.m │ ├── SimulatorDelegate.h │ ├── SimulatorViewController.h │ └── SimulatorViewController.m │ ├── Test Viewer │ ├── ResultsViewController.h │ └── ResultsViewController.m │ ├── ViewController.h │ ├── ViewController.m │ ├── conductor.entitlements │ └── main.m ├── ConductorTestApp ├── ConductorTestApp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── jontelang.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── jontelang.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist ├── ConductorTestApp │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ └── icon-hat256.imageset │ │ │ ├── Contents.json │ │ │ └── icon-hat256@2x.png │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── MainViewController.h │ ├── MainViewController.m │ ├── TrainModels │ │ ├── TrainModelsViewController.h │ │ └── TrainModelsViewController.m │ └── main.m └── ConductorTestAppUITests │ ├── ConductorTestAppUITests.m │ └── Info.plist ├── Metadata ├── Conductor-App-Icon.sketch ├── gif.gif ├── overview.png ├── preferences.png └── readme-graphics.png └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /Conductor/conductor.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4DE88F661FF260740076D7B8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DE88F651FF260740076D7B8 /* AppDelegate.m */; }; 11 | 4DE88F691FF260740076D7B8 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DE88F681FF260740076D7B8 /* ViewController.m */; }; 12 | 4DE88F6B1FF260740076D7B8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4DE88F6A1FF260740076D7B8 /* Assets.xcassets */; }; 13 | 4DE88F6E1FF260740076D7B8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4DE88F6C1FF260740076D7B8 /* Main.storyboard */; }; 14 | 4DE88F711FF260740076D7B8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DE88F701FF260740076D7B8 /* main.m */; }; 15 | 4DE88F961FF267CC0076D7B8 /* PreferencesViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DE88F861FF267CC0076D7B8 /* PreferencesViewController.m */; }; 16 | 4DE88F971FF267CC0076D7B8 /* Simulator.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DE88F881FF267CC0076D7B8 /* Simulator.m */; }; 17 | 4DE88F981FF267CC0076D7B8 /* SimulatorDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DE88F8B1FF267CC0076D7B8 /* SimulatorDataSource.m */; }; 18 | 4DE88F991FF267CC0076D7B8 /* SimulatorViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DE88F8C1FF267CC0076D7B8 /* SimulatorViewController.m */; }; 19 | 4DE88F9A1FF267CC0076D7B8 /* TestLogScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DE88F911FF267CC0076D7B8 /* TestLogScanner.m */; }; 20 | 4DE88F9B1FF267CC0076D7B8 /* ResultsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DE88F951FF267CC0076D7B8 /* ResultsViewController.m */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 4DE88F611FF260740076D7B8 /* conductor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = conductor.app; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | 4DE88F641FF260740076D7B8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 26 | 4DE88F651FF260740076D7B8 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 27 | 4DE88F671FF260740076D7B8 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 28 | 4DE88F681FF260740076D7B8 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 29 | 4DE88F6A1FF260740076D7B8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 30 | 4DE88F6D1FF260740076D7B8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 31 | 4DE88F6F1FF260740076D7B8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 32 | 4DE88F701FF260740076D7B8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 33 | 4DE88F721FF260740076D7B8 /* conductor.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = conductor.entitlements; sourceTree = ""; }; 34 | 4DE88F851FF267CC0076D7B8 /* PreferencesViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PreferencesViewController.h; sourceTree = ""; }; 35 | 4DE88F861FF267CC0076D7B8 /* PreferencesViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PreferencesViewController.m; sourceTree = ""; }; 36 | 4DE88F881FF267CC0076D7B8 /* Simulator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Simulator.m; sourceTree = ""; }; 37 | 4DE88F8A1FF267CC0076D7B8 /* SimulatorDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimulatorDataSource.h; sourceTree = ""; }; 38 | 4DE88F8B1FF267CC0076D7B8 /* SimulatorDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimulatorDataSource.m; sourceTree = ""; }; 39 | 4DE88F8C1FF267CC0076D7B8 /* SimulatorViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimulatorViewController.m; sourceTree = ""; }; 40 | 4DE88F8D1FF267CC0076D7B8 /* Simulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Simulator.h; sourceTree = ""; }; 41 | 4DE88F8E1FF267CC0076D7B8 /* SimulatorViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimulatorViewController.h; sourceTree = ""; }; 42 | 4DE88F901FF267CC0076D7B8 /* TestLogScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestLogScanner.h; sourceTree = ""; }; 43 | 4DE88F911FF267CC0076D7B8 /* TestLogScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestLogScanner.m; sourceTree = ""; }; 44 | 4DE88F921FF267CC0076D7B8 /* SimulatorDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimulatorDelegate.h; sourceTree = ""; }; 45 | 4DE88F941FF267CC0076D7B8 /* ResultsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResultsViewController.h; sourceTree = ""; }; 46 | 4DE88F951FF267CC0076D7B8 /* ResultsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ResultsViewController.m; sourceTree = ""; }; 47 | /* End PBXFileReference section */ 48 | 49 | /* Begin PBXFrameworksBuildPhase section */ 50 | 4DE88F5E1FF260740076D7B8 /* Frameworks */ = { 51 | isa = PBXFrameworksBuildPhase; 52 | buildActionMask = 2147483647; 53 | files = ( 54 | ); 55 | runOnlyForDeploymentPostprocessing = 0; 56 | }; 57 | /* End PBXFrameworksBuildPhase section */ 58 | 59 | /* Begin PBXGroup section */ 60 | 4DE88F581FF260740076D7B8 = { 61 | isa = PBXGroup; 62 | children = ( 63 | 4DE88F631FF260740076D7B8 /* conductor */, 64 | 4DE88F621FF260740076D7B8 /* Products */, 65 | ); 66 | sourceTree = ""; 67 | }; 68 | 4DE88F621FF260740076D7B8 /* Products */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 4DE88F611FF260740076D7B8 /* conductor.app */, 72 | ); 73 | name = Products; 74 | sourceTree = ""; 75 | }; 76 | 4DE88F631FF260740076D7B8 /* conductor */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 4DE88F841FF267CC0076D7B8 /* Preferences View */, 80 | 4DE88F871FF267CC0076D7B8 /* Simuator List */, 81 | 4DE88F801FF267CC0076D7B8 /* Test Results Viewer */, 82 | 4DE88F931FF267CC0076D7B8 /* Test Viewer */, 83 | 4DE88F641FF260740076D7B8 /* AppDelegate.h */, 84 | 4DE88F651FF260740076D7B8 /* AppDelegate.m */, 85 | 4DE88F671FF260740076D7B8 /* ViewController.h */, 86 | 4DE88F681FF260740076D7B8 /* ViewController.m */, 87 | 4DE88F6A1FF260740076D7B8 /* Assets.xcassets */, 88 | 4DE88F6C1FF260740076D7B8 /* Main.storyboard */, 89 | 4DE88F6F1FF260740076D7B8 /* Info.plist */, 90 | 4DE88F701FF260740076D7B8 /* main.m */, 91 | 4DE88F721FF260740076D7B8 /* conductor.entitlements */, 92 | ); 93 | path = conductor; 94 | sourceTree = ""; 95 | }; 96 | 4DE88F801FF267CC0076D7B8 /* Test Results Viewer */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | 4DE88F811FF267CC0076D7B8 /* Dragging */, 100 | 4DE88F821FF267CC0076D7B8 /* Model */, 101 | 4DE88F831FF267CC0076D7B8 /* Helpers */, 102 | ); 103 | path = "Test Results Viewer"; 104 | sourceTree = ""; 105 | }; 106 | 4DE88F811FF267CC0076D7B8 /* Dragging */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | ); 110 | path = Dragging; 111 | sourceTree = ""; 112 | }; 113 | 4DE88F821FF267CC0076D7B8 /* Model */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | ); 117 | path = Model; 118 | sourceTree = ""; 119 | }; 120 | 4DE88F831FF267CC0076D7B8 /* Helpers */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | ); 124 | path = Helpers; 125 | sourceTree = ""; 126 | }; 127 | 4DE88F841FF267CC0076D7B8 /* Preferences View */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 4DE88F851FF267CC0076D7B8 /* PreferencesViewController.h */, 131 | 4DE88F861FF267CC0076D7B8 /* PreferencesViewController.m */, 132 | ); 133 | path = "Preferences View"; 134 | sourceTree = ""; 135 | }; 136 | 4DE88F871FF267CC0076D7B8 /* Simuator List */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 4DE88F881FF267CC0076D7B8 /* Simulator.m */, 140 | 4DE88F891FF267CC0076D7B8 /* Data Source */, 141 | 4DE88F8C1FF267CC0076D7B8 /* SimulatorViewController.m */, 142 | 4DE88F8D1FF267CC0076D7B8 /* Simulator.h */, 143 | 4DE88F8E1FF267CC0076D7B8 /* SimulatorViewController.h */, 144 | 4DE88F8F1FF267CC0076D7B8 /* Helpers */, 145 | 4DE88F921FF267CC0076D7B8 /* SimulatorDelegate.h */, 146 | ); 147 | path = "Simuator List"; 148 | sourceTree = ""; 149 | }; 150 | 4DE88F891FF267CC0076D7B8 /* Data Source */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | 4DE88F8A1FF267CC0076D7B8 /* SimulatorDataSource.h */, 154 | 4DE88F8B1FF267CC0076D7B8 /* SimulatorDataSource.m */, 155 | ); 156 | path = "Data Source"; 157 | sourceTree = ""; 158 | }; 159 | 4DE88F8F1FF267CC0076D7B8 /* Helpers */ = { 160 | isa = PBXGroup; 161 | children = ( 162 | 4DE88F901FF267CC0076D7B8 /* TestLogScanner.h */, 163 | 4DE88F911FF267CC0076D7B8 /* TestLogScanner.m */, 164 | ); 165 | path = Helpers; 166 | sourceTree = ""; 167 | }; 168 | 4DE88F931FF267CC0076D7B8 /* Test Viewer */ = { 169 | isa = PBXGroup; 170 | children = ( 171 | 4DE88F941FF267CC0076D7B8 /* ResultsViewController.h */, 172 | 4DE88F951FF267CC0076D7B8 /* ResultsViewController.m */, 173 | ); 174 | path = "Test Viewer"; 175 | sourceTree = ""; 176 | }; 177 | /* End PBXGroup section */ 178 | 179 | /* Begin PBXNativeTarget section */ 180 | 4DE88F601FF260740076D7B8 /* conductor */ = { 181 | isa = PBXNativeTarget; 182 | buildConfigurationList = 4DE88F751FF260740076D7B8 /* Build configuration list for PBXNativeTarget "conductor" */; 183 | buildPhases = ( 184 | 4DE88F5D1FF260740076D7B8 /* Sources */, 185 | 4DE88F5E1FF260740076D7B8 /* Frameworks */, 186 | 4DE88F5F1FF260740076D7B8 /* Resources */, 187 | ); 188 | buildRules = ( 189 | ); 190 | dependencies = ( 191 | ); 192 | name = conductor; 193 | productName = conductor; 194 | productReference = 4DE88F611FF260740076D7B8 /* conductor.app */; 195 | productType = "com.apple.product-type.application"; 196 | }; 197 | /* End PBXNativeTarget section */ 198 | 199 | /* Begin PBXProject section */ 200 | 4DE88F591FF260740076D7B8 /* Project object */ = { 201 | isa = PBXProject; 202 | attributes = { 203 | LastUpgradeCheck = 0920; 204 | ORGANIZATIONNAME = "Jonathan Winger Lang"; 205 | TargetAttributes = { 206 | 4DE88F601FF260740076D7B8 = { 207 | CreatedOnToolsVersion = 9.2; 208 | ProvisioningStyle = Automatic; 209 | }; 210 | }; 211 | }; 212 | buildConfigurationList = 4DE88F5C1FF260740076D7B8 /* Build configuration list for PBXProject "conductor" */; 213 | compatibilityVersion = "Xcode 8.0"; 214 | developmentRegion = en; 215 | hasScannedForEncodings = 0; 216 | knownRegions = ( 217 | en, 218 | Base, 219 | ); 220 | mainGroup = 4DE88F581FF260740076D7B8; 221 | productRefGroup = 4DE88F621FF260740076D7B8 /* Products */; 222 | projectDirPath = ""; 223 | projectRoot = ""; 224 | targets = ( 225 | 4DE88F601FF260740076D7B8 /* conductor */, 226 | ); 227 | }; 228 | /* End PBXProject section */ 229 | 230 | /* Begin PBXResourcesBuildPhase section */ 231 | 4DE88F5F1FF260740076D7B8 /* Resources */ = { 232 | isa = PBXResourcesBuildPhase; 233 | buildActionMask = 2147483647; 234 | files = ( 235 | 4DE88F6B1FF260740076D7B8 /* Assets.xcassets in Resources */, 236 | 4DE88F6E1FF260740076D7B8 /* Main.storyboard in Resources */, 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | }; 240 | /* End PBXResourcesBuildPhase section */ 241 | 242 | /* Begin PBXSourcesBuildPhase section */ 243 | 4DE88F5D1FF260740076D7B8 /* Sources */ = { 244 | isa = PBXSourcesBuildPhase; 245 | buildActionMask = 2147483647; 246 | files = ( 247 | 4DE88F691FF260740076D7B8 /* ViewController.m in Sources */, 248 | 4DE88F971FF267CC0076D7B8 /* Simulator.m in Sources */, 249 | 4DE88F711FF260740076D7B8 /* main.m in Sources */, 250 | 4DE88F661FF260740076D7B8 /* AppDelegate.m in Sources */, 251 | 4DE88F961FF267CC0076D7B8 /* PreferencesViewController.m in Sources */, 252 | 4DE88F991FF267CC0076D7B8 /* SimulatorViewController.m in Sources */, 253 | 4DE88F9B1FF267CC0076D7B8 /* ResultsViewController.m in Sources */, 254 | 4DE88F981FF267CC0076D7B8 /* SimulatorDataSource.m in Sources */, 255 | 4DE88F9A1FF267CC0076D7B8 /* TestLogScanner.m in Sources */, 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | }; 259 | /* End PBXSourcesBuildPhase section */ 260 | 261 | /* Begin PBXVariantGroup section */ 262 | 4DE88F6C1FF260740076D7B8 /* Main.storyboard */ = { 263 | isa = PBXVariantGroup; 264 | children = ( 265 | 4DE88F6D1FF260740076D7B8 /* Base */, 266 | ); 267 | name = Main.storyboard; 268 | sourceTree = ""; 269 | }; 270 | /* End PBXVariantGroup section */ 271 | 272 | /* Begin XCBuildConfiguration section */ 273 | 4DE88F731FF260740076D7B8 /* Debug */ = { 274 | isa = XCBuildConfiguration; 275 | buildSettings = { 276 | ALWAYS_SEARCH_USER_PATHS = NO; 277 | CLANG_ANALYZER_NONNULL = YES; 278 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 279 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 280 | CLANG_CXX_LIBRARY = "libc++"; 281 | CLANG_ENABLE_MODULES = YES; 282 | CLANG_ENABLE_OBJC_ARC = YES; 283 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 284 | CLANG_WARN_BOOL_CONVERSION = YES; 285 | CLANG_WARN_COMMA = YES; 286 | CLANG_WARN_CONSTANT_CONVERSION = YES; 287 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 288 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 289 | CLANG_WARN_EMPTY_BODY = YES; 290 | CLANG_WARN_ENUM_CONVERSION = YES; 291 | CLANG_WARN_INFINITE_RECURSION = YES; 292 | CLANG_WARN_INT_CONVERSION = YES; 293 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 294 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 295 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 296 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 297 | CLANG_WARN_STRICT_PROTOTYPES = YES; 298 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 299 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 300 | CLANG_WARN_UNREACHABLE_CODE = YES; 301 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 302 | CODE_SIGN_IDENTITY = "-"; 303 | COPY_PHASE_STRIP = NO; 304 | DEBUG_INFORMATION_FORMAT = dwarf; 305 | ENABLE_STRICT_OBJC_MSGSEND = YES; 306 | ENABLE_TESTABILITY = YES; 307 | GCC_C_LANGUAGE_STANDARD = gnu11; 308 | GCC_DYNAMIC_NO_PIC = NO; 309 | GCC_NO_COMMON_BLOCKS = YES; 310 | GCC_OPTIMIZATION_LEVEL = 0; 311 | GCC_PREPROCESSOR_DEFINITIONS = ( 312 | "DEBUG=1", 313 | "$(inherited)", 314 | ); 315 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 316 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 317 | GCC_WARN_UNDECLARED_SELECTOR = YES; 318 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 319 | GCC_WARN_UNUSED_FUNCTION = YES; 320 | GCC_WARN_UNUSED_VARIABLE = YES; 321 | MACOSX_DEPLOYMENT_TARGET = 10.13; 322 | MTL_ENABLE_DEBUG_INFO = YES; 323 | ONLY_ACTIVE_ARCH = YES; 324 | SDKROOT = macosx; 325 | }; 326 | name = Debug; 327 | }; 328 | 4DE88F741FF260740076D7B8 /* Release */ = { 329 | isa = XCBuildConfiguration; 330 | buildSettings = { 331 | ALWAYS_SEARCH_USER_PATHS = NO; 332 | CLANG_ANALYZER_NONNULL = YES; 333 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 334 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 335 | CLANG_CXX_LIBRARY = "libc++"; 336 | CLANG_ENABLE_MODULES = YES; 337 | CLANG_ENABLE_OBJC_ARC = YES; 338 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 339 | CLANG_WARN_BOOL_CONVERSION = YES; 340 | CLANG_WARN_COMMA = YES; 341 | CLANG_WARN_CONSTANT_CONVERSION = YES; 342 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 343 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 344 | CLANG_WARN_EMPTY_BODY = YES; 345 | CLANG_WARN_ENUM_CONVERSION = YES; 346 | CLANG_WARN_INFINITE_RECURSION = YES; 347 | CLANG_WARN_INT_CONVERSION = YES; 348 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 349 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 350 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 351 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 352 | CLANG_WARN_STRICT_PROTOTYPES = YES; 353 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 354 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 355 | CLANG_WARN_UNREACHABLE_CODE = YES; 356 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 357 | CODE_SIGN_IDENTITY = "-"; 358 | COPY_PHASE_STRIP = NO; 359 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 360 | ENABLE_NS_ASSERTIONS = NO; 361 | ENABLE_STRICT_OBJC_MSGSEND = YES; 362 | GCC_C_LANGUAGE_STANDARD = gnu11; 363 | GCC_NO_COMMON_BLOCKS = YES; 364 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 365 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 366 | GCC_WARN_UNDECLARED_SELECTOR = YES; 367 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 368 | GCC_WARN_UNUSED_FUNCTION = YES; 369 | GCC_WARN_UNUSED_VARIABLE = YES; 370 | MACOSX_DEPLOYMENT_TARGET = 10.13; 371 | MTL_ENABLE_DEBUG_INFO = NO; 372 | SDKROOT = macosx; 373 | }; 374 | name = Release; 375 | }; 376 | 4DE88F761FF260740076D7B8 /* Debug */ = { 377 | isa = XCBuildConfiguration; 378 | buildSettings = { 379 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 380 | CODE_SIGN_ENTITLEMENTS = conductor/conductor.entitlements; 381 | CODE_SIGN_IDENTITY = "Mac Developer"; 382 | CODE_SIGN_STYLE = Automatic; 383 | COMBINE_HIDPI_IMAGES = YES; 384 | DEVELOPMENT_TEAM = 4V3J44VR2U; 385 | INFOPLIST_FILE = conductor/Info.plist; 386 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 387 | PRODUCT_BUNDLE_IDENTIFIER = com.jontelang.conductor; 388 | PRODUCT_NAME = "$(TARGET_NAME)"; 389 | PROVISIONING_PROFILE_SPECIFIER = ""; 390 | }; 391 | name = Debug; 392 | }; 393 | 4DE88F771FF260740076D7B8 /* Release */ = { 394 | isa = XCBuildConfiguration; 395 | buildSettings = { 396 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 397 | CODE_SIGN_ENTITLEMENTS = conductor/conductor.entitlements; 398 | CODE_SIGN_IDENTITY = "Mac Developer"; 399 | CODE_SIGN_STYLE = Automatic; 400 | COMBINE_HIDPI_IMAGES = YES; 401 | DEVELOPMENT_TEAM = 4V3J44VR2U; 402 | INFOPLIST_FILE = conductor/Info.plist; 403 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 404 | PRODUCT_BUNDLE_IDENTIFIER = com.jontelang.conductor; 405 | PRODUCT_NAME = "$(TARGET_NAME)"; 406 | PROVISIONING_PROFILE_SPECIFIER = ""; 407 | }; 408 | name = Release; 409 | }; 410 | /* End XCBuildConfiguration section */ 411 | 412 | /* Begin XCConfigurationList section */ 413 | 4DE88F5C1FF260740076D7B8 /* Build configuration list for PBXProject "conductor" */ = { 414 | isa = XCConfigurationList; 415 | buildConfigurations = ( 416 | 4DE88F731FF260740076D7B8 /* Debug */, 417 | 4DE88F741FF260740076D7B8 /* Release */, 418 | ); 419 | defaultConfigurationIsVisible = 0; 420 | defaultConfigurationName = Release; 421 | }; 422 | 4DE88F751FF260740076D7B8 /* Build configuration list for PBXNativeTarget "conductor" */ = { 423 | isa = XCConfigurationList; 424 | buildConfigurations = ( 425 | 4DE88F761FF260740076D7B8 /* Debug */, 426 | 4DE88F771FF260740076D7B8 /* Release */, 427 | ); 428 | defaultConfigurationIsVisible = 0; 429 | defaultConfigurationName = Release; 430 | }; 431 | /* End XCConfigurationList section */ 432 | }; 433 | rootObject = 4DE88F591FF260740076D7B8 /* Project object */; 434 | } 435 | -------------------------------------------------------------------------------- /Conductor/conductor.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Conductor/conductor.xcodeproj/project.xcworkspace/xcuserdata/jontelang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Conductor/conductor.xcodeproj/project.xcworkspace/xcuserdata/jontelang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Conductor/conductor.xcodeproj/xcuserdata/jontelang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | conductor.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Conductor/conductor/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // conductor 4 | // 5 | // Created by Jonathan on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Conductor/conductor/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // conductor 4 | // 5 | // Created by Jonathan on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 18 | // Insert code here to initialize your application 19 | } 20 | 21 | 22 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 23 | // Insert code here to tear down your application 24 | } 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Conductor/conductor/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "icon-hat16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "icon-hat16@2x.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "icon-hat32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "icon-hat32@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "icon-hat128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "icon-hat128@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "icon-hat256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "icon-hat256@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "idiom" : "mac", 53 | "size" : "512x512", 54 | "scale" : "1x" 55 | }, 56 | { 57 | "idiom" : "mac", 58 | "size" : "512x512", 59 | "scale" : "2x" 60 | } 61 | ], 62 | "info" : { 63 | "version" : 1, 64 | "author" : "xcode" 65 | } 66 | } -------------------------------------------------------------------------------- /Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat128.png -------------------------------------------------------------------------------- /Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat128@2x.png -------------------------------------------------------------------------------- /Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat16.png -------------------------------------------------------------------------------- /Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat16@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat16@2x.png -------------------------------------------------------------------------------- /Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat256.png -------------------------------------------------------------------------------- /Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat256@2x.png -------------------------------------------------------------------------------- /Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat32.png -------------------------------------------------------------------------------- /Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat32@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Conductor/conductor/Assets.xcassets/AppIcon.appiconset/icon-hat32@2x.png -------------------------------------------------------------------------------- /Conductor/conductor/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 | 45 | 46 | 47 | 48 | 49 | 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 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 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 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 392 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 539 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 580 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | -------------------------------------------------------------------------------- /Conductor/conductor/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSApplicationCategoryType 24 | public.app-category.developer-tools 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSHumanReadableCopyright 28 | Copyright © 2017 Jonathan Winger Lang. All rights reserved. 29 | NSMainStoryboardFile 30 | Main 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Conductor/conductor/Preferences View/PreferencesViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PreferencesViewController.h 3 | // Conductor 4 | // 5 | // Created by Jonathan Winger Lang on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface PreferencesViewController : NSViewController { 12 | __weak IBOutlet NSTextField *xcodeProhectFilePathTextField; 13 | __weak IBOutlet NSTextField *xcodeSchemeNameTextField; 14 | __weak IBOutlet NSTextField *xcodeUITestNameTextField; 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Conductor/conductor/Preferences View/PreferencesViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PreferencesViewController.m 3 | // Conductor 4 | // 5 | // Created by Jonathan Winger Lang on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import "PreferencesViewController.h" 10 | 11 | @implementation PreferencesViewController 12 | 13 | - (void)viewDidLoad { 14 | [super viewDidLoad]; 15 | 16 | NSString *projectPath = [[NSUserDefaults standardUserDefaults] valueForKey:@"project_path"]; 17 | if( projectPath ){ 18 | xcodeProhectFilePathTextField.stringValue = projectPath; 19 | } 20 | 21 | NSString *schemeName = [[NSUserDefaults standardUserDefaults] valueForKey:@"project_scheme_name"]; 22 | if( schemeName ){ 23 | xcodeSchemeNameTextField.stringValue = schemeName; 24 | } 25 | 26 | NSString *testName = [[NSUserDefaults standardUserDefaults] valueForKey:@"project_test_name"]; 27 | if( testName ){ 28 | xcodeUITestNameTextField.stringValue = testName; 29 | } 30 | } 31 | 32 | - (IBAction)savePressed:(id)sender { 33 | [[NSUserDefaults standardUserDefaults] setValue:xcodeProhectFilePathTextField.stringValue 34 | forKey:@"project_path"]; 35 | 36 | [[NSUserDefaults standardUserDefaults] setValue:xcodeSchemeNameTextField.stringValue 37 | forKey:@"project_scheme_name"]; 38 | 39 | [[NSUserDefaults standardUserDefaults] setValue:xcodeUITestNameTextField.stringValue 40 | forKey:@"project_test_name"]; 41 | 42 | [[NSUserDefaults standardUserDefaults] synchronize]; 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Conductor/conductor/Simuator List/Data Source/SimulatorDataSource.h: -------------------------------------------------------------------------------- 1 | // 2 | // SimulatorDataSource.h 3 | // Conductor 4 | // 5 | // Created by Jonathan Winger Lang on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // TODO: Make another name? 12 | @interface SimulatorDataSource : NSObject 13 | 14 | +(NSArray*)retrieveSimulatorsFromSystem; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Conductor/conductor/Simuator List/Data Source/SimulatorDataSource.m: -------------------------------------------------------------------------------- 1 | // 2 | // SimulatorDataSource.m 3 | // Conductor 4 | // 5 | // Created by Jonathan Winger Lang on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import "SimulatorDataSource.h" 10 | #import "Simulator.h" 11 | 12 | @implementation SimulatorDataSource 13 | 14 | +(NSArray*)retrieveSimulatorsFromSystem{ 15 | //int pid = [[NSProcessInfo processInfo] processIdentifier]; 16 | NSPipe *pipe = [NSPipe pipe]; 17 | NSFileHandle *file = pipe.fileHandleForReading; 18 | 19 | NSTask *task = [[NSTask alloc] init]; 20 | task.launchPath = @"/usr/bin/instruments"; 21 | task.arguments = @[@"-s",@"devices"]; 22 | task.standardOutput = pipe; 23 | task.standardError = pipe; 24 | 25 | [task launch]; 26 | 27 | NSData *data = [file readDataToEndOfFile]; 28 | [file closeFile]; 29 | 30 | //[task waitUntilExit]; 31 | 32 | NSString *output = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 33 | 34 | NSMutableArray *simulators = [[NSMutableArray alloc] init]; 35 | 36 | for (NSString *line in [output componentsSeparatedByString:@"\n"]) { 37 | Simulator *simulator = [Simulator simulatorFromString:line]; 38 | if( [simulator.simulatorName containsString:@"Watch"] ){ 39 | // Skip 40 | }else{ 41 | if( simulator ){ 42 | [simulators addObject:simulator]; 43 | } 44 | } 45 | } 46 | 47 | return simulators; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Conductor/conductor/Simuator List/Helpers/TestLogScanner.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestLogScanner.h 3 | // Conductor 4 | // 5 | // Created by Jonathan Winger Lang on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TestLogScanner : NSObject 12 | 13 | /// Method to scan a log for common error issues 14 | +(NSString*)statusForLog:(NSString*)log; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Conductor/conductor/Simuator List/Helpers/TestLogScanner.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestLogScanner.m 3 | // Conductor 4 | // 5 | // Created by Jonathan Winger Lang on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import "TestLogScanner.h" 10 | 11 | @implementation TestLogScanner 12 | 13 | +(NSString*)statusForLog:(NSString*)log{ 14 | // 15 | // Fail 16 | // 17 | NSRegularExpression *failRegex = [NSRegularExpression regularExpressionWithPattern:@"Test Suite \'.+\' failed" 18 | options:0 19 | error:nil]; 20 | if( [failRegex firstMatchInString:log options:0 range:NSMakeRange(0, log.length)] ){ 21 | return @"Test Suite Failed"; 22 | } 23 | 24 | // 25 | // Pass 26 | // 27 | NSRegularExpression *passRegex = [NSRegularExpression regularExpressionWithPattern:@"Test Suite \'.+\' passed" 28 | options:0 29 | error:nil]; 30 | if( [passRegex firstMatchInString:log options:0 range:NSMakeRange(0, log.length)] ){ 31 | return @"Test Suite Passed"; 32 | } 33 | 34 | // 35 | // UI Testing Not Supported 36 | // 37 | if( [log containsString:@"UI Testing is not supported on"] ){ 38 | return @"UI Testing Not Supported"; 39 | } 40 | 41 | // 42 | // Architecture Unsupported 43 | // 44 | if( [log containsString:@"Try installing a universal version"] ){ 45 | return @"Architecture Unsupported"; 46 | } 47 | 48 | // 49 | // Build Failure 50 | // 51 | if( [log containsString:@"The following build commands failed"] ){ 52 | return @"Build Failure"; 53 | } 54 | 55 | return @"Unknown Status"; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Conductor/conductor/Simuator List/Simulator.h: -------------------------------------------------------------------------------- 1 | // 2 | // Simulator.h 3 | // Conductor 4 | // 5 | // Created by Jonathan Winger Lang on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import // Sim output target 11 | #import "SimulatorDelegate.h" 12 | 13 | @interface Simulator : NSObject { 14 | // Task to be able to terminate it 15 | NSTask *task; 16 | } 17 | 18 | /// Helper that takes strings and spits out objects 19 | +(Simulator*)simulatorFromString:(NSString*)string; 20 | 21 | // Properties 22 | @property NSString *simulatorIdentifier; 23 | @property NSString *simulatorName; 24 | @property NSString *simulatorOS; 25 | 26 | // Kinda-properties 27 | @property (readonly) NSString *simulatorFullName; 28 | 29 | /// Nicely formatted information for display 30 | -(NSString*)prettyDescription; 31 | 32 | // Testing related 33 | 34 | /// Startes xcodebuild 35 | -(void)startTestingPath:(NSString*)path scheme:(NSString*)scheme test:(NSString*)test; 36 | 37 | /// Terminates the NSTask 38 | -(void)terminate; 39 | 40 | @property NSString *simulatorStatus; 41 | @property NSMutableString *simulatorOutput; 42 | @property (weak) id delegate; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Conductor/conductor/Simuator List/Simulator.m: -------------------------------------------------------------------------------- 1 | // 2 | // Simulator.m 3 | // Conductor 4 | // 5 | // Created by Jonathan Winger Lang on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import "Simulator.h" 10 | #import "TestLogScanner.h" 11 | 12 | @implementation Simulator 13 | 14 | +(Simulator*)simulatorFromString:(NSString*)string{ 15 | NSLog(@"line: %@", string); 16 | NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(iPhone.+)\\ \\((.+)\\)\\ \\[(.+)\\]" options:0 error:nil]; 17 | NSArray *matches = [regex matchesInString:string options:0 range:NSMakeRange(0, string.length)]; 18 | for (NSTextCheckingResult *match in matches){ 19 | for (int i = 0; i < match.numberOfRanges; i++) { 20 | NSLog(@"match %i: %@", i, [string substringWithRange:[match rangeAtIndex:i]]); 21 | } 22 | Simulator *simulator = [[Simulator alloc] init]; 23 | simulator.simulatorName = [string substringWithRange:[match rangeAtIndex:1]]; 24 | simulator.simulatorOS = [string substringWithRange:[match rangeAtIndex:2]]; 25 | simulator.simulatorIdentifier = [string substringWithRange:[match rangeAtIndex:3]]; 26 | simulator.simulatorStatus = @""; 27 | return simulator; 28 | } 29 | 30 | // Pls crash 31 | return nil; 32 | } 33 | 34 | -(NSString *)simulatorFullName{ 35 | return [NSString stringWithFormat:@"%@ (%@)", self.simulatorName, self.simulatorOS]; 36 | } 37 | 38 | -(NSString*)prettyDescription{ 39 | return [NSString stringWithFormat:@"Name: %@\nOS: %@\nID: %@", 40 | self.simulatorName, 41 | self.simulatorOS, 42 | self.simulatorIdentifier]; 43 | } 44 | 45 | -(void)startTestingPath:(NSString*)path scheme:(NSString*)scheme test:(NSString*)test{ 46 | // TODO: Make nicer? 47 | if( [task isRunning] ){ 48 | [self terminate]; 49 | } 50 | else{ 51 | _simulatorStatus = @"Testing"; 52 | 53 | 54 | //int pid = [[NSProcessInfo processInfo] processIdentifier]; 55 | NSPipe *pipe = [NSPipe pipe]; 56 | NSFileHandle *file = pipe.fileHandleForReading; 57 | 58 | [task terminate]; 59 | task = nil; 60 | task = [[NSTask alloc] init]; 61 | task.launchPath = @"/usr/bin/xcodebuild"; 62 | task.arguments = 63 | @[[path containsString:@".xcworkspace"] ? @"-workspace" : @"-project", 64 | [path stringByExpandingTildeInPath], // In case user wrote ~/Work/etc 65 | @"-scheme", 66 | scheme, 67 | @"-sdk", 68 | @"iphonesimulator", 69 | @"-destination", [NSString stringWithFormat:@"platform=iOS Simulator,OS=%@,id=%@", self.simulatorOS, self.simulatorIdentifier], 70 | [NSString stringWithFormat:@"-only-testing:%@", test], 71 | @"test"]; 72 | 73 | 74 | task.standardOutput = pipe; 75 | task.standardError = pipe; 76 | 77 | [task launch]; 78 | 79 | self.simulatorOutput = [[NSMutableString alloc] init]; 80 | 81 | file.readabilityHandler = ^(NSFileHandle * _Nonnull fileHandle) { 82 | NSData *data = [fileHandle availableData]; 83 | NSString *text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 84 | // NSLog(@"read: %@", text); 85 | 86 | dispatch_async(dispatch_get_main_queue(), ^{ 87 | [self.simulatorOutput appendString:text]; 88 | 89 | if( [self.delegate respondsToSelector:@selector(simulator:didReceiveOutput:)] ){ 90 | [self.delegate simulator:self didReceiveOutput:self.simulatorOutput]; 91 | } 92 | }); 93 | }; 94 | 95 | task.terminationHandler = ^(NSTask * _Nonnull task__) { 96 | _simulatorStatus = [TestLogScanner statusForLog:self.simulatorOutput]; 97 | 98 | dispatch_async(dispatch_get_main_queue(), ^{ 99 | // Notify if delegate is set only 100 | // TODO: Use a weakself thingy 101 | if( [self.delegate respondsToSelector:@selector(simulator:didFinishTesting:)] ){ 102 | [self.delegate simulator:self didFinishTesting:@"yay"]; 103 | } 104 | }); 105 | 106 | // It kept kicking off readabilityHandler blocks.. 107 | [file closeFile]; 108 | }; 109 | } 110 | } 111 | 112 | -(void)terminate{ 113 | [task terminate]; 114 | _simulatorStatus = @"Process Terminated"; 115 | 116 | dispatch_async(dispatch_get_main_queue(), ^{ 117 | // Notify if delegate is set only 118 | if( [self.delegate respondsToSelector:@selector(simulator:didFinishTesting:)] ){ 119 | [self.delegate simulator:self didFinishTesting:@"yay"]; 120 | } 121 | }); 122 | } 123 | 124 | -(NSString*)simulatorOutput{ 125 | if( _simulatorOutput == nil ){ 126 | return @""; 127 | } 128 | else{ 129 | return _simulatorOutput; 130 | } 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /Conductor/conductor/Simuator List/SimulatorDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SimulatorDelegate.h 3 | // Conductor 4 | // 5 | // Created by Jonathan Winger Lang on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class Simulator; 12 | 13 | @protocol SimulatorDelegate 14 | 15 | @required 16 | 17 | -(void)simulator:(Simulator*)simulator didFinishTesting:(NSString*)result; 18 | 19 | -(void)simulator:(Simulator*)simulator didReceiveOutput:(NSString*)output; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Conductor/conductor/Simuator List/SimulatorViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SimulatorViewController.h 3 | // Conductor 4 | // 5 | // Created by Jonathan Winger Lang on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SimulatorDelegate.h" 11 | 12 | @class Simulator; 13 | 14 | @interface SimulatorViewController : NSViewController 15 | { 18 | 19 | // Needed to reload manually 20 | __weak IBOutlet NSTableView *simulatorTableView; 21 | 22 | // Current sim selected 23 | Simulator *currentlySelectedSimulator; 24 | 25 | __weak IBOutlet NSTextField *currentSimulatorTextField; 26 | 27 | __unsafe_unretained IBOutlet NSTextView *textView; 28 | 29 | NSArray *simulators; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Conductor/conductor/Simuator List/SimulatorViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SimulatorViewController.m 3 | // Conductor 4 | // 5 | // Created by Jonathan Winger Lang on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import "SimulatorViewController.h" 10 | #import "Simulator.h" 11 | #import "SimulatorDataSource.h" 12 | 13 | // For the openability 14 | #import "ResultsViewController.h" 15 | 16 | @implementation SimulatorViewController 17 | 18 | - (void)viewDidLoad { 19 | [super viewDidLoad]; 20 | 21 | simulators = [SimulatorDataSource retrieveSimulatorsFromSystem]; 22 | 23 | // Since the simulators are created in another area, i need to set their 24 | // delegates to the current viewcontroller manually. 25 | [simulators makeObjectsPerformSelector:@selector(setDelegate:) withObject:self]; 26 | 27 | [simulatorTableView reloadData]; 28 | 29 | // No delegate method for this so.. 30 | [simulatorTableView setDoubleAction:@selector(doubleTappedRow)]; 31 | } 32 | 33 | 34 | // Delegate 35 | 36 | -(NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{ 37 | Simulator *simulator = simulators[row]; 38 | 39 | NSTableCellView *v = [tableView makeViewWithIdentifier:@"cell_text" owner:self]; 40 | v.textField.textColor = [NSColor textColor]; 41 | 42 | if( [tableColumn.identifier isEqualToString:@"column_simulator"] ){ 43 | v.textField.stringValue = simulator.simulatorFullName; 44 | } 45 | else if( [tableColumn.identifier isEqualToString:@"column_status"] ){ 46 | if( [simulator.simulatorStatus isEqualToString:@"Testing"] ){ 47 | v = [tableView makeViewWithIdentifier:@"cell_spinner" owner:self]; 48 | [((NSProgressIndicator*)v.subviews[0]) startAnimation:nil]; 49 | } 50 | else{ 51 | v.textField.stringValue = simulator.simulatorStatus; 52 | } 53 | } 54 | return v; 55 | } 56 | 57 | -(BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row{ 58 | // Remove the old target to avoid confusing output 59 | textView.string = @""; 60 | 61 | currentlySelectedSimulator = simulators[row]; 62 | currentSimulatorTextField.stringValue = [currentlySelectedSimulator prettyDescription]; 63 | 64 | // Specificalle when we select a row we need to set the text becuase 65 | // the target thing will only update when new data comes in 66 | textView.string = currentlySelectedSimulator.simulatorOutput; 67 | [textView scrollToEndOfDocument:nil]; 68 | 69 | return YES; 70 | } 71 | 72 | 73 | // DataSource 74 | 75 | -(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{ 76 | return [simulators count]; 77 | } 78 | 79 | 80 | // Actions stuff 81 | 82 | - (void)startTesting { 83 | NSString *projectPath = [[NSUserDefaults standardUserDefaults] valueForKey:@"project_path"]; 84 | NSString *schemeName = [[NSUserDefaults standardUserDefaults] valueForKey:@"project_scheme_name"]; 85 | NSString *testName = [[NSUserDefaults standardUserDefaults] valueForKey:@"project_test_name"]; 86 | 87 | if( !projectPath && !schemeName && !testName ){ 88 | NSAlert *alert = [[NSAlert alloc] init]; 89 | [alert addButtonWithTitle:@"OK"]; 90 | [alert setMessageText:@"No settings entered"]; 91 | [alert setInformativeText:@"To use this application, you need to first set up the paths etc to your project. Open the preferences page from the menu to do so. Or press CMD + ,"]; 92 | [alert setAlertStyle:NSAlertStyleCritical]; 93 | [alert runModal]; 94 | } 95 | else{ 96 | [currentlySelectedSimulator startTestingPath:projectPath scheme:schemeName test:testName]; 97 | // Reload only specific row + column we pressed 98 | [simulatorTableView reloadData]; 99 | } 100 | } 101 | 102 | -(void)doubleTappedRow{ 103 | NSInteger index = [simulatorTableView clickedRow]; 104 | NSLog(@"doubleTapped row: %i", (int)index); 105 | [self startTesting]; 106 | 107 | //NSStoryboard *storyboard = [NSStoryboard storyboardWithName:@"Main" bundle:nil]; 108 | //NSWindowController *nswc = (NSWindowController*)[storyboard instantiateControllerWithIdentifier:@"ResultsViewController_ID"]; 109 | //ResultsViewController *rvc = (ResultsViewController*)nswc.contentViewController; 110 | //[rvc test:[currentlySelectedSimulator prettyDescription]]; 111 | //[nswc showWindow:nil]; 112 | } 113 | 114 | 115 | // Simulator Delegate 116 | 117 | -(void)simulator:(Simulator *)simulator didFinishTesting:(NSString *)result{ 118 | [simulatorTableView reloadData]; 119 | } 120 | 121 | -(void)simulator:(Simulator*)simulator didReceiveOutput:(NSString*)output{ 122 | if( [simulator isEqualTo:currentlySelectedSimulator] ){ 123 | // Chugs like heeeeck otherwise if we allow all billion lines.. 124 | int index = (int)output.length-500; 125 | if( index < 0 ){ 126 | index = 0; 127 | } 128 | 129 | // https://stackoverflow.com/questions/5495065/cocoa-real-slow-nstextview-is-there-a-better-way-to-append-text-to-the-contents 130 | NSTextStorage *textStorage = [textView textStorage]; 131 | [textStorage beginEditing]; 132 | [textStorage replaceCharactersInRange:NSMakeRange([textStorage length], 0) 133 | withString:[output substringFromIndex:index]]; 134 | [textStorage endEditing]; 135 | 136 | [textView scrollToEndOfDocument:nil]; 137 | } 138 | } 139 | 140 | @end 141 | -------------------------------------------------------------------------------- /Conductor/conductor/Test Viewer/ResultsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ResultsViewController.h 3 | // Conductor 4 | // 5 | // Created by Jonathan Winger Lang on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ResultsViewController : NSViewController { 12 | __weak IBOutlet NSTextField *titleTextField; 13 | } 14 | 15 | -(void)test:(NSString*)s; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Conductor/conductor/Test Viewer/ResultsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ResultsViewController.m 3 | // Conductor 4 | // 5 | // Created by Jonathan Winger Lang on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import "ResultsViewController.h" 10 | 11 | @implementation ResultsViewController 12 | 13 | - (void)viewDidLoad { 14 | [super viewDidLoad]; 15 | // Do view setup here. 16 | } 17 | 18 | // Delegate 19 | 20 | -(NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row{ 21 | //Simulator *simulator = simulators[row]; 22 | 23 | NSTableCellView *v = [tableView makeViewWithIdentifier:@"cell_text" owner:self]; 24 | v.textField.textColor = [NSColor textColor]; 25 | 26 | if( [tableColumn.identifier isEqualToString:@"column_test_name"] ){ 27 | v.textField.stringValue = @"name"; 28 | } 29 | else if( [tableColumn.identifier isEqualToString:@"column_result"] ){ 30 | v.textField.stringValue = @"res"; 31 | } 32 | else if( [tableColumn.identifier isEqualToString:@"column_duration"] ){ 33 | v.textField.stringValue = @"dur"; 34 | } 35 | 36 | return v; 37 | } 38 | 39 | -(BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row{ 40 | return YES; 41 | } 42 | 43 | 44 | // DataSource 45 | 46 | -(NSInteger)numberOfRowsInTableView:(NSTableView *)tableView{ 47 | return 10; //[simulators count]; 48 | } 49 | 50 | 51 | // XX 52 | 53 | -(void)test:(NSString*)s{ 54 | titleTextField.stringValue = s; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /Conductor/conductor/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // conductor 4 | // 5 | // Created by Jonathan on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : NSViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Conductor/conductor/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // conductor 4 | // 5 | // Created by Jonathan on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @implementation ViewController 12 | 13 | - (void)viewDidLoad { 14 | [super viewDidLoad]; 15 | 16 | // Do any additional setup after loading the view. 17 | } 18 | 19 | 20 | - (void)setRepresentedObject:(id)representedObject { 21 | [super setRepresentedObject:representedObject]; 22 | 23 | // Update the view, if already loaded. 24 | } 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Conductor/conductor/conductor.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Conductor/conductor/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // conductor 4 | // 5 | // Created by Jonathan on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4DD4638E1FF26CA800225B03 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DD4638D1FF26CA800225B03 /* AppDelegate.m */; }; 11 | 4DD463911FF26CA800225B03 /* MainViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DD463901FF26CA800225B03 /* MainViewController.m */; }; 12 | 4DD463941FF26CA800225B03 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4DD463921FF26CA800225B03 /* Main.storyboard */; }; 13 | 4DD463961FF26CA800225B03 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4DD463951FF26CA800225B03 /* Assets.xcassets */; }; 14 | 4DD463991FF26CA800225B03 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4DD463971FF26CA800225B03 /* LaunchScreen.storyboard */; }; 15 | 4DD4639C1FF26CA800225B03 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DD4639B1FF26CA800225B03 /* main.m */; }; 16 | 4DD463B31FF26E9600225B03 /* TrainModelsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DD463B21FF26E9600225B03 /* TrainModelsViewController.m */; }; 17 | 4DD463BB1FF2754600225B03 /* ConductorTestAppUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4DD463BA1FF2754600225B03 /* ConductorTestAppUITests.m */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | 4DD463BD1FF2754600225B03 /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = 4DD463811FF26CA800225B03 /* Project object */; 24 | proxyType = 1; 25 | remoteGlobalIDString = 4DD463881FF26CA800225B03; 26 | remoteInfo = ConductorTestApp; 27 | }; 28 | /* End PBXContainerItemProxy section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | 4DD463891FF26CA800225B03 /* ConductorTestApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ConductorTestApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 4DD4638C1FF26CA800225B03 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 33 | 4DD4638D1FF26CA800225B03 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 34 | 4DD4638F1FF26CA800225B03 /* MainViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MainViewController.h; sourceTree = ""; }; 35 | 4DD463901FF26CA800225B03 /* MainViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MainViewController.m; sourceTree = ""; }; 36 | 4DD463931FF26CA800225B03 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 37 | 4DD463951FF26CA800225B03 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 38 | 4DD463981FF26CA800225B03 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 39 | 4DD4639A1FF26CA800225B03 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | 4DD4639B1FF26CA800225B03 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 41 | 4DD463B11FF26E9600225B03 /* TrainModelsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TrainModelsViewController.h; sourceTree = ""; }; 42 | 4DD463B21FF26E9600225B03 /* TrainModelsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TrainModelsViewController.m; sourceTree = ""; }; 43 | 4DD463B81FF2754600225B03 /* ConductorTestAppUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ConductorTestAppUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 4DD463BA1FF2754600225B03 /* ConductorTestAppUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ConductorTestAppUITests.m; sourceTree = ""; }; 45 | 4DD463BC1FF2754600225B03 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 46 | /* End PBXFileReference section */ 47 | 48 | /* Begin PBXFrameworksBuildPhase section */ 49 | 4DD463861FF26CA800225B03 /* Frameworks */ = { 50 | isa = PBXFrameworksBuildPhase; 51 | buildActionMask = 2147483647; 52 | files = ( 53 | ); 54 | runOnlyForDeploymentPostprocessing = 0; 55 | }; 56 | 4DD463B51FF2754600225B03 /* Frameworks */ = { 57 | isa = PBXFrameworksBuildPhase; 58 | buildActionMask = 2147483647; 59 | files = ( 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | /* End PBXFrameworksBuildPhase section */ 64 | 65 | /* Begin PBXGroup section */ 66 | 4DD463801FF26CA800225B03 = { 67 | isa = PBXGroup; 68 | children = ( 69 | 4DD4638B1FF26CA800225B03 /* ConductorTestApp */, 70 | 4DD463B91FF2754600225B03 /* ConductorTestAppUITests */, 71 | 4DD4638A1FF26CA800225B03 /* Products */, 72 | ); 73 | sourceTree = ""; 74 | }; 75 | 4DD4638A1FF26CA800225B03 /* Products */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 4DD463891FF26CA800225B03 /* ConductorTestApp.app */, 79 | 4DD463B81FF2754600225B03 /* ConductorTestAppUITests.xctest */, 80 | ); 81 | name = Products; 82 | sourceTree = ""; 83 | }; 84 | 4DD4638B1FF26CA800225B03 /* ConductorTestApp */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 4DD463B01FF26E7F00225B03 /* TrainModels */, 88 | 4DD4638C1FF26CA800225B03 /* AppDelegate.h */, 89 | 4DD4638D1FF26CA800225B03 /* AppDelegate.m */, 90 | 4DD4638F1FF26CA800225B03 /* MainViewController.h */, 91 | 4DD463901FF26CA800225B03 /* MainViewController.m */, 92 | 4DD463921FF26CA800225B03 /* Main.storyboard */, 93 | 4DD463951FF26CA800225B03 /* Assets.xcassets */, 94 | 4DD463971FF26CA800225B03 /* LaunchScreen.storyboard */, 95 | 4DD4639A1FF26CA800225B03 /* Info.plist */, 96 | 4DD4639B1FF26CA800225B03 /* main.m */, 97 | ); 98 | path = ConductorTestApp; 99 | sourceTree = ""; 100 | }; 101 | 4DD463B01FF26E7F00225B03 /* TrainModels */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 4DD463B11FF26E9600225B03 /* TrainModelsViewController.h */, 105 | 4DD463B21FF26E9600225B03 /* TrainModelsViewController.m */, 106 | ); 107 | path = TrainModels; 108 | sourceTree = ""; 109 | }; 110 | 4DD463B91FF2754600225B03 /* ConductorTestAppUITests */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 4DD463BA1FF2754600225B03 /* ConductorTestAppUITests.m */, 114 | 4DD463BC1FF2754600225B03 /* Info.plist */, 115 | ); 116 | path = ConductorTestAppUITests; 117 | sourceTree = ""; 118 | }; 119 | /* End PBXGroup section */ 120 | 121 | /* Begin PBXNativeTarget section */ 122 | 4DD463881FF26CA800225B03 /* ConductorTestApp */ = { 123 | isa = PBXNativeTarget; 124 | buildConfigurationList = 4DD463AA1FF26CA800225B03 /* Build configuration list for PBXNativeTarget "ConductorTestApp" */; 125 | buildPhases = ( 126 | 4DD463851FF26CA800225B03 /* Sources */, 127 | 4DD463861FF26CA800225B03 /* Frameworks */, 128 | 4DD463871FF26CA800225B03 /* Resources */, 129 | ); 130 | buildRules = ( 131 | ); 132 | dependencies = ( 133 | ); 134 | name = ConductorTestApp; 135 | productName = ConductorTestApp; 136 | productReference = 4DD463891FF26CA800225B03 /* ConductorTestApp.app */; 137 | productType = "com.apple.product-type.application"; 138 | }; 139 | 4DD463B71FF2754600225B03 /* ConductorTestAppUITests */ = { 140 | isa = PBXNativeTarget; 141 | buildConfigurationList = 4DD463BF1FF2754600225B03 /* Build configuration list for PBXNativeTarget "ConductorTestAppUITests" */; 142 | buildPhases = ( 143 | 4DD463B41FF2754600225B03 /* Sources */, 144 | 4DD463B51FF2754600225B03 /* Frameworks */, 145 | 4DD463B61FF2754600225B03 /* Resources */, 146 | ); 147 | buildRules = ( 148 | ); 149 | dependencies = ( 150 | 4DD463BE1FF2754600225B03 /* PBXTargetDependency */, 151 | ); 152 | name = ConductorTestAppUITests; 153 | productName = ConductorTestAppUITests; 154 | productReference = 4DD463B81FF2754600225B03 /* ConductorTestAppUITests.xctest */; 155 | productType = "com.apple.product-type.bundle.ui-testing"; 156 | }; 157 | /* End PBXNativeTarget section */ 158 | 159 | /* Begin PBXProject section */ 160 | 4DD463811FF26CA800225B03 /* Project object */ = { 161 | isa = PBXProject; 162 | attributes = { 163 | LastUpgradeCheck = 0920; 164 | ORGANIZATIONNAME = "Jonathan Winger Lang"; 165 | TargetAttributes = { 166 | 4DD463881FF26CA800225B03 = { 167 | CreatedOnToolsVersion = 9.2; 168 | ProvisioningStyle = Automatic; 169 | }; 170 | 4DD463B71FF2754600225B03 = { 171 | CreatedOnToolsVersion = 9.2; 172 | ProvisioningStyle = Automatic; 173 | TestTargetID = 4DD463881FF26CA800225B03; 174 | }; 175 | }; 176 | }; 177 | buildConfigurationList = 4DD463841FF26CA800225B03 /* Build configuration list for PBXProject "ConductorTestApp" */; 178 | compatibilityVersion = "Xcode 8.0"; 179 | developmentRegion = en; 180 | hasScannedForEncodings = 0; 181 | knownRegions = ( 182 | en, 183 | Base, 184 | ); 185 | mainGroup = 4DD463801FF26CA800225B03; 186 | productRefGroup = 4DD4638A1FF26CA800225B03 /* Products */; 187 | projectDirPath = ""; 188 | projectRoot = ""; 189 | targets = ( 190 | 4DD463881FF26CA800225B03 /* ConductorTestApp */, 191 | 4DD463B71FF2754600225B03 /* ConductorTestAppUITests */, 192 | ); 193 | }; 194 | /* End PBXProject section */ 195 | 196 | /* Begin PBXResourcesBuildPhase section */ 197 | 4DD463871FF26CA800225B03 /* Resources */ = { 198 | isa = PBXResourcesBuildPhase; 199 | buildActionMask = 2147483647; 200 | files = ( 201 | 4DD463991FF26CA800225B03 /* LaunchScreen.storyboard in Resources */, 202 | 4DD463961FF26CA800225B03 /* Assets.xcassets in Resources */, 203 | 4DD463941FF26CA800225B03 /* Main.storyboard in Resources */, 204 | ); 205 | runOnlyForDeploymentPostprocessing = 0; 206 | }; 207 | 4DD463B61FF2754600225B03 /* Resources */ = { 208 | isa = PBXResourcesBuildPhase; 209 | buildActionMask = 2147483647; 210 | files = ( 211 | ); 212 | runOnlyForDeploymentPostprocessing = 0; 213 | }; 214 | /* End PBXResourcesBuildPhase section */ 215 | 216 | /* Begin PBXSourcesBuildPhase section */ 217 | 4DD463851FF26CA800225B03 /* Sources */ = { 218 | isa = PBXSourcesBuildPhase; 219 | buildActionMask = 2147483647; 220 | files = ( 221 | 4DD463911FF26CA800225B03 /* MainViewController.m in Sources */, 222 | 4DD4639C1FF26CA800225B03 /* main.m in Sources */, 223 | 4DD4638E1FF26CA800225B03 /* AppDelegate.m in Sources */, 224 | 4DD463B31FF26E9600225B03 /* TrainModelsViewController.m in Sources */, 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | }; 228 | 4DD463B41FF2754600225B03 /* Sources */ = { 229 | isa = PBXSourcesBuildPhase; 230 | buildActionMask = 2147483647; 231 | files = ( 232 | 4DD463BB1FF2754600225B03 /* ConductorTestAppUITests.m in Sources */, 233 | ); 234 | runOnlyForDeploymentPostprocessing = 0; 235 | }; 236 | /* End PBXSourcesBuildPhase section */ 237 | 238 | /* Begin PBXTargetDependency section */ 239 | 4DD463BE1FF2754600225B03 /* PBXTargetDependency */ = { 240 | isa = PBXTargetDependency; 241 | target = 4DD463881FF26CA800225B03 /* ConductorTestApp */; 242 | targetProxy = 4DD463BD1FF2754600225B03 /* PBXContainerItemProxy */; 243 | }; 244 | /* End PBXTargetDependency section */ 245 | 246 | /* Begin PBXVariantGroup section */ 247 | 4DD463921FF26CA800225B03 /* Main.storyboard */ = { 248 | isa = PBXVariantGroup; 249 | children = ( 250 | 4DD463931FF26CA800225B03 /* Base */, 251 | ); 252 | name = Main.storyboard; 253 | sourceTree = ""; 254 | }; 255 | 4DD463971FF26CA800225B03 /* LaunchScreen.storyboard */ = { 256 | isa = PBXVariantGroup; 257 | children = ( 258 | 4DD463981FF26CA800225B03 /* Base */, 259 | ); 260 | name = LaunchScreen.storyboard; 261 | sourceTree = ""; 262 | }; 263 | /* End PBXVariantGroup section */ 264 | 265 | /* Begin XCBuildConfiguration section */ 266 | 4DD463A81FF26CA800225B03 /* Debug */ = { 267 | isa = XCBuildConfiguration; 268 | buildSettings = { 269 | ALWAYS_SEARCH_USER_PATHS = NO; 270 | CLANG_ANALYZER_NONNULL = YES; 271 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 272 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 273 | CLANG_CXX_LIBRARY = "libc++"; 274 | CLANG_ENABLE_MODULES = YES; 275 | CLANG_ENABLE_OBJC_ARC = YES; 276 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 277 | CLANG_WARN_BOOL_CONVERSION = YES; 278 | CLANG_WARN_COMMA = YES; 279 | CLANG_WARN_CONSTANT_CONVERSION = YES; 280 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 281 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 282 | CLANG_WARN_EMPTY_BODY = YES; 283 | CLANG_WARN_ENUM_CONVERSION = YES; 284 | CLANG_WARN_INFINITE_RECURSION = YES; 285 | CLANG_WARN_INT_CONVERSION = YES; 286 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 287 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 288 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 289 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 290 | CLANG_WARN_STRICT_PROTOTYPES = YES; 291 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 292 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 293 | CLANG_WARN_UNREACHABLE_CODE = YES; 294 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 295 | CODE_SIGN_IDENTITY = "iPhone Developer"; 296 | COPY_PHASE_STRIP = NO; 297 | DEBUG_INFORMATION_FORMAT = dwarf; 298 | ENABLE_STRICT_OBJC_MSGSEND = YES; 299 | ENABLE_TESTABILITY = YES; 300 | GCC_C_LANGUAGE_STANDARD = gnu11; 301 | GCC_DYNAMIC_NO_PIC = NO; 302 | GCC_NO_COMMON_BLOCKS = YES; 303 | GCC_OPTIMIZATION_LEVEL = 0; 304 | GCC_PREPROCESSOR_DEFINITIONS = ( 305 | "DEBUG=1", 306 | "$(inherited)", 307 | ); 308 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 309 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 310 | GCC_WARN_UNDECLARED_SELECTOR = YES; 311 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 312 | GCC_WARN_UNUSED_FUNCTION = YES; 313 | GCC_WARN_UNUSED_VARIABLE = YES; 314 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 315 | MTL_ENABLE_DEBUG_INFO = YES; 316 | ONLY_ACTIVE_ARCH = YES; 317 | SDKROOT = iphoneos; 318 | }; 319 | name = Debug; 320 | }; 321 | 4DD463A91FF26CA800225B03 /* Release */ = { 322 | isa = XCBuildConfiguration; 323 | buildSettings = { 324 | ALWAYS_SEARCH_USER_PATHS = NO; 325 | CLANG_ANALYZER_NONNULL = YES; 326 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 327 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 328 | CLANG_CXX_LIBRARY = "libc++"; 329 | CLANG_ENABLE_MODULES = YES; 330 | CLANG_ENABLE_OBJC_ARC = YES; 331 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 332 | CLANG_WARN_BOOL_CONVERSION = YES; 333 | CLANG_WARN_COMMA = YES; 334 | CLANG_WARN_CONSTANT_CONVERSION = YES; 335 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 336 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 337 | CLANG_WARN_EMPTY_BODY = YES; 338 | CLANG_WARN_ENUM_CONVERSION = YES; 339 | CLANG_WARN_INFINITE_RECURSION = YES; 340 | CLANG_WARN_INT_CONVERSION = YES; 341 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 342 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 343 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 344 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 345 | CLANG_WARN_STRICT_PROTOTYPES = YES; 346 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 347 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 348 | CLANG_WARN_UNREACHABLE_CODE = YES; 349 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 350 | CODE_SIGN_IDENTITY = "iPhone Developer"; 351 | COPY_PHASE_STRIP = NO; 352 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 353 | ENABLE_NS_ASSERTIONS = NO; 354 | ENABLE_STRICT_OBJC_MSGSEND = YES; 355 | GCC_C_LANGUAGE_STANDARD = gnu11; 356 | GCC_NO_COMMON_BLOCKS = YES; 357 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 358 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 359 | GCC_WARN_UNDECLARED_SELECTOR = YES; 360 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 361 | GCC_WARN_UNUSED_FUNCTION = YES; 362 | GCC_WARN_UNUSED_VARIABLE = YES; 363 | IPHONEOS_DEPLOYMENT_TARGET = 11.2; 364 | MTL_ENABLE_DEBUG_INFO = NO; 365 | SDKROOT = iphoneos; 366 | VALIDATE_PRODUCT = YES; 367 | }; 368 | name = Release; 369 | }; 370 | 4DD463AB1FF26CA800225B03 /* Debug */ = { 371 | isa = XCBuildConfiguration; 372 | buildSettings = { 373 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 374 | CODE_SIGN_STYLE = Automatic; 375 | DEVELOPMENT_TEAM = 4V3J44VR2U; 376 | INFOPLIST_FILE = ConductorTestApp/Info.plist; 377 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 378 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 379 | PRODUCT_BUNDLE_IDENTIFIER = com.jontelang.ConductorTestApp; 380 | PRODUCT_NAME = "$(TARGET_NAME)"; 381 | TARGETED_DEVICE_FAMILY = "1,2"; 382 | }; 383 | name = Debug; 384 | }; 385 | 4DD463AC1FF26CA800225B03 /* Release */ = { 386 | isa = XCBuildConfiguration; 387 | buildSettings = { 388 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 389 | CODE_SIGN_STYLE = Automatic; 390 | DEVELOPMENT_TEAM = 4V3J44VR2U; 391 | INFOPLIST_FILE = ConductorTestApp/Info.plist; 392 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 393 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 394 | PRODUCT_BUNDLE_IDENTIFIER = com.jontelang.ConductorTestApp; 395 | PRODUCT_NAME = "$(TARGET_NAME)"; 396 | TARGETED_DEVICE_FAMILY = "1,2"; 397 | }; 398 | name = Release; 399 | }; 400 | 4DD463C01FF2754600225B03 /* Debug */ = { 401 | isa = XCBuildConfiguration; 402 | buildSettings = { 403 | CODE_SIGN_STYLE = Automatic; 404 | DEVELOPMENT_TEAM = 4V3J44VR2U; 405 | INFOPLIST_FILE = ConductorTestAppUITests/Info.plist; 406 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 407 | PRODUCT_BUNDLE_IDENTIFIER = com.jontelang.ConductorTestAppUITests; 408 | PRODUCT_NAME = "$(TARGET_NAME)"; 409 | TARGETED_DEVICE_FAMILY = "1,2"; 410 | TEST_TARGET_NAME = ConductorTestApp; 411 | }; 412 | name = Debug; 413 | }; 414 | 4DD463C11FF2754600225B03 /* Release */ = { 415 | isa = XCBuildConfiguration; 416 | buildSettings = { 417 | CODE_SIGN_STYLE = Automatic; 418 | DEVELOPMENT_TEAM = 4V3J44VR2U; 419 | INFOPLIST_FILE = ConductorTestAppUITests/Info.plist; 420 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 421 | PRODUCT_BUNDLE_IDENTIFIER = com.jontelang.ConductorTestAppUITests; 422 | PRODUCT_NAME = "$(TARGET_NAME)"; 423 | TARGETED_DEVICE_FAMILY = "1,2"; 424 | TEST_TARGET_NAME = ConductorTestApp; 425 | }; 426 | name = Release; 427 | }; 428 | /* End XCBuildConfiguration section */ 429 | 430 | /* Begin XCConfigurationList section */ 431 | 4DD463841FF26CA800225B03 /* Build configuration list for PBXProject "ConductorTestApp" */ = { 432 | isa = XCConfigurationList; 433 | buildConfigurations = ( 434 | 4DD463A81FF26CA800225B03 /* Debug */, 435 | 4DD463A91FF26CA800225B03 /* Release */, 436 | ); 437 | defaultConfigurationIsVisible = 0; 438 | defaultConfigurationName = Release; 439 | }; 440 | 4DD463AA1FF26CA800225B03 /* Build configuration list for PBXNativeTarget "ConductorTestApp" */ = { 441 | isa = XCConfigurationList; 442 | buildConfigurations = ( 443 | 4DD463AB1FF26CA800225B03 /* Debug */, 444 | 4DD463AC1FF26CA800225B03 /* Release */, 445 | ); 446 | defaultConfigurationIsVisible = 0; 447 | defaultConfigurationName = Release; 448 | }; 449 | 4DD463BF1FF2754600225B03 /* Build configuration list for PBXNativeTarget "ConductorTestAppUITests" */ = { 450 | isa = XCConfigurationList; 451 | buildConfigurations = ( 452 | 4DD463C01FF2754600225B03 /* Debug */, 453 | 4DD463C11FF2754600225B03 /* Release */, 454 | ); 455 | defaultConfigurationIsVisible = 0; 456 | defaultConfigurationName = Release; 457 | }; 458 | /* End XCConfigurationList section */ 459 | }; 460 | rootObject = 4DD463811FF26CA800225B03 /* Project object */; 461 | } 462 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp.xcodeproj/project.xcworkspace/xcuserdata/jontelang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/ConductorTestApp/ConductorTestApp.xcodeproj/project.xcworkspace/xcuserdata/jontelang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp.xcodeproj/xcuserdata/jontelang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp.xcodeproj/xcuserdata/jontelang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | ConductorTestApp.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ConductorTestApp 4 | // 5 | // Created by Jonathan on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ConductorTestApp 4 | // 5 | // Created by Jonathan on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // 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. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // 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. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // 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. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/Assets.xcassets/icon-hat256.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon-hat256@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/Assets.xcassets/icon-hat256.imageset/icon-hat256@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/ConductorTestApp/ConductorTestApp/Assets.xcassets/icon-hat256.imageset/icon-hat256@2x.png -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/Base.lproj/LaunchScreen.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 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/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 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 45 | 57 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 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 | 130 | 131 | 132 | 133 | 134 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/MainViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewController.h 3 | // ConductorTestApp 4 | // 5 | // Created by Jonathan on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface MainViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/MainViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewController.m 3 | // ConductorTestApp 4 | // 5 | // Created by Jonathan on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import "MainViewController.h" 10 | 11 | @interface MainViewController () 12 | 13 | @end 14 | 15 | @implementation MainViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view, typically from a nib. 20 | } 21 | 22 | 23 | - (void)didReceiveMemoryWarning { 24 | [super didReceiveMemoryWarning]; 25 | // Dispose of any resources that can be recreated. 26 | } 27 | 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/TrainModels/TrainModelsViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // TrainModelsViewController.h 3 | // ConductorTestApp 4 | // 5 | // Created by Jonathan on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TrainModelsViewController : UITableViewController { 12 | NSArray *trainModels; 13 | } 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/TrainModels/TrainModelsViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // TrainModelsViewController.m 3 | // ConductorTestApp 4 | // 5 | // Created by Jonathan on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import "TrainModelsViewController.h" 10 | 11 | @interface TrainModelsViewController () 12 | 13 | @end 14 | 15 | @implementation TrainModelsViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | 20 | trainModels = @[ 21 | @"BB 221 2-6-4 Adriatic O27 New York Central", 22 | @"BB 224 2-6-2 Prairie O Lionel Lines", 23 | @"BB 233 2-4-2 Columbia O27 Lionel Lines", 24 | @"BB 235 2-4-2 Columbia O27 Lionel Lines", 25 | @"BB 236 2-4-2 Columbia O27 Lionel Lines", 26 | @"BB 237 2-4-2 Columbia O27 Lionel Lines", 27 | @"BB 238 2-4-2 Columbia O27 Lionel Lines", 28 | @"BB 239 2-4-2 Columbia O27 Lionel Lines", 29 | @"BB 240 2-4-2 Columbia O27 Lionel Lines", 30 | @"BB 241 2-4-2 Columbia O27 Lionel Lines", 31 | @"BB 242 2-4-2 Columbia O27 Lionel Lines", 32 | @"BB 243 2-4-2 Columbia O27 Lionel Lines", 33 | @"BB 244 2-4-2 Columbia O27 Lionel Lines", 34 | @"BB 245 2-4-2 Columbia O27 Lionel Lines", 35 | @"BB 246 2-4-2 Columbia O27 Lionel Lines", 36 | @"BB 247 2-4-2 Columbia O27 Baltimore & Ohio", 37 | @"BB 248 2-4-2 Columbia O27 Lionel Lines", 38 | @"BB 249 2-4-2 Columbia O27 Pennsylvania", 39 | @"BB 250 2-4-2 Columbia O27 Pennsylvania", 40 | @"BB 251 2-4-2 Columbia O27 Southern Pacific", 41 | @"BB 637 2-6-4 Adriatic O Pennsylvania", 42 | @"BB 646 4-6-4 Hudson O Lionel Lines", 43 | @"BB 665 4-6-4 Hudson O Lionel Lines", 44 | @"BB 671 6-8-6 Steam Turbine O Lionel Lines", 45 | @"BB 671R 6-8-6 Steam Turbine O Lionel Lines", 46 | @"BB 675 2-6-2 Prairie O Lionel Lines", 47 | @"BB 681 6-8-6 Steam Turbine O Lionel Lines", 48 | @"BB 682 6-8-6 Steam Turbine O Pennsylvania", 49 | @"BB 685 4-6-4 Hudson O Lionel Lines", 50 | @"BB 726 2-8-4 Berkshire O Lionel Lines", 51 | @"BB 726RR 2-8-4 Berkshire O Lionel Lines", 52 | @"BB 736 2-8-4 Berkshire O Lionel Lines", 53 | @"BB 746 4-8-4 Northern O Norfolk & Western", 54 | @"BB 773 4-6-4 Hudson O Scale Lionel Lines", 55 | @"BB 1001 2-4-2 Columbia O27 Lionel Scout", 56 | @"BB 1050 0-4-0 Switcher O27 Lionel Scout", 57 | @"BB 1060 2-4-2 Columbia O27 Lionel Scout", 58 | @"BB 1061 0-4-0 or 2-4-2 Columbia O27 Lionel Scout", 59 | @"BB 1062 0-4-0 or 2-4-2 Columbia O27 Lionel Scout", 60 | @"BB 1101 2-4-2 Columbia O27 Lionel Scout", 61 | @"BB 1110 2-4-2 Columbia O27 Lionel Scout", 62 | @"BB 1120 2-4-2 Columbia O27 Lionel Scout", 63 | @"BB 1130 2-4-2 Columbia O27 Lionel Scout", 64 | @"BB 1615 0-4-0 Switcher O27 Lionel Lines", 65 | @"BB 1625 0-4-0 Switcher O27 Lionel Lines", 66 | @"BB 1654 2-4-2 Columbia O27 Lionel Lines", 67 | @"BB 1655 2-4-2 Columbia O27 Lionel Lines", 68 | @"BB 1656 0-4-0 Switcher O27 Lionel Lines", 69 | @"BB 1665 0-4-0 Switcher O27 Lionel Lines", 70 | @"BB 1666 2-6-2 Prairie O27 Lionel Lines", 71 | @"BB 1862 4-4-0 American O27 General", 72 | @"BB 1872 4-4-0 American O General", 73 | @"BB 1882 4-4-0 American O27 General", 74 | @"BB 2016 2-6-4 Adriatic O27 Lionel Lines", 75 | @"BB 2018 2-6-4 Adriatic O27 Lionel Lines", 76 | @"BB 2020 6-8-6 Steam Turbine O27 Lionel Lines", 77 | @"BB 2025 2-6-2 Prairie O27 Lionel Lines", 78 | @"BB 2026 2-6-2 Prairie O27 Lionel Lines", 79 | @"BB 2029 2-6-4 Adriatic O27 Lionel Lines", 80 | @"BB 2034 2-4-2 Columbia O27 Lionel Lines", 81 | @"BB 2035 2-6-4 Adriatic O27 Lionel Lines", 82 | @"BB 2036 2-6-4 Adriatic O27 Lionel Lines", 83 | @"BB 2037 2-6-4 Adriatic O27 Lionel Lines", 84 | @"BB 2046 4-6-4 Hudson O27 Lionel Lines", 85 | @"BB 2055 4-6-4 Hudson O27 Lionel Lines", 86 | @"BB 2056 4-6-4 Hudson O27 Lionel Lines", 87 | @"BB 2065 4-6-4 Hudson O27 Lionel Lines", 88 | @"BB 6110 2-4-2 Columbia O27 Lionel Lines" 89 | ]; 90 | } 91 | 92 | - (void)didReceiveMemoryWarning { 93 | [super didReceiveMemoryWarning]; 94 | // Dispose of any resources that can be recreated. 95 | } 96 | 97 | #pragma mark - Table view data source 98 | 99 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 100 | return 1; 101 | } 102 | 103 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 104 | return [trainModels count]; 105 | } 106 | 107 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 108 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath]; 109 | cell.textLabel.text = trainModels[indexPath.row]; 110 | return cell; 111 | } 112 | 113 | @end 114 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestApp/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ConductorTestApp 4 | // 5 | // Created by Jonathan on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestAppUITests/ConductorTestAppUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ConductorTestAppUITests.m 3 | // ConductorTestAppUITests 4 | // 5 | // Created by Jonathan on 12/26/17. 6 | // Copyright © 2017 Jonathan Winger Lang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ConductorTestAppUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation ConductorTestAppUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testMainScreen { 36 | // 37 | // Ensures the buttons are present 38 | // 39 | XCUIApplication *app = [[XCUIApplication alloc] init]; 40 | XCTAssert( [[[app.buttons matchingIdentifier:@"showTrainModels"] firstMatch] exists] ); 41 | XCTAssert( [[[app.buttons matchingIdentifier:@"showAboutConductor"] firstMatch] exists] ); 42 | } 43 | 44 | - (void)testTrainModels { 45 | // 46 | // Ensures we can open the train model screen, find some element and then go back 47 | // 48 | XCUIApplication *app = [[XCUIApplication alloc] init]; 49 | [[[app.buttons matchingIdentifier:@"showTrainModels"] firstMatch] tap]; 50 | [[[app.staticTexts matchingIdentifier:@"BB 242 2-4-2 Columbia O27 Lionel Lines"] firstMatch] tap]; 51 | [[[app.buttons matchingIdentifier:@"Back"] firstMatch] tap]; 52 | 53 | // Use testMainScreen to check if we're looking at the main screen after going back 54 | [self testMainScreen]; 55 | } 56 | 57 | - (void)testAboutScreen { 58 | // 59 | // Ensures we can open the about screen 60 | // 61 | XCUIApplication *app = [[XCUIApplication alloc] init]; 62 | [[[app.buttons matchingIdentifier:@"showAboutConductor"] firstMatch] tap]; 63 | [[[app.buttons matchingIdentifier:@"Back"] firstMatch] tap]; 64 | 65 | // Use testMainScreen to check if we're looking at the main screen after going back 66 | [self testMainScreen]; 67 | } 68 | 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /ConductorTestApp/ConductorTestAppUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Metadata/Conductor-App-Icon.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Metadata/Conductor-App-Icon.sketch -------------------------------------------------------------------------------- /Metadata/gif.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Metadata/gif.gif -------------------------------------------------------------------------------- /Metadata/overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Metadata/overview.png -------------------------------------------------------------------------------- /Metadata/preferences.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Metadata/preferences.png -------------------------------------------------------------------------------- /Metadata/readme-graphics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jontelang/Conductor/4035a9ef66207c7a40ffcb93d6cbd5592abd8d75/Metadata/readme-graphics.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 | # In short 5 | Conductor is a macOS application that lets you start your UI tests on any installed simulator on your device without having to fiddle with the Xcode UI. 6 | 7 | 8 | # Demonstration 9 | This is what a simple run of _Conductor_ can look like. Here I start the UI tests on two different simulators on two different iOS versions. 10 | 11 |
12 | 13 | 14 | # How it works 15 | 16 | The app will ask the system (actually instruments.app) for the installed simulators on the system and list them nicely for the user. When a user clicks on a simulator, it will start a new task (NSTask) with Xcodes command line tool "xcodebuild" with the users project as the arguments. At that point xcodebuild essentially takes over the actual running of each test and _Conductor_ will simply read the output and try to determine the status of the test. 17 | 18 | # Screenshots 19 | 20 |
21 | 22 |
23 | 24 | 25 | # Use cases compared to other solutions 26 | 27 | Conductor was made to solve the problem of starting many UI tests without hassle (but not _too_ many) while also keeping the visual niceness of Xcodes UI testing tools. 28 | 29 | Currently there are a few other solutions, all good in their own way, but neither worked exactly the way I wanted them too, so I started building _Conductor_. Here they are and the reasons they didn't work for me: 30 | 31 | ### Xcode 32 | Has a nice UI and really really great inspection tools for each test that fails, with screenshots, logs and all sorts of data around the tests. However, it fails when you want to test on many different iOS versions and simulators simultaneously as you have to kick them off manually through a dropdown menu. It creates a lot of friction. 33 | 34 | ### xcodebuild (DIY scripts) 35 | Also pretty great (_Conductor_ uses it behind the scenes) as it allows a lot of flexibility. However since I wanted to have a bit more control over when I started each simulator, it made it more cumbersome to write increasingly large scripts. It also lacks the intuitive feel a GUI can give you. 36 | 37 | Another issue is that all test results are put into very large .plist files, making it tedious to get into the results without either using a third party inspector or manually go digging. 38 | 39 | _Conductor_ actually started off as a pure results viewer, and eventually it will return into the app. 40 | 41 | ### Fastlane 42 | Seemed to work, and it seemed to have the proper result viewer (or at least an HTML report generated) but since it is a CLI it is more useful for maybe continous integration type of settings. It wouldn't be easily possible to restart a specific simulator from it. 43 | 44 | It also needs another tool (Fastlane) installed which you might not want. 45 | 46 | ### Others 47 | I don't recall looking at other tools, but there might be some. 48 | 49 | # TODO 50 | 51 | - [ ] Results viewer 52 | 53 | - [ ] Filter simulator list by e.g. iOS version or device type 54 | 55 | - [ ] Allow for multi selection in list and starting multiple tests simultaneously 56 | 57 | - [ ] Get a nicer icon 58 | 59 | - [ ] See currently running test 60 | 61 | # Contributing 62 | 63 | Feel very free to send me ideas or PRs. I'll happily accept contributions. 64 | --------------------------------------------------------------------------------