@@ -36,6 +36,8 @@ @implementation NavViewController {
3636 NSString *_mapId;
3737 MapViewType _mapViewType;
3838 id <INavigationViewCallback> _viewCallbacks;
39+ BOOL _isSessionAttached;
40+ NSNumber *_isNavigationUIEnabled;
3941}
4042
4143- (instancetype )initWithMapViewType : (MapViewType)mapViewType {
@@ -62,17 +64,126 @@ - (void)loadView {
6264 }
6365
6466 _mapView = [[GMSMapView alloc ] initWithOptions: options];
65-
67+ if (_mapViewType == NAVIGATION) {
68+ _mapView.navigationEnabled = YES ;
69+ }
6670 self.view = _mapView;
6771 _mapView.delegate = self;
72+ }
73+
74+ - (void )viewDidLoad {
75+ [super viewDidLoad ];
76+
77+ [_viewCallbacks handleMapReady ];
78+ }
79+
80+ - (void )viewDidLayoutSubviews {
81+ [super viewDidLayoutSubviews ];
82+
83+ [self attachToNavigationSessionIfNeeded ];
84+ }
85+
86+ - (BOOL )attachToNavigationSessionIfNeeded {
87+ // Only attach if view has proper type, state and dimensions (not zero size)
88+ if (_mapViewType != NAVIGATION || _isSessionAttached || _mapView.bounds .size .width == 0 ||
89+ _mapView.bounds .size .height == 0 ) {
90+ return NO ;
91+ }
6892
6993 NavModule *navModule = [NavModule sharedInstance ];
70- if (navModule != nil && [navModule hasSession ]) {
71- [ self attachToNavigationSession: [navModule getSession ]] ;
94+ if (navModule == nil || ! [navModule hasSession ]) {
95+ return NO ;
7296 }
73- dispatch_async (dispatch_get_main_queue (), ^{
74- [_viewCallbacks handleMapReady ];
75- });
97+
98+ GMSNavigationSession *session = [navModule getSession ];
99+ if (_mapView == nil || session == nil ) {
100+ return NO ;
101+ }
102+
103+ // `enableNavigationWithSession` returns false if TOS is not accepted.
104+ // This should not be possible in normal usage as the NavModule ensures TOS acceptance before
105+ // navigation session creation.
106+ BOOL result = [_mapView enableNavigationWithSession: session];
107+
108+ if (result) {
109+ _mapView.navigationUIDelegate = self;
110+ [self applyStylingOptions ];
111+
112+ [self restoreNavigationUIState ];
113+
114+ _isSessionAttached = YES ;
115+
116+ [self forceInvalidateView ];
117+ }
118+
119+ return result;
120+ }
121+
122+ - (void )forceInvalidateView {
123+ if (_mapView) {
124+ // Defer to next run loop to ensure view is properly sized
125+ dispatch_async (dispatch_get_main_queue (), ^{
126+ if (self->_mapView ) {
127+ [self ->_mapView setNeedsLayout ];
128+ [self ->_mapView.layer setNeedsDisplay ];
129+ }
130+ });
131+ }
132+ }
133+
134+ - (void )restoreNavigationUIState {
135+ if (_mapView) {
136+ if (_isNavigationUIEnabled != nil ) {
137+ _mapView.navigationEnabled = [_isNavigationUIEnabled boolValue ];
138+ } else {
139+ _mapView.navigationEnabled = _mapViewType == NAVIGATION;
140+ }
141+ }
142+ }
143+
144+ - (void )navigationSessionDestroyed {
145+ _isSessionAttached = NO ;
146+ if (_mapView) {
147+ _mapView.navigationUIDelegate = nil ;
148+ _mapView.navigationEnabled = NO ;
149+ }
150+ }
151+
152+ - (void )cleanup {
153+ _isSessionAttached = NO ;
154+
155+ // Remove all delegates to break retain cycles
156+ if (_mapView) {
157+ _mapView.delegate = nil ;
158+ _mapView.navigationUIDelegate = nil ;
159+ _mapView.navigationEnabled = NO ;
160+ [_mapView clear ];
161+
162+ [_mapView removeFromSuperview ];
163+ _mapView = nil ;
164+ }
165+
166+ // Clear local arrays and set to nil
167+ [_markerList removeAllObjects ];
168+ [_polylineList removeAllObjects ];
169+ [_polygonList removeAllObjects ];
170+ [_circleList removeAllObjects ];
171+ [_groundOverlayList removeAllObjects ];
172+
173+ _markerList = nil ;
174+ _polylineList = nil ;
175+ _polygonList = nil ;
176+ _circleList = nil ;
177+ _groundOverlayList = nil ;
178+
179+ // Clear callbacks
180+ _viewCallbacks = nil ;
181+ }
182+
183+ - (void )dealloc {
184+ [self cleanup ];
185+ [self .view removeFromSuperview ];
186+ self.view = nil ;
76187}
77188
78189- (void )mapViewDidTapRecenterButton : (GMSMapView *)mapView {
@@ -195,6 +306,7 @@ - (void)setNavigationUIEnabled:(BOOL)isEnabled {
195306 if (_mapViewType != NAVIGATION) {
196307 return ;
197308 }
309+ _isNavigationUIEnabled = @(isEnabled);
198310 _mapView.navigationEnabled = isEnabled;
199311}
200312
@@ -327,16 +439,6 @@ - (void)setSpeedLimitIconEnabled:(BOOL)isEnabled {
327439
328440#pragma mark - View Controller functions
329441
330- - (BOOL )attachToNavigationSession : (GMSNavigationSession *)session {
331- if (_mapViewType != NAVIGATION) {
332- return NO ;
333- }
334- BOOL result = [_mapView enableNavigationWithSession: session];
335- _mapView.navigationUIDelegate = self;
336- [self applyStylingOptions ];
337- return result;
338- }
339-
340442- (void )onPromptVisibilityChange : (BOOL )isVisible {
341443 [_viewCallbacks handlePromptVisibilityChanged: isVisible];
342444}
0 commit comments