Skip to content

4.0.0-beta

Pre-release
Pre-release

Choose a tag to compare

@MoLice MoLice released this 21 Jul 11:36
· 155 commits to master since this release

重要说明

QMUI 4.0.0-beta 更新内容主要包含 iOS 13 的兼容(#615)、新增对应 Dark Mode 的换肤组件 QMUITheme、支持 iPad Slide Over/Split View(分屏)。由于与 iOS 13 相关的功能仅在使用 Xcode 11 Beta 编译时才保证正常,因此若使用 Xcode 10 编译则在 iOS 13 Beta 的设备上运行时可能产生非预期的效果,知会。

由于 iOS 13 尚未正式发布,因此 4.0.0 暂时以 pre-release 性质发布,短期内将会继续完善并发布 4.0.0 正式版,如业务项目有计划兼容 iOS 13,建议即刻升级到此版本,以减少后期的升级成本。

新增功能

  1. 适配 iOS 13,#615 列出了目前遇到的所有兼容问题,其中主要的问题是 iOS 13 系统会对某些 KVC 访问抛出异常,针对这个问题,我们提供3种方式解决:
    1. [推荐] 打开配置表新增的 IgnoreKVCAccessProhibited,即可全局屏蔽 iOS 13 KVC 异常,适用于大量使用 KVC 的场景,也不需要修改业务代码。
    2. 使用 NSObject (QMUI) 新增的 qmui_valueForKey:、qmui_setValue:forKey: 代替系统的方法,适用于频次较少的 KVC,也便于通过全局搜索替换的方式来兼容。
    3. 使用新增的 BeginIgnoreUIKVCAccessProhibited、EndIgnoreUIKVCAccessProhibited 宏,将有问题的 valueForKey:、setValue:forKey: 包裹起来,从而屏蔽被包裹的代码块可能产生的异常,适用于频次较少的 KVC。
  2. 支持 iPad 分屏的适配:
    1. 增加 QMUIWindowSizeMonitor 用于适配 iPad 分屏下的布局。
    2. QMUIHelper 增加方法 applicationSize (对应宏 APPLICATION_WIDTH、APPLICATION_HEIGHT)用于获取分屏后的 App 视窗大小,建议不管适不适配 iPad 分屏,都使用这个方法来代替 UIScreen.mainScreen.bounds.size。
    3. 增加宏 IS_SPLIT_SCREEN_IPAD 用于判断当前是否处于分屏。
    4. 增加宏 IPAD_SIMILAR_SCREEN_WIDTH 用于计算分屏后的尺寸近似于哪个 iPhone 设备的尺寸。
    5. PreferredValue 系列宏在打开了新的配置表项 DynamicPreferredValueForIPad 后,支持将分屏后的 iPad 视为某个 iPhone 的设备来布局。
  3. 增加 QMUITheme 组件用于适配 iOS 13 的 Dark Mode,同时也支持 iOS 12 及以下系统的使用,使用文档请查看 Wiki,Demo 请查看 Components->QMUITheme。
  4. 增加 QMUIAnimation 组件用于实现复杂动画。
  5. QMUINavigationButton 增加 adjustsImageTintColorAutomatically 属性便于控制图片和文字都跟随 tintColor 变化。
  6. QMUIKeyboardManager 增加 ignoreApplicationState 属性用于响应所有 UIApplicationState 下的键盘事件,同时解决 #565 提到的问题。
  7. QMUIPieProgressView 增加 shape、lineWidth 等属性用于支持新的环状样式。
  8. QMUILabel 的 highlightedBackgroundColor 属性支持 UIAppearance。
  9. UIView (QMUI) 增加 qmui_tintColorCustomized 属性用于判断当前 view 是否有设置过自定义的 tintColor。
  10. UITableViewCell (QMUI) 增加 qmui_selectedBackgroundColor 用于便捷地设置点击高亮时的背景色(否则你需要先初始化一个 selectedBackgroundView。
  11. UITableViewCell (QMUI) 增加 qmui_styledAsQMUITableViewCell 方法用于按照 QMUI 配置表的样式去配置一个 cell。
  12. 原本属于 UITableView (QMUI) 的属性 qmui_initialContentInset 已被迁移到 UIScrollView (QMUI)。
  13. 增加 UITraitCollection (QMUI) 以在 iOS 13 的 Dark Mode 发生切换前收到通知。
  14. CALayer (QMUI) 增加 qmui_isRootLayerOfView 属性用于判断当前的 layer 是否是某个 UIView 自带的 layer。
  15. CALayer (QMUI) 增加 qmui_performWithoutAnimation: 方法用于以无动画的形式修改 layer 属性。
  16. NSMethodSignature (QMUI) 增加 qmui_avoidExceptionSignature 方法用于生成一个避免 crash 的方法签名。
  17. NSString (QMUI) 增加 qmui_capitalizedString 用于把首字母转换为大写,系统的 capitalizedString 会强制把除首字母外的其他字母转换成小写。
  18. NSObject (QMUI) 增加若干方法便于调试时用:
    1. qmui_methodList 列出当前对象的所有方法(含继承)。
    2. qmui_shortMethodList 列出当前对象的所有方法(不含父类继承)。
    3. qmui_ivarList 列出当前对象的所有成员变量。
  19. QMUICommonDefines.h 增加函数 setterWithGetter 用于获取给定 getter 对应的 setter。
  20. 配置表增加 KeyboardAppearance 开关用于控制全局输入框默认的键盘样式。
  21. 配置表增加 NavBarStyle、TabBarStyle、ToolBarStyle 用于控制全局的 bar 的样式。
  22. 配置表增加 UISwitch 相关样式设置,具体请查看下方 如何适配新版。
  23. 配置表针对 Grouped 类型的 UITableView 增加若干项目,具体请查看下方 如何适配新版。
  24. 配置表增加 AdjustScrollIndicatorInsetsByContentInsetAdjustment 便于兼容 iOS 13 下新增的 -[UIScrollView automaticallyAdjustsScrollIndicatorInsets] 属性。

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

  1. UINavigationControllerBackButtonHandlerProtocol 协议里的 shouldHoldBackButtonEvent、canPopViewController 已被标记为废弃,请使用 shouldPopViewControllerByBackButtonOrPopGesture: 代替。
  2. QMUIMoreOperationController 的 contentEdgeMargin 属性类型从 CGFloat 改为 UIEdgeInsets ,同时重命名为 contentEdgeMargins,以便于灵活控制面板的布局。
  3. QMUITableViewCell 支持样式区分 Plain、Grouped 列表下的样式,因此内部的 didInitializeWithStyle: 调用时机发生了变化,导致继承 QMUITableViewCell 的子类如果在 initWithStyle:reuseIdentifier: 里设置 textLabel.textColor、detailTextLabel.textColor、self.backgroundColor,则这些设置将会被 QMUI 默认值覆盖。具体兼容方法请看下方 如何适配新版。

如何适配新版

  1. 如果遇到 iOS 13 系统对 KVC 抛出的异常,可将配置表的 IgnoreKVCAccessProhibited 置为 YES,或将遇到异常的代码改为用 qmui_valueForKey:、qmui_setValue:forKey:。
  2. 全局搜索“shouldHoldBackButtonEvent”、“canPopViewController”,将其改为新的 shouldPopViewControllerByBackButtonOrPopGesture:。
  3. 全局以 Matching Word 方式搜索 “contentEdgeMargin”,如果是 QMUIMoreOperationController 的属性,则将其改为 contentEdgeMargins,注意类型从 CGFloat 变为 UIEdgeInsets。
  4. 检查业务所有继承自 QMUITableViewCell 的类,如果有重写 initWithStyle:reuseIdentifier:,请将该方法删掉,将原本的内容迁移到 didInitializeWithStyle: 里。
  5. 如果有使用配置表,请将以下代码复制到 QMUIConfigurationTemplate.m 中,并按照业务需求改为需要的值:
QMUICMI.keyboardAppearance = UIKeyboardAppearanceDefault; // KeyboardAppearance : UITextView、UITextField、UISearchBar 的 keyboardAppearance

QMUICMI.switchOnTintColor = nil; // SwitchOnTintColor : UISwitch 打开时的背景色(除了圆点外的其他颜色)
QMUICMI.switchTintColor = nil; // SwitchTintColor : UISwitch 关闭时的周围边框颜色
QMUICMI.switchThumbTintColor = nil; // SwitchThumbTintColor : UISwitch 中间的操控圆点的颜色

QMUICMI.navBarStyle = UIBarStyleDefault; // NavBarStyle : UINavigationBar 的 barStyle
QMUICMI.tabBarStyle = UIBarStyleDefault; // TabBarStyle : UITabBar 的 barStyle
QMUICMI.toolBarStyle = UIBarStyleDefault; // ToolBarStyle : UIToolbar 的 barStyle

QMUICMI.tableViewGroupedCellTitleLabelColor = TableViewCellTitleLabelColor; // TableViewGroupedCellTitleLabelColor : Grouped 类型的 QMUITableView cell 里的标题颜色
QMUICMI.tableViewGroupedCellDetailLabelColor = TableViewCellDetailLabelColor; // TableViewGroupedCellDetailLabelColor : Grouped 类型的 QMUITableView cell 里的副标题颜色
QMUICMI.tableViewGroupedCellBackgroundColor = TableViewCellBackgroundColor; // TableViewGroupedCellBackgroundColor : Grouped 类型的 QMUITableView cell 背景色
QMUICMI.tableViewGroupedCellSelectedBackgroundColor = TableViewCellSelectedBackgroundColor; // TableViewGroupedCellSelectedBackgroundColor : Grouped 类型的 QMUITableView cell 点击时的背景色
QMUICMI.tableViewGroupedCellWarningBackgroundColor = TableViewCellWarningBackgroundColor; // tableViewGroupedCellWarningBackgroundColor : Grouped 类型的 QMUITableView cell 在提醒状态下的背景色

QMUICMI.dynamicPreferredValueForIPad = NO; // 当 iPad 处于 Slide Over 或 Split View 分屏模式下,宏 `PreferredValueForXXX` 是否自动把 iPad 视为某种屏幕宽度近似的 iPhone 来取值。

if (@available(iOS 13.0, *)) {
    QMUICMI.ignoreKVCAccessProhibited = NO; // IgnoreKVCAccessProhibited : 是否全局忽略 iOS 13 对 KVC 访问 UIKit 私有属性的限制
    QMUICMI.adjustScrollIndicatorInsetsByContentInsetAdjustment = NO; // AdjustScrollIndicatorInsetsByContentInsetAdjustment : 当将 UIScrollView.contentInsetAdjustmentBehavior 设为 UIScrollViewContentInsetAdjustmentNever 时,是否自动将 UIScrollView.automaticallyAdjustsScrollIndicatorInsets 设为 NO,以保证原本在 iOS 12 下的代码不用修改就能在 iOS 13 下正常控制滚动条的位置。
}

Bugfix

  1. #632 修复 UIAlertController 在 QMUITabBarController、QMUINavigationController 内 present 起来时会出现“[UIAlertController supportedInterfaceOrientations] was invoked recursively” 的 log 的 bug。
  2. #633 修复 NavigationBarHeight、TabBarHeight、ToolBarHeight 在某些设备下不准确的 bug。
  3. #660 修复 QMUIAlertController 的一处内存泄露。
  4. 修复 QMUINavigationTitleView 在开启了 UINavigationBar.prefersLargeTitles 模式的情况下无法与大标题兼容的问题,LargeTitle 的 Demo 请查看 QMUIKit->QMUINavigationController->兼容 LargeTitle。
  5. 修复 iOS 10 在某些情况下手势返回取消,navigationBar 的按钮将会重叠的 bug。