Skip to content

Commit ce3752b

Browse files
authored
feat(ios): support iOS 26+ source views for non-iPad devices (tidev#14258)
* feat(ios): support iOS 26+ source views for non-iPad devices * fix: fix memory handling
1 parent 6549100 commit ce3752b

File tree

3 files changed

+56
-94
lines changed

3 files changed

+56
-94
lines changed

apidoc/Titanium/UI/OptionDialog.yml

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -382,13 +382,7 @@ properties:
382382
optional: true
383383

384384
- name: view
385-
summary: View to which to attach the dialog.
385+
summary: |
386+
View to which to attach the dialog. Prior to iOS 26, this was only
387+
used on iPad.
386388
type: Titanium.UI.View
387-
388-
- name: rect
389-
summary: Positions the arrow of the option dialog relative to the attached view's dimensions.
390-
description: |
391-
Setting the x, y coordinates to (0, 0) places the dialog in the top-left corner of the
392-
view object. Set both the `width` and `height` properties to 1.
393-
type: Dimension
394-
optional: true

iphone/Classes/TiUIOptionDialogProxy.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
UIAlertController *alertController;
1515
TiViewProxy *dialogView;
1616
UIColor *tintColor;
17-
CGRect dialogRect;
1817
BOOL animated;
1918
NSUInteger accumulatedOrientationChanges;
2019
BOOL showDialog;

iphone/Classes/TiUIOptionDialogProxy.m

Lines changed: 53 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#import "TiUIOptionDialogProxy.h"
1010
#import "TiToolbarButton.h"
11+
#import "TiUIButtonProxy.h"
1112
#import <TitaniumKit/TiApp.h>
1213
#import <TitaniumKit/TiTab.h>
1314
#import <TitaniumKit/TiToolbar.h>
@@ -67,9 +68,7 @@ - (void)show:(id)args
6768
animated = [TiUtils boolValue:@"animated" properties:args def:YES];
6869
id obj = [args objectForKey:@"rect"];
6970
if (obj != nil) {
70-
dialogRect = [TiUtils rectValue:obj];
71-
} else {
72-
dialogRect = CGRectZero;
71+
DEPRECATED_REMOVED(@"UI.OptionDialog", @"13.0.0", @"13.0.0");
7372
}
7473

7574
RELEASE_TO_NIL(alertController);
@@ -110,23 +109,18 @@ - (void)show:(id)args
110109
if ([TiUtils isIPad]) {
111110
UIViewController *topVC = [[[TiApp app] controller] topPresentedController];
112111
isPopover = ((topVC.modalPresentationStyle == UIModalPresentationPopover) && (![topVC isKindOfClass:[UIAlertController class]]));
113-
/**
114-
** This block commented out since it seems to have no effect on the alert controller.
115-
** If you read the modalPresentationStyle after setting the value, it still shows UIModalPresentationPopover
116-
** However not configuring the UIPopoverPresentationController seems to do the trick.
117-
** This hack in place to conserve current behavior. Should revisit when iOS7 is dropped so that
118-
** option dialogs are always presented in UIModalPresentationPopover
119-
if (isPopover) {
120-
alertController.modalPresentationStyle = UIModalPresentationCurrentContext;
121-
alertController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
122-
}
123-
*/
124112
}
113+
125114
/*See Comment above. Remove if condition to see difference in behavior on iOS8*/
126115
if (!isPopover) {
127116
UIPopoverPresentationController *presentationController = alertController.popoverPresentationController;
128117
presentationController.permittedArrowDirections = UIPopoverArrowDirectionAny;
129118
presentationController.delegate = self;
119+
120+
// Configure anchor using `view` for all iOS devices (not iPad only)
121+
if (dialogView != nil) {
122+
[self configureSourceView:presentationController];
123+
}
130124
}
131125

132126
[self retain];
@@ -161,76 +155,6 @@ - (void)suspended:(NSNotification *)note
161155
}
162156
}
163157

