Skip to content

Commit 2c36881

Browse files
Added preferredContentSize support (see issue #26)
1 parent e430462 commit 2c36881

4 files changed

Lines changed: 192 additions & 64 deletions

File tree

WYPopoverController/WYPopoverController.m

Lines changed: 173 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,14 @@ + (void)load
6363
Method original, swizzle;
6464

6565
original = class_getInstanceMethod(self, @selector(pushViewController:animated:));
66-
6766
swizzle = class_getInstanceMethod(self, @selector(sizzled_pushViewController:animated:));
6867

6968
method_exchangeImplementations(original, swizzle);
69+
70+
original = class_getInstanceMethod(self, @selector(setViewControllers:animated:));
71+
swizzle = class_getInstanceMethod(self, @selector(sizzled_setViewControllers:animated:));
72+
73+
method_exchangeImplementations(original, swizzle);
7074
}
7175

7276
- (BOOL)isEmbedInPopover
@@ -88,23 +92,99 @@ - (void)setEmbedInPopover:(BOOL)value
8892
objc_setAssociatedObject(self, UINavigationControllerEmbedInPopoverTagKey, [NSNumber numberWithBool:value], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
8993
}
9094

91-
- (void)sizzled_pushViewController:(UIViewController *)viewController animated:(BOOL)animated
95+
- (void)sizzled_pushViewController:(UIViewController *)aViewController animated:(BOOL)aAnimated
96+
{
97+
if (self.isEmbedInPopover)
98+
{
99+
#ifdef WY_BASE_SDK_7_ENABLED
100+
if ([aViewController respondsToSelector:@selector(setEdgesForExtendedLayout:)])
101+
{
102+
aViewController.edgesForExtendedLayout = UIRectEdgeNone;
103+
}
104+
#endif
105+
}
106+
107+
[self sizzled_pushViewController:aViewController animated:aAnimated];
108+
}
109+
110+
- (void)sizzled_setViewControllers:(NSArray *)aViewControllers animated:(BOOL)aAnimated
92111
{
93112
if (self.isEmbedInPopover)
94113
{
95114
#ifdef WY_BASE_SDK_7_ENABLED
96-
if ([viewController respondsToSelector:@selector(setEdgesForExtendedLayout:)])
115+
if (aViewControllers && [aViewControllers count] > 0)
97116
{
98-
viewController.edgesForExtendedLayout = UIRectEdgeNone;
117+
for (UIViewController *viewController in aViewControllers) {
118+
if ([viewController respondsToSelector:@selector(setEdgesForExtendedLayout:)])
119+
{
120+
viewController.edgesForExtendedLayout = UIRectEdgeNone;
121+
}
122+
}
99123
}
100124
#endif
101125
}
102126

103-
[self sizzled_pushViewController:viewController animated:animated];
127+
[self sizzled_setViewControllers:aViewControllers animated:aAnimated];
104128
}
105129

106130
@end
107131

132+
////////////////////////////////////////////////////////////////////////////////////////////////////////
133+
134+
@interface UIViewController (WYPopover)
135+
@end
136+
137+
@implementation UIViewController (WYPopover)
138+
139+
+ (void)load
140+
{
141+
Method original, swizzle;
142+
143+
#pragma clang diagnostic push
144+
#pragma GCC diagnostic ignored "-Wdeprecated"
145+
original = class_getInstanceMethod(self, @selector(setContentSizeForViewInPopover:));
146+
swizzle = class_getInstanceMethod(self, @selector(sizzled_setContentSizeForViewInPopover:));
147+
method_exchangeImplementations(original, swizzle);
148+
#pragma clang diagnostic pop
149+
150+
#ifdef WY_BASE_SDK_7_ENABLED
151+
original = class_getInstanceMethod(self, @selector(setPreferredContentSize:));
152+
swizzle = class_getInstanceMethod(self, @selector(sizzled_setPreferredContentSize:));
153+
154+
if (original != NULL) {
155+
method_exchangeImplementations(original, swizzle);
156+
}
157+
#endif
158+
}
159+
160+
- (void)sizzled_setContentSizeForViewInPopover:(CGSize)aSize
161+
{
162+
[self sizzled_setContentSizeForViewInPopover:aSize];
163+
164+
if ([self isKindOfClass:[UINavigationController class]] == NO && self.navigationController != nil)
165+
{
166+
#pragma clang diagnostic push
167+
#pragma GCC diagnostic ignored "-Wdeprecated"
168+
[self.navigationController setContentSizeForViewInPopover:aSize];
169+
#pragma clang diagnostic pop
170+
}
171+
}
172+
173+
- (void)sizzled_setPreferredContentSize:(CGSize)aSize
174+
{
175+
[self sizzled_setPreferredContentSize:aSize];
176+
177+
if ([self isKindOfClass:[UINavigationController class]] == NO && self.navigationController != nil)
178+
{
179+
#ifdef WY_BASE_SDK_7_ENABLED
180+
if ([self respondsToSelector:@selector(setPreferredContentSize:)]) {
181+
[self.navigationController setPreferredContentSize:aSize];
182+
}
183+
#endif
184+
}
185+
}
186+
187+
@end
108188

