QMUI IOS Versions Save

QMUI iOS——致力于提高项目 UI 开发效率的解决方案

4.7.0

9 months ago

综述

随着 QMUI 最初的几位老人家各奔天涯,历经7年自费集资的老官网 qmuiteam.com在不久的将来费用消耗完就不再维护了,以后都在 GitHub。对应地,依附于官网的自动上报统计 SendAnalyticsToQMUITeam 也在这个版本删除,借此也跟大家分享下统计数据(毕竟在座的各位都参与其中)。

截止至2023-7-24,QMUI iOS 累计接入6w项目(以Bundle Id为维度),日活跃项目 1.6k+,月活跃项目 4.3k+。


这个版本主要是累积这段时间的修修补补。

新增功能

  1. qmui_outsideEdgeUIBarButtonItem.customView 也生效,以后你可以让导航栏按钮的响应区域扩大到导航栏之外了。
  2. CALayer(QMUI) 增加属性 qmui_maskPathBlock 用于快捷添加遮罩。
  3. CALayer(QMUI) 增加属性 qmui_evenOddMaskPathBlock 用于快捷镂空一个区域。
  4. NSArray(QMUI) 增加方法 qmui_compactMapWithBlock: 用于转换数组里的元素类型,并支持过滤掉 nil
  5. 增加 NSDictionary(QMUI) 分类,提供 qmui_mapWithBlock: 方法用于转换字典里的 key-value 类型,提供 qmui_deepMapWithBlock: 方法用于深度拷贝的转换。
  6. 新增 hook 用于保护 -[NSMutableAttributedString appendAttributedString:] 遇到参数为 nil 时会命中系统 assert: nil argument 的情况。
  7. UILabel(QMUI) 增加 qmui_centerOfCapHeight 属性用于获取单行文本里 font.capHeight 的位置。
  8. UINavigationController(QMUI) 增加属性 qmui_alwaysInvokeAppearanceMethods 用于在 UINavigationController 不可视时进行 push/pop 依然能触发 vc 生命周期方法的方法。
  9. UINavigationController(QMUI) 增加属性 qmui_lastOperation 用于获取当前正在进行的切换界面动画类型(push 或 pop)。
  10. UITextField(QMUI) 增加属性 qmui_respondsToDeleteActionAtLeading 用于对齐 UITextView 的行为:在输入框开头继续按删除按钮也可以触发 shoudChange 的 delegate 方法。

会带来 QMUI 新旧版本兼容问题的更新

  1. 配置表删除 SendAnalyticsToQMUITeam

如何适配新版

  1. 如果你有使用配置表,请删除其中的 SendAnalyticsToQMUITeam

Bugfix

  1. #1451 对因为被 present 盖住的界面,修改 navigationBar 样式时的 assert 条件做优化。
  2. 修复 #1473 UISearchController.searchBar 作为 UITableView.tableHeaderView 时,进入搜索状态,搜索结果列表顶部有一大片空白的问题。
  3. 修复 #1498 开启 forceEnableInteractivePopGestureRecognizer 的界面被 push 的过程中快速手势返回,容易导致 App 卡死的 bug。
  4. #1501 修复 AutomaticCustomNavigationBarTransitionStylesetViewControllers: 场景下的若干问题。
  5. 修复 QMUIImagePickerViewController 初始滚动位置可能错误的 bug。
  6. 修复 QMUIAlertControllerActionSheet 演示呈现较长内容时,顶部布局没考虑 safeAreaInsets 的问题。
  7. 修复 QMUIBadge 对纯文本的 UIBarButtonItem 基准布局错误的 bug。
  8. 修复 QMUIButtonadjustsButtonWhenDisabled = NO 时也会在 setEnabled:YES 里重置 alpha 的问题。
  9. 优化 QMUINavigationButton 自定义返回按钮点击区域太小的问题。
  10. 修复 QMUIKeyboardManager 在以 iPad“侧拉”模式打开的 App 中获取键盘可视高度错误的 bug,iPhone、iPad 全屏/分屏/台前调度,都没这个问题。
  11. 修复QMUITheme 在切换 theme 时错误地覆盖 UITextView.textColor 导致如果输入框内存在不同颜色的富文本时会颜色错误的 bug。
  12. 修复同一个对象对不同 window 分别调用 qmui_addSizeObserverForWindow:,最终其中某个 window size 发生变化时所有 block 都被触发的 bug。
  13. 解决在未使用配置表的情况下,QMUIAssert 应使自动变成 NSAssert 的问题。
  14. 修复 QMUI Demo 无法使用 XCTest 的问题。
  15. 修复 UISearchBar(QMUI) 快速在 show/hide left/right accessoryView 时容易出现状态错误的 bug。
  16. 修复 UIView(QMUI).qmui_shouldShowDebugColor 属性在开启又关闭后可能导致元素背景全黑的问题。

4.6.3

1 year ago

🎆🎉🧨🧧 2022→2023

Bugfix

  1. 修复 QMUIThemeColor.CGColor 内存泄漏的 bug。
  2. 修复 QMUITextFieldQMUITextView 在某些情况下 shouldChangeCaractersInRange:replacementString:originalValue: 没被调用的 bug。
  3. 优化某些场景即便调用 qmui_rotateToInterfaceOrientation 依然无法触发屏幕方向旋转的问题。

4.6.1

1 year ago

综述

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 新旧版本兼容问题的更新

  1. 删除常量 QMUITableViewStyleInsetGrouped
  2. 删除 UITableView (QMUI)qmui_style 属性。
  3. 删除宏 QMUIStatusBarStyleDarkContent
  4. 删除 QMUIHelper.statusBarStyleDarkContent 方法。
  5. 删除 UISearchBar (QMUI)qmui_textField 属性。
  6. 删除配置表里的 ShouldFixTabBarTransitionBugInIPhoneX 开关。