164-
#pragma mark UIPopoverPresentationControllerDelegate
165-
- (void)prepareForPopoverPresentation:(UIPopoverPresentationController *)popoverPresentationController
166-
{
167-
if (dialogView != nil) {
168-
if ([dialogView supportsNavBarPositioning] && [dialogView isUsingBarButtonItem]) {
169-
UIBarButtonItem *theItem = [dialogView barButtonItem];
170-
if (theItem != nil) {
171-
popoverPresentationController.barButtonItem = [dialogView barButtonItem];
172-
return;
173-
}
174-
}
175-
176-
if ([dialogView conformsToProtocol:@protocol(TiToolbar)]) {
177-
UIToolbar *toolbar = [(id<TiToolbar>)dialogView toolbar];
178-
if (toolbar != nil) {
179-
popoverPresentationController.sourceView = toolbar;
180-
popoverPresentationController.sourceRect = [toolbar bounds];
181-
return;
182-
}
183-
}
184-
185-
if ([dialogView conformsToProtocol:@protocol(TiTab)]) {
186-
id<TiTab> tab = (id<TiTab>)dialogView;
187-
UITabBar *tabbar = [[tab tabGroup] tabbar];
188-
if (tabbar != nil) {
189-
popoverPresentationController.sourceView = tabbar;
190-
popoverPresentationController.sourceRect = [tabbar bounds];
191-
return;
192-
}
193-
}
194-
195-
UIView *view = [dialogView view];
196-
if (view != nil) {
197-
popoverPresentationController.sourceView = view;
198-
popoverPresentationController.sourceRect = (CGRectEqualToRect(CGRectZero, dialogRect) ? CGRectMake(view.bounds.size.width / 2, view.bounds.size.height / 2, 1, 1) : dialogRect);
199-
return;
200-
}
201-
}
202-
203-
// Fell through.
204-
UIViewController *presentingController = [alertController presentingViewController];
205-
popoverPresentationController.permittedArrowDirections = 0;
206-
popoverPresentationController.sourceView = [presentingController view];
207-
popoverPresentationController.sourceRect = (CGRectEqualToRect(CGRectZero, dialogRect) ? CGRectMake(presentingController.view.bounds.size.width / 2, presentingController.view.bounds.size.height / 2, 1, 1) : dialogRect);
208-
;
209-
}
210-
211-
- (void)popoverPresentationController:(UIPopoverPresentationController *)popoverPresentationController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView **)view
212-
{
213-
// This will never be called when using bar button item
214-
BOOL canUseDialogRect = !CGRectEqualToRect(CGRectZero, dialogRect);
215-
UIView *theSourceView = *view;
216-
BOOL shouldUseViewBounds = ([theSourceView isKindOfClass:[UIToolbar class]] || [theSourceView isKindOfClass:[UITabBar class]]);
217-
218-
if (shouldUseViewBounds) {
219-
rect->origin = CGPointMake(theSourceView.bounds.origin.x, theSourceView.bounds.origin.y);
220-
rect->size = CGSizeMake(theSourceView.bounds.size.width, theSourceView.bounds.size.height);
221-
} else if (!canUseDialogRect) {
222-
rect->origin = CGPointMake(theSourceView.bounds.size.width / 2, theSourceView.bounds.size.height / 2);
223-
rect->size = CGSizeMake(1, 1);
224-
}
225-
226-
popoverPresentationController.sourceRect = *rect;
227-
}
228-
229-
- (void)popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController
230-
{
231-
[self cleanup];
232-
}
233-
234158
#pragma mark Internal Use Only
235159
- (void)fireClickEventWithAction:(UIAlertAction *)theAction
236160
{
@@ -271,6 +195,51 @@ - (void)cleanup
271195
}
272196
}
273197

198+
- (void)configureSourceView:(UIPopoverPresentationController *)presentationController
199+
{
200+
if ([dialogView isKindOfClass:TiUIButtonProxy.class]) {
201+
if ([dialogView isUsingBarButtonItem]) {
202+
UIBarButtonItem *theItem = [dialogView barButtonItem];
203+
if (theItem != nil) {
204+
presentationController.barButtonItem = theItem;
205+
}
206+
} else {
207+
UIView *btnView = [dialogView view];
208+
if (btnView != nil) {
209+
presentationController.sourceView = btnView;
210+
}
211+
}
212+
} else if ([dialogView supportsNavBarPositioning] && [dialogView isUsingBarButtonItem]) {
213+
UIBarButtonItem *theItem = [dialogView barButtonItem];
214+
if (theItem != nil) {
215+
presentationController.barButtonItem = theItem;
216+
}
217+
} else if ([dialogView conformsToProtocol:@protocol(TiToolbar)]) {
218+
UIToolbar *toolbar = [(id<TiToolbar>)dialogView toolbar];
219+
if (toolbar != nil) {
220+
presentationController.sourceView = toolbar;
221+
}
222+
} else if ([dialogView conformsToProtocol:@protocol(TiTab)]) {
223+
id<TiTab> tab = (id<TiTab>)dialogView;
224+
UITabBar *tabbar = [[tab tabGroup] tabbar];
225+
if (tabbar != nil) {
226+
presentationController.sourceView = tabbar;
227+
}
228+
} else {
229+
UIView *view = [dialogView view];
230+
if (view != nil) {
231+
presentationController.sourceView = view;
232+
}
233+
}
234+
}
235+
236+
#pragma mark UIPopoverPresentationControllerDelegate
237+
238+
- (void)presentationControllerDidDismiss:(UIPresentationController *)presentationController
239+
{
240+
[self cleanup];
241+
}
242+
274243
@end
275244

276245
#endif

0 commit comments

Comments
 (0)