109189
////////////////////////////////////////////////////////////////////////////////////////////////////////
110190

@@ -1342,7 +1422,7 @@ @interface WYPopoverController () <WYPopoverOverlayViewDelegate>
13421422
WYPopoverAnimationOptions options;
13431423
}
13441424

1345-
@property (nonatomic, assign, readonly) CGSize contentSizeForViewInPopover;
1425+
//@property (nonatomic, assign, readonly) CGSize contentSizeForViewInPopover;
13461426

13471427
- (void)dismissPopoverAnimated:(BOOL)animated
13481428
options:(WYPopoverAnimationOptions)options
@@ -1406,75 +1486,76 @@ - (CGSize)popoverContentSize
14061486
{
14071487
CGSize result = CGSizeZero;
14081488

1409-
#ifdef WY_BASE_SDK_7_ENABLED
1410-
if ([viewController respondsToSelector:@selector(preferredContentSize)])
1411-
{
1412-
result = [viewController preferredContentSize];
1413-
}
1414-
else
1415-
#endif
1489+
UIViewController *topViewController = viewController;
1490+
1491+
if ([viewController isKindOfClass:[UINavigationController class]] == YES)
14161492
{
1417-
#pragma clang diagnostic push
1418-
#pragma GCC diagnostic ignored "-Wdeprecated"
1419-
result = [viewController contentSizeForViewInPopover];
1420-
#pragma clang diagnostic pop
1493+
UINavigationController *navigationController = (UINavigationController *)viewController;
1494+
topViewController = [navigationController topViewController];
14211495
}
14221496

1423-
return result;
1424-
}
1425-
1426-
- (void)setPopoverContentSize:(CGSize)size
1427-
{
14281497
#ifdef WY_BASE_SDK_7_ENABLED
1429-
if ([viewController respondsToSelector:@selector(setPreferredContentSize:)])
1498+
if ([topViewController respondsToSelector:@selector(preferredContentSize)])
14301499
{
1431-
[viewController setPreferredContentSize:size];
1500+
result = topViewController.preferredContentSize;
14321501
}
1433-
else
14341502
#endif
1503+
1504+
if (CGSizeEqualToSize(result, CGSizeZero))
14351505
{
14361506
#pragma clang diagnostic push
14371507
#pragma GCC diagnostic ignored "-Wdeprecated"
1438-
[viewController setContentSizeForViewInPopover:size];
1508+
result = topViewController.contentSizeForViewInPopover;
14391509
#pragma clang diagnostic pop
14401510
}
14411511

1442-
[self positionPopover];
1512+
if (CGSizeEqualToSize(result, CGSizeZero))
1513+
{
1514+
result = CGSizeMake(320, 1100);
1515+
}
1516+
1517+
return result;
14431518
}
14441519