如何适配新版

  1. 全局搜索 QMUITableViewStyleInsetGrouped,将其替换为系统的 UITableViewStyleInsetGrouped
  2. 全局搜索使用到 UITableView.qmui_style 的地方(包括 Xib 文件),将其替换为系统的 UITableView.style 属性。
  3. 全局搜索 QMUIStatusBarStyleDarkContent,将其替换为系统的 UIStatusBarStyleDarkContent
  4. 全局搜索用到 QMUIHelper.statusBarStyleDarkContent 的地方,将其替换为系统的 UIStatusBarStyleDarkContent
  5. 全局搜索用到 UISearchBar.qmui_textField 的地方,将其改为系统的 UISearchBar.searchTextField
  6. 如果有使用配置表,请删除你配置表里的 ShouldFixTabBarTransitionBugInIPhoneX

4.6.0

1 year ago

综述

QMUI 4.6.0 版本主要内容是兼容 iOS 16 及 iPhone 14 等新设备,以屏幕旋转、键盘管理为主。其中屏幕旋转的使用方式可以查看 Wiki:《适用于 iOS 16 及以下版本的屏幕方向控制方式》

新增功能

  1. QMUIPopupMenuView 增加 sectionSpacing 属性用于控制 section 之间的间隙。
  2. QMUIThemeColorQMUIThemeImageQMUIThemeVisualEffect 均增加了 name 属性及对应的 init 方法,让业务可以用字符串来标记该动态对象。
  3. 增加 NSShadow (QMU) 分类提供一个便捷的 init 方法。
  4. CALayer (QMUI) 增加属性 qmui_shadow 支持用 NSShadow 对象来描述投影样式,从而可以一行代码完成投影的设置。
  5. NSArray (QMUI) 增加方法 qmui_firstMatchWithBlock: 用于过滤第一个符合 block 条件的元素。
  6. UIBezierPath (QMUI) 增加方法 qmui_bezierPathWithMediaTimingFunction: 支持将一个 CAMediaTimingFunction 转成一条宽高为 1 的贝塞尔曲线(可以理解为数据可视化)。
  7. QMUICommonDefines.h 增加 IOS16_SDK_ALLOWED 宏用来标志当前是否为 Xcode 14 编译环境。
  8. 增加 [QMUIHelper screenSizeFor67InchAndiPhone14Later] 方法、[QMUIHelper is67InchScreenAndiPhone14Later] 方法、IS_67INCH_SCREEN_AND_IPHONE14 宏用于标记当前设备是否为 iPhone 14 Pro Max 尺寸的屏幕。
  9. 增加 [QMUIHelper statusBarHeightConstant] 用于获取静态的状态栏高度。
  10. -[QMUIHelper deviceName]-[QMUIHelper deviceModel] 增加新设备的信息。
  11. -[QMUIHelper safeAreaInsetsForDeviceWithNotch] 增加新设备的值。
  12. UIViewController (QMUI_Interface) 增加方法 qmui_rotateToInterfaceOrientation: 用于强制将当前界面旋转到某个指定方向。
  13. UIViewController (QMUI_Interface) 增加方法 qmui_setNeedsUpdateOfSupportedInterfaceOrientations 对应 iOS 16 系统的 setNeedsUpdateOfSupportedInterfaceOrientations,用于告诉系统当前希望刷新屏幕方向。
  14. UITableViewCell (QMUI) 增加属性 qmui_configureReorderingStyleBlock 支持修改 cell 在排序过程中的样式。

会带来 QMUI 新旧版本兼容问题的更新

  1. QMUIPopupContainerViewUIColor *shadowColor 属性改为 NSShadow *shadow 以支持更完整的投影样式。
  2. UISlider (QMUI)qmui_thumbShadowColorqmui_thumbShadowOffsetqmui_thumbShadowRadius 删除,改为新增的 qmui_thumbShadow 属性。
  3. 使 StatusBarHeightConstant 能兼容 iOS 16、iPhone 14 Pro 灵动岛。
  4. 将 iPhone 14 Pro Max 加入到 AS_65INCH_SCREEN 宏内。
  5. 将 iPhone 14 Pro Max 加入到 -[QMUIHelper isRegularScreen] 内。
  6. 删除 +[QMUIHelper rotateToDeviceOrientation:] 方法。

如何适配新版

  1. 全局搜索使用到 QMUIPopupContainerView.shadowColor 的地方,将其改为新的 shadow 属性。
  2. 全局搜索使用到 UISlider.qmui_thumbShadowColorUISlider.qmui_thumbShadowOffsetUISlider.qmui_thumbShadowRadius 的地方,将其替换为新的 qmui_thumbShadow 属性。
  3. 全局搜索用到 StatusBarHeightConstant 的地方,分别测试其在 iPhone 13 和 iPhone 14 Pro 下的布局是否正确。
  4. 全局搜素用到 AS_65INCH_SCREEN 的地方,测试其在 iPhone 14 Pro Max 下的布局是否正确。
  5. 全局搜索用到 -[QMUIHelper isRegularScreen] 的地方,测试其在 iPhone 14 Pro Max 下表现是否正确。
  6. 全局搜索使用到 +[QMUIHelper rotateToDeviceOrientation:] 的地方,将其换成 -[UIViewController qmui_rotateToInterfaceOrientation:]

