Skip to content

Commit

Permalink
4.7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
molicechen committed Jul 24, 2023
1 parent cc0c1d6 commit b2f7f48
Show file tree
Hide file tree
Showing 43 changed files with 632 additions and 163 deletions.
1 change: 0 additions & 1 deletion QMUIConfigurationTemplate/QMUIConfigurationTemplate.m
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,6 @@ - (void)applyConfigurationTemplate {
QMUICMI.shouldFixTabBarSafeAreaInsetsBug = NO; // ShouldFixTabBarSafeAreaInsetsBug : 是否要对 iOS 11 及以后的版本修复当存在 UITabBar 时,UIScrollView 的 inset.bottom 可能错误的 bug(issue #218 #934),默认为 YES
QMUICMI.shouldFixSearchBarMaskViewLayoutBug = NO; // ShouldFixSearchBarMaskViewLayoutBug : 是否自动修复 UISearchController.searchBar 被当作 tableHeaderView 使用时可能出现的布局 bug(issue #950)
QMUICMI.shouldPrintQMUIWarnLogToConsole = IS_DEBUG; // ShouldPrintQMUIWarnLogToConsole : 是否在出现 QMUILogWarn 时自动把这些 log 以 QMUIConsole 的方式显示到设备屏幕上
QMUICMI.sendAnalyticsToQMUITeam = YES; // SendAnalyticsToQMUITeam : 是否允许在 DEBUG 模式下上报 Bundle Identifier 和 Display Name 给 QMUI 统计用
QMUICMI.dynamicPreferredValueForIPad = NO; // DynamicPreferredValueForIPad : 当 iPad 处于 Slide Over 或 Split View 分屏模式下,宏 `PreferredValueForXXX` 是否把 iPad 视为某种屏幕宽度近似的 iPhone 来取值。
QMUICMI.ignoreKVCAccessProhibited = NO; // IgnoreKVCAccessProhibited : 是否全局忽略 iOS 13 对 KVC 访问 UIKit 私有属性的限制
QMUICMI.adjustScrollIndicatorInsetsByContentInsetAdjustment = NO; // AdjustScrollIndicatorInsetsByContentInsetAdjustment : 当将 UIScrollView.contentInsetAdjustmentBehavior 设为 UIScrollViewContentInsetAdjustmentNever 时,是否自动将 UIScrollView.automaticallyAdjustsScrollIndicatorInsets 设为 NO,以保证原本在 iOS 12 下的代码不用修改就能在 iOS 13 下正常控制滚动条的位置。
Expand Down
6 changes: 3 additions & 3 deletions QMUIKit.podspec
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
Pod::Spec.new do |s|
s.name = "QMUIKit"
s.version = "4.6.3"
s.version = "4.7.0"
s.summary = "致力于提高项目 UI 开发效率的解决方案"
s.description = <<-DESC
QMUI iOS 是一个致力于提高项目 UI 开发效率的解决方案,其设计目的是用于辅助快速搭建一个具备基本设计还原效果的 iOS 项目,同时利用自身提供的丰富控件及兼容处理, 让开发者能专注于业务需求而无需耗费精力在基础代码的设计上。不管是新项目的创建,或是已有项目的维护,均可使开发效率和项目质量得到大幅度提升。
DESC
s.homepage = "https://qmuiteam.com/ios"
s.homepage = "https://github.com/Tencent/QMUI_iOS"
s.license = 'MIT'
s.author = {"qmuiteam" => "[email protected]"}
s.source = {:git => "https://github.com/Tencent/QMUI_iOS.git", :tag => s.version.to_s}
#s.source = {:git => "https://github.com/Tencent/QMUI_iOS.git", :branch => 'master'}
s.social_media_url = 'https://github.com/Tencent/QMUI_iOS'
s.requires_arc = true
s.documentation_url = 'https://qmuiteam.com/ios/page/document.html'
s.documentation_url = 'https://github.com/Tencent/QMUI_iOS'
s.screenshot = 'https://cloud.githubusercontent.com/assets/1190261/26751376/63f96538-486a-11e7-81cf-5bc83a945207.png'

s.platform = :ios, '13.0'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,16 @@ - (void)viewWillAppear:(BOOL)animated {
[self.collectionView reloadData];
}

- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];

// 在 pop 回相簿列表时重置标志位以使下次进来 picker 时 collection 可以滚动到正确的初始位置
// 但不能影响从 picker 进入大图的路径
if (self.navigationController && ![self.navigationController.viewControllers containsObject:self]) {
self.hasScrollToInitialPosition = NO;
}
}