1445-
- (CGSize)contentSizeForViewInPopover
1520+
- (void)setPopoverContentSize:(CGSize)size
14461521
{
1447-
CGSize result = CGSizeZero;
1448-
1449-
UIViewController *controller = viewController;
1522+
UIViewController *topViewController = viewController;
14501523

1451-
if ([controller isKindOfClass:[UINavigationController class]])
1524+
if ([viewController isKindOfClass:[UINavigationController class]] == YES)
14521525
{
1453-
UINavigationController *navigationController = (UINavigationController *)controller;
1454-
1455-
controller = [navigationController visibleViewController];
1526+
UINavigationController *navigationController = (UINavigationController *)viewController;
1527+
topViewController = [navigationController topViewController];
14561528
}
14571529

14581530
#ifdef WY_BASE_SDK_7_ENABLED
1459-
if ([controller respondsToSelector:@selector(preferredContentSize)])
1531+
if ([viewController respondsToSelector:@selector(setPreferredContentSize:)])
14601532
{
1461-
result = controller.preferredContentSize;
1533+
@try {
1534+
[viewController removeObserver:self forKeyPath:NSStringFromSelector(@selector(setPreferredContentSize))];
1535+
}
1536+
@catch (NSException * __unused exception) {}
1537+
1538+
[topViewController setPreferredContentSize:size];
1539+
1540+
[viewController addObserver:self forKeyPath:NSStringFromSelector(@selector(preferredContentSize)) options:0 context:nil];
14621541
}
1542+
else
14631543
#endif
1464-
if (CGSizeEqualToSize(result, CGSizeZero))
14651544
{
14661545
#pragma clang diagnostic push
14671546
#pragma GCC diagnostic ignored "-Wdeprecated"
1468-
result = controller.contentSizeForViewInPopover;
1547+
@try {
1548+
[viewController removeObserver:self forKeyPath:NSStringFromSelector(@selector(contentSizeForViewInPopover))];
1549+
}
1550+
@catch (NSException * __unused exception) {}
1551+
1552+
[topViewController setContentSizeForViewInPopover:size];
1553+
1554+
[viewController addObserver:self forKeyPath:NSStringFromSelector(@selector(contentSizeForViewInPopover)) options:0 context:nil];
14691555
#pragma clang diagnostic pop
14701556
}
14711557

1472-
if (CGSizeEqualToSize(result, CGSizeZero))
1473-
{
1474-
result = CGSizeMake(320, 1100);
1475-
}
1476-
1477-
return result;
1558+
[self positionPopover];
14781559
}
14791560

14801561
- (void)presentPopoverFromRect:(CGRect)aRect
@@ -1532,7 +1613,7 @@ - (void)presentPopoverFromRect:(CGRect)aRect
15321613
animated = aAnimated;
15331614
options = aOptions;
15341615

1535-
CGSize contentViewSize = self.contentSizeForViewInPopover;
1616+
CGSize contentViewSize = self.popoverContentSize;
15361617

15371618
if (overlayView == nil)
15381619
{
@@ -1603,6 +1684,15 @@ - (void)presentPopoverFromRect:(CGRect)aRect
16031684
}
16041685

16051686
strongSelf->containerView.accessibilityViewIsModal = NO;
1687+
1688+
if ([strongSelf->viewController respondsToSelector:@selector(preferredContentSize)])
1689+
{
1690+
[strongSelf->viewController addObserver:self forKeyPath:NSStringFromSelector(@selector(preferredContentSize)) options:0 context:nil];
1691+
}
1692+
else
1693+
{
1694+
[strongSelf->viewController addObserver:self forKeyPath:NSStringFromSelector(@selector(contentSizeForViewInPopover)) options:0 context:nil];
1695+
}
16061696
}
16071697

16081698
if (completion)
@@ -1613,6 +1703,8 @@ - (void)presentPopoverFromRect:(CGRect)aRect
16131703
{
16141704
[strongSelf->delegate popoverControllerDidPresentPopover:strongSelf];
16151705
}
1706+
1707+
16161708
};
16171709

16181710
#ifdef WY_BASE_SDK_7_ENABLED
@@ -1823,24 +1915,23 @@ - (CGAffineTransform)transformForArrowDirection:(WYPopoverArrowDirection)arrowDi
18231915

18241916
- (void)setPopoverNavigationBarBackgroundImage
18251917
{
1826-
if (wantsDefaultContentAppearance == NO && [viewController isKindOfClass:[UINavigationController class]])
1918+
if ([viewController isKindOfClass:[UINavigationController class]] == YES)
18271919
{
18281920
UINavigationController *navigationController = (UINavigationController *)viewController;
18291921
navigationController.embedInPopover = YES;
18301922

1831-
if ([navigationController viewControllers] && [[navigationController viewControllers] count] > 0)
1832-
{
18331923
#ifdef WY_BASE_SDK_7_ENABLED
1834-
UIViewController *firstViewController = (UIViewController *)[[navigationController viewControllers] objectAtIndex:0];
1835-
1836-
if ([firstViewController respondsToSelector:@selector(setEdgesForExtendedLayout:)])
1837-
{
1838-
[firstViewController setEdgesForExtendedLayout:UIRectEdgeNone];
1839-
}
1840-
#endif
1924+
if ([navigationController respondsToSelector:@selector(setEdgesForExtendedLayout:)])
1925+
{
1926+
UIViewController *topViewController = [navigationController topViewController];
1927+
[topViewController setEdgesForExtendedLayout:UIRectEdgeNone];
18411928
}
1929+
#endif
18421930

1843-
[navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:[UIColor clearColor]] forBarMetrics:UIBarMetricsDefault];
1931+
if (wantsDefaultContentAppearance == NO)
1932+
{
1933+
[navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:[UIColor clearColor]] forBarMetrics:UIBarMetricsDefault];
1934+
}
18441935
}
18451936

