4.3.0
新增功能
QMUICommonDefines.h
增加宏QMUIAssert
用于代替NSAssert
,作用是当业务使用QMUIConsole
且打开了配置表ShouldPrintQMUIWarnLogToConsole
时,该 assert 会把信息显示到QMUIConsole
面板里,而不会触发NSAssert
,从而避免中断程序的运行。但如果业务项目没打开ShouldPrintQMUIWarnLogToConsole
,则该宏等价于NSAssert
。UIViewController(QMUI)
增加qmui_isSystemContainerViewController
方法(共两个,一个是类方法,一个是实例方法)用于判断当前的 viewController 是否为系统自带的 Container View Controller(例如UINavigationController
、UITabBarController
)。QMUIGridView
增加padding
属性用于设置内部的间距。QMUIKeyboardManager
增加isFloatingKeyboard
属性用于判断当前是否为 iPad 上的浮动键盘。QMUIPopupMenuBaseItem
、QMUIPopupMenuButtonItem
的height
属性支持赋值为QMUIViewSelfSizingHeight
,以使每一行的高度自动根据当前行的内容来计算。在此之前该高度仅支持写死的固定值。QMUISearchController
增加initWithContentsViewController:resultsTableViewStyle:
方法用于指定搜索结果列表的 style。QMUISearchController
增加dimmingColor
用于设置搜索框聚焦键盘升起时的遮罩颜色。QMUIWeakObjectContainer
增加isQMUIWeakObjectContainer
用于判断当前对象是否为QMUIWeakObjectContainer
,同时修复 QMUI 里若干用到这个类的地方判断写法不正确的问题(虽然写法不正确,但由于内部会做消息转发,所以不会引起实质性问题)。QMUIHelper
增加canUpdateAppearance
属性用于判断当前是否可以设置UIAppearance
,该方法主要用于解决 #1281,具体请查看下方专项说明。QMUIHelper
增加topMarginForAttributedImage:attributes:
可以根据图片大小、图片所在的富文本样式,计算得出一个能让图片在当前富文本里垂直居中的顶部偏移值。- 新增
UIApplication(QMUI)
分类,提供qmui_didFinishLaunching
属性用于判断当前 App 是否已完全启动。 NSAttributedString(QMUI)
增加qmui_attributedStringWithImage:alignByAttributes:
方法用于把UIImage
转为NSAttributedString
并利用参数的属性来自动调整 image 的垂直位置。NSAttributedString(QMUI)
增加qmui_attributedStringWithImage:margins:
用于把UIImage
转为NSAttributedString
并利用参数调整 image 的上下左右布局偏移。NSString(QMUI)
增加qmui_stringMatchedByPattern:groupIndex:
、qmui_stringMatchedByPattern:groupName:
方法支持使用正则表达式匹配字符串后返回指定分组的结果。UIButton(QMUI)
增加qmui_setImageTintColor:forState:
方法用于便捷地给不同状态的 image 设置不同颜色。UIControl(QMUI)
增加qmui_setSelectedBlock:
、qmui_setEnabledBlock:
便于在 selected、enabled 发生变化时做一些事情。- 增加
UIFontMediumMake
、UIFontMediumWithFont
、UIDynamicFontMediumMake
、UIDynamicFontMediumMakeWithLimit
宏,以及-[UIFont(QMUI) qmui_mediumSystemFontOfSize:]
方法用于生成 Medium 字重的字体。 UIImage(QMUI)
增加qmui_imageWithGradientColors:type:locations:size:cornerRadiusArray:
方法用于生成一张渐变图片。UILabel(QMUI)
增加属性qmui_showPrincipalLines
可以显示当前文字的 descender、xHeight、capHeight、lineHeight,便于调试。UITextField(QMUI).qmui_selectedRange
属性从readonly
改为readwrite
,方便业务通过NSRange
形式去修改选中的区域,不用人工做一次类型转换。UITextView(QMUI)
增加qmui_selectedRange
便于获取NSRange
类型的选中区域。UIView(QMUI)
增加qmui_fixedSize
属性用于简单地把某个 view 设置为固定大小,通常使用的场景是某个网络上加载下来的图片(大小不确定)要放在某个 UIButton 上,并且希望不管什么图都固定显示为某个 size,以前通常只有两种方式来实现:一是将图片裁剪为指定大小,二是重写一个自定义的 UIButton,现在可以简单地设置 UIButton.imageView.qmui_fixedSize 即可。UIView(QMUIBorder)
增加qmui_borderInsets
用于调整边框的偏移值,具体效果可查看 QMUI Demo 里的 UIView+QMUI 示例。
会带来 QMUI 新旧版本兼容问题的更新
- #1231 #1284 近期若干个 App 提交 App Store 时会被拒绝,提示“The app references non-public selectors in Frameworks/QMUIKit.framework/QMUIKit: navigationBarBackgroundImage, navigationBarStyle, navigationBarTintColor”,但大部分 App 没收到这个提醒。其中提到的几个方法均为 QMUI 开天辟地时就存在的方法命名,之前一直没问题,暂不清楚原因。目前只能将其重命名,增加
qmui_
前缀以避免审查。 - 废弃
QMUILinkButton
,该组件的能力完全可以用新版的UIView(QMUIBorder)
代替。 - 废弃
QMUIVisualEffectView
,该组件的能力完全可以用UIVisualEffectView(QMUI)
代替。但须注意这两者有细微的色差——系统的UIVisualEffectView
内部由“磨砂+半透明前景色”组成,而QMUIVisualEffectView
的实现方式是在系统基础上再叠加一个前景色,也即“磨砂+系统前景色+QMUI 前景色”,但UIVisualEffectView.qmui_foregroundColor
是把系统自带前景色去掉后再叠加一层前景色,也即“磨砂+QMUI 前景色”,从而能更精准控制磨砂的样式。但更换为新版后,业务的磨砂效果应该会变得更明显,需要业务自行检查是否要重新调整foregroundColor
。 - 删除配置表
SwitchTintColor
开关,这个开关仅在 iOS 12 及以前才有效,作用是在UISwitch
关闭时显示外圈的颜色,一般没什么用,就不再提供了。 - 将
-[NSAttributedString(QMUI) qmui_attributedStringWithImage:baselineOffset:leftMargin:rightMargin:]
标记为已废弃,且很快会在后续版本删除,请尽快使用新增的qmui_attributedStringWithImage:margins:
代替。 - 删除
QMUICustomizeButtonPropType
及关联的qmui_hasCustomizedButtonPropForState:
、qmui_hasCustomizedButtonPropWithType:forState:
方法,忘了当初为什么加这些东西了。 UILabel(QMUI).qmui_lineHeight
属性原本只是简单地设置文字的 lineHeight,但由于 iOS 的特性,不管 lineHeight 设置为多少,文字都是居底部对齐,但市面上基本所有的设计软件(如 figma、sketch),以及其他平台的布局代码,默认都是文字在行高内垂直居中,这容易导致布局还原效果差,需要反复调整,因此这版本里qmui_lineHeight
默认会使文字垂直居中,项目里原本使用该属性的地方,更新版本后间距可能会变化,需要业务项目检查。经过衡量,我们认为长远来看该更新成本是值得的。
如何适配新版
- 以 Matching Word 形式全局 Replace
QMUINavigationControllerAppearanceDelegate
里的7个方法,加上“qmui_”前缀。 - Matching Word 形式全局搜索“QMUILinkButton”,将用到的地方改为
QMUIButton
+UIView.qmui_borderPosition
代替。例如:// QMUILinkButton *linkButton = QMUILinkButton.new; QMUIButton *linkButton = QMUIButton.new; linkButton.qmui_borderPosition = QMUIViewBorderPositionBottom; linkButton.qmui_borderColor = linkButton.currentTitleColor; linkButton.qmui_borderWidth = 1;// QMUILinkButton 之前默认的下划线大小为1pt
- Matching Word 形式全局搜索“QMUIVisualEffectView”,将用到的地方改为
UIVisualEffect.qmui_foregroundColor
,并检查其效果是否符合业务的需求。 - 全局搜索用到
-[NSAttributedString(QMUI) qmui_attributedStringWithImage:baselineOffset:leftMargin:rightMargin:]
的地方,将其改为新方法-[NSAttributedString(QMUI) qmui_attributedStringWithImage:margins:]
。 - 全局搜索 “QMUICustomizeButtonPropType”、
qmui_hasCustomizedButtonPropForState:
、qmui_hasCustomizedButtonPropWithType:forState:
,如果有用到,请将相关的 QMUI 旧代码复制为业务代码使用。 - 全局搜索用到“qmui_lineHeight”的地方,查看该地方的布局是否有问题(更新 QMUI 后布局应该会比之前偏上)。
- 如果有使用配置表,请删除其中的“SwitchTintColor”相关代码。
Bugfix
- #1152 #1159 #1227 #1278 重新优化“Main Thread Checker: UI API called on a background thread: -[UIWindow traitCollection]”的问题。
- #1180 修复没有使用
QMUINavigationController
的情况下,执行 pop 操作时可能依然还在上一次转场动画过程中,此次的 pop 会被系统忽略,导致命中UINavigationController (QMUI)
里的 NSAssert 的问题。 - #1232 修复
UISearchBar(QMUI).qmui_alwaysEnableCancelButton
可能出现 crash 的 bug。 - 修复
UISearchBar(QMUI)
在没有设置qmui_cancelButtonMarginsBlock
的情况下 qmuisb_shouldFixLayoutWhenUsedAsTableHeaderView 无效的 bug。 - #1243 [UIKit Bug] 修复 iOS 11 及以上,关闭 estimated height 的 tableView 可能出现数据错乱引发 crash 的 bug。
- #1246 修复
QMUIButton.highlightedBackgroundColor
没有兼容qmui_maskedCorners
的 bug。 - #1253 修复配置表
AutomaticCustomNavigationBarTransitionStyle
为YES
的效果在 pop 时可能出错的 bug。 - #1257 #1263 修复在非全面屏的 Regular 设备里,仅支持竖屏的 App 在横屏启动时界面错乱的 bug。
- #1258 修复
QMUITextView
在使用placeholder
的情况下调用sizeToFit
会出现NaN
的 bug。 - #1281 [UIKit Bug] 修复 App 处于后台时修改 UIAppearance 里 UIImage 类型的属性很大几率导致第三方键盘 crash 的 bug。——该 bug 很重要,在下文专项说明
- #1282 修复
QMUITextField
通过代码setText:
修改文字后,光标无法正确置于文字末尾的 bug。 - #1283 修复
-[UIButton(QMUI) qmui_setTitleAttributes:forState:]
在 iOS 12 及以下系统无效的 bug。 - #1286 [UIKit Bug] 修复使用
UITabBarAppearance
将UITabBarItem
选中时的字体设置为 bold 则无法完整显示 title 的 bug。 - 重构
-[UIButton(QMUI) qmui_setTitleAttributes:forState:]
方法,修复其他 state 下无法设置 title 的 bug。 - 修复
-[QMUIButton sizeThatFits]
在参数为CGSizeZero
时错误返回了高度为 0 的大小(系统UIButton
在这种情况下会返回真实内容大小)。 - 修复
QMUIMultipleDelegates
与RAC
冲突导致死循环的 bug。 - 修复
QMUISearchController
在 iPad 分屏时用QMUIEmptyView
显示空结果的情况下,改变分屏的比例,QMUIEmptyView
的宽度没有刷新的 bug。 - 修复
QMUITextView
设置了textAlignment
为Right
后placeholder
样式没同步的 bug。 - 修复
QMUIThemeImage
在使用resizableImageWithCapInsets:
、resizableImageWithCapInsets:resizingMode:
后无法保持其动态特性的 bug。 - 修复 iOS 10-11,
QMUITheme
动态颜色在UILabel.textColor
上无法及时刷新的 bug。 - 修复
QMUITheme
里处理keyboardAppearance
的逻辑会对UITextField
内部的UIFieldEditor
也生效的 bug。 - 修复关闭 theme 主题跟随系统的开关后,切换 App 里的 Light/Dark theme,
UITabBar
的backgroundEffect
值刷新但样式没刷新的 bug。 - 修复
UITraitCollection(QMUI)
里没有对 window 过滤 nil 导致 App 从桌面唤醒时可能无法立即显示正确的 style 的 bug。 - 修复
UIView(QMUIBorder)
在不显示 border 时依然会触发多次不必要的 setNeedsLayout 的 bug。 - 修复
QMUIKeyboardManager
在某些情况下键盘 hide 过程中还会触发 show 的 bug。
其他
QMUIAlertController
内部的titleLabel
、messageLabel
类型从UILabel
改为QMUILabel
以支持长按复制。- 将分类
NSMutableParagraphStyle(QMUI)
改为NSParagraphStyle(QMUI)
以支持更多类型。 - 监听
UIGestureRecognizer
执行过程中是否被禁用(典型案例是试图在viewWillAppear:
里禁用当前界面的手势返回,这样会导致从当前界面的下一个界面手势返回时界面卡死)。 UINavigationController(QMUI)
增加对pushViewController:
、setViewControllers:
的保护,避免重复 push 触发系统的 crash。- 优化
UIVisualEffectView(QMUI).qmui_foregroundColor
,当开启系统的“降低透明度”辅助功能开关后, 屏蔽它的半透明效果,避免出现怪异表现。
关于 #1281 的特别说明
近期我们意识到在使用 QMUI 的 App 里,第三方键盘很容易被系统杀掉重启,经过一番测试,证实确实与 QMUI 有关,但问题的根源在于系统的 UIAppearance 协议在某些场景下的使用会导致内存暴涨,而 QMUI 刚好命中了这些场景。具体的分析解释请查看 #1281 (comment) ,建议必读。
总结来说,使用 QMUI 的项目要规避这个问题,不能仅依靠 QMUI 自己的更新,业务项目也需要同步配合进行以下几个措施:
- 更新最新版的 QMUI(4.3.0 及后续版本)。
- 配置表里
UIImage
、UIColor
的属性,都用一个全局变量存起来,目的是为了保证切换 theme 时不会重新赋值(指针相同就不会执行 setter)。 - 搜索项目业务代码,确保在 theme 变化时会设置的 UIAppearance 逻辑,用
if (QMUIHelper.canUpdateAppearance)
的判断包起来。
做完以上举措后,可以用最新版 QMUI Demo 验证效果(内置 Keyboard Extension)。
- 在你的模拟器/真机上运行 QMUI Demo,此时设置里会出现新键盘“QMUIKeyboard-QMUI(Debug)”,将其添加为唯一的输入法。
- 打开你的 App,点击某个输入框以升起 QMUI 键盘,可看到键盘上显示了一个数字。
- 保持键盘显示的状态,不断重复“回到桌面-打开App-回到桌面”,观察键盘上的数字是否稳定“每次增加固定值”,例如以 QMUI Demo 为例,每次都会增加5。
如果测试结果符合第3点,该数字没有指数型上升,就意味着你的业务项目是正常的,可以放心使用。