Skip to content

Commit 3df698a

Browse files
committed
4.4.0
1 parent 3c65d4d commit 3df698a

98 files changed

Lines changed: 2585 additions & 2290 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

QMUIConfigurationTemplate/QMUIConfigurationTemplate.m

Lines changed: 31 additions & 16 deletions
Large diffs are not rendered by default.

QMUIKit.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "QMUIKit"
3-
s.version = "4.3.0"
3+
s.version = "4.4.0"
44
s.summary = "致力于提高项目 UI 开发效率的解决方案"
55
s.description = <<-DESC
66
QMUI iOS 是一个致力于提高项目 UI 开发效率的解决方案,其设计目的是用于辅助快速搭建一个具备基本设计还原效果的 iOS 项目,同时利用自身提供的丰富控件及兼容处理, 让开发者能专注于业务需求而无需耗费精力在基础代码的设计上。不管是新项目的创建,或是已有项目的维护,均可使开发效率和项目质量得到大幅度提升。

QMUIKit/QMUIComponents/ImagePickerLibrary/QMUIImagePickerPreviewViewController.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,9 @@ - (void)viewDidLayoutSubviews {
130130
self.topToolBarView.frame = CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), NavigationContentTopConstant);
131131
CGFloat topToolbarPaddingTop = SafeAreaInsetsConstantForDeviceWithNotch.top;
132132
CGFloat topToolbarContentHeight = CGRectGetHeight(self.topToolBarView.bounds) - topToolbarPaddingTop;
133-
self.backButton.frame = CGRectSetXY(self.backButton.frame, 16 + self.view.qmui_safeAreaInsets.left, topToolbarPaddingTop + CGFloatGetCenter(topToolbarContentHeight, CGRectGetHeight(self.backButton.frame)));
133+
self.backButton.frame = CGRectSetXY(self.backButton.frame, 16 + self.view.safeAreaInsets.left, topToolbarPaddingTop + CGFloatGetCenter(topToolbarContentHeight, CGRectGetHeight(self.backButton.frame)));
134134
if (!self.checkboxButton.hidden) {
135-
self.checkboxButton.frame = CGRectSetXY(self.checkboxButton.frame, CGRectGetWidth(self.topToolBarView.frame) - 10 - self.view.qmui_safeAreaInsets.right - CGRectGetWidth(self.checkboxButton.frame), topToolbarPaddingTop + CGFloatGetCenter(topToolbarContentHeight, CGRectGetHeight(self.checkboxButton.frame)));
135+
self.checkboxButton.frame = CGRectSetXY(self.checkboxButton.frame, CGRectGetWidth(self.topToolBarView.frame) - 10 - self.view.safeAreaInsets.right - CGRectGetWidth(self.checkboxButton.frame), topToolbarPaddingTop + CGFloatGetCenter(topToolbarContentHeight, CGRectGetHeight(self.checkboxButton.frame)));
136136
}
137137
}
138138

