Fix up iOS Add to App tests (#38603)

diff --git a/.cirrus.yml b/.cirrus.yml
index d19c275..958113b 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -534,6 +534,8 @@
     - name: add2app-macos
       env:
         SHARD: add2app_test
+      setup_xcpretty_script:
+        - sudo gem install xcpretty
       test_all_script:
         - ulimit -S -n 2048 # https://github.com/flutter/flutter/issues/2976
         - dart --enable-asserts dev/bots/test.dart
diff --git a/dev/integration_tests/ios_add2app/build_and_test.sh b/dev/integration_tests/ios_add2app/build_and_test.sh
index 4c08afd..1681699 100755
--- a/dev/integration_tests/ios_add2app/build_and_test.sh
+++ b/dev/integration_tests/ios_add2app/build_and_test.sh
@@ -10,4 +10,15 @@
 
 pod install
 os_version=$(xcrun --show-sdk-version --sdk iphonesimulator)
-xcodebuild -workspace ios_add2app.xcworkspace -scheme ios_add2appTests -sdk "iphonesimulator$os_version" -destination "OS=$os_version,name=iPhone X" test
\ No newline at end of file
+
+PRETTY="cat"
+if which xcpretty; then
+  PRETTY="xcpretty"
+fi
+
+set -o pipefail && xcodebuild \
+  -workspace ios_add2app.xcworkspace \
+  -scheme ios_add2appTests \
+  -sdk "iphonesimulator$os_version" \
+  -destination "OS=$os_version,name=iPhone X" test | $PRETTY
+
diff --git a/dev/integration_tests/ios_add2app/ios_add2app.xcodeproj/project.pbxproj b/dev/integration_tests/ios_add2app/ios_add2app.xcodeproj/project.pbxproj
index 40bddef..2b1925d 100644
--- a/dev/integration_tests/ios_add2app/ios_add2app.xcodeproj/project.pbxproj
+++ b/dev/integration_tests/ios_add2app/ios_add2app.xcodeproj/project.pbxproj
@@ -338,7 +338,7 @@
 			name = "[CP-User] Run Flutter Build Script";
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "set -e\nset -u\nsource \"${SRCROOT}/flutterapp/.ios/Flutter/flutter_export_environment.sh\"\n\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/xcode_backend.sh build\n";
+			shellScript = "set -e\nset -u\nsource \"${SRCROOT}/flutterapp/.ios/Flutter/flutter_export_environment.sh\"\n\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/xcode_backend.sh build";
 		};
 		DE5CDCD8B3565EAB9F38F455 /* [CP] Check Pods Manifest.lock */ = {
 			isa = PBXShellScriptBuildPhase;
@@ -502,8 +502,10 @@
 					"DEBUG=1",
 					"$(inherited)",
 				);
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_PEDANTIC = YES;
 				GCC_WARN_UNDECLARED_SELECTOR = YES;
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
@@ -513,6 +515,11 @@
 				MTL_FAST_MATH = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = iphoneos;
+				WARNING_CFLAGS = "-Wno-gnu";
+				WARNING_LDFLAGS = (
+					"-Wall",
+					"-Werror",
+				);
 			};
 			name = Debug;
 		};
@@ -556,8 +563,10 @@
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu11;
 				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
 				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
 				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_PEDANTIC = YES;
 				GCC_WARN_UNDECLARED_SELECTOR = YES;
 				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
 				GCC_WARN_UNUSED_FUNCTION = YES;
@@ -567,6 +576,11 @@
 				MTL_FAST_MATH = YES;
 				SDKROOT = iphoneos;
 				VALIDATE_PRODUCT = YES;
+				WARNING_CFLAGS = "-Wno-gnu";
+				WARNING_LDFLAGS = (
+					"-Wall",
+					"-Werror",
+				);
 			};
 			name = Release;
 		};
diff --git a/dev/integration_tests/ios_add2app/ios_add2app/AppDelegate.h b/dev/integration_tests/ios_add2app/ios_add2app/AppDelegate.h
index 816e424..43a7e63 100644
--- a/dev/integration_tests/ios_add2app/ios_add2app/AppDelegate.h
+++ b/dev/integration_tests/ios_add2app/ios_add2app/AppDelegate.h
@@ -8,7 +8,6 @@
 @interface AppDelegate : FlutterAppDelegate
 
 @property(nonatomic, strong) FlutterEngine* engine;
-@property(nonatomic, strong) UIWindow* window;
 @property(nonatomic, strong) FlutterBasicMessageChannel* reloadMessageChannel;
 
 @end
diff --git a/dev/integration_tests/ios_add2app/ios_add2app/AppDelegate.m b/dev/integration_tests/ios_add2app/ios_add2app/AppDelegate.m
index b69c346..6d5a00f 100644
--- a/dev/integration_tests/ios_add2app/ios_add2app/AppDelegate.m
+++ b/dev/integration_tests/ios_add2app/ios_add2app/AppDelegate.m
@@ -41,7 +41,7 @@
 
   _reloadMessageChannel = [[FlutterBasicMessageChannel alloc]
          initWithName:_kReloadChannelName
-      binaryMessenger:_engine
+      binaryMessenger:_engine.binaryMessenger
                 codec:[FlutterStringCodec sharedInstance]];
 
   self.window.rootViewController = _navigationController;
