Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
MoLice authored Aug 10, 2022
2 parents 61b4309 + 0e7d274 commit 0ee53a9
Show file tree
Hide file tree
Showing 60 changed files with 1,026 additions and 510 deletions.
7 changes: 6 additions & 1 deletion QMUIKit.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "QMUIKit"
s.version = "4.4.3"
s.version = "4.5.0"
s.summary = "致力于提高项目 UI 开发效率的解决方案"
s.description = <<-DESC
QMUI iOS 是一个致力于提高项目 UI 开发效率的解决方案,其设计目的是用于辅助快速搭建一个具备基本设计还原效果的 iOS 项目,同时利用自身提供的丰富控件及兼容处理, 让开发者能专注于业务需求而无需耗费精力在基础代码的设计上。不管是新项目的创建,或是已有项目的维护,均可使开发效率和项目质量得到大幅度提升。
Expand Down Expand Up @@ -41,6 +41,11 @@ Pod::Spec.new do |s|

s.subspec 'QMUIResources' do |ss|
ss.resource_bundles = {'QMUIResources' => ['QMUIKit/QMUIResources/*.*']}
ss.pod_target_xcconfig = {
'EXPANDED_CODE_SIGN_IDENTITY' => '',
'CODE_SIGNING_REQUIRED' => 'NO',
'CODE_SIGNING_ALLOWED' => 'NO',
}
end

s.subspec 'QMUIWeakObjectContainer' do |ss|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#import "UINavigationBar+Transition.h"
#import "QMUICore.h"
#import "UINavigationBar+QMUI.h"
#import "UINavigationBar+QMUIBarProtocol.h"
#import "QMUIWeakObjectContainer.h"
#import "UIImage+QMUI.h"

Expand Down Expand Up @@ -53,17 +54,53 @@ + (void)load {
}
});

ExtendImplementationOfVoidMethodWithTwoArguments([UINavigationBar class], @selector(setBackgroundImage:forBarMetrics:), UIImage *, UIBarMetrics, ^(UINavigationBar *selfObject, UIImage *backgroundImage, UIBarMetrics barMetrics) {
if (selfObject.qmuinb_copyStylesToBar) {
[selfObject.qmuinb_copyStylesToBar setBackgroundImage:backgroundImage forBarMetrics:barMetrics];
}
OverrideImplementation([UINavigationBar class], @selector(setBackgroundImage:forBarPosition:barMetrics:), ^id(__unsafe_unretained Class originClass, SEL originCMD, IMP (^originalIMPProvider)(void)) {
return ^(UINavigationBar *selfObject, UIImage *image, UIBarPosition barPosition, UIBarMetrics barMetrics) {

// call super
void (*originSelectorIMP)(id, SEL, UIImage *, UIBarPosition, UIBarMetrics);
originSelectorIMP = (void (*)(id, SEL, UIImage *, UIBarPosition, UIBarMetrics))originalIMPProvider();
originSelectorIMP(selfObject, originCMD, image, barPosition, barMetrics);

if (selfObject.qmuinb_copyStylesToBar) {
[selfObject.qmuinb_copyStylesToBar setBackgroundImage:image forBarPosition:barPosition barMetrics:barMetrics];
}
};
});

ExtendImplementationOfVoidMethodWithSingleArgument([UINavigationBar class], @selector(setShadowImage:), UIImage *, ^(UINavigationBar *selfObject, UIImage *firstArgv) {
if (selfObject.qmuinb_copyStylesToBar) {
selfObject.qmuinb_copyStylesToBar.shadowImage = firstArgv;
}
});

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

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

if (selfObject.qmuinb_copyStylesToBar) {
selfObject.qmuinb_copyStylesToBar.qmui_effect = firstArgv;
}
};
});

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

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

if (selfObject.qmuinb_copyStylesToBar) {
selfObject.qmuinb_copyStylesToBar.qmui_effectForegroundColor = firstArgv;
}
};
});
});
}

Expand Down Expand Up @@ -105,9 +142,13 @@ - (void)setQmuinb_copyStylesToBar:(UINavigationBar *)copyStylesToBar {
if (![copyStylesToBar.barTintColor isEqual:self.barTintColor]) {
copyStylesToBar.barTintColor = self.barTintColor;
}

#ifdef IOS15_SDK_ALLOWED
}
#endif

copyStylesToBar.qmui_effect = self.qmui_effect;
copyStylesToBar.qmui_effectForegroundColor = self.qmui_effectForegroundColor;
}

