make the ios development path less mandatory
diff --git a/packages/flutter_tools/lib/src/ios/device_ios.dart b/packages/flutter_tools/lib/src/ios/device_ios.dart
index f705fd0..908cb3e 100644
--- a/packages/flutter_tools/lib/src/ios/device_ios.dart
+++ b/packages/flutter_tools/lib/src/ios/device_ios.dart
@@ -86,6 +86,9 @@
   bool get supportsStartPaused => false;
 
   static List<IOSDevice> getAttachedDevices([IOSDevice mockIOS]) {
+    if (!doctor.iosWorkflow.hasIdeviceId)
+      return <IOSDevice>[];
+
     List<IOSDevice> devices = [];
     for (String id in _getAttachedDeviceIDs(mockIOS)) {
       String name = _getDeviceName(id, mockIOS);
@@ -176,7 +179,7 @@
     // Step 1: Install the precompiled application if necessary
     bool buildResult = await _buildIOSXcodeProject(app, buildForDevice: true);
     if (!buildResult) {
-      printError('Could not build the precompiled application for the device');
+      printError('Could not build the precompiled application for the device.');
       return false;
     }
 
@@ -184,7 +187,7 @@
     Directory bundle = new Directory(path.join(app.localPath, 'build', 'Release-iphoneos', 'Runner.app'));
     bool bundleExists = bundle.existsSync();
     if (!bundleExists) {
-      printError('Could not find the built application bundle at ${bundle.path}');
+      printError('Could not find the built application bundle at ${bundle.path}.');
       return false;
     }
 
@@ -202,7 +205,7 @@
     ]);
 
     if (installationResult != 0) {
-      printError('Could not install ${bundle.path} on $id');
+      printError('Could not install ${bundle.path} on $id.');
       return false;
     }
 
@@ -246,6 +249,9 @@
   IOSSimulator(String id, { this.name }) : super(id);
 
   static List<IOSSimulator> getAttachedDevices() {
+    if (!xcode.isInstalled)
+      return <IOSSimulator>[];
+
     return SimControl.getConnectedDevices().map((SimDevice device) {
       return new IOSSimulator(device.udid, name: device.name);
     }).toList();
@@ -317,7 +323,7 @@
     // Step 1: Build the Xcode project
     bool buildResult = await _buildIOSXcodeProject(app, buildForDevice: false);
     if (!buildResult) {
-      printError('Could not build the application for the simulator');
+      printError('Could not build the application for the simulator.');
       return false;
     }
 
@@ -325,7 +331,7 @@
     Directory bundle = new Directory(path.join(app.localPath, 'build', 'Release-iphonesimulator', 'Runner.app'));
     bool bundleExists = await bundle.exists();
     if (!bundleExists) {
-      printError('Could not find the built application bundle at ${bundle.path}');
+      printError('Could not find the built application bundle at ${bundle.path}.');
       return false;
     }
 
@@ -476,7 +482,8 @@
           String category = match.group(1);
           String content = match.group(2);
           if (category == 'Game Center' || category == 'itunesstored' || category == 'nanoregistrylaunchd' ||
-              category == 'mstreamd' || category == 'syncdefaultsd' || category == 'companionappd' || category == 'searchd')
+              category == 'mstreamd' || category == 'syncdefaultsd' || category == 'companionappd' ||
+              category == 'searchd')
             return null;
 
           _lastWasFiltered = false;
diff --git a/packages/flutter_tools/lib/src/ios/ios_workflow.dart b/packages/flutter_tools/lib/src/ios/ios_workflow.dart
new file mode 100644
index 0000000..8dfc94f
--- /dev/null
+++ b/packages/flutter_tools/lib/src/ios/ios_workflow.dart
@@ -0,0 +1,82 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'dart:io';
+
+import '../base/globals.dart';
+import '../base/process.dart';
+import '../doctor.dart';
+
+class IOSWorkflow extends Workflow {
+  IOSWorkflow() : super('iOS');
+
+  bool get appliesToHostPlatform => Platform.isMacOS;
+
+  // We need xcode (+simctl) to list simulator devices, and idevice_id to list real devices.
+  bool get canListDevices => xcode.isInstalled;
+
+  // We need xcode to launch simulator devices, and ideviceinstaller and ios-deploy
+  // for real devices.
+  bool get canLaunchDevices => xcode.isInstalled;
+
+  void diagnose() {
+    Validator iosValidator = new Validator('Develop for iOS devices');
+
+    Function _xcodeExists = () {
+      return xcode.isInstalled ? ValidationType.installed : ValidationType.missing;
+    };
+
+    Function _brewExists = () {
+      return exitsHappy(<String>['brew', '-v'])
+        ? ValidationType.installed : ValidationType.missing;
+    };
+
+    Function _ideviceinstallerExists = () {
+      return exitsHappy(<String>['ideviceinstaller', '-h'])
+        ? ValidationType.installed : ValidationType.missing;
+    };
+
+    Function _iosdeployExists = () {
+      return hasIdeviceId ? ValidationType.installed : ValidationType.missing;
+    };
+
+    iosValidator.addValidator(new Validator(
+      'XCode',
+      description: 'enable development for iOS devices',
+      resolution: 'Download at https://developer.apple.com/xcode/download/',
+      validatorFunction: _xcodeExists
+    ));
+
+    iosValidator.addValidator(new Validator(
+      'brew',
+      description: 'install additional development packages',
+      resolution: 'Download at http://brew.sh/',
+      validatorFunction: _brewExists
+    ));
+
+    iosValidator.addValidator(new Validator(
+      'ideviceinstaller',
+      description: 'discover connected iOS devices',
+      resolution: "Install via 'brew install ideviceinstaller'",
+      validatorFunction: _ideviceinstallerExists
+    ));
+
+    iosValidator.addValidator(new Validator(
+      'ios-deploy',
+      description: 'deploy to connected iOS devices',
+      resolution: "Install via 'brew install ios-deploy'",
+      validatorFunction: _iosdeployExists
+    ));
+
+    iosValidator.validate().print();
+  }
+
+  bool get hasIdeviceId => exitsHappy(<String>['idevice_id', '-h']);
+
+  /// Return whether the tooling to list and deploy to real iOS devices (not the
+  /// simulator) is installed on the user's machine.
+  bool get canWorkWithIOSDevices {
+    return exitsHappy(<String>['ideviceinstaller', '-h']) && hasIdeviceId;
+  }
+}
diff --git a/packages/flutter_tools/lib/src/ios/mac.dart b/packages/flutter_tools/lib/src/ios/mac.dart
new file mode 100644
index 0000000..47f5e79
--- /dev/null
+++ b/packages/flutter_tools/lib/src/ios/mac.dart
@@ -0,0 +1,14 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import '../base/context.dart';
+import '../base/process.dart';
+
+class XCode {
+  static void initGlobal() {
+    context[XCode] = new XCode();
+  }
+
+  bool get isInstalled => exitsHappy(<String>['xcode-select', '--print-path']);
+}