#1 楼
首先,这是与退出暗模式相关的Apple条目。此链接的内容适用于Xcode 11和iOS 13:
此部分适用于Xcode 11的用法
如果您希望退出整个应用程序
方法#1
请在info.plist文件中使用以下密钥:
UIUserInterfaceStyle
,并为其分配值
Light
。UIUserInterfaceStyle
分配的XML: br />方法#2 您可以针对应用程序的
overrideUserInterfaceStyle
变量设置window
。 。<key>UIUserInterfaceStyle</key>
<string>Light</string>
如果您希望逐个退出UIViewController
if #available(iOS 13.0, *) {
window?.overrideUserInterfaceStyle = .light
}
Apple文档overrideUserInterfaceStyle
上面的代码在Xcode 11中的外观:
/>本节适用于Xcode 10.x用法
如果您正在使用Xcode 11进行提交,则可以放心忽略此行下的所有内容。
由于iOS 12中不存在相关的API,因此在尝试使用上面提供的值时会出错:
用于在
AppDelegate
中设置SceneDelegate
如果您希望逐个退出UIViewController,
可以通过测试编译器版本和iOS版本在Xcode 10中进行处理:
override func viewDidLoad() {
super.viewDidLoad()
// overrideUserInterfaceStyle is available with iOS 13
if #available(iOS 13.0, *) {
// Always adopt a light interface style.
overrideUserInterfaceStyle = .light
}
}
如果愿意退出整个应用程序
您可以修改上述代码段,使其适用于Xcode 10的整个应用程序,方法是在
overrideUserInterfaceStyle
文件中添加以下代码。#if compiler(>=5.1)
if #available(iOS 13.0, *) {
// Always adopt a light interface style.
overrideUserInterfaceStyle = .light
}
#endif
但是,使用Xcode版本10.x时plist设置将失败:
感谢@Aron Nelson,@ Raimundas Sakalauskas,@ NSLeader和rmaddy通过他们的反馈来改善此答案。
评论
立即更新/上传应用程序时,UIUserInterfaceStyle指示灯被阻止。它被标记为无效的plist条目。 (无效的plist键)
–阿伦·尼尔森(Aron Nelson)
19年8月15日在18:20
无法针对iOS SDK 12(当前最新的稳定SDK)进行编译。请参阅stackoverflow.com/a/57521901/2249485,以获得适用于iOS 12 SDK的解决方案。
– Raimundas Sakalauskas
19年8月16日在9:13
这太不公平了,以至于比“原始问题”具有更多视图的问题被锁定以提供答案。 :(
– Raimundas Sakalauskas
19-09-18在12:35
您可以在应用程序的主窗口中将其设置一次,而不是在每个视图控制器的viewDidLoad中设置overrideUserInterfaceStyle。如果您想让整个应用程序表现为一种方式,那就容易得多。
–rmaddy
19-09-19在7:38
使用#if编译器(> = 5.1)代替response(to :)和setValue
– NSLeader
19年9月24日在11:28
#2 楼
根据苹果公司关于“在iOS上实现暗模式”的会议(https://developer.apple.com/videos/play/wwdc2019/214/,从31:13开始),可以在任何视图上将overrideUserInterfaceStyle
设置为UIUserInterfaceStyleLight
或UIUserInterfaceStyleDark
控制器或视图,将在traitCollection
中用于任何子视图或视图控制器。正如SeanR所提到的,您可以在应用程序的plist文件中将
UIUserInterfaceStyle
设置为Light
或Dark
,以将其更改为您整个应用程序。评论
如果您设置UIUserInterfaceStyle键,则您的应用将在应用商店中被拒绝
– Sonius
19年8月20日在7:44
苹果拒绝使用ITMS-90190错误代码forums.developer.apple.com/thread/121028
– PRASAD1240
19年8月20日在14:04
拒绝最有可能发生,因为iOS 13 SDK尚未超出Beta版。我认为这应该在Xcode 11 GM可用后立即生效。
– dorbeetle
19年8月21日在9:24
@dorbeetle,这不是真的,我像1个月前用Xcode 10一样成功地用此密钥上传了我的应用程序。拒绝是最近发生的。苹果似乎采取了一些新的策略。
–steven
19年8月28日在5:09
它仍在发生。 Xcode GM2返回了应用程序签名错误。 Xcode 10.3返回:“无效的Info.plist密钥。有效载荷/Galileo.appInfo.plist文件中的密钥'UIUserInterfaceStyle'无效。
– Evgen Bodunov
19-09-20在20:29
#3 楼
如果您未使用Xcode 11或更高版本(即iOS 13或更高版本的SDK),则您的应用尚未自动选择支持暗模式。因此,无需退出暗模式。如果您使用的是Xcode 11或更高版本,则系统会自动为您的应用启用暗模式。有两种方法可以根据您的喜好禁用暗模式。您可以完全禁用它,也可以对任何特定的窗口,视图或视图控制器禁用它。
完全为您的应用禁用暗模式
您可以通过在应用的Info.plist文件中包含
UIUserInterfaceStyle
键(其值为Light
)来禁用暗模式。 这会忽略用户的偏好,并始终为您的应用程序添加浅色外观。
禁用Window,View或View Controller的深色模式
您可以强制通过设置适当的窗口,视图或视图控制器的
overrideUserInterfaceStyle
属性,您的界面始终以浅色或深色样式显示。视图控制器:
override func viewDidLoad() {
super.viewDidLoad()
/* view controller’s views and child view controllers
always adopt a light interface style. */
overrideUserInterfaceStyle = .light
}
视图:
// The view and all of its subviews always adopt light style.
youView.overrideUserInterfaceStyle = .light
窗口:
/* Everything in the window adopts the style,
including the root view controller and all presentation controllers that
display content in that window.*/
window.overrideUserInterfaceStyle = .light
注意:苹果强烈建议您在应用中支持暗模式。因此,
您只能暂时禁用黑暗模式。
此处更多:为iOS应用选择特定的界面样式
#4 楼
********** Xcode 11及更高版本的最简单方法***********在
</dict></plist>
之前将其添加到info.plist <key>UIUserInterfaceStyle</key>
<string>Light</string>
评论
在Xcode 10.x上提交应用程序时,此解决方案将失败
– Tawfik Bouabid
19-10-23在7:33
#5 楼
我想我已经找到了解决方案。我最初是通过UIUserInterfaceStyle-信息属性列表和UIUserInterfaceStyle-UIKit进行拼凑而成的,但现在发现它确实记录在为iOS应用选择特定界面样式时。在
info.plist
中,设置UIUserInterfaceStyle
(接口样式)到1(UIUserInterfaceStyle.light
)。编辑:根据dorbeetle的回答,对于
UIUserInterfaceStyle
更为合适的设置可能是Light
。评论
但是,通过将值设置为2来强制使用暗模式是不起作用的:[UIInterfaceStyle]'2'不是UIUserInterfaceStyle的可识别值。默认为Light。
–funkenstrahlen
19年6月11日在9:09
在plist中拥有此密钥将导致App Store拒绝。
–何塞
19年8月20日在7:53
AppStore不再在plist.info中拒绝此属性。我把“ Dark”(大写)放进去,因为我们的应用程序已经很暗。没问题。这可以让我们正确使用系统控件。
– nickdnk
19-09-25在16:31
是的,我做到了。 Apple确实在plist中接受了此参数,这一事实并没有改变,这就是我试图阐明的事实。
– nickdnk
19-09-26在11:06
我尝试设置“ LIGHT”,“ Light”,“ light”,“。light”,“ 1”-都是一样的-它不起作用。 Xcode:版本11.3.1(11C504)
–安德鲁(Andrew)
20 Jan 16 '18:53
#6 楼
如果您想退出整个应用程序,则上述答案有效。如果您使用的是具有UI的lib,并且您对.plist的编辑并不奢侈,那么也可以通过代码来实现。如果要针对iOS 13 SDK进行编译,则只需使用以下代码即可:
Swift:
if #available(iOS 13.0, *) {
self.overrideUserInterfaceStyle = .light
}
obj-C:
if (@available(iOS 13.0, *)) {
self.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
}
但是,如果您也希望代码也可以针对iOS 12 SDK进行编译(目前仍是最新的稳定SDK),诉诸使用选择器。带选择器的代码:
Swift(XCode将显示该代码的警告,但这是目前唯一的方法,因为SDK 12中不存在该属性,因此无法编译):
if #available(iOS 13.0, *) {
if self.responds(to: Selector("overrideUserInterfaceStyle")) {
self.setValue(UIUserInterfaceStyle.light.rawValue, forKey: "overrideUserInterfaceStyle")
}
}
OBJ-C:
if (@available(iOS 13.0, *)) {
if ([self respondsToSelector:NSSelectorFromString(@"overrideUserInterfaceStyle")]) {
[self setValue:@(UIUserInterfaceStyleLight) forKey:@"overrideUserInterfaceStyle"];
}
}
评论
如果指定属性overrideUserInterfaceStyle属于什么会更好。
–黎明之歌
19-09-26在14:25
#7 楼
Xcode 12和iOS 14更新。我已经尝试了以前的选项来选择退出暗模式,而info.plist文件中的这句话对我不起作用: >此设置将阻止整个应用程序中的所有黑暗模式。编辑:
修正错字谢谢@sarah
评论
有点错字,应该是外观:)
–萨拉
20-11-06在9:23
固定!谢谢@Sarah :)
– Wazowski
20年11月6日,12:07
工作和更新的解决方案
–纳粹艾哈迈德(Naveed Ahmad)
昨天
#8 楼
您可以在Xcode 11中的整个应用程序中关闭“暗模式”:转到Info.plist
添加波纹管,如
<key>UIUserInterfaceStyle</key>
<string>Light</string>
Info.plist如下所示...
评论
由于某些原因不适用于Xcode 11.3.1(11C504)
–安德鲁(Andrew)
20 Jan 16 '20 at 18:43
#9 楼
最新更新-如果您使用的是Xcode 10.x,则iOS 13.x的默认
UIUserInterfaceStyle
为light
。在iOS 13设备上运行时,它将仅在灯光模式下工作。 无需在Info.plist文件中显式添加
UIUserInterfaceStyle
密钥,添加它会在验证应用程序时出现错误,提示:无效信息.plist键。 Payload / AppName.appInfo.plist文件中的键'UIUserInterfaceStyle'无效。
使用Xcode 11.x时,仅在Info.plist文件中添加
UIUserInterfaceStyle
键。 />评论
这与Xcode 10或11无关。如果用户部署Xcode 10形式的应用程序并且不处理暗模式,则该应用程序安装在iPhone 11,Pro或Pro Max中时将出现暗模式问题。您需要更新到Xcode 11并解决此问题。
– Niranjan Molkeri
19-09-16在18:35
@NiranjanMolkeri这与较新的iPhone无关。这与iOS 13上的暗模式有关。在以前的iOS 13 Beta版本中,如果未明确处理,则UI会出现暗模式问题。但是在最新版本中,此问题已修复。如果您使用的是XCode 10,则iOS13的默认UIUserInterfaceStyle是light。如果您使用的是Xode11,则需要进行处理。
–kumarsiddharth123
19-09-17在7:28
如果使用Xcode 10.3将应用程序上载到TestFligth,并且plist包含键UIUserInterfaceStyle,则会遇到问题。它将说这是一个无效的plist文件。如果在Xcode 10中进行构建,则必须将其删除,或者使用Xcode 11进行上传
– eharo2
19-10-23在19:45
#10 楼
如果将UIUserInterfaceStyle
密钥添加到plist文件中,则Apple可能会拒绝此处所述的发行版本:https://stackoverflow.com/a/56546554/7524146 无论如何,明确告诉每个ViewController
self.overrideUserInterfaceStyle = .light
都是很烦的。但是,您可以对根window
对象使用一次此和平代码:在那个早期。但是您以后可以做。如果您在应用程序中使用自定义application(application: didFinishLaunchingWithOptions:)
或true
类,而不是自动在AppDelegate中启动UI,那么这非常容易。#11 楼
-对于整个应用程序(窗口):window!.overrideUserInterfaceStyle = .light
您可以从
SceneDelegate
获取窗口-对于单个ViewController:
viewController.overrideUserInterfaceStyle = .light
即使在viewController本身内,也可以设置任何
viewController
-对于单个视图: >
即使在视图本身内,您也可以设置任何
view
如果支持较早的iOS版本,则可能需要使用
if #available(iOS 13.0, *) { ,,, }
。#12 楼
除了其他响应之外,据我了解,您仅需要在针对iOS 13 SDK(使用XCode 11)进行编译时为Dark模式做准备。系统假定应用程序已链接针对iOS 13或更高版本的SDK
支持亮色和深色外观。在iOS中,可以通过为窗口,视图或视图控制器分配特定的界面样式
来指定所需的特定外观。您还可以完全使用Info.plist键禁用对黑暗模式的支持。
链接
#13 楼
Swift 5将暗模式切换为亮模式的两种方法:
1- info.plist
<key>UIUserInterfaceStyle</key>
<string>Light</string>
2-以编程方式或运行时
@IBAction private func switchToDark(_ sender: UIButton){
UIApplication.shared.windows.forEach { window in
//here you can switch between the dark and light
window.overrideUserInterfaceStyle = .dark
}
}
#14 楼
我的应用程序目前不支持深色模式,并使用浅色应用程序栏颜色。通过将以下密钥添加到我的Info.plist
中,我能够将状态栏内容强制为深色文本和图标: / uikit / uistatusbarstyle Flutter用户
别忘了在Flutter应用栏上设置应用栏亮度属性,如下所示:
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleDarkContent</string>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
#15 楼
是的,您可以在viewDidLoad中添加以下代码来跳过:if #available(iOS 13.0, *) {
// Always adopt a light interface style.
overrideUserInterfaceStyle = .light
}
#16 楼
if #available(iOS 13.0, *) {
overrideUserInterfaceStyle = .light
} else {
// Fallback on earlier versions
}
评论
您能否解释一下此答案将如何解决问题,而不是发布仅代码的答案。
– Arun Vinoth
19/12/26在17:19
是的,肯定@ArunVinoth在IOS 13中引入了暗模式,因此,如果您的部署目标低于13,则使用上述代码,否则您可以使用if编写的简单语句。
–塔拉·拉索尔(Talha Rasool)
19/12/27在18:01
#17 楼
Objective-C版本 if (@available(iOS 13.0, *)) {
_window.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
}
#18 楼
iOS 14.3和Xcode 12.3更新在info.plist文件中将外观添加为浅色。
<key>Appearance</key>
<string>Light</string>
评论
在模拟器上不起作用
– Yodagama
20 Dec 23'2:02
@Yodagama,请检查您的模拟器的iOS版本和Xcode版本。它应该可以正常工作,我刚刚在模拟器中对其进行了测试。
–阿尔文
20 Dec 23 '13:06
我在xcode 12.1和ios 14.2上做过
– Yodagama
20 Dec 23 '13:08
它可以在Xcode 12.3和iOS 14.3中正常工作。对于您的版本,请尝试以下
–阿尔文
20 Dec 23 '13:10
#19 楼
以下是一些提示和技巧,您可以在应用程序中使用它们来支持或绕过黑暗模式。第一个提示:要覆盖ViewController样式
,您可以覆盖UIViewController的界面样式,由
1:overrideUserInterfaceStyle = .dark //对于暗模式
2:overrideUserInterfaceStyle = .light //对于亮模式
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
overrideUserInterfaceStyle = .light
}
}
第二个技巧:在info.plist中添加密钥
只需添加一个新密钥
UIUserInterfaceStyle
在您的应用程序info.plist中,并将其值设置为Light或Dark。这会将应用默认样式替换为您提供的值。
您不必添加overrideUserInterfaceStyle = .light在每个viewController中添加此行,仅在info.plist中添加一行即可。
#20 楼
只需在您的info.plist
文件中添加以下密钥:<key>UIUserInterfaceStyle</key>
<string>Light</string>
#21 楼
只需将这些行添加到info.plist文件中:<key>UIUserInterfaceStyle</key>
<string>light</string>
这将强制应用仅在轻模式下运行。
评论
这已经被评论并回答了很多次。即使是公认的答案也暗示了这一点。因此,此注释不会添加任何新信息。
– Jeroen
19/12/18在12:22
#22 楼
在Xcode 12中,您可以将添加更改为“外观”。这将起作用!#23 楼
将此添加到info.plist
<key>UIUserInterfaceStyle</key>
<string>Light</string>
评论
已经在接受的答案中对此进行了解释。
–阿米特·乔希(Amit Joshi)
20/12/21在13:59
#24 楼
由于窗口属性可能会在应用程序生命周期中更改,因此我将使用此解决方案。因此,需要重复分配“ overrideUserInterfaceStyle = .light”。 UIWindow.appearance()使我们能够设置将用于新创建的UIWindow对象的默认值。import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
if #available(iOS 13.0, *) {
UIWindow.appearance().overrideUserInterfaceStyle = .light
}
return true
}
}
#25 楼
import UIKit
extension UIViewController {
override open func awakeFromNib() {
super.awakeFromNib()
if #available(iOS 13.0, *) {
overrideUserInterfaceStyle = .light
}
}
}
评论
请通过编辑为答案添加一些解释,以便其他人可以从中学习
– Nico Haase
20年4月7日在6:45
#26 楼
您可以执行以下操作:将此新键UIUserInterfaceStyle添加到Info.plist并将其值设置为Light。并检查警报控制器以浅色模式出现。您的Info.plist文件并将其值设置为亮或暗。#27 楼
这个问题有很多答案,而不是在info.plist
中使用它,您可以像这样在AppDelegate
中设置它:#28 楼
实际上,我只是编写了一些代码,使您可以在代码中全局选择退出暗模式,而不必在应用程序中使用每个viw控制器。通过管理课程列表,可以将其优化为逐班选择退出。对我而言,我想要的是让用户查看他们是否喜欢我的应用程序的暗模式界面,如果他们不喜欢它,则可以将其关闭。这将使他们能够在其余应用程序中继续使用暗模式。用户选择是好的(哎呀,看着苹果,这是应该实现的方式)。 。加载时,它将替换本机的viewDidLoad方法,该方法将检查一个全局标志以查看是否对所有内容都禁用了暗模式。
因为在UIViewController加载时触发了它,它应该自动启动并默认情况下禁用黑暗模式。如果这不是您想要的,那么您需要及早到达某个地方并设置标志,否则只需设置默认标志即可。
我还没有写任何内容来回应用户打开或关闭标志。因此,这基本上是示例代码。如果我们希望用户与此交互,则所有视图控制器都需要重新加载。我不知道如何立即执行此操作,但是可能会发送一些通知来解决问题。因此,目前,暗模式下的全局打开/关闭仅在启动或重新启动应用程序时起作用。
现在,仅在大型应用程序中的每个MFING viewController中尝试关闭暗模式是不够的。如果您使用的是色彩资产,那么您将完全陷入困境。我们十多年以来一直将不可变对象理解为不可变的。从颜色资产目录中获得的颜色表示它们是UIColor,但是它们是动态(可变)颜色,并且随着系统从暗到亮模式的变化,它们在您的下方也会发生变化。那应该是一个功能。但是当然,没有主开关要求这些事情停止进行更改(据我所知,也许有人可以对此进行改进)。
所以解决方案分为两部分:
UIViewController上的公共类别提供了一些实用和便捷的方法...例如,我认为苹果公司没有想到我们中有些人将Web代码混入了我们的应用程序。因此,我们需要基于暗或亮模式切换样式表。因此,您要么需要构建某种动态样式表对象(这会很好),要么只是询问当前状态是什么(不好但很容易)。
加载时此类别将替换该类别的viewDidLoad方法UIViewController类并拦截调用。我不知道这是否违反了应用商店的规则。如果是这样,可能还有其他方法可以解决,但您可以认为这是概念证明。例如,您可以使所有主要视图控制器类型的一个子类,并使您自己的所有视图控制器都继承自这些视图控制器,然后可以使用DarkMode类别提示并对其进行调用以强制选择退出所有视图控制器。这很丑陋,但不会违反任何规则。我更喜欢使用运行时,因为这是运行时要做的。因此,在我的版本中,您只需添加类别,就可以在类别上设置一个全局变量,以决定是否要阻止暗模式,并且可以做到这一点。
如前所述,您还没有走出困境,另一个问题是UIColor基本上会做任何想要的事情。因此,即使您的视图控制器阻止了暗模式,UIColor也不知道您在哪里或如何使用它,因此无法适应。因此,您可以正确地获取它,但是将来它会在将来的某个时候恢复。也许很快,也许以后。因此,解决方法是使用CGColor对其分配两次,然后将其转换为静态颜色。这意味着,如果您的用户返回并在设置页面上重新启用了暗模式(此处的目的是使此项工作正常进行,以便用户可以在系统其余部分之上控制您的应用),所有这些静态颜色需要更换。到目前为止,这还有待其他人解决。最简单的方法是将您退出黑暗模式的默认值设为默认值,除以零会使应用程序崩溃,因为您无法退出该应用程序并告诉用户重新启动它。这可能也违反了应用商店的指导方针,但这是一个主意。
不需要公开UIColor类别,它只适用于调用colorNamed:...如果您不告诉DarkMode ViewController,类以阻止黑暗模式,它将按预期完美运行。尝试使某些东西变得优雅,而不是标准的苹果花粉代码,这意味着如果要以编程方式选择退出暗模式或切换它,则必须修改大部分应用程序。现在,我不知道是否有更好的方法以编程方式更改Info.plist以根据需要关闭暗模式。就我的理解而言,这是一个编译时功能,在此之后您便会陷入困境。
所以这是您需要的代码。应该加入,仅使用一种方法来设置UI样式或在代码中设置默认值。您可以出于任何目的随意使用,修改,执行任何您想做的事情,并且不提供任何担保,而且我不知道它是否会通过应用程序商店。改进非常欢迎。
合理的警告我不使用ARC或任何其他手持方法。
单独的文件。不过,这是标准的东西,您可以在任何地方找到类似的代码。
////// H file
#import <UIKit/UIKit.h>
@interface UIViewController(DarkMode)
// if you want to globally opt out of dark mode you call these before any view controllers load
// at the moment they will only take effect for future loaded view controllers, rather than currently
// loaded view controllers
// we are doing it like this so you don't have to fill your code with @availables() when you include this
typedef enum {
QOverrideUserInterfaceStyleUnspecified,
QOverrideUserInterfaceStyleLight,
QOverrideUserInterfaceStyleDark,
} QOverrideUserInterfaceStyle;
// the opposite condition is light interface mode
+ (void)setOverrideUserInterfaceMode:(QOverrideUserInterfaceStyle)override;
+ (QOverrideUserInterfaceStyle)overrideUserInterfaceMode;
// utility methods
// this will tell you if any particular view controller is operating in dark mode
- (BOOL)isUsingDarkInterfaceStyle;
// this will tell you if any particular view controller is operating in light mode mode
- (BOOL)isUsingLightInterfaceStyle;
// this is called automatically during all view controller loads to enforce a single style
- (void)tryToOverrideUserInterfaceStyle;
@end
////// M file
//
// QDarkMode.m
#import "UIViewController+DarkMode.h"
#import "q-runtime.h"
@implementation UIViewController(DarkMode)
typedef void (*void_method_imp_t) (id self, SEL cmd);
static void_method_imp_t _nativeViewDidLoad = NULL;
// we can't @available here because we're not in a method context
static long _override = -1;
+ (void)load;
{
#define DEFAULT_UI_STYLE UIUserInterfaceStyleLight
// we won't mess around with anything that is not iOS 13 dark mode capable
if (@available(iOS 13,*)) {
// default setting is to override into light style
_override = DEFAULT_UI_STYLE;
/*
This doesn't work...
NSUserDefaults *d = NSUserDefaults.standardUserDefaults;
[d setObject:@"Light" forKey:@"UIUserInterfaceStyle"];
id uiStyle = [d objectForKey:@"UIUserInterfaceStyle"];
NSLog(@"%@",uiStyle);
*/
if (!_nativeViewDidLoad) {
Class targetClass = UIViewController.class;
SEL targetSelector = @selector(viewDidLoad);
SEL replacementSelector = @selector(_overrideModeViewDidLoad);
_nativeViewDidLoad = (void_method_imp_t)QMethodImplementationForSEL(targetClass,targetSelector);
QInstanceMethodOverrideFromClass(targetClass, targetSelector, targetClass, replacementSelector);
}
}
}
// we do it like this because it's not going to be set often, and it will be tested often
// so we can cache the value that we want to hand to the OS
+ (void)setOverrideUserInterfaceMode:(QOverrideUserInterfaceStyle)style;
{
if (@available(iOS 13,*)){
switch(style) {
case QOverrideUserInterfaceStyleLight: {
_override = UIUserInterfaceStyleLight;
} break;
case QOverrideUserInterfaceStyleDark: {
_override = UIUserInterfaceStyleDark;
} break;
default:
/* FALLTHROUGH - more modes can go here*/
case QOverrideUserInterfaceStyleUnspecified: {
_override = UIUserInterfaceStyleUnspecified;
} break;
}
}
}
+ (QOverrideUserInterfaceStyle)overrideUserInterfaceMode;
{
if (@available(iOS 13,*)){
switch(_override) {
case UIUserInterfaceStyleLight: {
return QOverrideUserInterfaceStyleLight;
} break;
case UIUserInterfaceStyleDark: {
return QOverrideUserInterfaceStyleDark;
} break;
default:
/* FALLTHROUGH */
case UIUserInterfaceStyleUnspecified: {
return QOverrideUserInterfaceStyleUnspecified;
} break;
}
} else {
// we can't override anything below iOS 12
return QOverrideUserInterfaceStyleUnspecified;
}
}
- (BOOL)isUsingDarkInterfaceStyle;
{
if (@available(iOS 13,*)) {
if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark){
return YES;
}
}
return NO;
}
- (BOOL)isUsingLightInterfaceStyle;
{
if (@available(iOS 13,*)) {
if (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleLight){
return YES;
}
// if it's unspecified we should probably assume light mode, esp. iOS 12
}
return YES;
}
- (void)tryToOverrideUserInterfaceStyle;
{
// we have to check again or the compile will bitch
if (@available(iOS 13,*)) {
[self setOverrideUserInterfaceStyle:(UIUserInterfaceStyle)_override];
}
}
// this method will be called via the viewDidLoad chain as we will patch it into the
// UIViewController class
- (void)_overrideModeViewDidLoad;
{
if (_nativeViewDidLoad) {
_nativeViewDidLoad(self,@selector(viewDidLoad));
}
[self tryToOverrideUserInterfaceStyle];
}
@end
// keep this in the same file, hidden away as it needs to switch on the global ... yeah global variables, I know, but viewDidLoad and colorNamed: are going to get called a ton and already it's adding some inefficiency to an already inefficient system ... you can change if you want to make it a class variable.
// this is necessary because UIColor will also check the current trait collection when using asset catalogs
// so we need to repair colorNamed: and possibly other methods
@interface UIColor(DarkMode)
@end
@implementation UIColor (DarkMode)
typedef UIColor *(*color_method_imp_t) (id self, SEL cmd, NSString *name);
static color_method_imp_t _nativeColorNamed = NULL;
+ (void)load;
{
// we won't mess around with anything that is not iOS 13 dark mode capable
if (@available(iOS 13,*)) {
// default setting is to override into light style
if (!_nativeColorNamed) {
// we need to call it once to force the color assets to load
Class targetClass = UIColor.class;
SEL targetSelector = @selector(colorNamed:);
SEL replacementSelector = @selector(_overrideColorNamed:);
_nativeColorNamed = (color_method_imp_t)QClassMethodImplementationForSEL(targetClass,targetSelector);
QClassMethodOverrideFromClass(targetClass, targetSelector, targetClass, replacementSelector);
}
}
}
// basically the colors you get
// out of colorNamed: are dynamic colors... as the system traits change underneath you, the UIColor object you
// have will also change since we can't force override the system traits all we can do is force the UIColor
// that's requested to be allocated out of the trait collection, and then stripped of the dynamic info
// unfortunately that means that all colors throughout the app will be static and that is either a bug or
// a good thing since they won't respond to the system going in and out of dark mode
+ (UIColor *)_overrideColorNamed:(NSString *)string;
{
UIColor *value = nil;
if (@available(iOS 13,*)) {
value = _nativeColorNamed(self,@selector(colorNamed:),string);
if (_override != UIUserInterfaceStyleUnspecified) {
// the value we have is a dynamic color... we need to resolve against a chosen trait collection
UITraitCollection *tc = [UITraitCollection traitCollectionWithUserInterfaceStyle:_override];
value = [value resolvedColorWithTraitCollection:tc];
}
} else {
// this is unreachable code since the method won't get patched in below iOS 13, so this
// is left blank on purpose
}
return value;
}
@end
自q-runtime.h起,我将其复制并粘贴到几个文件中。是我的可重用库,这只是其中的一部分。如果无法编译,请通知我。
评论
正如这个问题所讨论的,在控制UIColor行为方面,您并没有碰运气:stackoverflow.com/questions/56487679/…
–raven_raven
19年9月5日13:06
评论
在您的Info.Plist中将UIUserInterfaceStyle设置为Light。请参阅developer.apple.com/library/archive/documentation/General/…感谢您的询问-我们所有人。有很多应用程序要经历。这是保持应用程序运行到切换准备就绪所必需的。
import Foundation import UIKit扩展UIViewController {重写open func awakeFromNib(){super.awakeFromNib()if #available(iOS 13.0,*){//始终采用浅色界面样式。 overrideUserInterfaceStyle = .light}}}
只需在plist中添加UIUserInterfaceStyle。就这么简单
在将应用程序提交到appstore时,由于处于Light模式的UIUserInterfaceStyle,Apple会接受。