Started clearing out the parent of orphaned semantic objects. (#17499)

diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h
index d6e0bb6..772c84e 100644
--- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h
+++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h
@@ -43,7 +43,7 @@
  * The parent of this node in the node tree. Will be nil for the root node and
  * during transient state changes.
  */
-@property(nonatomic, assign) SemanticsObject* parent;
+@property(nonatomic, readonly) SemanticsObject* parent;
 
 /**
  * The accessibility bridge that this semantics object is attached to. This
@@ -85,13 +85,15 @@
  * Direct children of this semantics object. Each child's `parent` property must
  * be equal to this object.
  */
-@property(nonatomic, strong) NSMutableArray<SemanticsObject*>* children;
+@property(nonatomic, strong) NSArray<SemanticsObject*>* children;
 
 /**
  * Used if this SemanticsObject is for a platform view.
  */
 @property(strong, nonatomic) FlutterPlatformViewSemanticsContainer* platformViewSemanticsContainer;
 
+- (void)replaceChildAtIndex:(NSInteger)index withChild:(SemanticsObject*)child;
+
 - (BOOL)nodeWillCauseLayoutChange:(const flutter::SemanticsNode*)node;
 
 #pragma mark - Designated initializers
diff --git a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm
index 53f097e..46224c1 100644
--- a/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm
+++ b/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm
@@ -14,6 +14,8 @@
 #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h"
 #include "flutter/shell/platform/darwin/ios/platform_view_ios.h"
 
+FLUTTER_ASSERT_NOT_ARC
+
 namespace {
 
 constexpr int32_t kRootNodeId = 0;
@@ -162,8 +164,14 @@
 
 @end
 
+@interface SemanticsObject ()
+/** Should only be called in conjunction with setting child/parent relationship. */
+- (void)privateSetParent:(SemanticsObject*)parent;
+@end
+
 @implementation SemanticsObject {
   fml::scoped_nsobject<SemanticsObjectContainer> _container;
+  NSMutableArray<SemanticsObject*>* _children;
 }
 
 #pragma mark - Override base class designated initializers
@@ -197,7 +205,7 @@
 
 - (void)dealloc {
   for (SemanticsObject* child in _children) {
-    child.parent = nil;
+    [child privateSetParent:nil];
   }
   [_children removeAllObjects];
   [_children release];
@@ -239,6 +247,28 @@
   return [self.children count] != 0;
 }
 
+- (void)privateSetParent:(SemanticsObject*)parent {
+  _parent = parent;
+}
+
+- (void)setChildren:(NSArray<SemanticsObject*>*)children {
+  for (SemanticsObject* child in _children) {
+    [child privateSetParent:nil];
+  }
+  [_children release];
+  _children = [[NSMutableArray alloc] initWithArray:children];
+  for (SemanticsObject* child in _children) {
+    [child privateSetParent:self];
+  }
+}
+
+- (void)replaceChildAtIndex:(NSInteger)index withChild:(SemanticsObject*)child {
+  SemanticsObject* oldChild = _children[index];
+  [oldChild privateSetParent:nil];
+  [child privateSetParent:self];
+  [_children replaceObjectAtIndex:index withObject:child];
+}
+
 #pragma mark - UIAccessibility overrides
 
 - (BOOL)isAccessibilityElement {
@@ -653,7 +683,7 @@
     return ((FlutterPlatformViewSemanticsContainer*)element).index;
   }
 
-  NSMutableArray<SemanticsObject*>* children = [_semanticsObject children];
+  NSArray<SemanticsObject*>* children = [_semanticsObject children];
   for (size_t i = 0; i < [children count]; i++) {
     SemanticsObject* child = children[i];
     if ((![child hasChildren] && child == element) ||
@@ -741,7 +771,6 @@
         [[[NSMutableArray alloc] initWithCapacity:newChildCount] autorelease];
     for (NSUInteger i = 0; i < newChildCount; ++i) {
       SemanticsObject* child = GetOrCreateObject(node.childrenInTraversalOrder[i], nodes);
-      child.parent = object;
       [newChildren addObject:child];
     }
     object.children = newChildren;
@@ -847,10 +876,8 @@
   assert(oldObject.node.id == newObject.node.id);
   NSNumber* nodeId = @(oldObject.node.id);
   NSUInteger positionInChildlist = [oldObject.parent.children indexOfObject:oldObject];
-  SemanticsObject* parent = oldObject.parent;
   [objects removeObjectForKey:nodeId];
-  newObject.parent = parent;
-  [newObject.parent.children replaceObjectAtIndex:positionInChildlist withObject:newObject];
+  [oldObject.parent replaceChildAtIndex:positionInChildlist withChild:newObject];
   objects[nodeId] = newObject;
 }