Releases: Tencent/QMUI_iOS
4.7.0
综述
随着 QMUI 最初的几位老人家各奔天涯,历经7年自费集资的老官网 qmuiteam.com在不久的将来费用消耗完就不再维护了,以后都在 GitHub。对应地,依附于官网的自动上报统计 SendAnalyticsToQMUITeam
也在这个版本删除,借此也跟大家分享下统计数据(毕竟在座的各位都参与其中)。
截止至2023-7-24,QMUI iOS 累计接入6w项目(以Bundle Id为维度),日活跃项目 1.6k+,月活跃项目 4.3k+。
这个版本主要是累积这段时间的修修补补。
新增功能
- 令
qmui_outsideEdge
对UIBarButtonItem.customView
也生效,以后你可以让导航栏按钮的响应区域扩大到导航栏之外了。 CALayer(QMUI)
增加属性qmui_maskPathBlock
用于快捷添加遮罩。CALayer(QMUI)
增加属性qmui_evenOddMaskPathBlock
用于快捷镂空一个区域。NSArray(QMUI)
增加方法qmui_compactMapWithBlock:
用于转换数组里的元素类型,并支持过滤掉nil
。- 增加
NSDictionary(QMUI)
分类,提供qmui_mapWithBlock:
方法用于转换字典里的 key-value 类型,提供qmui_deepMapWithBlock:
方法用于深度拷贝的转换。 - 新增 hook 用于保护
-[NSMutableAttributedString appendAttributedString:]
遇到参数为nil
时会命中系统 assert: nil argument 的情况。 UILabel(QMUI)
增加qmui_centerOfCapHeight
属性用于获取单行文本里font.capHeight
的位置。UINavigationController(QMUI)
增加属性qmui_alwaysInvokeAppearanceMethods
用于在UINavigationController
不可视时进行 push/pop 依然能触发 vc 生命周期方法的方法。UINavigationController(QMUI)
增加属性qmui_lastOperation
用于获取当前正在进行的切换界面动画类型(push 或 pop)。UITextField(QMUI)
增加属性qmui_respondsToDeleteActionAtLeading
用于对齐UITextView
的行为:在输入框开头继续按删除按钮也可以触发 shoudChange 的 delegate 方法。
会带来 QMUI 新旧版本兼容问题的更新
- 配置表删除
SendAnalyticsToQMUITeam
。
如何适配新版
- 如果你有使用配置表,请删除其中的
SendAnalyticsToQMUITeam
。
Bugfix
- #1451 对因为被 present 盖住的界面,修改 navigationBar 样式时的 assert 条件做优化。
- 修复 #1473
UISearchController.searchBar
作为UITableView.tableHeaderView
时,进入搜索状态,搜索结果列表顶部有一大片空白的问题。 - 修复 #1498 开启
forceEnableInteractivePopGestureRecognizer
的界面被 push 的过程中快速手势返回,容易导致 App 卡死的 bug。 - #1501 修复
AutomaticCustomNavigationBarTransitionStyle
在setViewControllers:
场景下的若干问题。 - 修复
QMUIImagePickerViewController
初始滚动位置可能错误的 bug。 - 修复
QMUIAlertController
以ActionSheet
演示呈现较长内容时,顶部布局没考虑safeAreaInsets
的问题。 - 修复
QMUIBadge
对纯文本的UIBarButtonItem
基准布局错误的 bug。 - 修复
QMUIButton
在adjustsButtonWhenDisabled = NO
时也会在setEnabled:YES
里重置alpha
的问题。 - 优化
QMUINavigationButton
自定义返回按钮点击区域太小的问题。 - 修复
QMUIKeyboardManager
在以 iPad“侧拉”模式打开的 App 中获取键盘可视高度错误的 bug,iPhone、iPad 全屏/分屏/台前调度,都没这个问题。 - 修复
QMUITheme
在切换 theme 时错误地覆盖UITextView.textColor
导致如果输入框内存在不同颜色的富文本时会颜色错误的 bug。 - 修复同一个对象对不同 window 分别调用
qmui_addSizeObserverForWindow:
,最终其中某个 window size 发生变化时所有 block 都被触发的 bug。 - 解决在未使用配置表的情况下,QMUIAssert 应使自动变成 NSAssert 的问题。
- 修复 QMUI Demo 无法使用 XCTest 的问题。
- 修复
UISearchBar(QMUI)
快速在 show/hide left/right accessoryView 时容易出现状态错误的 bug。 - 修复
UIView(QMUI).qmui_shouldShowDebugColor
属性在开启又关闭后可能导致元素背景全黑的问题。
4.6.3
4.6.1 - 兼容 iOS 13-16
综述
QMUI 4.6.1 版本主要是在 4.6.0 的基础上把最低 iOS 支持版本从 11 提升到 13,以对齐微信。也正因此,很多仅对 iOS 11、12 写的代码也一并去除了(包括很多 hook),所以建议大部分项目都升级到 QMUI 4.6.1 以使用更精简的代码。
仍需支持 iOS 11、12 系统的项目,请使用 QMUI 4.6.0 。
会带来 QMUI 新旧版本兼容问题的更新
- 删除常量
QMUITableViewStyleInsetGrouped
。 - 删除
UITableView (QMUI)
的qmui_style
属性。 - 删除宏
QMUIStatusBarStyleDarkContent
。 - 删除
QMUIHelper.statusBarStyleDarkContent
方法。 - 删除
UISearchBar (QMUI)
的qmui_textField
属性。 - 删除配置表里的
ShouldFixTabBarTransitionBugInIPhoneX
开关。
如何适配新版
- 全局搜索
QMUITableViewStyleInsetGrouped
,将其替换为系统的UITableViewStyleInsetGrouped
。 - 全局搜索使用到
UITableView.qmui_style
的地方(包括 Xib 文件),将其替换为系统的UITableView.style
属性。 - 全局搜索
QMUIStatusBarStyleDarkContent
,将其替换为系统的UIStatusBarStyleDarkContent
。 - 全局搜索用到
QMUIHelper.statusBarStyleDarkContent
的地方,将其替换为系统的UIStatusBarStyleDarkContent
。 - 全局搜索用到
UISearchBar.qmui_textField
的地方,将其改为系统的UISearchBar.searchTextField
。 - 如果有使用配置表,请删除你配置表里的
ShouldFixTabBarTransitionBugInIPhoneX
。
4.6.0 - 兼容 iOS 11-16
综述
QMUI 4.6.0 版本主要内容是兼容 iOS 16 及 iPhone 14 等新设备,以屏幕旋转、键盘管理为主。其中屏幕旋转的使用方式可以查看 Wiki:《适用于 iOS 16 及以下版本的屏幕方向控制方式》。
新增功能
QMUIPopupMenuView
增加sectionSpacing
属性用于控制section
之间的间隙。QMUIThemeColor
、QMUIThemeImage
、QMUIThemeVisualEffect
均增加了name
属性及对应的 init 方法,让业务可以用字符串来标记该动态对象。- 增加
NSShadow (QMU)
分类提供一个便捷的 init 方法。 CALayer (QMUI)
增加属性qmui_shadow
支持用NSShadow
对象来描述投影样式,从而可以一行代码完成投影的设置。NSArray (QMUI)
增加方法qmui_firstMatchWithBlock:
用于过滤第一个符合 block 条件的元素。UIBezierPath (QMUI)
增加方法qmui_bezierPathWithMediaTimingFunction:
支持将一个CAMediaTimingFunction
转成一条宽高为 1 的贝塞尔曲线(可以理解为数据可视化)。QMUICommonDefines.h
增加IOS16_SDK_ALLOWED
宏用来标志当前是否为 Xcode 14 编译环境。- 增加
[QMUIHelper screenSizeFor67InchAndiPhone14Later]
方法、[QMUIHelper is67InchScreenAndiPhone14Later]
方法、IS_67INCH_SCREEN_AND_IPHONE14
宏用于标记当前设备是否为 iPhone 14 Pro Max 尺寸的屏幕。 - 增加
[QMUIHelper statusBarHeightConstant]
用于获取静态的状态栏高度。 -[QMUIHelper deviceName]
、-[QMUIHelper deviceModel]
增加新设备的信息。-[QMUIHelper safeAreaInsetsForDeviceWithNotch]
增加新设备的值。UIViewController (QMUI_Interface)
增加方法qmui_rotateToInterfaceOrientation:
用于强制将当前界面旋转到某个指定方向。UIViewController (QMUI_Interface)
增加方法qmui_setNeedsUpdateOfSupportedInterfaceOrientations
对应 iOS 16 系统的setNeedsUpdateOfSupportedInterfaceOrientations
,用于告诉系统当前希望刷新屏幕方向。UITableViewCell (QMUI)
增加属性qmui_configureReorderingStyleBlock
支持修改 cell 在排序过程中的样式。
会带来 QMUI 新旧版本兼容问题的更新
QMUIPopupContainerView
将UIColor *shadowColor
属性改为NSShadow *shadow
以支持更完整的投影样式。UISlider (QMUI)
将qmui_thumbShadowColor
、qmui_thumbShadowOffset
、qmui_thumbShadowRadius
删除,改为新增的qmui_thumbShadow
属性。- 使
StatusBarHeightConstant
能兼容 iOS 16、iPhone 14 Pro 灵动岛。 - 将 iPhone 14 Pro Max 加入到
AS_65INCH_SCREEN
宏内。 - 将 iPhone 14 Pro Max 加入到
-[QMUIHelper isRegularScreen]
内。 - 删除
+[QMUIHelper rotateToDeviceOrientation:]
方法。
如何适配新版
- 全局搜索使用到
QMUIPopupContainerView.shadowColor
的地方,将其改为新的shadow
属性。 - 全局搜索使用到
UISlider.qmui_thumbShadowColor
、UISlider.qmui_thumbShadowOffset
、UISlider.qmui_thumbShadowRadius
的地方,将其替换为新的qmui_thumbShadow
属性。 - 全局搜索用到
StatusBarHeightConstant
的地方,分别测试其在 iPhone 13 和 iPhone 14 Pro 下的布局是否正确。 - 全局搜素用到
AS_65INCH_SCREEN
的地方,测试其在 iPhone 14 Pro Max 下的布局是否正确。 - 全局搜索用到
-[QMUIHelper isRegularScreen]
的地方,测试其在 iPhone 14 Pro Max 下表现是否正确。 - 全局搜索使用到
+[QMUIHelper rotateToDeviceOrientation:]
的地方,将其换成-[UIViewController qmui_rotateToInterfaceOrientation:]
。
Bugfix
- #1437 修复在 iOS 15 里打开一个默认隐藏导航栏的界面,返回按钮样式错误的 bug。
- #1438 修复
QMUIPopupContainerView
将sourceView
设置为nil
时 crash 的 bug。 - #1439
UIView.qmui_hitTestBlock
的返回值应该添加_Nullable
以对齐系统。 - #1447 #1450 #1453 #1458 #1460 解决 iOS 16 下
QMUIKeyboardManager
的各种 bug。 - #1449 #1463 修复将
UIView.backgroundColor
设置为QMUIThemeColor
后再设置为另一个与QMUIThemeColor
当前色值相同的颜色时,后者无效的 bug。 - #1451 修复在尚未添加到 window 的
UINavigationController
里修改navigationBar
可能会导致navigationBar
样式错误的 bug。 - #1452 修复开启系统辅助功能粗体文本的情况下,设置了
tintColorAdjustsTitleAndImage
的QMUIButton
在 App 切到桌面再切回来时颜色错误的 bug。 - #1457 修复 Xcode 14 编译的 App 在 iOS 16.0 上可能存在顶部标题布局错乱的 bug。
- 修复
QMUINavigationTitleView.subAccessoryView
在计算布局时如果subAccessoryView
带有transform
则布局错误的 bug。 - 修复
QMUIPopupContainerView
在sourceView
、sourceBarItem
的值更新时没有清除与旧值的绑定关系的 bug。 - 修复
QMUIPopupContainerView
计算宽高可能不准确的 bug:应该取 px 整数而不是 pt 整数。 - 修复
QMUIPopupMenuButtonItem
里强制修改button.contentEdgeInsets.top/bottom
为 0 的 bug。 - 修复 iOS 16 里
QMUITextView
文本颜色设置为QMUIThemeColor
后无法响应 theme 变化的 bug。 - 修复
-[QMUIHelper keyboardHeightWithNotification:inView:]
在 iOS 16 台前调度下无法返回正确值的 bug。 - 修复
UITableViewCell(QMUI).qmui_selectedBackgroundColor
有时候失效的 bug。
其他
- #1378 支持 Mac Catalyst 编译。
- 由于 iOS 16 对横竖屏体验的优化,所以配置表里的
AutomaticallyRotateDeviceOrientation
在 iOS 16 下已经不需要了,请业务项目知悉即可。
4.5.1
会带来 QMUI 新旧版本兼容问题的更新
NSObject (QMUI).qmui_ivarList
输出的内容里,为每个 Ivar 开头增加了 offset 值的展示,同时显示十进制和十六进制的值,中间用“|”隔开。
如何适配新版
- 全局搜索“qmui_ivarList”,检查使用到的地方是否有影响。
Bugfix
- #1432 修复开启
AutomaticCustomNavigationBarTransitionStyle
的情况下,从界面 B pop 回界面 A 的过程,如果 A 的导航栏效果与全局默认效果不同,则在 pop 过程中 A 的导航栏样式错误的 bug。 - #1434 修复
qmui_outsideEdge
在不可见的 view 上生效的 bug。 - 修复
QMUIAlertController
在 alert、actionSheet 两种 style 下,如果不存在 title、message、customView 时,第一个 action 的顶部依然错误出现分隔线的 bug。 - 修复
UIScrollView (QMUI).qmui_alreadyAtTop
可能因为浮点精度问题导致返回值错误的 bug。
4.5.0
新增功能
- 增加
QMUIBarProtocol
用于同时约定UINavigationBar
、UITabBar
的功能接口,因为这两种 bar 所需要的功能基本都一样,用 protocol 来约定也便于后续同步调整这两种 bar 的功能。同时也因此使得UINavigationBar (QMUI)
新增了qmui_effectView
、qmui_effectViews
、qmui_effect
、qmui_effectForegroundColor
几个与磨砂相关的接口。 - 由于
QMUIBarProtocol
为UINavigationBar
带来更多的能力,所以这个版本我们优化了QMUISmoothEffect
、AutomaticCustomNavigationBarTransitionStyle
里与磨砂相关的表现,使其更符合组件预期。 - 增加
UIView (QMUINavigationTitleView).qmui_useAsNavigationTitleView
属性用于标记某个 view 为自定义的导航栏 titleView,以便 QMUI 自动帮你处理一些布局上的系统 bug。 QMUIPopupMenuView
增加willHandleButtonItemEventBlock
属性便于统一管理 item 的点击行为。CALayer (QMUI)
增加qmui_layerWithName:
方法用于便捷查找指定 name 的 layer。UIActivityIndicator(QMUI)
支持用qmui_size
指定大小。
会带来 QMUI 新旧版本兼容问题的更新
- 由于
QMUIBarProtocol
的调整,我们同时删除了UINavigationBar (QMUI).qmui_backgroundContentView
属性。 UISearchController.dimsBackgroundDuringPresentation
默认值在 iOS 15 下被改为 NO 了,为了保持与旧版本的一致,QMUISearchController
里将其改为 YES。- #1425
QMUICommonTableViewController
内自带的QMUISearchController
的搜索结果列表的UITableViewStyle
从 Plain 改为与当前宿主 vc 的 tableView.style 一致。 - 将 QMUIStringPrivate
qmui_substringFromIndex
的参数 index 等于字符串长度时返回的值从 nil 改为 @"",以保持与系统方法一致。
如何适配新版
- 如果仍需要
UINavigationBar (QMUI).qmui_backgroundContentView
属性,请将 QMUIKit 旧代码抄到业务项目里。 - 检查 iOS 15 里用到
QMUISearchController
的地方,检查进入搜索状态时界面表现是否符合预期。 - 简单检查用到
QMUICommonTableViewController
、带有搜索功能,且 style 不为UITableViewStylePlain
的列表,其搜索结果的 tableViewStyle 是否符合预期。 - 请检查用到
qmui_substringFromIndex
的地方,在 index 等于 string.length 时表现是否正常。
Bugfix
- 修复
QMUIAlertController
以 alert 形式显示时,如果内容特别多,浮层会溢出到屏幕的 safeAreaInsets 区域的问题。 - 修复
QMUIConsole.canShow = NO
时依然会创建相关的 view、viewController 对象的问题。 - 修复 iOS 15.4 启动 App 后到系统设置-辅助功能-显示与文字大小-修改一下“按钮形状”的开关,会 crash:
-[UILabel _accessibilityButtonShapesChangedNotification:]: message sent to deallocated instance 0x17e751d60
的问题。 - 修复
QMUIMultipleDelegates
在 iOS 16 下配合UIScrollView
可能引发 crash 的问题。 - 修复
QMUINavigationTitleView.needsLoadingPlaceholderSpace = NO
时即便不显示 loading,loading 也会占位,导致文字偏右的问题。 - 修复
QMUITextView
文字换行时丢失系统滚动动画特效的 bug。 - 修复
- [QMUITextView setFrame:]
被调用时即便 size 没变化也会触发setContentOffset:
产生滚动的问题。 - 修复配置表的值发生变化时重新应用的时候,对于业务 App 使用自定义 container viewController 的场景,无法正确刷新它的 navigationBar、tabBar 样式的 bug。
- 修复
+[QMUIHelper applicationSize]
在 MacCatalyst App / M1 上返回了CGSizeZero
导致APPLICATION_WIDTH
、APPLICATION_HEIGHT
的值为 0 的 bug。 - 修复在 root controller 实现了
preferredStatusBarStyle
方法并且在其中调用childViewControllerForStatusBarStyle
方法的情况下,iOS 12 present 起AVPlayerViewController
在 dismiss 时会触发preferredStatusBarStyle
导致死循环的 bug:因为AVPlayerViewController
内部的preferredStatusBarStyle
会转向presentingViewController
的preferredStatusBarStyle
,而后者又会return AVPlayerViewController
,于是死循环。 - 修复
qmui_substringAvoidBreakingUpCharacterSequences
系列方法在遇到 length 为1、range 与 string 相等的情况时会 crash 的 bug。 - 修复
QMUIStringPrivate
里的 assert 条件与系统方法不匹配的问题。 - 修复
substring:avoidBreakingUpCharacterSequencesWithRange:lessValue:countingNonASCIICharacterAsTwo:
在接受的 range 头尾都刚好落在一个 emoji 的中间时会得到一个负值 range 并引起 crash 的 bug,同时对负值 range 做 QMUIAssert 的提醒但不干预其返回值。 - #1248 #1274 #1377 修复
QMUIConsole
在没使用配置表或者配置表里没设置TableViewCellBackgroundColor
的情况下,打印出来的日志背景是白色的,看不见文字的 bug。 - #1326 调整
StatusBarHeightConstant
的值,使其在 statusBarHidden 时,iOS 14 下返回44,iOS 15 返回50,保持与系统UIApplication.statusBarFrame.size.height
一致。 - #1391 修复
NSURL (QMUI).qmui_queryItems
item 类型错误的 bug。 - #1404 修复
QMUITextView
当文本较多,在真机上长按系统输入法的删除按钮达到快速删除模式时,输入框底部容易出现大段空白的 bug。 - #1411 修复
UITableView.delegate
开启了qmui_multipleDelegatesEnabled
后在 dealloc 时可能引发 crash 的问题。 - #1413 修复
UISlider(QMUI)
先设置qmui_step
再设置qmui_stepDidChangeBlock
后某些情况下首次点击无法触发 block 的 bug。 - #1418 修复
UIImageView
、UIButton
配合 template image 使用时无法通过tintColor
来修改图片颜色的 bug。 - #1415 修复
QMUINavigationTitleView
先设置needsLoadingView = YES
再修改loadingViewSize
会导致文字无法完整显示的 bug。 - #1421 修复
QMUILabel.truncatingTailView
在 label.text 为空时 crash 的 bug。 - #1427 修复 QMUI 里
UITableView
先setDelegate:
再setDataSource:
可能引发 crash 的问题。
其他
- 将
QMUIConsole
专属的 window 类型从UIWindow
改为QMUIConsoleWindow
,使其更容易与其他 window 区分开(例如在 Lookin 里查看结构时)。 - [NSString (QMUI) qmui_trim]
默认去掉 C 里的字符串结束符“\0”。
4.4.3
UISlider (QMUI)
增加qmui_stepDidChangeBlock
以更便捷的方式监听 step 的变化,同时修复之前用 value changed 监听可能不准确的 bug。- 优化 UIImage (QMUI) 里与 QMUITheme 相关的一些报错的判断方式,之前的写法会导致“对一个 QMUIThemeImage 调用 qmui_imageWithTintColor: 会误判”的问题。
- 优化 QMUIStringPrivate 里对 substrings 系列方法的报错,将其从 NSAssert 改为 QMUIAssert,这样业务如果不太关注的话,可以以 log 的形式输出,而不会中断 Debug。
- 优化
-[NSString (QMUI) qmui_capitalizedString
的实现,如果字符串以 Emoji 开头,就不应该尝试转为大写了。 - #1358 修复
UITabBar (QMUI).qmui_effectViews
在 iOS 12 及以下会 crash 的 bug。
4.4.2
新增功能
QMUIStringPrivate
增加对NSString
substring 系列接口的异常情况的保护,方便自动发现类似裁剪字符串时不小心把 emoji 从中间裁剪的场景,避免出现乱码、crash。NSObject (QMUI)
增加qmui_viewInfo
属性用于 Debug 时方便地输出某个 view 的 view 层级结构。
会带来 QMUI 新旧版本兼容问题的更新
- 为了修复 #1351 的 bug,我们修改了
QMUINavigationBarScrollingAnimator
自动获取UINavigationBar
的逻辑,旧版本是通过QMUIHelper.visibleViewController.navigationController.navigationBar
来获取,新版本改为通过绑定的 scrollView 一层一层往上找,找到所在的 viewController 的导航栏。所以如果业务项目以前存在“scrollView 所在的 viewController,和 scrollView 控制的 navigationBar 不处于同一个 UINavigationController” 里时,则更新 QMUI 版本后 animator 会失效。大部分情况下业务项目应该不会存在这种场景。
如何适配新版
- 检查业务项目里使用了
QMUINavigationBarScrollingAnimator
、QMUINavigationBarScrollingSnapAnimator
的地方,效果是否与 4.4.1 一致。
Bugfix
- #1330 #1346 修复
NavBarRemoveBackgroundEffectAutomatically
在开启了AutomaticCustomNavigationBarTransitionStyle
时可能对假 bar 无效的 bug。 - #1351 修复
QMUINavigationBarScrollingAnimator
在 scrollView 所在的 viewController 已经被推出UINavigationController
时,滚动器依然能对 UINavigationBar 产生影响的 bug。 - #1352 修复
QMUIButton
开启了adjustsImageTintColorAutomatically
后修改 normal 的 image,highlighted、disabled 的 image 无法同步更新的 bug。 - 修复
QMUIModalPresentationAnimationStylePopup
的 hide 动画无法看到缩小过程的 bug。
QMUI Demo
- 修复
QMUISmoothEffect
在转场过程中修改 effect 可能出现的 crash。
4.4.1
新增功能
- 新增
UILabel (QMUI_Marquee)
分类,支持开启系统UILabel
内置的跑马灯效果,功能比QMUIMarqueeLabel
简单,但由于是系统内置的能力,性能应该是不需要担心的。我们推荐在满足需求的前提下优先使用UILabel (QMUI_Marquee)
。 - 新增
UISlider (QMUI)
分类用于取代之前的QMUISlider
(后者已删除),提供同等功能的同时,增加了qmui_numberOfSteps
用于支持离散式数据,同时让UIView (QMUI).qmui_outsideEdge
作用在UISlider
上时,可以扩大中间圆点的响应区域(以前是扩大整个 slider,这通常不符合预期)。UISlider+QMUI.mov
QMUITextFieldDelegate
增加方法textField:shouldChangeCharactersInRange:replacementString:originalValue:
,用于业务使用了maximumTextLength
时可以通过这个方法来实现业务自定义的输入限制。在之前的版本里,自定义的输入限制和maximumTextLength
是两个互斥的能力。- 同上,
QMUITextViewDelegate
也增加了方法textView:shouldChangeTextInRange:text:originalValue:
,原因不再赘述。 UIImage (QMUI)
里的qmui_imageWithTintColor:
、qmui_imageWithColor:
方法增加 QMUIAssert 用于辅助发现业务里“无法正确用一个 QMUIThemeColor 生成一张 QMUIThemeImage” 的场景。UITabBar (QMUI)
增加qmui_effectViews
用于在 iOS 15 里获取所有的背景磨砂 view。
会带来 QMUI 新旧版本兼容问题的更新
- 由于
QMUISlider
提供的功能没必要非要以子类的形式存在,因此这个版本我们删除了QMUISlider
,同时新增了功能更加强大的UISlider (QMUI)
分类。 - 上个版本里,为了修复 #1320 的问题,引入了 #1320 (comment) 所述的新问题,经过考虑,这个版本我们回退了 4.4.0 里的改动(也即与 4.3.0 一致),至于 #1320 的问题,是 OC 和 Swift 语言特性导致的,QMUI 暂时不处理,业务请自行规避该用法。
如何适配新版
- 如果你的 App 是用 Xcode 13 打包的,请检查运行在 iOS 15 上时 QMUITheme 功能是否正常。
- 如果你的项目里有使用
QMUISlider
,请将其改为UISlider (QMUI)
里的对应属性(通常都是加个qmui_
前缀而已),或者也可以直接复制 QMUISlider.h/.m 到项目内继续使用。 - 请检查项目里继承自
QMUITableViewCell
并且重写了initWithStyle:reuseIdentifier:
方法,但在业务使用时通过initForTableView:withStyle:reuseIdentifier:
构造 cell 的场景,表现是否正常(预期应该与 4.3.0 保持一致)。 - 更新项目内的 QMUI 版本,运行起来后,请检查 Xcode 控制台是否输出“QMUIThemeColor 生成的图片却不是 QMUIThemeImage”字样的 log,如果有,意味着该处的 image 可能无法自动响应 theme 变化。
如果有使用配置表
- 请将配置表里
QMUILog
段落的位置迁移到UIControl
的前面,这样才能保证其他模块在用到与 QMUILog 相关的开关时能读取到正确的值。
Bugfix
- #1236 由于新增的
UISlider (QMUI)
分类,顺便修复了 iOS 14 及以后的系统里无法正确获取到 thumbView 的 bug。 - #1247 修复 iOS 14 及以后的系统里,如果项目对一个
UIView
使用了qmui_layoutSubviewsBlock
属性,则会导致在 iPad 里开启悬浮键盘时,聚焦一个带有inputAccessoryView
的输入框时会死循环卡死的 bug。 - 修复开启了
NavBarRemoveBackgroundEffectAutomatically
后 iOS 15 里的barTintColor
无法与effectView
共存的 bug。 - #1335 修复
AutomaticCustomNavigationBarTransitionStyle
在前后两个导航栏的显隐状态不一致时表现错误的 bug。 - 修复 Xcode 13 编译的 App 在 iOS 15 下运行时,如果某个界面通过
QMUINavigationControllerAppearanceDelegate
系列方法控制自己的导航栏样式,则停留在该界面时切换 QMUITheme,导航栏样式会被覆盖为配置表的全局样式,而非该界面自己设置的值。 - 修复
-[NSString(QMUI) qmui_substringAvoidBreakingUpCharacterSequencesToIndex:]
方法在 index 刚好等于string.length
时会 crash 的 bug:从语义上这样的 index 应当是合法的,此时需要返回当前 string 的 copy。 - 修复
UITabBar (QMUI).qmui_effectView
在 iOS 15 下无法正确获取到背景磨砂 view 的 bug,会导致UITabBar (QMUI).qmui_effect
失效。 - 修复
QMUITableViewStyleInsetGrouped
的列表,每个 section 最后一个 cell 右下角的圆角丢失的 bug。
QMUI Demo
- 重新制作
UISlider (QMUI)
的 Demo。 QMUIMarqueeLabel
Demo 增加UILabel (QMUI_Marquee)
功能的展示。- 优化
QMUIInteractiveDebugPanelViewController
的使用方式,使其可以方便地以 subview 的形式添加到界面上显示,也可以配置自己项目的外观。 UIImage (QMUI)
Demo 增加渐变图片的展示。UITextField (QMUI)
Demo 增加对自定义内容格式限制的展示。
4.4.0
综述
4.4.0 版本主要内容是适配 iOS 15,同时废弃对 iOS 10 的支持。
iOS 15 对开发者而言最大的 UI 改动就是三种系统 bar(UINavigationBar、UITabBar、UIToolbar)默认样式都分为两个状态:滚动前、滚动后。只要你用 Xcode 13 打包,什么都不改的情况下就会出现这两种状态差异,而大部分 App 的预期应该是维持 iOS 14 相同的表现——因为 iOS 15 的这个特性只能在 iOS 15 上生效,系统无法向后兼容,这意味着如果你要保持系统这个特性,你就需要额外为自己的 App 在 iOS 15 上重新设计一套 bar 的外观。因此 QMUI 的兼容思路也是如此:在配置表提供若干开关,尽量减少业务项目达到“维持 App 外观不变”所需要付出的工作量。如果你的适配思路与此相悖,那么本次更新的内容可能对你作用不大,请降低预期。
另,如果你希望全 iOS 版本均能实现 iOS 15 这种滚动效果,建议使用 QMUINavigationBarScrollingAnimator
,它比系统功能更丰富,可以精准控制滚动过程中每一个时机的样式,可以联动除了 navigationBar、statusBar 之外的其他任何事情,而系统的仅仅只能定义起始和结束两个状态的 navigationBar 的属性,也无法监听当前的状态变化,局限性还是比较大的。以下是 QMUI Demo 中 QMUINavigationBarScrollingAnimator
功能的演示视频。
QMUINavigationBarScrollingAnimator.mov
新增功能
- 配置表增加开关
NavBarUsesStandardAppearanceOnly
,当业务项目打开的时候,会保持UINavigationBar.scrollEdgeAppearance
与UINavigationBar.standardAppearance
对齐,从而实现 iOS 15 上的导航栏在滚动前后样式一致。 - 配置表增加开关
NavBarRemoveBackgroundEffectAutomatically
,当业务项目打开的时候,会让UINavigationBar
在设置了backgroundImage
、barTintColor
时自动隐藏磨砂,在backgroundImage
、barTintColor
为nil
时自动显示磨砂(也即维持 iOS 14 的默认行为)。因为 iOS 15 及以后,backgroundEffect
可以和backgroundImage
、barTintColor
同时存在了,这与之前业务项目的代码逻辑的预期是不匹配的,要么你用这个开关来回到 iOS 14 的表现,要么你自己为 iOS 15 增加适配逻辑。 - 配置表增加开关
TabBarUsesStandardAppearanceOnly
、TabBarRemoveBackgroundEffectAutomatically
、ToolBarUsesStandardAppearanceOnly
、ToolBarRemoveBackgroundEffectAutomatically
,具体含义请参考上面的NavBar
,这里不再赘述。 - 配置表增加开关
TableViewSectionHeaderTopPadding
、TableViewGroupedSectionHeaderTopPadding
、TableViewInsetGroupedSectionHeaderTopPadding
,分别设置三种 style 的QMUITableView
在 iOS 15 上的sectionHeaderTopPadding
默认值,默认不修改的话,UITableViewStylePlain
会在每个 sectionHeader 之前多出来23pt的空白,另外两种 style 的列表与 iOS 14 一致。 QMUICommonDefines.h
增加宏IOS15_SDK_ALLOWED
用于区分当前是否是 Xcode 13 编译。QMUIAnimationHelper
增加接口bounceFromValue:toValue:time:coeff:
用于实现系统UIScrollView
拖到尽头那种阻尼感的体验。QMUILabel
增加属性truncatingTailView
用于在文字缩略时可以显示一个自定义的 View,具体可查看 QMUI Demo 的效果。
QMUIModalPresentationViewController
增加属性window
允许业务获取到 modal 内部正在使用的UIWindow
对象。QMUIModalPresentationViewController
增加属性shouldDimmedAppAutomatically
用于控制当前 modal 显示时是否需要把背后的 App 界面置灰(类似系统的UIAlertController
显示时的效果)。QMUIPopupContainerView
增加属性contentViewSizeThatFitsBlock
方便业务在外部控制 popup 内容的大小,而不一定非要继承一个子类。QMUIPopupContainerView
增加属性backgroundView
支持用一个自定义的 View(例如磨砂)作为 popup 的背景,当使用了这个属性后,arrowImage
只会作为遮罩来使用,不会显示arrowImage
图片内部的纹理(也即只用箭头的造型,不用它的内容)。
QMUIPopupContainerView
优化属性arrowImage
的实现,允许你将一张UIImageRenderingModeAlwaysTemplate
的图片作为箭头图片,当你这么做时,图片的颜色会自动跟随backgroundColor
走,从而避免以前设置了自定义箭头图片后再修改backgroundColor
,会看到箭头颜色与背景色不一致的问题。- #1295
QMUITextField
增加与QMUITextView
相同的canPerformPasteActionBlock
、pasteBlock
接口以支持控制粘贴事件(例如你可以在粘贴文本时把文本变成一张图放在输入框里)。 +[QMUIHelper deviceModel]
增加 iPhone 13、iPad 新设备的信息。- 增加协议
QMUIStringProtocol
,将原本NSString(QMUI)
支持的功能也迁移到NSAttributedString(QMUI)
内。 - 增加
UIBlurEffect(QMUI)
分类,提供qmui_effectWithBlurRadius:
支持指定明确的模糊半径,提供qmui_style
支持获取当前 blur 对象的 style 值。同时 QMUI Demo 内增加UIBlurEffect(QMUI)
的 Demo 展示。 UITableView(QMUI_InsetGrouped)
支持在 iOS 12 及以下的 Interface Builder 里设置 tableView 为InsetGrouped
。- #1290 @xixisplit
- [UIImage(QMUI) qmui_imageWithGradientColors:]
增加QMUIImageGradientTypeTopLeftToBottomRight
、QMUIImageGradientTypeTopRightToBottomLeft
类型。
会带来 QMUI 新旧版本兼容问题的更新
- 为了适配 iOS 15,
UINavigationBar
、UIToolbar
从这个版本开始,改为用 iOS 13 就提供的新系统接口UINavigationBarAppearance
、UIToolbarAppearance
来设置样式(UITabBar
的在 QMUI 4.0.0 适配 iOS 13 时就已经换成新接口了),新旧接口是互斥的,一旦项目里某个地方用了新接口,整个项目的旧接口都会失效。但为了尽量减少业务项目更新 QMUI 版本的工作量,我们在UINavigationBar(QMUI)
、UIToolbar(QMUI)
内对旧接口做了映射,统一转换为新接口,因此预期业务项目更新版本后应该不会出现UINavigationBar
、UIToolbar
的样式差异问题。 - 由于最低版本从 iOS 10 升级到 iOS 11,因此去掉了 QMUI 内所有为 iOS 10 写的代码,并且以前为了兼容 iOS 11 才有的 API 而加的接口(例如
qmui_safeAreaInsets
)也没必要了。 - 由于 #1325 的问题,再考虑到该功能原本的实现代码有些混乱,因此这个版本重构了
AutomaticCustomNavigationBarTransitionStyle
的实现,减少了对QMUINavigationControllerAppearanceDelegate
系列接口多次不必要的调用,并且更稳定。 - 由于现如今
QMUIButton
的功能已足够灵活,相比之下基于它衍生的QMUIFillButton
、QMUIGhostButton
显得有点鸡肋,且预设的 enum 难以准确满足业务项目的配色需求,因此这个版本我们将QMUIFillButton
、QMUIGhostButton
删除,建议原本在用的项目将其改为QMUIButton
,或者你也可以复制这两个类的文件放在业务项目里继续使用。 - 4.3.0 里标记为废弃的
QMUILinkButton
在 4.4.0 里正式删除。 - 更换
QMUITheme
在 iOS 13 及以后的系统里监听系统userInterfaceStyle
变化的方式,从而达到:- 避免之前监听
-[UIWindow traitCollection]
会导致每次有任何界面操作(触摸、按下键盘快捷键、Dark Mode 切换)时都会触发这段逻辑,而我们仅仅只希望利用它来监听 Dark Mode 切换而已。 - #1087 #1318 避免之前 hook
-[UIWindow traitCollection]
导致在 Xcode 唤醒的场景里 App 第一次升起键盘会触发 Main Thread Checker 的问题。 - 旧的实现方案在系统
userInterfaceStyle
发生变化,到 QMUITheme 成功切换之间的耗时较长,在此期间访问QMUIThemeManager.currentTheme
得到的值必定都是错误的(例如这过程中就会触发 UIViewController preferredStatusBarStyle,而业务项目在该方法里获取当前 QMUIThemeManager.currentTheme 的操作还是比较常见的)问题。
- 避免之前监听
- 去掉
QMUIThemePrivate
里重写-[UIView setBackgroundColor:]
、-[UITableViewCell setBackgroundColor:]
的代码,实测 iOS 11-15 均不需要这种处理了,而这段代码会导致QMUIThemeColor
无法搭配UIViewPropertyAnimator
使用。 - 去掉
QMUIThemePrivate
里重写-[UITextField setNeedsDisplay]
的代码,实测不需要。 QMUIHelper
重命名is61InchScreenAndiPhone12
为is61InchScreenAndiPhone12Later
,重命名screenSizeFor61InchAndiPhone12
为screenSizeFor61InchAndiPhone12Later
。QMUIHelper.safeAreaInsetsForDeviceWithNotch
对全面屏 iPad 返回的 top 值从 0 改为 24。QMUIHelper.resetDimmedApplicationWindow
的实现里,把 Normal 改为系统默认的 Automatic(免测)。- 配置表开关
NavBarButtonFontBold
在 iOS 15 里对系统的 Done 类型的UIBarButtonItem
也能生效,iOS 14 及以前只能对QMUINavigationButtonTypeBold
才生效。 - 删除配置表开关
StatusbarStyleLightInitially
,新增配置表开关DefaultStatusBarStyle
,新开关的类型为UIStatusBarStyle
,可以支持精准的状态栏样式控制,从而避免类似 #1311 的问题。
如何适配新版
- 全局搜索“QMUIFillButton”、“QMUIGhostButton”,将用到的地方换成
QMUIButton
,如果较多,建议在项目里创建工具方法(可以参考 QMUI Demo 里的+[QDUIHelper generateGhostButtonWithColor:]
。或者也可以将这两个被删除的文件移到业务项目中继续使用。 - 全局搜索“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
- 全局搜索”qmui_safeAreaInsets“,将其替换为系统的
safeAreaInsets
,前者依然能用但已被标记为废弃,下个版本会删除。 - 全局搜索”qmui_contentInset“,将其替换为系统的
adjustedContentInset
,前者依然能用但已被标记为废弃,下个版本会删除。 - 全局搜索”qmui_maskedCorners“,将其替换为系统的
maskedCorners
,前者依然能用但已被标记为废弃,下个版本会删除。 - 全局搜索”qmui_performBatchUpdates“,将其替换为系统的
performBatchUpdates
。 - 全局搜索 “is61InchScreenAndiPhone12”,将其重命名为 “is61InchScreenAndiPhone12Later”。
- 全局搜索 “screenSizeFor61InchAndiPhone12”,将其重命名为“screenSizeFor61InchAndiPhone12Later”。
- 检查用到
QMUIHelper.safeAreaInsetsForDeviceWithNotch
的地方在 iPad 上是否正常。 - 检查用到
AutomaticCustomNavigationBarTransitionStyle
效果的地方是否正常。 - 检查将
QMUIThemeColor
作为UIView.backgroundColor
、UITableViewCell.backgroundColor
的地方,theme 切换时是否正常。 - 检查 theme 切换时
UITextField
的文字颜色是否正常。 - 如果项目有使用 QMUITheme,请检查 App 的 Dark Mode 功能是否正常,特别留意 App 在后台、有键盘升起的时候。另外请检查项目里是否有使用
UITraitCollection.currentTraitCollection.userInterfaceStyle
来判断当前 App 样式的写法,有的话,请去掉并改为用QMUIThemeManagerCenter.defaultThemeManager.currentThemeIdentifier
,因为前者这个系统的方法在 Dark Mode 切换过程中可能会得到错误的值。
如果有使用配置表
- 请删除包含”fillButton“、”ghostButton“字样的10个开关。
- 在
#pragma mark - NavigationBar
分段里添加以下开关,并将其设置为项目所需的值。请保证语句的顺序在其他 navBar 开关之前。if (@available(iOS 15.0, *)) { QMUICMI.navBarUsesStandardAppearanceOnly = NO; QMUICMI.navBarRemoveBackgroundEffectAutomatically = NO; }
- 在
#pragma mark - TabBar
分段里添加以下开关,并将其设置为项目所需的值。请保证语句的顺序在其他 tabBar 开关之前。if (@available(iOS 15.0, *)) { QMUICMI.tabBarUsesStandardAppearanceOnly = NO; QMUICMI.tabBarRemoveBackgroundEffectAutomatically = NO; }
- 在
#pragma mark - Toolbar
分段里添加以下开关,并将其设置为项目所需的值。请保证语句的顺序在其他 toolBar 开关之前。if (@available(iOS 15.0, *)) { QMUICMI.toolBarUsesStandardAppearanceOnly = NO; QMUICMI.toolBarRemoveBackgroundEffectAutomatically = NO; }
- 将下方代码添加到配置表里的适当位置,并将其设置为项目所需的值。
if (@available(iOS 15, *)) { QMUICMI.tableViewSectionHeaderTopPadding = UITableViewAutomaticDimension; QMUICMI.tableViewGroupedSectionHeaderTopPadding = UITableViewAutomaticDimension; QMUICMI.tableViewInsetGroupedSectionHeaderTopPadding = UITableViewAutomaticDimension; }
- 请检查项目里用到的 Done 类型的
UIBarButtonItem
,字体样式是否符合预期。 - 将下方代码添加到配置表里,并将其设置为项目所需的值。同时全局搜索”StatusbarStyleLightInitially“字样,将用到的地方换成新的”DefaultStatusBarStyle“。
QMUICMI.defaultStatusBarStyle = UIStatusBarStyleDefault; // DefaultStatusBarStyle : 默认的状态栏样式,默认值为 UIStatusBarStyleDefault,也即在 iOS 12 及以前是黑色文字,iOS 13 及以后会自动根据当前 App 是否处于 Dark Mode 切换颜色。如果你希望固定为白色,请设置为 UIStatusBarStyleLightContent,固定黑色则设置为 QMUIStatusBarStyleDarkContent。
Bugfix
- #1276 修复 QMUITextView 重写错 init 方法,导致 initWithFrame:textContainer: 无法应用初始值的 bug。
- #1308 #1316 修复在输入框内长按移动光标时会错误触发
UIGestureRecognizer(QMUI)
assert 的问题。 - #1312 修复启动时试图通过
qmui_getProjectClassList
获取项目里所有业务 Class 失败的 bug。 - #1320 修复
- [QMUITableViewCell initForTableView:xxx]
方法的实现不恰当,可能引起 Swift 内重复调用 init 的问题。 - #1322 @ACFancy 修复
QMUITextField
、QMUITextView
在进行”重做“操作时依然可能引发 #1168 里描述的问题的 bug。 - 修复
QMUIPopupMenuView
在itemTitleFont
、itemTitleColor
、padding
的值发生变化时没有刷新 item 样式的 bug。 - 修复 `U...