- (UINavigationBar *)qmuinb_copyStylesToBar {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#import "UINavigationBar+Transition.h"
#import "QMUINavigationTitleView.h"
#import "UINavigationBar+QMUI.h"
#import "UINavigationBar+QMUIBarProtocol.h"
#import "UIView+QMUI.h"
#import "QMUILog.h"

Expand Down Expand Up @@ -260,6 +261,7 @@ - (void)layoutTransitionNavigationBar {
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 盖住
}
}

Expand Down
4 changes: 2 additions & 2 deletions QMUIKit/QMUIComponents/QMUIAlertController.m
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ - (void)viewDidLayoutSubviews {
self.buttonScrollView.contentSize = CGSizeMake(CGRectGetWidth(self.buttonScrollView.bounds), contentOriginY);
// 容器最后布局
CGFloat contentHeight = CGRectGetHeight(self.headerScrollView.bounds) + CGRectGetHeight(self.buttonScrollView.bounds);
CGFloat screenSpaceHeight = CGRectGetHeight(self.view.bounds);
CGFloat screenSpaceHeight = CGRectGetHeight(self.view.bounds) - UIEdgeInsetsGetVerticalValue(SafeAreaInsetsConstantForDeviceWithNotch);
if (contentHeight > screenSpaceHeight - 20) {
screenSpaceHeight -= 20;
CGFloat contentH = fmin(CGRectGetHeight(self.headerScrollView.bounds), screenSpaceHeight / 2);
Expand All @@ -649,7 +649,7 @@ - (void)viewDidLayoutSubviews {
self.scrollWrapView.frame = CGRectMake(0, 0, CGRectGetWidth(self.scrollWrapView.bounds), contentHeight);
self.mainVisualEffectView.frame = self.scrollWrapView.bounds;

self.containerView.qmui_frameApplyTransform = CGRectMake((CGRectGetWidth(self.view.bounds) - CGRectGetWidth(self.containerView.frame)) / 2, (screenSpaceHeight - contentHeight - self.keyboardHeight) / 2, CGRectGetWidth(self.containerView.frame), CGRectGetHeight(self.scrollWrapView.bounds));
self.containerView.qmui_frameApplyTransform = CGRectMake((CGRectGetWidth(self.view.bounds) - CGRectGetWidth(self.containerView.frame)) / 2, SafeAreaInsetsConstantForDeviceWithNotch.top + (screenSpaceHeight - contentHeight - self.keyboardHeight) / 2, CGRectGetWidth(self.containerView.frame), CGRectGetHeight(self.scrollWrapView.bounds));
}

else if (self.preferredStyle == QMUIAlertControllerStyleActionSheet) {
Expand Down
1 change: 0 additions & 1 deletion QMUIKit/QMUIComponents/QMUIButton/QMUIButton.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

#import "QMUIButton.h"
#import "QMUICore.h"
#import "QMUILog.h"
#import "CALayer+QMUI.h"
#import "UIButton+QMUI.h"

Expand Down
1 change: 0 additions & 1 deletion QMUIKit/QMUIComponents/QMUIButton/QMUINavigationButton.m
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#import "UIColor+QMUI.h"
#import "UIViewController+QMUI.h"
#import "QMUINavigationController.h"
#import "QMUILog.h"
#import "UIControl+QMUI.h"
#import "UIView+QMUI.h"
#import "NSString+QMUI.h"
Expand Down
47 changes: 31 additions & 16 deletions QMUIKit/QMUIComponents/QMUIConsole/QMUIConsole.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,37 @@
#import "UIColor+QMUI.h"
#import "QMUITextView.h"

/// 定义一个 class 只是为了在 Lookin 里表达这是一个 console window 而已,不需要实现什么东西
@interface QMUIConsoleWindow : UIWindow
@end

@implementation QMUIConsoleWindow

- (instancetype)init {
if (self = [super init]) {
self.backgroundColor = nil;
if (QMUICMIActivated) {
self.windowLevel = UIWindowLevelQMUIConsole;
} else {
self.windowLevel = 1;
}
self.qmui_capturesStatusBarAppearance = NO;
}
return self;
}

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
// 当显示 QMUIConsole 时,点击空白区域,consoleViewController hitTest 会 return nil,从而将事件传递给 window,再由 window hitTest return nil 来把事件传递给 UIApplication.delegate.window。但在 iPad 12-inch 里,当 consoleViewController hitTest return nil 后,事件会错误地传递给 consoleViewController.view.superview(而不是 consoleWindow),不清楚原因,暂时做一下保护
// https://github.com/Tencent/QMUI_iOS/issues/1169
UIView *originalView = [super hitTest:point withEvent:event];
return originalView == self || originalView == self.rootViewController.view.superview ? nil : originalView;
}

@end

@interface QMUIConsole ()

@property(nonatomic, strong) UIWindow *consoleWindow;
@property(nonatomic, strong) QMUIConsoleWindow *consoleWindow;
@property(nonatomic, strong) QMUIConsoleViewController *consoleViewController;
@end

Expand Down Expand Up @@ -65,6 +93,7 @@ + (id)allocWithZone:(struct _NSZone *)zone{

+ (void)logWithLevel:(NSString *)level name:(NSString *)name logString:(id)logString {
QMUIConsole *console = [QMUIConsole sharedInstance];
if (!QMUIConsole.sharedInstance.canShow) return;
[console initConsoleWindowIfNeeded];
[console.consoleViewController logWithLevel:level name:name logString:logString];
if (console.showConsoleAutomatically) {
Expand Down Expand Up @@ -105,21 +134,7 @@ + (void)hide {

- (void)initConsoleWindowIfNeeded {
if (!self.consoleWindow) {
self.consoleWindow = [[UIWindow alloc] init];
self.consoleWindow.backgroundColor = nil;
if (QMUICMIActivated) {
self.consoleWindow.windowLevel = UIWindowLevelQMUIConsole;
} else {
self.consoleWindow.windowLevel = 1;
}
self.consoleWindow.qmui_capturesStatusBarAppearance = NO;
__weak __typeof(self)weakSelf = self;
self.consoleWindow.qmui_hitTestBlock = ^__kindof UIView * _Nonnull(CGPoint point, UIEvent * _Nonnull event, __kindof UIView * _Nonnull originalView) {
// 当显示 QMUIConsole 时,点击空白区域,consoleViewController hitTest 会 return nil,从而将事件传递给 window,再由 window hitTest return nil 来把事件传递给 UIApplication.delegate.window。但在 iPad 12-inch 里,当 consoleViewController hitTest return nil 后,事件会错误地传递给 consoleViewController.view.superview(而不是 consoleWindow),不清楚原因,暂时做一下保护
// https://github.com/Tencent/QMUI_iOS/issues/1169
return originalView == weakSelf.consoleWindow || originalView == weakSelf.consoleViewController.view.superview ? nil : originalView;
};

self.consoleWindow = [[QMUIConsoleWindow alloc] init];
self.consoleViewController = [[QMUIConsoleViewController alloc] init];
self.consoleWindow.rootViewController = self.consoleViewController;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ @implementation QMUIConsoleLogItemCell

- (void)didInitializeWithStyle:(UITableViewCellStyle)style {
[super didInitializeWithStyle:style];
self.backgroundColor = nil;
self.backgroundColor = UIColor.clearColor;
self.selectionStyle = UITableViewCellSelectionStyleNone;

self.textView = [[QMUITextView alloc] init];
Expand Down
2 changes: 1 addition & 1 deletion QMUIKit/QMUIComponents/QMUIDialogViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -450,8 +450,8 @@ - (void)didInitialize {
self.selectedItemIndexes = [[NSMutableSet alloc] init];

self.tableView = [[QMUITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.tableView.alwaysBounceVertical = NO;
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ - (void)didInitializedWithFrame:(CGRect)frame {
self.collectionViewLayout.allowsMultipleItemScroll = NO;

_collectionView = [[UICollectionView alloc] initWithFrame:CGRectMakeWithSize(frame.size) collectionViewLayout:self.collectionViewLayout];
self.collectionView.delegate = self;
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
self.collectionView.backgroundColor = UIColorClear;
self.collectionView.showsHorizontalScrollIndicator = NO;
self.collectionView.showsVerticalScrollIndicator = NO;
Expand Down
4 changes: 0 additions & 4 deletions QMUIKit/QMUIComponents/QMUIMarqueeLabel.m
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,6 @@ - (BOOL)requestToStopAnimation {

@implementation UILabel (QMUI_Marquee)

- (void)dealloc {
[self qmuimq_removeObserver];
}

- (void)qmui_startNativeMarquee {
// 系统有 _startMarqueeIfNecessary、_startMarquee,但直接开启的方法其实是 marqueeRunning
BOOL running = YES;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,7 @@ - (void)qmui_registerDelegateSelector:(SEL)getter {
return;
}

// 为这个 selector 创建一个 QMUIMultipleDelegates 容器
NSString *delegateGetterKey = NSStringFromSelector(getter);
if (!self.qmuimd_delegates[delegateGetterKey]) {
objc_property_t prop = class_getProperty(self.class, delegateGetterKey.UTF8String);
QMUIPropertyDescriptor *property = [QMUIPropertyDescriptor descriptorWithProperty:prop];
if (property.isStrong) {
// strong property
QMUIMultipleDelegates *strongDelegates = [QMUIMultipleDelegates strongDelegates];
strongDelegates.parentObject = self;
self.qmuimd_delegates[delegateGetterKey] = strongDelegates;
} else {
// weak property
QMUIMultipleDelegates *weakDelegates = [QMUIMultipleDelegates weakDelegates];
weakDelegates.parentObject = self;
self.qmuimd_delegates[delegateGetterKey] = weakDelegates;
}
}

[QMUIHelper executeBlock:^{
IMP originIMP = method_getImplementation(originMethod);
Expand All @@ -90,16 +74,34 @@ - (void)qmui_registerDelegateSelector:(SEL)getter {
return;
}

// 为这个 selector 创建一个 QMUIMultipleDelegates 容器
QMUIMultipleDelegates *delegates = selfObject.qmuimd_delegates[delegateGetterKey];

if (!aDelegate) {
// 对应 setDelegate:nil,表示清理所有的 delegate
[delegates removeAllDelegates];
// 只要 qmui_multipleDelegatesEnabled 开启,就会保证 delegate 一直是 delegates,所以不去调用系统默认的 set nil
// originSelectorIMP(selfObject, originDelegateSetter, nil);
if (delegates) {
[delegates removeAllDelegates];
[selfObject.qmuimd_delegates removeObjectForKey:delegateGetterKey];
}
// 必须要清空,否则遇到像 tableView:cellForRowAtIndexPath: 这种“要求返回值不能为 nil” 的场景就会中 assert
// https://github.com/Tencent/QMUI_iOS/issues/1411
originSelectorIMP(selfObject, originDelegateSetter, nil);
return;
}

if (!delegates) {
objc_property_t prop = class_getProperty(selfObject.class, delegateGetterKey.UTF8String);
QMUIPropertyDescriptor *property = [QMUIPropertyDescriptor descriptorWithProperty:prop];
if (property.isStrong) {
// strong property
delegates = [QMUIMultipleDelegates strongDelegates];
} else {
// weak property
delegates = [QMUIMultipleDelegates weakDelegates];
}
delegates.parentObject = selfObject;
selfObject.qmuimd_delegates[delegateGetterKey] = delegates;
}

if (aDelegate != delegates) {// 过滤掉容器自身,避免把 delegates 传进去 delegates 里,导致死循环
[delegates addDelegate:aDelegate];
}
Expand All @@ -125,7 +127,7 @@ - (void)qmui_registerDelegateSelector:(SEL)getter {
}

- (void)qmui_removeDelegate:(id)delegate {
if (!self.qmui_multipleDelegatesEnabled) {
if (!self.qmuimd_delegates) {
return;
}
NSMutableArray<NSString *> *delegateGetters = [[NSMutableArray alloc] init];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,10 @@ - (BOOL)respondsToSelector:(SEL)aSelector {

#pragma mark - Overrides

- (BOOL)isProxy {
return YES;
}

- (BOOL)isKindOfClass:(Class)aClass {
BOOL result = [super isKindOfClass:aClass];
if (result) return YES;
Expand Down
8 changes: 7 additions & 1 deletion QMUIKit/QMUIComponents/QMUINavigationTitleView.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ typedef NS_ENUM(NSInteger, QMUINavigationTitleViewAccessoryType) {
@property(nonatomic, assign) BOOL loadingViewHidden;

/*
* 如果为YES则title居中,loading放在title的左边,title右边有一个跟左边loading一样大的占位空间;如果为NO,loading和title整体居中。默认值为YES。
* 如果为YES则title居中,loading放在title的左边,title右边有一个跟左边loading一样大的占位空间(目的是为了让切换 loading 时文字不跳动);如果为NO,loading和title整体居中。默认值为YES。
*/
@property(nonatomic, assign) BOOL needsLoadingPlaceholderSpace;

Expand Down Expand Up @@ -175,3 +175,9 @@ typedef NS_ENUM(NSInteger, QMUINavigationTitleViewAccessoryType) {
- (instancetype)initWithStyle:(QMUINavigationTitleViewStyle)style;

@end

@interface UIView (QMUINavigationTitleView)

/// 标记当前 view 是用于自定义的导航栏标题,QMUI 可以帮你自动处理系统的一些布局 bug。对于 QMUINavigationTitleView 而言默认值为 YES,其他 UIView 默认值为 NO
@property(nonatomic, assign) BOOL qmui_useAsNavigationTitleView;
@end
Loading

0 comments on commit 0ee53a9

Please sign in to comment.