Bugfix

  1. #1437 修复在 iOS 15 里打开一个默认隐藏导航栏的界面,返回按钮样式错误的 bug。
  2. #1438 修复 QMUIPopupContainerViewsourceView 设置为 nil 时 crash 的 bug。
  3. #1439 UIView.qmui_hitTestBlock 的返回值应该添加 _Nullable 以对齐系统。
  4. #1447 #1450 #1453 #1458 #1460 解决 iOS 16 下 QMUIKeyboardManager 的各种 bug。
  5. #1449 #1463 修复将 UIView.backgroundColor 设置为 QMUIThemeColor 后再设置为另一个与 QMUIThemeColor 当前色值相同的颜色时,后者无效的 bug。
  6. #1451 修复在尚未添加到 window 的 UINavigationController 里修改 navigationBar 可能会导致 navigationBar 样式错误的 bug。
  7. #1452 修复开启系统辅助功能粗体文本的情况下,设置了 tintColorAdjustsTitleAndImageQMUIButton 在 App 切到桌面再切回来时颜色错误的 bug。
  8. #1457 修复 Xcode 14 编译的 App 在 iOS 16.0 上可能存在顶部标题布局错乱的 bug。
  9. 修复 QMUINavigationTitleView.subAccessoryView 在计算布局时如果 subAccessoryView 带有 transform 则布局错误的 bug。
  10. 修复 QMUIPopupContainerViewsourceViewsourceBarItem 的值更新时没有清除与旧值的绑定关系的 bug。
  11. 修复 QMUIPopupContainerView 计算宽高可能不准确的 bug:应该取 px 整数而不是 pt 整数。
  12. 修复 QMUIPopupMenuButtonItem 里强制修改 button.contentEdgeInsets.top/bottom 为 0 的 bug。
  13. 修复 iOS 16 里 QMUITextView 文本颜色设置为 QMUIThemeColor 后无法响应 theme 变化的 bug。
  14. 修复 -[QMUIHelper keyboardHeightWithNotification:inView:] 在 iOS 16 台前调度下无法返回正确值的 bug。
  15. 修复 UITableViewCell(QMUI).qmui_selectedBackgroundColor 有时候失效的 bug。

其他

  1. #1378 支持 Mac Catalyst 编译。
  2. 由于 iOS 16 对横竖屏体验的优化,所以配置表里的 AutomaticallyRotateDeviceOrientation 在 iOS 16 下已经不需要了,请业务项目知悉即可。

4.5.1

1 year ago

会带来 QMUI 新旧版本兼容问题的更新

  1. NSObject (QMUI).qmui_ivarList 输出的内容里,为每个 Ivar 开头增加了 offset 值的展示,同时显示十进制和十六进制的值,中间用“|”隔开。

如何适配新版

  1. 全局搜索“qmui_ivarList”,检查使用到的地方是否有影响。

Bugfix

  1. #1432 修复开启 AutomaticCustomNavigationBarTransitionStyle 的情况下,从界面 B pop 回界面 A 的过程,如果 A 的导航栏效果与全局默认效果不同,则在 pop 过程中 A 的导航栏样式错误的 bug。
  2. #1434 修复 qmui_outsideEdge 在不可见的 view 上生效的 bug。
  3. 修复 QMUIAlertController 在 alert、actionSheet 两种 style 下,如果不存在 title、message、customView 时,第一个 action 的顶部依然错误出现分隔线的 bug。
  4. 修复 UIScrollView (QMUI).qmui_alreadyAtTop 可能因为浮点精度问题导致返回值错误的 bug。

4.5.0

1 year ago

新增功能

  1. 增加 QMUIBarProtocol 用于同时约定 UINavigationBarUITabBar 的功能接口,因为这两种 bar 所需要的功能基本都一样,用 protocol 来约定也便于后续同步调整这两种 bar 的功能。同时也因此使得 UINavigationBar (QMUI) 新增了 qmui_effectViewqmui_effectViewsqmui_effectqmui_effectForegroundColor 几个与磨砂相关的接口。
  2. 由于 QMUIBarProtocolUINavigationBar 带来更多的能力,所以这个版本我们优化了 QMUISmoothEffectAutomaticCustomNavigationBarTransitionStyle 里与磨砂相关的表现,使其更符合组件预期。
  3. 增加 UIView (QMUINavigationTitleView).qmui_useAsNavigationTitleView 属性用于标记某个 view 为自定义的导航栏 titleView,以便 QMUI 自动帮你处理一些布局上的系统 bug。
  4. QMUIPopupMenuView 增加 willHandleButtonItemEventBlock 属性便于统一管理 item 的点击行为。
  5. CALayer (QMUI) 增加 qmui_layerWithName: 方法用于便捷查找指定 name 的 layer。
  6. UIActivityIndicator(QMUI) 支持用 qmui_size 指定大小。

会带来 QMUI 新旧版本兼容问题的更新

  1. 由于 QMUIBarProtocol 的调整,我们同时删除了 UINavigationBar (QMUI).qmui_backgroundContentView 属性。
  2. UISearchController.dimsBackgroundDuringPresentation 默认值在 iOS 15 下被改为 NO 了,为了保持与旧版本的一致,QMUISearchController 里将其改为 YES。
  3. #1425 QMUICommonTableViewController 内自带的 QMUISearchController 的搜索结果列表的 UITableViewStyle 从 Plain 改为与当前宿主 vc 的 tableView.style 一致。
  4. 将 QMUIStringPrivate qmui_substringFromIndex 的参数 index 等于字符串长度时返回的值从 nil 改为 @"",以保持与系统方法一致。

如何适配新版

  1. 如果仍需要 UINavigationBar (QMUI).qmui_backgroundContentView 属性,请将 QMUIKit 旧代码抄到业务项目里。
  2. 检查 iOS 15 里用到 QMUISearchController 的地方,检查进入搜索状态时界面表现是否符合预期。
  3. 简单检查用到 QMUICommonTableViewController、带有搜索功能,且 style 不为 UITableViewStylePlain 的列表,其搜索结果的 tableViewStyle 是否符合预期。
  4. 请检查用到 qmui_substringFromIndex 的地方,在 index 等于 string.length 时表现是否正常。