diff --git a/dev/integration_tests/ios_add2app/ios_add2app/HybridViewController.m b/dev/integration_tests/ios_add2app/ios_add2app/HybridViewController.m
index af58413..df6b254 100644
--- a/dev/integration_tests/ios_add2app/ios_add2app/HybridViewController.m
+++ b/dev/integration_tests/ios_add2app/ios_add2app/HybridViewController.m
@@ -56,7 +56,7 @@
 
   _messageChannel = [[FlutterBasicMessageChannel alloc]
          initWithName:_kChannel
-      binaryMessenger:_flutterViewController
+      binaryMessenger:_flutterViewController.binaryMessenger
                 codec:[FlutterStringCodec sharedInstance]];
   [self addChildViewController:_flutterViewController];
   [stackView addArrangedSubview:_flutterViewController.view];
diff --git a/dev/integration_tests/ios_add2app/ios_add2appTests/FlutterViewControllerTests.m b/dev/integration_tests/ios_add2app/ios_add2appTests/FlutterViewControllerTests.m
index 6aee224..46cf50e 100644
--- a/dev/integration_tests/ios_add2app/ios_add2appTests/FlutterViewControllerTests.m
+++ b/dev/integration_tests/ios_add2app/ios_add2appTests/FlutterViewControllerTests.m
@@ -21,7 +21,7 @@
    [viewController viewWillAppear:NO];
    [viewController viewDidDisappear:NO];
  }
- XCTAssertNil(weakEngine);
+ XCTAssertNil(weakEngine, @"Engine failed to release.");
 }
 
 @end
diff --git a/dev/integration_tests/ios_add2app/ios_add2appTests/IntegrationTests.m b/dev/integration_tests/ios_add2app/ios_add2appTests/IntegrationTests.m
index 6c6b36e..c92e1b1 100644
--- a/dev/integration_tests/ios_add2app/ios_add2appTests/IntegrationTests.m
+++ b/dev/integration_tests/ios_add2app/ios_add2appTests/IntegrationTests.m
@@ -11,36 +11,6 @@
 #import "../ios_add2app/MainViewController.h"
 #import "../ios_add2app/HybridViewController.h"
 
-static void waitForFlutterSemanticsTree(FlutterViewController *viewController) {
-  int tries = 10;
-  double delay = 1.0;
-
-  // ensureSemanticsEnabled is a synchronous call, but only ensures that the
-  // semantics tree will be built on a subsequent frame (as opposed to being
-  // available at time it returns).
-  // To actually get the tree, we have to wait for the FlutterSemanticsUpdate
-  // notification, which lets us know that a semantics tree has been built;
-  // but we cannot block the main thread while waiting (so we use
-  // CFRunLoopRunInMode).
-
-  __block BOOL semanticsAvailable = NO;
-  __block id<NSObject> observer = [[NSNotificationCenter defaultCenter]
-      addObserverForName:@"FlutterSemanticsUpdate"
-                  object:viewController
-                   queue:nil
-              usingBlock:^(NSNotification *notification) {
-                semanticsAvailable = YES;
-                [[NSNotificationCenter defaultCenter] removeObserver:observer];
-              }];
-  [viewController.engine ensureSemanticsEnabled];
-  while (semanticsAvailable == NO && tries != 0) {
-    CFRunLoopRunInMode(kCFRunLoopDefaultMode, delay, false);
-    tries--;
-    [viewController.engine ensureSemanticsEnabled];
-  }
-  GREYAssertTrue(semanticsAvailable, @"Semantics Tree did not build!");
-}
-
 @interface FlutterTests : XCTestCase
 @end
 
@@ -58,6 +28,12 @@
   return self;
 }
 
+- (void)expectSemanticsNotification:(FlutterViewController*)viewController {
+  [self expectationForNotification:FlutterSemanticsUpdateNotification object:viewController handler:nil];
+  [viewController.engine ensureSemanticsEnabled];
+  [self waitForExpectationsWithTimeout:30.0 handler:nil];
+}
+
 - (void)testFullScreenCanPop {
   [[EarlGrey selectElementWithMatcher:grey_keyWindow()]
       assertWithMatcher:grey_sufficientlyVisible()];
@@ -74,7 +50,7 @@
             .window.rootViewController;
     weakViewController =
         (FullScreenViewController *)navController.visibleViewController;
-    waitForFlutterSemanticsTree(weakViewController);
+    [self expectSemanticsNotification:weakViewController];
     GREYAssertNotNil(weakViewController,
                      @"Expected non-nil FullScreenViewController.");
   }
@@ -112,8 +88,8 @@
         (DualFlutterViewController *)navController.visibleViewController;
     GREYAssertNotNil(viewController,
                      @"Expected non-nil DualFlutterViewController.");
-    waitForFlutterSemanticsTree(viewController.topFlutterViewController);
-    waitForFlutterSemanticsTree(viewController.bottomFlutterViewController);
+    [self expectSemanticsNotification:viewController.topFlutterViewController];
+    [self expectSemanticsNotification:viewController.bottomFlutterViewController];
   }
 
   // Verify that there are two Flutter views with the expected marquee text.
@@ -148,7 +124,7 @@
         (HybridViewController *)navController.visibleViewController;
     GREYAssertNotNil(viewController.flutterViewController,
                      @"Expected non-nil FlutterViewController.");
-    waitForFlutterSemanticsTree(viewController.flutterViewController);
+    [self expectSemanticsNotification:viewController.flutterViewController];
   }
 
   [self validateCountsFlutter:@"Platform" count:0];