QMUIKit/QMUIComponents/ImagePickerLibrary/QMUIImagePickerViewController.m

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ - (void)viewDidLayoutSubviews {
146146
if (!CGSizeEqualToSize(self.collectionView.frame.size, self.view.bounds.size)) {
147147
self.collectionView.frame = self.view.bounds;
148148
}
149-
UIEdgeInsets contentInset = UIEdgeInsetsMake(self.qmui_navigationBarMaxYInViewCoordinator, self.collectionView.qmui_safeAreaInsets.left, MAX(operationToolBarViewHeight, self.collectionView.qmui_safeAreaInsets.bottom), self.collectionView.qmui_safeAreaInsets.right);
149+
UIEdgeInsets contentInset = UIEdgeInsetsMake(self.qmui_navigationBarMaxYInViewCoordinator, self.collectionView.safeAreaInsets.left, MAX(operationToolBarViewHeight, self.collectionView.safeAreaInsets.bottom), self.collectionView.safeAreaInsets.right);
150150
if (!UIEdgeInsetsEqualToEdgeInsets(self.collectionView.contentInset, contentInset)) {
151151
self.collectionView.contentInset = contentInset;
152152
self.collectionView.scrollIndicatorInsets = UIEdgeInsetsMake(contentInset.top, 0, contentInset.bottom, 0);
@@ -273,11 +273,7 @@ - (UICollectionView *)collectionView {
273273
_collectionView.backgroundColor = UIColorClear;
274274
[_collectionView registerClass:[QMUIImagePickerCollectionViewCell class] forCellWithReuseIdentifier:kVideoCellIdentifier];
275275
[_collectionView registerClass:[QMUIImagePickerCollectionViewCell class] forCellWithReuseIdentifier:kImageOrUnknownCellIdentifier];
276-
if (@available(iOS 11, *)) {
277-
_collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
278-
} else {
279-
self.automaticallyAdjustsScrollViewInsets = NO;
280-
}
276+
_collectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
281277
}
282278
return _collectionView;
283279
}

QMUIKit/QMUIComponents/NavigationBarTransition/UINavigationBar+Transition.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
@interface UINavigationBar (Transition)
1919

2020
/// 用来模仿真的navBar,配合 UINavigationController+NavigationBarTransition 在转场过程中存在的一条假navBar
21-
@property(nonatomic, strong) UINavigationBar *transitionNavigationBar;
21+
@property(nonatomic, weak) UINavigationBar *qmuinb_copyStylesToBar;
22+
@end
23+
24+
@interface _QMUITransitionNavigationBar : UINavigationBar
2225

26+
// 建立假 bar 到真 bar 的关系,内部会通过 qmuinb_copyStylesToBar 同时设置真 bar 到假 bar 的关系
27+
@property(nonatomic, weak) UINavigationBar *originalNavigationBar;
28+
@property(nonatomic, assign) BOOL shouldPreventAppearance;
2329
@end

QMUIKit/QMUIComponents/NavigationBarTransition/UINavigationBar+Transition.m

Lines changed: 142 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,164 @@
1515

1616
#import "UINavigationBar+Transition.h"
1717
#import "QMUICore.h"
18+
#import "UINavigationBar+QMUI.h"
19+
#import "QMUIWeakObjectContainer.h"
20+
#import "UIImage+QMUI.h"
1821

1922
@implementation UINavigationBar (Transition)
2023

21-
QMUISynthesizeIdStrongProperty(transitionNavigationBar, setTransitionNavigationBar)
22-
2324
+ (void)load {
2425
static dispatch_once_t onceToken;
2526
dispatch_once(&onceToken, ^{
26-
ExtendImplementationOfVoidMethodWithSingleArgument([UINavigationBar class], @selector(setShadowImage:), UIImage *, ^(UINavigationBar *selfObject, UIImage *firstArgv) {
27-
if (selfObject.transitionNavigationBar) {
28-
selfObject.transitionNavigationBar.shadowImage = firstArgv;
27+
28+
#ifdef IOS15_SDK_ALLOWED
29+
if (@available(iOS 15.0, *)) {
30+
ExtendImplementationOfVoidMethodWithSingleArgument([UINavigationBar class], @selector(setStandardAppearance:), UINavigationBarAppearance *, ^(UINavigationBar *selfObject, UINavigationBarAppearance *appearance) {
31+
if (selfObject.qmuinb_copyStylesToBar) {
32+
selfObject.qmuinb_copyStylesToBar.standardAppearance = appearance;
33+
}
34+
});
35+
36+
ExtendImplementationOfVoidMethodWithSingleArgument([UINavigationBar class], @selector(setScrollEdgeAppearance:), UINavigationBarAppearance *, ^(UINavigationBar *selfObject, UINavigationBarAppearance *appearance) {
37+
if (selfObject.qmuinb_copyStylesToBar) {
38+
selfObject.qmuinb_copyStylesToBar.scrollEdgeAppearance = appearance;
39+
}
40+
});
41+
}
42+
#endif
43+
44+
ExtendImplementationOfVoidMethodWithSingleArgument([UINavigationBar class], @selector(setBarStyle:), UIBarStyle, ^(UINavigationBar *selfObject, UIBarStyle barStyle) {
45+
if (selfObject.qmuinb_copyStylesToBar && selfObject.qmuinb_copyStylesToBar.barStyle != barStyle) {
46+
selfObject.qmuinb_copyStylesToBar.barStyle = barStyle;
2947
}
3048
});
3149

32-
ExtendImplementationOfVoidMethodWithSingleArgument([UINavigationBar class], @selector(setBarTintColor:), UIColor *, ^(UINavigationBar *selfObject, UIColor *firstArgv) {
33-
if (selfObject.transitionNavigationBar) {
34-
selfObject.transitionNavigationBar.barTintColor = firstArgv;
50+
ExtendImplementationOfVoidMethodWithSingleArgument([UINavigationBar class], @selector(setBarTintColor:), UIColor *, ^(UINavigationBar *selfObject, UIColor *barTintColor) {
51+
if (selfObject.qmuinb_copyStylesToBar && ![selfObject.qmuinb_copyStylesToBar.barTintColor isEqual:barTintColor]) {
52+
selfObject.qmuinb_copyStylesToBar.barTintColor = barTintColor;
3553
}
3654
});
3755

3856
ExtendImplementationOfVoidMethodWithTwoArguments([UINavigationBar class], @selector(setBackgroundImage:forBarMetrics:), UIImage *, UIBarMetrics, ^(UINavigationBar *selfObject, UIImage *backgroundImage, UIBarMetrics barMetrics) {
39-
if (selfObject.transitionNavigationBar) {
40-
[selfObject.transitionNavigationBar setBackgroundImage:backgroundImage forBarMetrics:barMetrics];
57+
if (selfObject.qmuinb_copyStylesToBar) {
58+
[selfObject.qmuinb_copyStylesToBar setBackgroundImage:backgroundImage forBarMetrics:barMetrics];
59+
}
60+
});
61+
62+
ExtendImplementationOfVoidMethodWithSingleArgument([UINavigationBar class], @selector(setShadowImage:), UIImage *, ^(UINavigationBar *selfObject, UIImage *firstArgv) {
63+
if (selfObject.qmuinb_copyStylesToBar) {
64+
selfObject.qmuinb_copyStylesToBar.shadowImage = firstArgv;
4165
}
4266
});
4367
});
4468
}
4569

70+
static char kAssociatedObjectKey_copyStylesToBar;
71+
- (void)setQmuinb_copyStylesToBar:(UINavigationBar *)copyStylesToBar {
72+
QMUIWeakObjectContainer *weakContainer = objc_getAssociatedObject(self, &kAssociatedObjectKey_copyStylesToBar);
73+
if (!weakContainer) {
74+
weakContainer = [[QMUIWeakObjectContainer alloc] init];
75+
}
76+
weakContainer.object = copyStylesToBar;
77+
objc_setAssociatedObject(self, &kAssociatedObjectKey_copyStylesToBar, weakContainer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
78+
79+
#ifdef IOS15_SDK_ALLOWED
80+
if (@available(iOS 15.0, *)) {
81+
copyStylesToBar.standardAppearance = self.standardAppearance;
82+
copyStylesToBar.scrollEdgeAppearance = self.scrollEdgeAppearance;
83+
} else {
84+
#endif
85+
UIImage *backgroundImage = [self backgroundImageForBarMetrics:UIBarMetricsDefault];
86+
if (backgroundImage && backgroundImage.size.width <= 0 && backgroundImage.size.height <= 0) {
87+
// 假设这里的图片时通过`[UIImage new]`这种形式创建的,那么会navBar会奇怪地显示为系统默认navBar的样式。不知道为什么 navController 设置自己的 navBar 为 [UIImage new] 却没事,所以这里做个保护。
88+
backgroundImage = [UIImage qmui_imageWithColor:UIColorClear];
89+
}
90+
[copyStylesToBar setBackgroundImage:backgroundImage forBarMetrics:UIBarMetricsDefault];
91+
92+
copyStylesToBar.shadowImage = self.shadowImage;
93+
94+
if (copyStylesToBar.barStyle != self.barStyle) {
95+
copyStylesToBar.barStyle = self.barStyle;
96+
}
97+
98+
// setTranslucent 要在 setBackgroundImage 之后,因为 setBackgroundImage 内部会改变 translucent 的值
99+
if (copyStylesToBar.translucent != self.translucent) {
100+
copyStylesToBar.translucent = self.translucent;
101+
}
102+
103+
if (![copyStylesToBar.barTintColor isEqual:self.barTintColor]) {
104+
copyStylesToBar.barTintColor = self.barTintColor;
105+
}
106+
#ifdef IOS15_SDK_ALLOWED
107+
}
108+
#endif
109+
}
110+
111+
- (UINavigationBar *)qmuinb_copyStylesToBar {
112+
return (UINavigationBar *)((QMUIWeakObjectContainer *)objc_getAssociatedObject(self, &kAssociatedObjectKey_copyStylesToBar)).object;
113+
}
114+
115+
@end
116+
117+
@implementation _QMUITransitionNavigationBar
118+
119+
+ (void)load {
120+
static dispatch_once_t onceToken;
121+
dispatch_once(&onceToken, ^{
122+
// iOS 14 开启 customNavigationBarTransitionKey 的情况下转场效果错误
123+
// https://github.com/Tencent/QMUI_iOS/issues/1081
124+
if (@available(iOS 14.0, *)) {
125+
OverrideImplementation([_QMUITransitionNavigationBar class], NSSelectorFromString([NSString stringWithFormat:@"_%@_%@", @"accessibility", @"navigationController"]), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
126+
return ^UINavigationController *(_QMUITransitionNavigationBar *selfObject) {
127+
if (selfObject.originalNavigationBar) {
128+
BeginIgnorePerformSelectorLeaksWarning
129+
return [selfObject.originalNavigationBar performSelector:originCMD];
130+
EndIgnorePerformSelectorLeaksWarning
131+
}
132+
133+
// call super
134+
UINavigationController *(*originSelectorIMP)(id, SEL);
135+
originSelectorIMP = (UINavigationController *(*)(id, SEL))originalIMPProvider();
136+
UINavigationController *result = originSelectorIMP(selfObject, originCMD);
137+
return result;
138+
};
139+
});
140+
}
141+
142+
#ifdef IOS15_SDK_ALLOWED
143+
if (@available(iOS 15.0, *)) {
144+
// -[UINavigationBar _didMoveFromWindow:toWindow:]
145+
OverrideImplementation([_QMUITransitionNavigationBar class], NSSelectorFromString(@"_didMoveFromWindow:toWindow:"), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
146+
return ^(_QMUITransitionNavigationBar *selfObject, UIWindow *firstArgv, UIWindow *secondArgv) {
147+
148+
if (selfObject.shouldPreventAppearance) {
149+
return;
150+
}
151+
152+
// call super
153+
void (*originSelectorIMP)(id, SEL, UIWindow *, UIWindow *);
154+
originSelectorIMP = (void (*)(id, SEL, UIWindow *, UIWindow *))originalIMPProvider();
155+
originSelectorIMP(selfObject, originCMD, firstArgv, secondArgv);
156+
};
157+
});
158+
}
159+
#endif
160+
161+
});
162+
}
163+
164+
- (void)setOriginalNavigationBar:(UINavigationBar *)originBar {
165+
_originalNavigationBar = originBar;
166+
167+
// 只复制当前 originBar 的样式,所以复制完立马就清空
168+
originBar.qmuinb_copyStylesToBar = self;
169+
originBar.qmuinb_copyStylesToBar = nil;
170+
}
171+
172+
- (void)layoutSubviews {
173+
[super layoutSubviews];
174+
// 实测 iOS 11 Beta 1-5 里,自己 init 的 navigationBar.backgroundView.height 默认一直是 44,所以才加上这个兼容
175+
self.qmui_backgroundView.frame = self.bounds;
176+
}
177+
46178
@end

0 commit comments

Comments
 (0)