18461937
viewController.view.clipsToBounds = YES;
@@ -1855,7 +1946,7 @@ - (void)positionPopover
18551946
{
18561947
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
18571948

1858-
CGSize contentViewSize = self.contentSizeForViewInPopover;
1949+
CGSize contentViewSize = self.popoverContentSize;
18591950
CGSize minContainerSize = WY_POPOVER_MIN_SIZE;
18601951

18611952
CGRect viewFrame;
@@ -2116,8 +2207,6 @@ - (void)positionPopover
21162207

21172208
containerFrame = CGRectIntegral(containerFrame);
21182209

2119-
containerView.frame = containerFrame;
2120-
21212210
containerView.wantsDefaultContentAppearance = wantsDefaultContentAppearance;
21222211

21232212
[containerView setViewController:viewController];
@@ -2145,9 +2234,7 @@ - (void)positionPopover
21452234
containerFrame = containerView.frame;
21462235

21472236
containerFrame.origin = WYPointRelativeToOrientation(containerOrigin, containerFrame.size, orientation);
2148-
2149-
2150-
2237+
21512238
containerView.frame = containerFrame;
21522239
}
21532240

@@ -2285,6 +2372,15 @@ - (void)dismissPopoverAnimated:(BOOL)aAnimated
22852372
[viewController viewWillDisappear:aAnimated];
22862373
}
22872374

2375+
@try {
2376+
if ([viewController respondsToSelector:@selector(preferredContentSize)]) {
2377+
[viewController removeObserver:self forKeyPath:NSStringFromSelector(@selector(preferredContentSize))];
2378+
} else {
2379+
[viewController removeObserver:self forKeyPath:NSStringFromSelector(@selector(contentSizeForViewInPopover))];
2380+
}
2381+
}
2382+
@catch (NSException * __unused exception) {}
2383+
22882384
if (aAnimated)
22892385
{
22902386
[UIView animateWithDuration:duration animations:^{
@@ -2315,6 +2411,20 @@ - (void)dismissPopoverAnimated:(BOOL)aAnimated
23152411
overlayView.isAccessibilityElement = NO;
23162412
}
23172413

2414+
#pragma mark KVO
2415+
2416+
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
2417+
{
2418+
if (object == viewController)
2419+
{
2420+
if ([keyPath isEqualToString:NSStringFromSelector(@selector(preferredContentSize))]
2421+
|| [keyPath isEqualToString:NSStringFromSelector(@selector(contentSizeForViewInPopover))])
2422+
{
2423+
[self positionPopover];
2424+
}
2425+
}
2426+
}
2427+
23182428
#pragma mark WYPopoverOverlayViewDelegate
23192429

23202430
- (void)popoverOverlayView:(WYPopoverOverlayView *)aOverlayView didTouchAtPoint:(CGPoint)aPoint
@@ -2708,7 +2818,6 @@ - (void)keyboardWillShow:(NSNotification *)notification
27082818
UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
27092819

27102820
WY_LOG(@"orientation = %@", WYStringFromOrientation(orientation));
2711-
27122821
WY_LOG(@"keyboardRect = %@", NSStringFromCGRect(keyboardRect));
27132822

27142823
[self positionPopover];

demos/Demo/WYPopoverDemo/WYAnotherViewController.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,9 @@
99
#import <UIKit/UIKit.h>
1010

1111
@interface WYAnotherViewController : UIViewController
12+
{
13+
}
14+
15+
- (IBAction)resizeme:(id)sender;
1216

1317
@end

0 commit comments

Comments
 (0)