Bugfix

  1. 修复 QMUIAlertController 以 alert 形式显示时,如果内容特别多,浮层会溢出到屏幕的 safeAreaInsets 区域的问题。
  2. 修复 QMUIConsole.canShow = NO 时依然会创建相关的 view、viewController 对象的问题。
  3. 修复 iOS 15.4 启动 App 后到系统设置-辅助功能-显示与文字大小-修改一下“按钮形状”的开关,会 crash:-[UILabel _accessibilityButtonShapesChangedNotification:]: message sent to deallocated instance 0x17e751d60 的问题。
  4. 修复 QMUIMultipleDelegates 在 iOS 16 下配合 UIScrollView 可能引发 crash 的问题。
  5. 修复 QMUINavigationTitleView.needsLoadingPlaceholderSpace = NO 时即便不显示 loading,loading 也会占位,导致文字偏右的问题。
  6. 修复 QMUITextView 文字换行时丢失系统滚动动画特效的 bug。
  7. 修复 - [QMUITextView setFrame:] 被调用时即便 size 没变化也会触发 setContentOffset: 产生滚动的问题。
  8. 修复配置表的值发生变化时重新应用的时候,对于业务 App 使用自定义 container viewController 的场景,无法正确刷新它的 navigationBar、tabBar 样式的 bug。
  9. 修复 +[QMUIHelper applicationSize] 在 MacCatalyst App / M1 上返回了 CGSizeZero 导致 APPLICATION_WIDTHAPPLICATION_HEIGHT 的值为 0 的 bug。
  10. 修复在 root controller 实现了 preferredStatusBarStyle 方法并且在其中调用 childViewControllerForStatusBarStyle 方法的情况下,iOS 12 present 起 AVPlayerViewController 在 dismiss 时会触发 preferredStatusBarStyle 导致死循环的 bug:因为 AVPlayerViewController 内部的 preferredStatusBarStyle 会转向 presentingViewControllerpreferredStatusBarStyle,而后者又会 return AVPlayerViewController,于是死循环。
  11. 修复 qmui_substringAvoidBreakingUpCharacterSequences 系列方法在遇到 length 为1、range 与 string 相等的情况时会 crash 的 bug。
  12. 修复 QMUIStringPrivate 里的 assert 条件与系统方法不匹配的问题。
  13. 修复 substring:avoidBreakingUpCharacterSequencesWithRange:lessValue:countingNonASCIICharacterAsTwo: 在接受的 range 头尾都刚好落在一个 emoji 的中间时会得到一个负值 range 并引起 crash 的 bug,同时对负值 range 做 QMUIAssert 的提醒但不干预其返回值。
  14. #1248 #1274 #1377 修复 QMUIConsole 在没使用配置表或者配置表里没设置 TableViewCellBackgroundColor 的情况下,打印出来的日志背景是白色的,看不见文字的 bug。
  15. #1326 调整 StatusBarHeightConstant 的值,使其在 statusBarHidden 时,iOS 14 下返回44,iOS 15 返回50,保持与系统 UIApplication.statusBarFrame.size.height 一致。
  16. #1391 修复 NSURL (QMUI).qmui_queryItems item 类型错误的 bug。
  17. #1404 修复 QMUITextView 当文本较多,在真机上长按系统输入法的删除按钮达到快速删除模式时,输入框底部容易出现大段空白的 bug。
  18. #1411 修复 UITableView.delegate 开启了 qmui_multipleDelegatesEnabled 后在 dealloc 时可能引发 crash 的问题。
  19. #1413 修复 UISlider(QMUI) 先设置 qmui_step 再设置 qmui_stepDidChangeBlock 后某些情况下首次点击无法触发 block 的 bug。
  20. #1418 修复 UIImageViewUIButton 配合 template image 使用时无法通过 tintColor 来修改图片颜色的 bug。
  21. #1415 修复 QMUINavigationTitleView 先设置 needsLoadingView = YES 再修改 loadingViewSize 会导致文字无法完整显示的 bug。
  22. #1421 修复 QMUILabel.truncatingTailView 在 label.text 为空时 crash 的 bug。
  23. #1427 修复 QMUI 里 UITableViewsetDelegate:setDataSource: 可能引发 crash 的问题。

其他

  1. QMUIConsole 专属的 window 类型从 UIWindow 改为 QMUIConsoleWindow,使其更容易与其他 window 区分开(例如在 Lookin 里查看结构时)。
  2. - [NSString (QMUI) qmui_trim] 默认去掉 C 里的字符串结束符“\0”。

4.4.3

