无traitCollectionDidChange的OC图片编辑器明暗模式适配问题
这个问题完全可以解决,核心是让自定义编辑器ViewController能够响应系统明暗模式的变化,以下是几种可行的方案:
方案1:使用动态UIColor(最简洁)
不需要监听模式变化,直接给工具栏图标和文字设置动态颜色,系统会自动根据当前的明暗模式切换颜色。
修改你跳转前的颜色设置逻辑(包括traitCollectionDidChange里的updateColorData方法):
private func updateColorData(for traitCollection: UITraitCollection) { guard let editor = editor else { return } // 注意:这里要用当前已创建的editor实例,不要新建 // 设置动态颜色 editor.theme.toolIconColor = UIColor { tc in tc.userInterfaceStyle == .dark ? .white : .black } editor.theme.toolbarTextColor = UIColor { tc in tc.userInterfaceStyle == .dark ? .white : .black } }
同时,在TappedOnEditBtn里初始化editor时,也直接用动态颜色替代固定的白色/黑色:
@IBAction func TappedOnEditBtn(_ sender: Any) { guard let image = img.image else { print("Error on DemoImageEditor!") return } editor = DemoImageEditor(image: image) editor?.delegate = self editor?.theme.backgroundColor = .white editor?.theme.toolbarColor = .white // 直接设置动态颜色 editor?.theme.toolIconColor = UIColor { tc in tc.userInterfaceStyle == .dark ? .white : .black } editor?.theme.toolbarTextColor = UIColor { tc in tc.userInterfaceStyle == .dark ? .white : .black } editor?.modalPresentationStyle = .fullScreen present(editor!, animated: true, completion: nil) }
这种方案的前提是DemoImageEditor的theme属性支持存储动态UIColor(只要它用的是UIColor类型而不是底层的CGColor就没问题),系统会自动处理颜色切换,不需要额外监听代码。
方案2:给Objective-C的DemoImageEditor添加 trait 变化监听
如果可以修改DemoImageEditor的Objective-C源码,直接在它的实现文件里添加traitCollectionDidChange方法,响应模式变化:
在DemoImageEditor.m中添加:
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { [super traitCollectionDidChange:previousTraitCollection]; // 只在颜色外观变化时处理 if ([self.traitCollection hasDifferentColorAppearanceComparedToTraitCollection:previousTraitCollection]) { BOOL isDarkMode = self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark; self.theme.toolIconColor = isDarkMode ? [UIColor whiteColor] : [UIColor blackColor]; self.theme.toolbarTextColor = isDarkMode ? [UIColor whiteColor] : [UIColor blackColor]; // 如果工具栏的控件没有自动刷新,这里可以手动触发UI更新,比如: // [self.toolbar setNeedsDisplay]; // 或者遍历工具栏子控件重新设置颜色 } }
这样当用户在编辑器页面内切换明暗模式时,DemoImageEditor会自动检测到变化并更新颜色。
方案3:Swift扩展重写 traitCollectionDidChange(无法修改Objective-C源码时用)
如果不能修改DemoImageEditor的源码(比如是第三方库),可以在Swift侧给它写一个扩展,重写traitCollectionDidChange方法:
extension DemoImageEditor { @objc override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) guard let previousTC = previousTraitCollection, traitCollection.hasDifferentColorAppearance(comparedTo: previousTC) else { return } let isDark = traitCollection.userInterfaceStyle == .dark theme.toolIconColor = isDark ? .white : .black theme.toolbarTextColor = isDark ? .white : .black // 按需刷新工具栏UI } }
注意:这个扩展需要确保DemoImageEditor是UIViewController的子类(显然它是),且@objc标记必须加上,这样Objective-C的运行时才能识别这个重写的方法。
修复现有代码的问题
你当前的updateColorData方法里每次都新建一个DemoImageEditor实例,这完全没用——这个新建的实例和当前显示的编辑器不是同一个对象,修改它的theme不会影响已经present的页面。必须直接修改你在TappedOnEditBtn里创建并存储的editor属性:
private func updateColorData(for traitCollection: UITraitCollection) { guard let editor = self.editor else { return } // 使用已有的editor实例 let isDark = traitCollection.userInterfaceStyle == .dark editor.theme.toolIconColor = isDark ? .white : .black editor.theme.toolbarTextColor = isDark ? .white : .black }
不过这个修改只能解决在当前ViewController活跃时切换模式的情况,无法解决在编辑器页面内切换的问题,所以还是需要结合上面的方案1/2/3来彻底解决。
内容的提问来源于stack exchange,提问作者multiverse