- (void)showEmptyView {
[super showEmptyView];
self.emptyView.backgroundColor = self.view.backgroundColor; // 为了盖住背后的 collectionView,这里加个背景色(不盖住的话会看到 collectionView 先滚到列表顶部然后跳到列表底部)
Expand Down Expand Up @@ -244,10 +254,6 @@ - (void)scrollToInitialPositionIfNeeded {
}
}

- (void)willPopInNavigationControllerWithAnimated:(BOOL)animated {
self.hasScrollToInitialPosition = NO;
}

#pragma mark - Getters & Setters

@synthesize collectionViewLayout = _collectionViewLayout;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@

@interface _QMUITransitionNavigationBar : UINavigationBar

@property(nonatomic, weak) UIViewController *parentViewController;

// 建立假 bar 到真 bar 的关系,内部会通过 qmuinb_copyStylesToBar 同时设置真 bar 到假 bar 的关系
@property(nonatomic, weak) UINavigationBar *originalNavigationBar;

@property(nonatomic, assign) BOOL shouldPreventAppearance;

// 根据当前的系统导航栏布局,刷新自身在 vc.view 上的布局
- (void)updateLayout;
@end
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,63 @@ + (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{

#ifdef IOS15_SDK_ALLOWED
if (@available(iOS 15.0, *)) {
ExtendImplementationOfVoidMethodWithSingleArgument([UINavigationBar class], @selector(setStandardAppearance:), UINavigationBarAppearance *, ^(UINavigationBar *selfObject, UINavigationBarAppearance *appearance) {
if (selfObject.qmuinb_copyStylesToBar) {
selfObject.qmuinb_copyStylesToBar.standardAppearance = appearance;
}

OverrideImplementation([UINavigationBar class], @selector(setStandardAppearance:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
return ^(UINavigationBar *selfObject, UINavigationBarAppearance *appearance) {

// call super
void (*originSelectorIMP)(id, SEL, UINavigationBarAppearance *);
originSelectorIMP = (void (*)(id, SEL, UINavigationBarAppearance *))originalIMPProvider();
originSelectorIMP(selfObject, originCMD, appearance);

if (selfObject.qmuinb_copyStylesToBar) {
selfObject.qmuinb_copyStylesToBar.standardAppearance = appearance;
}
};
});

ExtendImplementationOfVoidMethodWithSingleArgument([UINavigationBar class], @selector(setScrollEdgeAppearance:), UINavigationBarAppearance *, ^(UINavigationBar *selfObject, UINavigationBarAppearance *appearance) {
if (selfObject.qmuinb_copyStylesToBar) {
selfObject.qmuinb_copyStylesToBar.scrollEdgeAppearance = appearance;
}
OverrideImplementation([UINavigationBar class], @selector(setScrollEdgeAppearance:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
return ^(UINavigationBar *selfObject, UINavigationBarAppearance *appearance) {

// call super
void (*originSelectorIMP)(id, SEL, UINavigationBarAppearance *);
originSelectorIMP = (void (*)(id, SEL, UINavigationBarAppearance *))originalIMPProvider();
originSelectorIMP(selfObject, originCMD, appearance);

if (selfObject.qmuinb_copyStylesToBar) {
selfObject.qmuinb_copyStylesToBar.standardAppearance = appearance;
}
};
});
}
#endif

ExtendImplementationOfVoidMethodWithSingleArgument([UINavigationBar class], @selector(setBarStyle:), UIBarStyle, ^(UINavigationBar *selfObject, UIBarStyle barStyle) {
if (selfObject.qmuinb_copyStylesToBar && selfObject.qmuinb_copyStylesToBar.barStyle != barStyle) {
selfObject.qmuinb_copyStylesToBar.barStyle = barStyle;
}
OverrideImplementation([UINavigationBar class], @selector(setBarStyle:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
return ^(UINavigationBar *selfObject, UIBarStyle barStyle) {

// call super
void (*originSelectorIMP)(id, SEL, UIBarStyle);
originSelectorIMP = (void (*)(id, SEL, UIBarStyle))originalIMPProvider();
originSelectorIMP(selfObject, originCMD, barStyle);

if (selfObject.qmuinb_copyStylesToBar && selfObject.qmuinb_copyStylesToBar.barStyle != barStyle) {
selfObject.qmuinb_copyStylesToBar.barStyle = barStyle;
}
};
});

ExtendImplementationOfVoidMethodWithSingleArgument([UINavigationBar class], @selector(setBarTintColor:), UIColor *, ^(UINavigationBar *selfObject, UIColor *barTintColor) {
if (selfObject.qmuinb_copyStylesToBar && ![selfObject.qmuinb_copyStylesToBar.barTintColor isEqual:barTintColor]) {
selfObject.qmuinb_copyStylesToBar.barTintColor = barTintColor;
}
OverrideImplementation([UINavigationBar class], @selector(setBarTintColor:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
return ^(UINavigationBar *selfObject, UIColor *barTintColor) {

// call super
void (*originSelectorIMP)(id, SEL, UIColor *);
originSelectorIMP = (void (*)(id, SEL, UIColor *))originalIMPProvider();
originSelectorIMP(selfObject, originCMD, barTintColor);

if (selfObject.qmuinb_copyStylesToBar && ![selfObject.qmuinb_copyStylesToBar.barTintColor isEqual:barTintColor]) {
selfObject.qmuinb_copyStylesToBar.barTintColor = barTintColor;
}
};
});

OverrideImplementation([UINavigationBar class], @selector(setBackgroundImage:forBarMetrics:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
Expand All @@ -68,10 +99,18 @@ + (void)load {
};
});

ExtendImplementationOfVoidMethodWithSingleArgument([UINavigationBar class], @selector(setShadowImage:), UIImage *, ^(UINavigationBar *selfObject, UIImage *firstArgv) {
if (selfObject.qmuinb_copyStylesToBar) {
selfObject.qmuinb_copyStylesToBar.shadowImage = firstArgv;
}
OverrideImplementation([UINavigationBar class], @selector(setShadowImage:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
return ^(UINavigationBar *selfObject, UIImage *shadowImage) {

// call super
void (*originSelectorIMP)(id, SEL, UIImage *);
originSelectorIMP = (void (*)(id, SEL, UIImage *))originalIMPProvider();
originSelectorIMP(selfObject, originCMD, shadowImage);

if (selfObject.qmuinb_copyStylesToBar) {
selfObject.qmuinb_copyStylesToBar.shadowImage = shadowImage;
}
};
});

OverrideImplementation([UINavigationBar class], @selector(setQmui_effect:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
Expand Down Expand Up @@ -211,6 +250,8 @@ - (void)setOriginalNavigationBar:(UINavigationBar *)originBar {
// 只复制当前 originBar 的样式,所以复制完立马就清空
originBar.qmuinb_copyStylesToBar = self;
originBar.qmuinb_copyStylesToBar = nil;

[self updateLayout];
}

- (void)layoutSubviews {
Expand All @@ -228,4 +269,13 @@ - (void)didAddSubview:(UIView *)subview {
}
}

- (void)updateLayout {
if ([self.parentViewController isViewLoaded] && self.originalNavigationBar) {
[self.parentViewController.view bringSubviewToFront:self];
UIView *backgroundView = self.originalNavigationBar.qmui_backgroundView;
CGRect rect = [backgroundView.superview convertRect:backgroundView.frame toView:self.parentViewController.view];
self.frame = CGRectSetX(rect, 0);// push/pop 过程中系统的导航栏转换过来的 x 可能是 112、-112
}
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ + (void)load {
switch (action) {
case QMUINavigationActionDidPush:
case QMUINavigationActionWillPop:
case QMUINavigationActionWillSet: {
case QMUINavigationActionDidSet: {
BOOL shouldCustomNavigationBarTransition =
[weakNavigationController shouldCustomTransitionAutomaticallyForOperation:UINavigationControllerOperationPush firstViewController:disappearingViewController secondViewController:appearingViewController];
if (shouldCustomNavigationBarTransition) {
Expand Down Expand Up @@ -173,9 +173,7 @@ + (void)load {

OverrideImplementation([UIViewController class], @selector(viewWillLayoutSubviews), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
return ^(UIViewController *selfObject) {
if (selfObject.transitionNavigationBar) {
[selfObject layoutTransitionNavigationBar];
}
[selfObject.transitionNavigationBar updateLayout];

// call super
void (*originSelectorIMP)(id, SEL);
Expand Down Expand Up @@ -233,24 +231,26 @@ - (void)addTransitionNavigationBarAndBindNavigationBar:(BOOL)shouldBind {
}

_QMUITransitionNavigationBar *customBar = [[_QMUITransitionNavigationBar alloc] init];
customBar.parentViewController = self;
self.transitionNavigationBar = customBar;

// iOS 15 里,假 bar 在 add 到界面上时会被强制同步为 UIAppearance 的值,不管你之前是否设置过自己的样式。而且在那个 runloop 内不管你后续怎么更新 standardAppearance,都会呈现出 UIAppearance 里的统一的值的样式。所以这里一方面屏蔽 didMoveToWindow,从而避免在这时候应用 UIAppearance,另一方面要保证先 add 到界面上再同步当前导航栏的样式。
// 经测试只有 push 时需要这么处理,pop 没问题
// 经测试只有 push 或 push 动画的 set 需要这么处理,pop 及 pop 动画的 set 没问题
// iOS 14 及以下没这种问题。
#ifdef IOS15_SDK_ALLOWED
// https://github.com/Tencent/QMUI_iOS/issues/1501
if (@available(iOS 15.0, *)) {
if (self.navigationController.qmui_navigationAction == QMUINavigationActionDidPush) {
BOOL isPush = self.navigationController.qmui_navigationAction == QMUINavigationActionDidPush;
BOOL isSet = self.navigationController.qmui_navigationAction == QMUINavigationActionDidSet;
BOOL isPopAnimation = isSet && self.navigationController.qmui_lastOperation == UINavigationControllerOperationPop;
if (isPush || (isSet && !isPopAnimation)) {
customBar.shouldPreventAppearance = YES;
}
}
#endif
[self.view addSubview:customBar];
customBar.originalNavigationBar = self.navigationController.navigationBar;// 注意这里内部不会保留真 bar 和假 bar 的 copy 关系
if (shouldBind) {
self.navigationController.navigationBar.qmuinb_copyStylesToBar = customBar;
}
[self layoutTransitionNavigationBar];
}

- (void)removeTransitionNavigationBar {
Expand All @@ -264,15 +264,6 @@ - (void)removeTransitionNavigationBar {
}
}

- (void)layoutTransitionNavigationBar {
if (self.isViewLoaded && self.navigationController) {
UIView *backgroundView = self.navigationController.navigationBar.qmui_backgroundView;
CGRect rect = [backgroundView.superview convertRect:backgroundView.frame toView:self.view];
self.transitionNavigationBar.frame = CGRectSetX(rect, 0);// push/pop 过程中系统的导航栏转换过来的 x 可能是 112、-112
[self.view bringSubviewToFront:self.transitionNavigationBar];// 避免在后续被其他 subviews 盖住
}
}

#pragma mark - 工具方法

// 根据当前的viewController,统一处理导航栏的显隐、样式
Expand Down
4 changes: 2 additions & 2 deletions QMUIKit/QMUIComponents/QMUIAlertController.m
Original file line number Diff line number Diff line change
Expand Up @@ -759,7 +759,7 @@ - (void)viewDidLayoutSubviews {
}
// 把上下的margin都加上用于跟整个屏幕的高度做比较
CGFloat contentHeight = contentOriginY + UIEdgeInsetsGetVerticalValue(self.sheetContentMargin);
CGFloat screenSpaceHeight = CGRectGetHeight(self.view.bounds);
CGFloat screenSpaceHeight = CGRectGetHeight(self.view.bounds) - SafeAreaInsetsConstantForDeviceWithNotch.top - (self.isExtendBottomLayout ? 0 : SafeAreaInsetsConstantForDeviceWithNotch.bottom);
if (contentHeight > screenSpaceHeight) {
CGFloat cancelButtonAreaHeight = (self.cancelAction ? (CGRectGetHeight(self.cancelAction.button.bounds) + self.sheetCancelButtonMarginTop) : 0);
screenSpaceHeight = screenSpaceHeight - cancelButtonAreaHeight - UIEdgeInsetsGetVerticalValue(self.sheetContentMargin);
Expand Down Expand Up @@ -789,7 +789,7 @@ - (void)viewDidLayoutSubviews {
contentHeight -= self.sheetContentMargin.top;
}

self.containerView.qmui_frameApplyTransform = CGRectMake((CGRectGetWidth(self.view.bounds) - CGRectGetWidth(self.containerView.frame)) / 2, screenSpaceHeight - contentHeight - SafeAreaInsetsConstantForDeviceWithNotch.bottom, CGRectGetWidth(self.containerView.frame), contentHeight + (self.isExtendBottomLayout ? SafeAreaInsetsConstantForDeviceWithNotch.bottom : 0));
self.containerView.qmui_frameApplyTransform = CGRectMake((CGRectGetWidth(self.view.bounds) - CGRectGetWidth(self.containerView.frame)) / 2, SafeAreaInsetsConstantForDeviceWithNotch.top + screenSpaceHeight - contentHeight, CGRectGetWidth(self.containerView.frame), contentHeight + (self.isExtendBottomLayout ? SafeAreaInsetsConstantForDeviceWithNotch.bottom : 0));

self.extendLayer.frame = CGRectFlatMake(0, CGRectGetHeight(self.containerView.bounds) - SafeAreaInsetsConstantForDeviceWithNotch.bottom - 1, CGRectGetWidth(self.containerView.bounds), SafeAreaInsetsConstantForDeviceWithNotch.bottom + 1);
}
Expand Down
Loading

0 comments on commit b2f7f48

Please sign in to comment.