2 years ago
  1. UISlider (QMUI) 增加 qmui_stepDidChangeBlock 以更便捷的方式监听 step 的变化,同时修复之前用 value changed 监听可能不准确的 bug。
  2. 优化 UIImage (QMUI) 里与 QMUITheme 相关的一些报错的判断方式,之前的写法会导致“对一个 QMUIThemeImage 调用 qmui_imageWithTintColor: 会误判”的问题。
  3. 优化 QMUIStringPrivate 里对 substrings 系列方法的报错,将其从 NSAssert 改为 QMUIAssert,这样业务如果不太关注的话,可以以 log 的形式输出,而不会中断 Debug。
  4. 优化 -[NSString (QMUI) qmui_capitalizedString 的实现,如果字符串以 Emoji 开头,就不应该尝试转为大写了。
  5. #1358 修复 UITabBar (QMUI).qmui_effectViews 在 iOS 12 及以下会 crash 的 bug。

4.4.2

2 years ago

新增功能

  1. QMUIStringPrivate 增加对 NSString substring 系列接口的异常情况的保护,方便自动发现类似裁剪字符串时不小心把 emoji 从中间裁剪的场景,避免出现乱码、crash。
  2. NSObject (QMUI) 增加 qmui_viewInfo 属性用于 Debug 时方便地输出某个 view 的 view 层级结构。

会带来 QMUI 新旧版本兼容问题的更新

  1. 为了修复 #1351 的 bug,我们修改了 QMUINavigationBarScrollingAnimator 自动获取 UINavigationBar 的逻辑,旧版本是通过 QMUIHelper.visibleViewController.navigationController.navigationBar 来获取,新版本改为通过绑定的 scrollView 一层一层往上找,找到所在的 viewController 的导航栏。所以如果业务项目以前存在“scrollView 所在的 viewController,和 scrollView 控制的 navigationBar 不处于同一个 UINavigationController” 里时,则更新 QMUI 版本后 animator 会失效。大部分情况下业务项目应该不会存在这种场景。

如何适配新版

  1. 检查业务项目里使用了 QMUINavigationBarScrollingAnimatorQMUINavigationBarScrollingSnapAnimator 的地方,效果是否与 4.4.1 一致。

Bugfix

  1. #1330 #1346 修复 NavBarRemoveBackgroundEffectAutomatically 在开启了 AutomaticCustomNavigationBarTransitionStyle 时可能对假 bar 无效的 bug。
  2. #1351 修复 QMUINavigationBarScrollingAnimator 在 scrollView 所在的 viewController 已经被推出 UINavigationController 时,滚动器依然能对 UINavigationBar 产生影响的 bug。
  3. #1352 修复 QMUIButton 开启了 adjustsImageTintColorAutomatically 后修改 normal 的 image,highlighted、disabled 的 image 无法同步更新的 bug。
  4. 修复 QMUIModalPresentationAnimationStylePopup 的 hide 动画无法看到缩小过程的 bug。

QMUI Demo

  1. 修复 QMUISmoothEffect 在转场过程中修改 effect 可能出现的 crash。

4.4.1

2 years ago

新增功能

  1. 新增 UILabel (QMUI_Marquee) 分类,支持开启系统 UILabel 内置的跑马灯效果,功能比 QMUIMarqueeLabel 简单,但由于是系统内置的能力,性能应该是不需要担心的。我们推荐在满足需求的前提下优先使用 UILabel (QMUI_Marquee)
  2. 新增 UISlider (QMUI) 分类用于取代之前的 QMUISlider(后者已删除),提供同等功能的同时,增加了 qmui_numberOfSteps 用于支持离散式数据,同时让 UIView (QMUI).qmui_outsideEdge 作用在 UISlider 上时,可以扩大中间圆点的响应区域(以前是扩大整个 slider,这通常不符合预期)。
  3. QMUITextFieldDelegate 增加方法 textField:shouldChangeCharactersInRange:replacementString:originalValue:,用于业务使用了 maximumTextLength 时可以通过这个方法来实现业务自定义的输入限制。在之前的版本里,自定义的输入限制和 maximumTextLength 是两个互斥的能力。
  4. 同上,QMUITextViewDelegate 也增加了方法 textView:shouldChangeTextInRange:text:originalValue:,原因不再赘述。
  5. UIImage (QMUI) 里的 qmui_imageWithTintColor:qmui_imageWithColor: 方法增加 QMUIAssert 用于辅助发现业务里“无法正确用一个 QMUIThemeColor 生成一张 QMUIThemeImage” 的场景。
  6. UITabBar (QMUI) 增加 qmui_effectViews 用于在 iOS 15 里获取所有的背景磨砂 view。

会带来 QMUI 新旧版本兼容问题的更新

  1. 由于 QMUISlider 提供的功能没必要非要以子类的形式存在,因此这个版本我们删除了 QMUISlider,同时新增了功能更加强大的 UISlider (QMUI) 分类。
  2. 上个版本里,为了修复 #1320 的问题,引入了 https://github.com/Tencent/QMUI_iOS/issues/1320#issuecomment-988600747 所述的新问题,经过考虑,这个版本我们回退了 4.4.0 里的改动(也即与 4.3.0 一致),至于 #1320 的问题,是 OC 和 Swift 语言特性导致的,QMUI 暂时不处理,业务请自行规避该用法。

如何适配新版

  1. 如果你的 App 是用 Xcode 13 打包的,请检查运行在 iOS 15 上时 QMUITheme 功能是否正常。
  2. 如果你的项目里有使用 QMUISlider,请将其改为 UISlider (QMUI) 里的对应属性(通常都是加个 qmui_ 前缀而已),或者也可以直接复制 QMUISlider.h/.m 到项目内继续使用。
  3. 请检查项目里继承自 QMUITableViewCell 并且重写了 initWithStyle:reuseIdentifier: 方法,但在业务使用时通过 initForTableView:withStyle:reuseIdentifier: 构造 cell 的场景,表现是否正常(预期应该与 4.3.0 保持一致)。
  4. 更新项目内的 QMUI 版本,运行起来后,请检查 Xcode 控制台是否输出“QMUIThemeColor 生成的图片却不是 QMUIThemeImage”字样的 log,如果有,意味着该处的 image 可能无法自动响应 theme 变化。

如果有使用配置表

  1. 请将配置表里 QMUILog 段落的位置迁移到 UIControl 的前面,这样才能保证其他模块在用到与 QMUILog 相关的开关时能读取到正确的值。

Bugfix

  1. #1236 由于新增的 UISlider (QMUI) 分类,顺便修复了 iOS 14 及以后的系统里无法正确获取到 thumbView 的 bug。
  2. #1247 修复 iOS 14 及以后的系统里,如果项目对一个 UIView 使用了 qmui_layoutSubviewsBlock 属性,则会导致在 iPad 里开启悬浮键盘时,聚焦一个带有 inputAccessoryView 的输入框时会死循环卡死的 bug。
  3. 修复开启了 NavBarRemoveBackgroundEffectAutomatically 后 iOS 15 里的 barTintColor 无法与 effectView 共存的 bug。
  4. #1335 修复 AutomaticCustomNavigationBarTransitionStyle 在前后两个导航栏的显隐状态不一致时表现错误的 bug。
  5. 修复 Xcode 13 编译的 App 在 iOS 15 下运行时,如果某个界面通过 QMUINavigationControllerAppearanceDelegate 系列方法控制自己的导航栏样式,则停留在该界面时切换 QMUITheme,导航栏样式会被覆盖为配置表的全局样式,而非该界面自己设置的值。
  6. 修复 -[NSString(QMUI) qmui_substringAvoidBreakingUpCharacterSequencesToIndex:] 方法在 index 刚好等于 string.length 时会 crash 的 bug:从语义上这样的 index 应当是合法的,此时需要返回当前 string 的 copy。
  7. 修复 UITabBar (QMUI).qmui_effectView 在 iOS 15 下无法正确获取到背景磨砂 view 的 bug,会导致 UITabBar (QMUI).qmui_effect 失效。
  8. 修复 QMUITableViewStyleInsetGrouped 的列表,每个 section 最后一个 cell 右下角的圆角丢失的 bug。

QMUI Demo

  1. 重新制作 UISlider (QMUI) 的 Demo。
  2. QMUIMarqueeLabel Demo 增加 UILabel (QMUI_Marquee) 功能的展示。
  3. 优化 QMUIInteractiveDebugPanelViewController 的使用方式,使其可以方便地以 subview 的形式添加到界面上显示,也可以配置自己项目的外观。
  4. UIImage (QMUI) Demo 增加渐变图片的展示。
  5. UITextField (QMUI) Demo 增加对自定义内容格式限制的展示。

4.4.0

2 years ago

综述

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 功能的演示视频。

新增功能

  1. 配置表增加开关 NavBarUsesStandardAppearanceOnly,当业务项目打开的时候,会保持 UINavigationBar.scrollEdgeAppearanceUINavigationBar.standardAppearance 对齐,从而实现 iOS 15 上的导航栏在滚动前后样式一致。
  2. 配置表增加开关 NavBarRemoveBackgroundEffectAutomatically,当业务项目打开的时候,会让 UINavigationBar 在设置了 backgroundImagebarTintColor 时自动隐藏磨砂,在 backgroundImagebarTintColornil 时自动显示磨砂(也即维持 iOS 14 的默认行为)。因为 iOS 15 及以后,backgroundEffect 可以和 backgroundImagebarTintColor 同时存在了,这与之前业务项目的代码逻辑的预期是不匹配的,要么你用这个开关来回到 iOS 14 的表现,要么你自己为 iOS 15 增加适配逻辑。
  3. 配置表增加开关 TabBarUsesStandardAppearanceOnlyTabBarRemoveBackgroundEffectAutomaticallyToolBarUsesStandardAppearanceOnlyToolBarRemoveBackgroundEffectAutomatically,具体含义请参考上面的 NavBar,这里不再赘述。
  4. 配置表增加开关 TableViewSectionHeaderTopPaddingTableViewGroupedSectionHeaderTopPaddingTableViewInsetGroupedSectionHeaderTopPadding,分别设置三种 style 的 QMUITableView 在 iOS 15 上的 sectionHeaderTopPadding 默认值,默认不修改的话,UITableViewStylePlain 会在每个 sectionHeader 之前多出来23pt的空白,另外两种 style 的列表与 iOS 14 一致。
  5. QMUICommonDefines.h 增加宏 IOS15_SDK_ALLOWED 用于区分当前是否是 Xcode 13 编译。
  6. QMUIAnimationHelper 增加接口 bounceFromValue:toValue:time:coeff: 用于实现系统 UIScrollView 拖到尽头那种阻尼感的体验。
  7. QMUILabel 增加属性 truncatingTailView 用于在文字缩略时可以显示一个自定义的 View,具体可查看 QMUI Demo 的效果。
  8. QMUIModalPresentationViewController 增加属性 window 允许业务获取到 modal 内部正在使用的 UIWindow 对象。
  9. QMUIModalPresentationViewController 增加属性 shouldDimmedAppAutomatically 用于控制当前 modal 显示时是否需要把背后的 App 界面置灰(类似系统的 UIAlertController 显示时的效果)。
  10. QMUIPopupContainerView 增加属性 contentViewSizeThatFitsBlock 方便业务在外部控制 popup 内容的大小,而不一定非要继承一个子类。
  11. QMUIPopupContainerView 增加属性 backgroundView 支持用一个自定义的 View(例如磨砂)作为 popup 的背景,当使用了这个属性后,arrowImage 只会作为遮罩来使用,不会显示 arrowImage 图片内部的纹理(也即只用箭头的造型,不用它的内容)。
  12. QMUIPopupContainerView 优化属性 arrowImage 的实现,允许你将一张 UIImageRenderingModeAlwaysTemplate 的图片作为箭头图片,当你这么做时,图片的颜色会自动跟随 backgroundColor 走,从而避免以前设置了自定义箭头图片后再修改 backgroundColor,会看到箭头颜色与背景色不一致的问题。
  13. #1295 QMUITextField 增加与 QMUITextView 相同的 canPerformPasteActionBlockpasteBlock 接口以支持控制粘贴事件(例如你可以在粘贴文本时把文本变成一张图放在输入框里)。
  14. +[QMUIHelper deviceModel] 增加 iPhone 13、iPad 新设备的信息。
  15. 增加协议 QMUIStringProtocol,将原本 NSString(QMUI) 支持的功能也迁移到 NSAttributedString(QMUI) 内。
  16. 增加 UIBlurEffect(QMUI) 分类,提供 qmui_effectWithBlurRadius: 支持指定明确的模糊半径,提供 qmui_style 支持获取当前 blur 对象的 style 值。同时 QMUI Demo 内增加 UIBlurEffect(QMUI) 的 Demo 展示。
  17. UITableView(QMUI_InsetGrouped) 支持在 iOS 12 及以下的 Interface Builder 里设置 tableView 为 InsetGrouped
  18. #1290 @xixisplit - [UIImage(QMUI) qmui_imageWithGradientColors:] 增加 QMUIImageGradientTypeTopLeftToBottomRightQMUIImageGradientTypeTopRightToBottomLeft 类型。

会带来 QMUI 新旧版本兼容问题的更新

  1. 为了适配 iOS 15,UINavigationBarUIToolbar 从这个版本开始,改为用 iOS 13 就提供的新系统接口 UINavigationBarAppearanceUIToolbarAppearance 来设置样式(UITabBar 的在 QMUI 4.0.0 适配 iOS 13 时就已经换成新接口了),新旧接口是互斥的,一旦项目里某个地方用了新接口,整个项目的旧接口都会失效。但为了尽量减少业务项目更新 QMUI 版本的工作量,我们在 UINavigationBar(QMUI)UIToolbar(QMUI) 内对旧接口做了映射,统一转换为新接口,因此预期业务项目更新版本后应该不会出现 UINavigationBarUIToolbar 的样式差异问题。
  2. 由于最低版本从 iOS 10 升级到 iOS 11,因此去掉了 QMUI 内所有为 iOS 10 写的代码,并且以前为了兼容 iOS 11 才有的 API 而加的接口(例如 qmui_safeAreaInsets)也没必要了。
  3. 由于 #1325 的问题,再考虑到该功能原本的实现代码有些混乱,因此这个版本重构了 AutomaticCustomNavigationBarTransitionStyle 的实现,减少了对 QMUINavigationControllerAppearanceDelegate 系列接口多次不必要的调用,并且更稳定。
  4. 由于现如今 QMUIButton 的功能已足够灵活,相比之下基于它衍生的 QMUIFillButtonQMUIGhostButton 显得有点鸡肋,且预设的 enum 难以准确满足业务项目的配色需求,因此这个版本我们将 QMUIFillButtonQMUIGhostButton 删除,建议原本在用的项目将其改为 QMUIButton,或者你也可以复制这两个类的文件放在业务项目里继续使用。
  5. 4.3.0 里标记为废弃的 QMUILinkButton 在 4.4.0 里正式删除。
  6. 更换 QMUITheme 在 iOS 13 及以后的系统里监听系统 userInterfaceStyle 变化的方式,从而达到:
    1. 避免之前监听 -[UIWindow traitCollection] 会导致每次有任何界面操作(触摸、按下键盘快捷键、Dark Mode 切换)时都会触发这段逻辑,而我们仅仅只希望利用它来监听 Dark Mode 切换而已。
    2. #1087 #1318 避免之前 hook -[UIWindow traitCollection] 导致在 Xcode 唤醒的场景里 App 第一次升起键盘会触发 Main Thread Checker 的问题。
    3. 旧的实现方案在系统 userInterfaceStyle 发生变化,到 QMUITheme 成功切换之间的耗时较长,在此期间访问 QMUIThemeManager.currentTheme 得到的值必定都是错误的(例如这过程中就会触发 UIViewController preferredStatusBarStyle,而业务项目在该方法里获取当前 QMUIThemeManager.currentTheme 的操作还是比较常见的)问题。
  7. 去掉 QMUIThemePrivate 里重写 -[UIView setBackgroundColor:]-[UITableViewCell setBackgroundColor:] 的代码,实测 iOS 11-15 均不需要这种处理了,而这段代码会导致 QMUIThemeColor 无法搭配 UIViewPropertyAnimator 使用。
  8. 去掉 QMUIThemePrivate 里重写 -[UITextField setNeedsDisplay] 的代码,实测不需要。
  9. QMUIHelper 重命名 is61InchScreenAndiPhone12is61InchScreenAndiPhone12Later,重命名 screenSizeFor61InchAndiPhone12screenSizeFor61InchAndiPhone12Later
  10. QMUIHelper.safeAreaInsetsForDeviceWithNotch 对全面屏 iPad 返回的 top 值从 0 改为 24。
  11. QMUIHelper.resetDimmedApplicationWindow 的实现里,把 Normal 改为系统默认的 Automatic(免测)。
  12. 配置表开关 NavBarButtonFontBold 在 iOS 15 里对系统的 Done 类型的 UIBarButtonItem 也能生效,iOS 14 及以前只能对 QMUINavigationButtonTypeBold 才生效。
  13. 删除配置表开关 StatusbarStyleLightInitially,新增配置表开关 DefaultStatusBarStyle,新开关的类型为 UIStatusBarStyle,可以支持精准的状态栏样式控制,从而避免类似 #1311 的问题。

如何适配新版

  1. 全局搜索“QMUIFillButton”、“QMUIGhostButton”,将用到的地方换成 QMUIButton,如果较多,建议在项目里创建工具方法(可以参考 QMUI Demo 里的 +[QDUIHelper generateGhostButtonWithColor:]。或者也可以将这两个被删除的文件移到业务项目中继续使用。
  2. 全局搜索“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
    
  3. 全局搜索”qmui_safeAreaInsets“,将其替换为系统的 safeAreaInsets,前者依然能用但已被标记为废弃,下个版本会删除。
  4. 全局搜索”qmui_contentInset“,将其替换为系统的 adjustedContentInset,前者依然能用但已被标记为废弃,下个版本会删除。
  5. 全局搜索”qmui_maskedCorners“,将其替换为系统的 maskedCorners,前者依然能用但已被标记为废弃,下个版本会删除。
  6. 全局搜索”qmui_performBatchUpdates“,将其替换为系统的 performBatchUpdates
  7. 全局搜索 “is61InchScreenAndiPhone12”,将其重命名为 “is61InchScreenAndiPhone12Later”。
  8. 全局搜索 “screenSizeFor61InchAndiPhone12”,将其重命名为“screenSizeFor61InchAndiPhone12Later”。
  9. 检查用到 QMUIHelper.safeAreaInsetsForDeviceWithNotch 的地方在 iPad 上是否正常。
  10. 检查用到 AutomaticCustomNavigationBarTransitionStyle 效果的地方是否正常。
  11. 检查将 QMUIThemeColor 作为 UIView.backgroundColorUITableViewCell.backgroundColor 的地方,theme 切换时是否正常。
  12. 检查 theme 切换时 UITextField 的文字颜色是否正常。
  13. 如果项目有使用 QMUITheme,请检查 App 的 Dark Mode 功能是否正常,特别留意 App 在后台、有键盘升起的时候。另外请检查项目里是否有使用 UITraitCollection.currentTraitCollection.userInterfaceStyle 来判断当前 App 样式的写法,有的话,请去掉并改为用 QMUIThemeManagerCenter.defaultThemeManager.currentThemeIdentifier,因为前者这个系统的方法在 Dark Mode 切换过程中可能会得到错误的值。

如果有使用配置表

  1. 请删除包含”fillButton“、”ghostButton“字样的10个开关。
  2. #pragma mark - NavigationBar 分段里添加以下开关,并将其设置为项目所需的值。请保证语句的顺序在其他 navBar 开关之前。
    if (@available(iOS 15.0, *)) {
        QMUICMI.navBarUsesStandardAppearanceOnly = NO;
        QMUICMI.navBarRemoveBackgroundEffectAutomatically = NO;
    }
    
  3. #pragma mark - TabBar 分段里添加以下开关,并将其设置为项目所需的值。请保证语句的顺序在其他 tabBar 开关之前。
    if (@available(iOS 15.0, *)) {
        QMUICMI.tabBarUsesStandardAppearanceOnly = NO;
        QMUICMI.tabBarRemoveBackgroundEffectAutomatically = NO;
    }
    
  4. #pragma mark - Toolbar 分段里添加以下开关,并将其设置为项目所需的值。请保证语句的顺序在其他 toolBar 开关之前。
    if (@available(iOS 15.0, *)) {
        QMUICMI.toolBarUsesStandardAppearanceOnly = NO;
        QMUICMI.toolBarRemoveBackgroundEffectAutomatically = NO;
    }
    
  5. 将下方代码添加到配置表里的适当位置,并将其设置为项目所需的值。
    if (@available(iOS 15, *)) {
        QMUICMI.tableViewSectionHeaderTopPadding = UITableViewAutomaticDimension;
        QMUICMI.tableViewGroupedSectionHeaderTopPadding = UITableViewAutomaticDimension;
        QMUICMI.tableViewInsetGroupedSectionHeaderTopPadding = UITableViewAutomaticDimension;
    }
    
  6. 请检查项目里用到的 Done 类型的 UIBarButtonItem,字体样式是否符合预期。
  7. 将下方代码添加到配置表里,并将其设置为项目所需的值。同时全局搜索”StatusbarStyleLightInitially“字样,将用到的地方换成新的”DefaultStatusBarStyle“。
    QMUICMI.defaultStatusBarStyle = UIStatusBarStyleDefault; // DefaultStatusBarStyle : 默认的状态栏样式,默认值为 UIStatusBarStyleDefault,也即在 iOS 12 及以前是黑色文字,iOS 13 及以后会自动根据当前 App 是否处于 Dark Mode 切换颜色。如果你希望固定为白色,请设置为 UIStatusBarStyleLightContent,固定黑色则设置为 QMUIStatusBarStyleDarkContent。
    

Bugfix

  1. #1276 修复 QMUITextView 重写错 init 方法,导致 initWithFrame:textContainer: 无法应用初始值的 bug。
  2. #1308 #1316 修复在输入框内长按移动光标时会错误触发 UIGestureRecognizer(QMUI) assert 的问题。
  3. #1312 修复启动时试图通过 qmui_getProjectClassList 获取项目里所有业务 Class 失败的 bug。
  4. #1320 修复 - [QMUITableViewCell initForTableView:xxx] 方法的实现不恰当,可能引起 Swift 内重复调用 init 的问题。
  5. #1322 @ACFancy 修复 QMUITextFieldQMUITextView 在进行”重做“操作时依然可能引发 #1168 里描述的问题的 bug。
  6. 修复 QMUIPopupMenuViewitemTitleFontitemTitleColorpadding 的值发生变化时没有刷新 item 样式的 bug。
  7. 修复 UITextField 的文字颜色无法响应 QMUITheme 切换的 bug(包含聚焦和非聚焦状态都有问题)。
  8. 修复对一个 QMUIThemeImage 调用 qmui_imageWithTintColor: 时如果参数是个 QMUIThemeColor,则最终这个图片无效的 bug。
  9. 修复使用 UILabel(QMUI).qmui_textAttributes 的时候,先设置 textAlignment 再设置 texttextAlignment 不生效的 bug。
  10. 修复在 iOS 13 及以上的系统里,当业务在 willDisplayCell 里修改 cell.backgroundColor 时会导致 UITableView(QMUI).qmui_insetGroupedCornerRadius 无效的 bug。

QMUI Demo

  1. 增加 QMUIKit→UIBlurEffect(QMUI) 的 Demo。
  2. 增加 Lab→Animation→Animation Curves 用于将动画曲线以图表形式表达,并支持不同曲线之间对比的 Demo。
  3. 增加 Lab→Dropdown Notification 用于实现 App 内自己的顶部通知功能。
  4. QMUILabel 增加对新功能 truncatingTailView 的展示。
  5. QMUIInteractiveDebugPanelItem 增加快速生成文本 item、segmentedControl item 的方法。
  6. UINavigationBar(QMUISmoothEffect) 适配了 QMUI 4.4.0 里对 AutomaticCustomNavigationBarTransitionStyle 的重构。
  7. UINavigationItem(QMUIBottomAccessoryView) 适配了 QMUI 4.4.0 里对 AutomaticCustomNavigationBarTransitionStyle 的重构。

QMUI Code Snippets

  1. if os 默认值从 iOS 14 改为 iOS 15。