เป็นไปได้หรือไม่ที่จะยกเลิกโหมดมืดบน iOS 13?


297

แอพของฉันส่วนใหญ่ประกอบด้วยมุมมองทางเว็บเพื่อให้ฟังก์ชันการทำงานยังไม่พร้อมใช้งานผ่านการใช้งานดั้งเดิม ทีมงานเว็บไม่มีแผนที่จะใช้ธีมสีเข้มสำหรับเว็บไซต์ ดังนั้นแอพของฉันจะดูเล็กน้อยครึ่ง / ครึ่งพร้อมการรองรับ Dark Mode บน iOS 13

เป็นไปได้หรือไม่ที่จะยกเลิกการรองรับ Dark Mode แอพของเราจะแสดงโหมดแสงให้ตรงกับธีมของเว็บไซต์


71
ตั้งUIUserInterfaceStyleเป็นLightใน Info.Plist ของคุณ ดู developer.apple.com/library/archive/documentation/General/…
Tieme

1
ขอบคุณที่สอบถาม - สำหรับพวกเราทุกคน แอพที่ผ่านมามากมาย สิ่งนี้เป็นสิ่งจำเป็นเพื่อให้แอปทำงานต่อไปจนกว่าการสลับจะพร้อมใช้งาน
user3741598

นำเข้ารากฐานการนำเข้าส่วนขยาย UIKit UIViewController {แทนที่ open func awakeFromNib () {super.awakeFromNib () ถ้า #available (iOS 13.0, *) {// นำสไตล์แสงแบบอินเทอร์เฟซมาใช้เสมอ overrideUserInterfaceStyle = .light}}}
Mohammad Razipour

1
เพียงเพิ่มUIUserInterfaceStyle แบบเต็ม มันง่ายมาก
Fattie

ในขณะที่ส่งแอพไปยัง appstore แอปเปิ้ลยอมรับเนื่องจาก UIUserInterfaceStyle ในโหมด Light
kiran

คำตอบ:


684

ก่อนอื่นนี่คือรายการของ Appleที่เกี่ยวข้องกับการยกเลิกโหมดมืด เนื้อหาที่ลิงค์นี้เขียนขึ้นสำหรับ Xcode 11 และ iOS 13 :

ส่วนนี้ใช้กับการใช้ Xcode 11


หากคุณต้องการยกเลิกการสมัครทั้งหมด

วิธีการ # 1

ใช้รหัสต่อไปนี้ในไฟล์info.plist ของคุณ :

UIUserInterfaceStyle

Lightและกำหนดค่าของ

XMLสำหรับUIUserInterfaceStyleการมอบหมาย:

<key>UIUserInterfaceStyle</key>
<string>Light</string>

วิธีการ # 2

คุณสามารถตั้งค่าoverrideUserInterfaceStyleกับwindowตัวแปรของแอพ

ขึ้นอยู่กับว่าโครงการของคุณถูกสร้างขึ้นนี้อาจจะอยู่ในไฟล์หรือAppDelegateSceneDelegate

if #available(iOS 13.0, *) {
    window?.overrideUserInterfaceStyle = .light
}


หากคุณต้องการยกเลิกการใช้ UIViewController เป็นรายบุคคล

override func viewDidLoad() {
    super.viewDidLoad()
    // overrideUserInterfaceStyle is available with iOS 13
    if #available(iOS 13.0, *) {
        // Always adopt a light interface style.
        overrideUserInterfaceStyle = .light
    }
}

เอกสารประกอบ Apple สำหรับ overrideUserInterfaceStyle

ลักษณะของโค้ดด้านบนจะเป็นอย่างไรใน Xcode 11:

ป้อนคำอธิบายรูปภาพที่นี่

ส่วนนี้ใช้กับการใช้ Xcode 10.x


หากคุณใช้ Xcode 11 สำหรับการส่งของคุณคุณสามารถเพิกเฉยต่อทุกสิ่งที่อยู่ด้านล่างบรรทัดนี้ได้อย่างปลอดภัย

เนื่องจาก API ที่เกี่ยวข้องไม่มีอยู่ใน iOS 12 คุณจะได้รับข้อผิดพลาดเมื่อพยายามใช้ค่าที่ให้ไว้ด้านบน:

สำหรับการตั้งค่าoverrideUserInterfaceStyleในUIViewController

ป้อนคำอธิบายรูปภาพที่นี่

หากคุณต้องการยกเลิกการใช้ UIViewController เป็นรายบุคคล

สิ่งนี้สามารถจัดการได้ใน Xcode 10 โดยการทดสอบเวอร์ชันคอมไพเลอร์และเวอร์ชั่น iOS:

#if compiler(>=5.1)
if #available(iOS 13.0, *) {
    // Always adopt a light interface style.
    overrideUserInterfaceStyle = .light
}
#endif

หากคุณต้องการยกเลิกการสมัครทั้งหมด

คุณสามารถแก้ไขตัวอย่างข้างต้นเพื่อทำงานกับแอปพลิเคชันทั้งหมดสำหรับ Xcode 10 โดยเพิ่มรหัสต่อไปนี้ลงในAppDelegateไฟล์ของคุณ

#if compiler(>=5.1)
if #available(iOS 13.0, *) {
    // Always adopt a light interface style.
    window?.overrideUserInterfaceStyle = .light
}
#endif

อย่างไรก็ตามการตั้งค่า plist จะล้มเหลวเมื่อใช้ Xcode เวอร์ชั่น 10.x:

ป้อนคำอธิบายรูปภาพที่นี่

ขอมอบเครดิตให้แก่@Aron Nelson , @Raimundas Sakalauskas , @NSLeaderและrmaddyสำหรับการปรับปรุงคำตอบนี้พร้อมข้อเสนอแนะ


2
ไฟ UIUserInterfaceStyle ถูกบล็อกเมื่ออัปเดต / อัปโหลดแอปของคุณทันที ได้รับการตั้งค่าสถานะเป็นรายการ plist ที่ไม่ถูกต้อง (คีย์ plist ไม่ถูกต้อง)
Aron Nelson

2
สิ่งนี้จะไม่รวบรวมกับ iOS SDK 12 (ปัจจุบันมีเสถียรภาพ SDK ล่าสุด) ดูstackoverflow.com/a/57521901/2249485สำหรับโซลูชันที่จะทำงานกับ iOS 12 SDK ได้เช่นกัน
Raimundas Sakalauskas

นี่ไม่ยุติธรรมเลยที่คำถามที่มีมุมมองมากกว่า "คำถามดั้งเดิม" นั้นถูกล็อคไว้เพื่อให้คำตอบ :(
Raimundas Sakalauskas

7
แทนที่จะตั้งค่าoverrideUserInterfaceStyleในviewDidLoadทุกตัวควบคุมมุมมองคุณสามารถตั้งค่าได้ครั้งเดียวในหน้าต่างหลักของแอพ ง่ายกว่านี้มากถ้าคุณต้องการให้แอปทั้งหมดทำงานในทิศทางเดียว
rmaddy

2
ใช้#if compiler(>=5.1)แทนresponds(to:)และsetValue
NSLeader

162

ตามเซสชั่นแอปเปิ้ลใน "โหมดเข้มการใช้บน iOS" ( https://developer.apple.com/videos/play/wwdc2019/214/เริ่มต้นที่ 31:13) มันเป็นไปได้ที่จะตั้งค่าoverrideUserInterfaceStyleการUIUserInterfaceStyleLightหรือUIUserInterfaceStyleDarkบนตัวควบคุมมุมมองใด ๆ หรือมุมมอง ซึ่งจะถูกใช้ในการtraitCollectionสำหรับมุมมองย่อยหรือตัวควบคุมมุมมอง

ดังที่ได้กล่าวไว้แล้วโดย SeanR คุณสามารถตั้งค่าUIUserInterfaceStyleเป็นLightหรือDarkในไฟล์ plist ของแอปเพื่อเปลี่ยนแปลงสิ่งนี้สำหรับแอปทั้งหมดของคุณ


17
หากคุณตั้งค่า UIUserInterfaceStyle คีย์แอปของคุณจะถูกปฏิเสธใน App store
Sonius

2
Apple ถูกปฏิเสธด้วยรหัสข้อผิดพลาด ITMS-90190 forums.developer.apple.com/thread/121028
PRASAD1240

11
การปฏิเสธมักเกิดขึ้นเนื่องจาก iOS 13 SDK ยังไม่ออกจากเบต้า ฉันคิดว่านี่น่าจะใช้งานได้ทันทีที่ Xcode 11 GM พร้อมใช้งาน
dorbeetle

2
@dorbeetle ไม่เป็นความจริงฉันอัพโหลดแอปของฉันด้วยคีย์นี้เรียบร้อยแล้วเช่น 1 เดือนที่ผ่านมาด้วย Xcode 10 การปฏิเสธเกิดขึ้นเร็ว ๆ นี้ ดูเหมือนว่ากลยุทธ์ใหม่ของ Apple บางชนิด
steven

1
มันยังคงเกิดขึ้น Xcode GM2 ส่งคืนข้อผิดพลาดในการเซ็นชื่อแอป Xcode 10.3 ส่งคืน: "คีย์ Info.plist ไม่ถูกต้องคีย์ 'UIUserInterfaceStyle' ในไฟล์ Payload / Galileo.appInfo.plist ไม่ถูกต้อง"
Evgen Bodunov

64

หากคุณไม่ได้ใช้ Xcode 11 หรือใหม่กว่า (i, e iOS 13 หรือใหม่กว่า SDK) แอปของคุณไม่ได้เลือกที่จะรองรับโหมดมืดโดยอัตโนมัติ ดังนั้นไม่จำเป็นต้องยกเลิกโหมดมืด

หากคุณใช้ Xcode 11 หรือใหม่กว่าระบบจะเปิดใช้งานโหมดมืดสำหรับแอปของคุณโดยอัตโนมัติ มีสองวิธีในการปิดใช้งานโหมดมืดขึ้นอยู่กับความต้องการของคุณ คุณสามารถปิดการใช้งานทั้งหมดหรือปิดการใช้งานมันสำหรับหน้าต่างมุมมองหรือมุมมองที่เฉพาะเจาะจง

ปิดใช้งานโหมดมืดทั้งหมดสำหรับแอปของคุณ

คุณสามารถปิดการใช้งานโหมดมืดได้โดยใส่UIUserInterfaceStyleรหัสด้วยค่าเช่นเดียวกับLightในไฟล์ 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

หมายเหตุ: Apple สนับสนุนอย่างยิ่งให้สนับสนุนโหมดมืดในแอปของคุณ ดังนั้นคุณสามารถปิดการใช้งานโหมดมืดชั่วคราวเท่านั้น

อ่านเพิ่มเติมได้ที่นี่: การเลือกสไตล์อินเทอร์เฟซเฉพาะสำหรับแอพ iOS ของคุณ


34

********** วิธีที่ง่ายที่สุดสำหรับ Xcode 11 ขึ้นไป ***********

เพิ่มลงใน info.plist ก่อน </dict></plist>

<key>UIUserInterfaceStyle</key>
<string>Light</string>

วิธีการแก้ปัญหานี้จะล้มเหลวเมื่อไม่ส่งแอพใน Xcode 10.x
Tawfik Bouabid

27

ฉันคิดว่าฉันพบวิธีแก้ปัญหาแล้ว ผมเริ่มปะติดปะต่อมันเข้าด้วยกันจากUIUserInterfaceStyle - ข้อมูลรายการทรัพย์สินและUIUserInterfaceStyle - UIKitแต่ตอนนี้ได้พบว่าเอกสารจริงในการเลือกรูปแบบหน้าจอที่เฉพาะเจาะจงสำหรับแอป iOS ของคุณ

ในของคุณinfo.plistตั้งค่าUIUserInterfaceStyle( ลักษณะส่วนต่อประสานผู้ใช้ ) เป็น1 ( UIUserInterfaceStyle.light)

แก้ไข: ตามคำตอบ dorbeetle ของการตั้งค่าที่เหมาะสมสำหรับอาจจะUIUserInterfaceStyleLight


การบังคับใช้โหมดมืดโดยการตั้งค่าที่ 2 ไม่ทำงานแม้ว่า:[UIInterfaceStyle] '2' is not a recognized value for UIUserInterfaceStyle. Defaulting to Light.
funkenstrahlen

3
การใช้คีย์นี้ในการวางแผนจะส่งผลให้การปฏิเสธ App Store
José

1
AppStore ไม่ปฏิเสธคุณสมบัตินี้ใน plist.info อีกต่อไป ฉันใส่ "Dark" (ตัวพิมพ์ใหญ่) เนื่องจากแอปของเรามืดแล้ว ไม่มีปัญหา. สิ่งนี้ช่วยให้เราใช้ระบบควบคุมได้อย่างถูกต้อง
nickdnk

@nickdnk ฉันคิดว่าคุณสร้างแอปของคุณด้วย Xcode 11 ซึ่ง Apple แนะนำ
DawnSong

1
ใช่ฉันทำ. มันไม่ได้เปลี่ยนความจริงที่ว่า Apple ยอมรับพารามิเตอร์นี้ในแผนการซึ่งเป็นสิ่งที่ฉันพยายามทำให้ชัดเจน
nickdnk

23

คำตอบข้างต้นใช้งานได้หากคุณต้องการยกเลิกแอปทั้งหมด หากคุณกำลังทำงานกับ lib ที่มี UI และคุณไม่มีความหรูหราในการแก้ไข. plist คุณสามารถทำได้ผ่านรหัสเช่นกัน

หากคุณกำลังรวบรวมกับ iOS 13 SDK คุณสามารถใช้รหัสต่อไปนี้:

สวิฟท์:

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เป็นของ
DawnSong

12

ปรับปรุงล่าสุด-

หากคุณกำลังใช้ Xcode 10.x แล้วเริ่มต้นUIUserInterfaceStyleเป็นlightสำหรับ iOS 13.x. เมื่อทำงานบนอุปกรณ์ iOS 13 มันจะทำงานในโหมดแสงเท่านั้น

ไม่จำเป็นต้องเพิ่มUIUserInterfaceStyleคีย์ในไฟล์ Info.plist อย่างชัดเจนการเพิ่มคีย์จะทำให้เกิดข้อผิดพลาดเมื่อคุณตรวจสอบแอปของคุณว่า:

คีย์ Info.plist ไม่ถูกต้อง คีย์ 'UIUserInterfaceStyle' ในไฟล์ Payload / AppName.appInfo.plist ไม่ถูกต้อง

เพิ่มUIUserInterfaceStyleคีย์ในไฟล์ Info.plist เมื่อใช้ Xcode 11.x เท่านั้น


1
สิ่งนี้ไม่เกี่ยวกับ Xcode 10 หรือ 11 หากผู้ใช้ปรับใช้แอปฟอร์ม Xcode 10 และไม่ดูแลโหมดมืดแอพเมื่อติดตั้งใน iPhone 11, Pro หรือ Pro Max จะมีปัญหาโหมดมืด คุณต้องอัปเดตเป็น Xcode 11 และแก้ไขปัญหานี้
Niranjan Molkeri

3
@NiranjanMolkeri สิ่งนี้ไม่เกี่ยวกับ iPhones ที่ใหม่กว่า เป็นเรื่องเกี่ยวกับโหมด Dark ใน iOS 13 ใน iOS เวอร์ชันเบต้า 13 ของ iOS แอพมีปัญหาเกี่ยวกับโหมดมืด แต่ในเวอร์ชั่นล่าสุดนั้นได้รับการแก้ไขแล้ว หากคุณใช้ XCode 10 ค่าเริ่มต้นของ UIUserInterfaceStyle นั้นจะเบาสำหรับ iOS13 หากคุณใช้ Xode11 คุณต้องจัดการมัน
kumarsiddharth123

คุณจะมีปัญหาหากคุณอัปโหลดแอปไปยัง TestFligth โดยใช้ Xcode 10.3 และตัวย่อรวมถึงคีย์ UIUserInterfaceStyle มันจะบอกว่ามันเป็นไฟล์ plist ที่ไม่ถูกต้อง คุณต้องลบมันออกถ้าสร้างใน Xcode 10 หรืออัปโหลดโดยใช้ Xcode 11
eharo2

9

หากคุณจะเพิ่มUIUserInterfaceStyleที่สำคัญในการไฟล์ plist อาจจะเป็นแอปเปิ้ลจะปฏิเสธการเปิดตัวสร้างเป็นที่กล่าวถึงที่นี่: https://stackoverflow.com/a/56546554/7524146 อย่างไรก็ตามมันน่ารำคาญอย่างชัดเจนบอกแต่ละ self.overrideUserInterfaceStyle = .lightViewController แต่คุณสามารถใช้รหัสสันติภาพนี้หนึ่งครั้งสำหรับwindowวัตถุรูตของคุณ:

if #available(iOS 13.0, *) {
    if window.responds(to: Selector(("overrideUserInterfaceStyle"))) {
        window.setValue(UIUserInterfaceStyle.light.rawValue, forKey: "overrideUserInterfaceStyle")
    }
}

เพิ่งสังเกตเห็นว่าคุณไม่สามารถทำสิ่งนี้ภายในapplication(application: didFinishLaunchingWithOptions:)เพราะสำหรับตัวเลือกนี้จะไม่ตอบสนองtrueในช่วงแรกนั้น แต่คุณสามารถทำได้ในภายหลัง มันง่ายมากถ้าคุณใช้กำหนดเองAppPresenterหรือAppRouterคลาสในแอพของคุณแทนที่จะเริ่ม UI ใน AppDelegate โดยอัตโนมัติ


9

คุณสามารถปิดโหมดมืดในแอปพลิเคชันทั้งหมดใน Xcode 11:

  1. ไปที่ Info.plist
  2. เพิ่มร้องเหมือน

    <key>UIUserInterfaceStyle</key>
    <string>Light</string>

Info.plist จะมีลักษณะดังนี้ ...

ป้อนคำอธิบายรูปภาพที่นี่


1
ใช้งานไม่ได้กับ Xcode เวอร์ชัน 11.3.1 (11C504) ด้วยเหตุผลบางอย่าง
Andrew

7

- สำหรับแอปทั้งหมด (หน้าต่าง):

window!.overrideUserInterfaceStyle = .light

คุณสามารถรับหน้าต่างได้จาก SceneDelegate

- สำหรับ ViewController เดียว:

viewController.overrideUserInterfaceStyle = .light

คุณสามารถตั้งค่าใด ๆviewControllerแม้ใน viewController มันด้วยตนเอง

- สำหรับมุมมองเดียว:

view.overrideUserInterfaceStyle = .light

คุณสามารถตั้งค่าใด ๆviewแม้ในมุมมองมันด้วยตนเอง

คุณอาจต้องใช้if #available(iOS 13.0, *) { ,,, }หากคุณรองรับ iOS เวอร์ชันก่อนหน้า


6

นอกเหนือจากการตอบสนองอื่น ๆ จากความเข้าใจของฉันต่อไปนี้คุณจะต้องเตรียมตัวสำหรับโหมดมืดเมื่อรวบรวมกับ iOS 13 SDK (ใช้ XCode 11)

ระบบจะถือว่าแอพที่เชื่อมโยงกับ iOS 13 หรือ SDK ที่ใหม่กว่ารองรับการปรากฏทั้งรูปแบบแสงและสีเข้ม ใน iOS คุณระบุลักษณะที่ปรากฏที่คุณต้องการโดยกำหนดสไตล์อินเตอร์เฟสเฉพาะให้กับหน้าต่างมุมมองหรือมุมมองคอนโทรลเลอร์ของคุณ นอกจากนี้คุณยังสามารถปิดการใช้งานการรองรับ Dark Mode โดยใช้ปุ่ม Info.plist

ลิงค์



2

แอพของฉันไม่รองรับโหมดมืดในขณะนี้และใช้สีแถบแอพแบบเบา ฉันสามารถบังคับให้เนื้อหาแถบสถานะเป็นข้อความและไอคอนสีเข้มได้โดยการเพิ่มคีย์ต่อไปนี้ในInfo.plist:

<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleDarkContent</string>
<key>UIUserInterfaceStyle</key>
<string>Light</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>

ค้นหาค่าที่เป็นไปได้อื่น ๆ ที่นี่: https://developer.apple.com/documentation/uikit/uistatusbarstyle


2

วัตถุประสงค์ -c รุ่น

 if (@available(iOS 13.0, *)) {
        _window.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
    }

1

นี่คือเคล็ดลับและกลเม็ดเล็ก ๆ น้อย ๆ ที่คุณสามารถใช้ในแอพของคุณเพื่อสนับสนุนหรือเลี่ยงโหมดมืด

เคล็ดลับแรก: เพื่อแทนที่ลักษณะของ ViewController

คุณสามารถลบล้างลักษณะอินเตอร์เฟสของ UIViewController โดย

1: overrideUserInterfaceStyle = .dark // สำหรับโหมดมืด

2: overrideUserInterfaceStyle = .light // สำหรับโหมดไฟ

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        overrideUserInterfaceStyle = .light    
    }
}

เคล็ดลับที่สอง: การเพิ่มคีย์ใน info.plist

เพียงคุณสามารถเพิ่มรหัสใหม่

UIUserInterfaceStyle

ในข้อมูลแอพพลิเคชั่นของคุณและตั้งค่าเป็น Light หรือ Dark สิ่งนี้จะแทนที่สไตล์เริ่มต้นของแอปตามค่าที่คุณระบุ คุณไม่ต้องเพิ่ม overrideUserInterfaceStyle = .light บรรทัดนี้ในทุก viewController เพียงหนึ่งบรรทัดใน info.plist เท่านั้น


1

เพียงเพิ่มคีย์ต่อไปนี้ในinfo.plistไฟล์ของคุณ:

<key>UIUserInterfaceStyle</key>
    <string>Light</string>

1
 if #available(iOS 13.0, *) {
            overrideUserInterfaceStyle = .light
        } else {
            // Fallback on earlier versions
        }

คุณช่วยอธิบายได้นิดหน่อยว่าคำตอบนี้จะแก้ปัญหาได้อย่างไรแทนที่จะโพสต์คำตอบเฉพาะรหัสเท่านั้น
Arun Vinoth

ใช่ @ArunVinoth ใน IOS 13 จะมีการเปิดตัวโหมดมืดดังนั้นหากเป้าหมายการปรับใช้ของคุณต่ำกว่า 13 ให้ใช้รหัสข้างต้นอื่นคุณสามารถใช้คำสั่งง่ายๆที่เขียนไว้ในบล็อก
Talha Rasool

1

สวิฟท์ 5

สองวิธีในการสลับโหมดมืดเป็นแสง:

1- info.plist

    <key>UIUserInterfaceStyle</key>
    <string>Light</string>

2- โดยทางโปรแกรม

 UIApplication.shared.windows.forEach { window in
     window.overrideUserInterfaceStyle = .light
  } 

0

ฉันจะใช้วิธีแก้ปัญหานี้เนื่องจากคุณสมบัติของหน้าต่างอาจมีการเปลี่ยนแปลงระหว่างวงจรชีวิตของแอพ ดังนั้นการกำหนด "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
    }
}

0

เพียงเพิ่มบรรทัดเหล่านี้ในไฟล์ info.plist:

<key>UIUserInterfaceStyle</key>
<string>light</string>

สิ่งนี้จะบังคับให้แอปทำงานในโหมดไฟเท่านั้น


สิ่งนี้มีการแสดงความคิดเห็นแล้วและตอบหลายครั้ง แม้แต่คำตอบที่ได้รับการยอมรับก็คือการแนะนำสิ่งนี้ ดังนั้นความคิดเห็นนี้จะไม่เพิ่มข้อมูลใหม่
JeroenJK

0
import UIKit

extension UIViewController {

    override open func awakeFromNib() {

        super.awakeFromNib()

        if #available(iOS 13.0, *) {

            overrideUserInterfaceStyle = .light

        }

    }
}

2
โปรดเพิ่มคำอธิบายให้กับคำตอบของคุณโดยแก้ไขมันเพื่อให้คนอื่นสามารถเรียนรู้จากมันได้
Nico Haase

0

คุณสามารถทำได้: เพิ่มคีย์ใหม่ UIUserInterfaceStyle เป็น Info.plist และตั้งค่าเป็น Light และตรวจสอบตัวควบคุมการแจ้งเตือนปรากฏขึ้นพร้อมโหมดแสง

UIUserInterfaceStyle Light หากคุณเป็นโหมดบังคับแสง / มืดในแอปพลิเคชันทั้งหมดโดยไม่คำนึงถึงการตั้งค่าของผู้ใช้โดยการเพิ่มคีย์ UIUserInterfaceStyle ลงในไฟล์ Info.plist ของคุณและตั้งค่าเป็น Light หรือ Dark


0

คำถามนี้มีคำตอบมากมายแทนที่จะใช้ในinfo.plistคุณสามารถตั้งเป็นAppDelegateดังนี้:

#if compiler(>=5.1)
        if #available(iOS 13.0, *) {
            self.window?.overrideUserInterfaceStyle = .light
        }
        #endif

ทดสอบ Xcode 11.3, iOS 13.3


-8

ที่จริงแล้วฉันเพิ่งเขียนโค้ดบางอย่างที่จะช่วยให้คุณสามารถยกเลิกโหมดมืดในโค้ดโดยไม่ต้อง putz กับคอนโทรลเลอร์ viw ทุกตัวในแอปพลิเคชันของคุณ สิ่งนี้อาจได้รับการขัดเกลาเพื่อเลือกไม่เข้าชั้นเรียนตามระดับชั้นเรียนโดยจัดการรายการของชั้นเรียน สำหรับฉันสิ่งที่ฉันต้องการคือให้ผู้ใช้ของฉันดูว่าพวกเขาชอบอินเทอร์เฟซโหมดมืดสำหรับแอพของฉันหรือไม่และถ้าพวกเขาไม่ชอบมันพวกเขาสามารถปิดได้ นี่จะช่วยให้พวกเขาใช้โหมดมืดต่อไปสำหรับแอปพลิเคชั่นที่เหลือ

ตัวเลือกของผู้ใช้เป็นสิ่งที่ดี (อะแฮ่มมองคุณ Apple นี่เป็นวิธีที่คุณควรนำไปใช้)

ดังนั้นวิธีการทำงานนี้เป็นเพียงหมวดหมู่ของ UIViewController เมื่อมันโหลดมันจะแทนที่เมธอด native viewDidLoad ด้วยวิธีที่จะตรวจสอบค่าสถานะโกลบอลเพื่อดูว่าโหมดมืดถูกปิดใช้งานสำหรับทุกสิ่งหรือไม่

เนื่องจากมันถูกทริกเกอร์ในการโหลด UIViewController มันควรจะเริ่มต้นโดยอัตโนมัติและปิดการใช้งานโหมดมืดโดยค่าเริ่มต้น หากนี่ไม่ใช่สิ่งที่คุณต้องการคุณจะต้องเข้าที่ก่อนกำหนดและตั้งค่าสถานะหรืออื่น ๆ เพียงตั้งค่าสถานะเริ่มต้น

ฉันยังไม่ได้เขียนอะไรเพื่อตอบสนองต่อผู้ใช้ในการเปิดหรือปิดการตั้งค่าสถานะ ดังนั้นนี่คือตัวอย่างโค้ดโดยทั่วไป หากเราต้องการให้ผู้ใช้โต้ตอบกับสิ่งนี้ผู้ควบคุมมุมมองทั้งหมดจะต้องโหลดซ้ำ ฉันไม่รู้ว่าจะทำอย่างไรในทันทีทันใด แต่การส่งการแจ้งเตือนบางอย่างอาจเป็นการหลอกลวง ดังนั้นในตอนนี้การเปิด / ปิดส่วนกลางสำหรับโหมดมืดจะทำงานเมื่อเริ่มต้นหรือเริ่มแอพใหม่เท่านั้น

ตอนนี้มันยังไม่เพียงพอที่จะลองปิดโหมดมืดในทุก ๆ มุมมอง MFING viewController ในแอพขนาดใหญ่ของคุณ หากคุณกำลังใช้สินทรัพย์สีคุณจะมีกระดูกสมบูรณ์ พวกเราเป็นเวลากว่า 10 ปีที่เข้าใจวัตถุที่ไม่เปลี่ยนรูปแบบซึ่งไม่อาจเปลี่ยนแปลงได้ สีที่คุณได้รับจากแคตตาล็อกสินทรัพย์สีระบุว่าเป็น UIColor แต่เป็นสีแบบไดนามิก (ไม่แน่นอน) และจะเปลี่ยนแปลงภายใต้ตัวคุณเนื่องจากระบบจะเปลี่ยนจากโหมดมืดเป็นแสง นั่นควรจะเป็นคุณสมบัติ แต่แน่นอนว่าไม่มีการสลับหลักเพื่อขอให้สิ่งเหล่านี้หยุดทำการเปลี่ยนแปลง (เท่าที่ฉันรู้ในตอนนี้บางทีอาจมีใครบางคนสามารถปรับปรุงได้)

ดังนั้นวิธีการแก้ปัญหาอยู่ในสองส่วน:

  1. หมวดหมู่สาธารณะบน UIViewController ที่ให้ประโยชน์ด้านสาธารณูปโภคและความสะดวกสบาย ... ตัวอย่างเช่นฉันไม่คิดว่าแอปเปิลคิดเกี่ยวกับข้อเท็จจริงที่ว่าพวกเราบางคนผสมโค้ดเว็บลงในแอพของเรา ด้วยเหตุนี้เราจึงมีสไตล์ชีทที่ต้องเปิดใช้งานตามโหมดมืดหรือสว่าง ดังนั้นคุณต้องสร้างวัตถุสไตล์ชีตแบบไดนามิก (ซึ่งจะดี) หรือถามว่าสถานะปัจจุบันคืออะไร (ไม่ดี แต่ง่าย)

  2. หมวดหมู่นี้เมื่อโหลดจะแทนที่เมธอด viewDidLoad ของคลาส UIViewController และการสกัดกั้นการโทร ฉันไม่รู้ว่านี่ทำผิดกฎของ App Store หรือไม่ ถ้าเป็นเช่นนั้นมีวิธีอื่นที่อาจเป็นไปได้ แต่คุณสามารถพิจารณาได้ว่าเป็นการพิสูจน์แนวคิด ตัวอย่างเช่นคุณสามารถสร้างคลาสย่อยหนึ่งประเภทของตัวควบคุมมุมมองหลักทั้งหมดและทำให้ตัวควบคุมมุมมองของคุณเองทั้งหมดสืบทอดจากสิ่งเหล่านั้นจากนั้นคุณสามารถใช้แนวคิดหมวดหมู่ DarkMode และเรียกใช้เพื่อบังคับให้ยกเลิกตัวควบคุมมุมมองทั้งหมดของคุณ มันน่าเกลียด แต่มันจะไม่ผิดกฎใด ๆ ฉันชอบที่จะใช้ runtime เพราะนั่นคือสิ่งที่ runtime ทำขึ้นมา ดังนั้นในรุ่นของฉันคุณเพียงแค่เพิ่มหมวดหมู่คุณตั้งค่าตัวแปรส่วนกลางในหมวดหมู่ว่าคุณต้องการให้มันปิดกั้นโหมดมืดหรือไม่และมันจะทำเช่นนั้น

  3. คุณยังไม่ได้ออกจากป่าดังที่กล่าวมาปัญหาอีกข้อคือ UIColor ทำสิ่งที่มันต้องการ ดังนั้นแม้ว่าตัวควบคุมมุมมองของคุณกำลังบล็อกโหมดมืด UIColor ไม่ทราบว่าคุณกำลังใช้อยู่ที่ไหนหรือวิธีการดังกล่าวไม่สามารถปรับได้ เป็นผลให้คุณสามารถดึงข้อมูลได้อย่างถูกต้อง แต่จากนั้นจะสามารถคืนค่าคุณได้ในอนาคต อาจจะช้าในภายหลัง ทางรอบนั้นคือการจัดสรรมันสองครั้งโดยใช้ CGColor และเปลี่ยนมันเป็นสีคงที่ ซึ่งหมายความว่าหากผู้ใช้ของคุณย้อนกลับไปและเปิดใช้งานโหมดมืดบนหน้าการตั้งค่าของคุณ (ความคิดที่นี่คือการทำให้การทำงานนี้เพื่อให้ผู้ใช้สามารถควบคุมแอปของคุณมากกว่าและเหนือส่วนที่เหลือของระบบ) สีคงทั้งหมดเหล่านั้น จำเป็นต้องเปลี่ยน จนถึงตอนนี้เหลือสำหรับคนอื่นที่จะแก้ปัญหา วิธีที่ง่ายที่สุดในการทำคือการเริ่มต้นให้คุณ กำลังออกจากโหมดมืดโดยแบ่งเป็นศูนย์เพื่อหยุดแอพเนื่องจากคุณไม่สามารถออกจากมันและบอกให้ผู้ใช้เพิ่งรีสตาร์ท นั่นอาจเป็นการละเมิดหลักเกณฑ์ของ App Store เช่นกัน แต่เป็นแนวคิด

หมวดหมู่ 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

#import <Foundation/Foundation.h>
#import <objc/message.h>
#import <stdatomic.h>

// returns the method implementation for the selector
extern IMP
QMethodImplementationForSEL(Class aClass, SEL aSelector);

// as above but gets class method
extern IMP
QClassMethodImplementationForSEL(Class aClass, SEL aSelector);


extern BOOL
QClassMethodOverrideFromClass(Class targetClass, SEL targetSelector,
                              Class replacementClass, SEL replacementSelector);

extern BOOL
QInstanceMethodOverrideFromClass(Class targetClass, SEL targetSelector,
                                 Class replacementClass, SEL replacementSelector);


// q-runtime.m

static BOOL
_QMethodOverride(Class targetClass, SEL targetSelector, Method original, Method replacement)
{
    BOOL flag = NO;
    IMP imp = method_getImplementation(replacement);
    // we need something to work with
    if (replacement) {
        // if something was sitting on the SEL already
        if (original) {
            flag = method_setImplementation(original, imp) ? YES : NO;
            // if we're swapping, use this
            //method_exchangeImplementations(om, rm);
        } else {
            // not sure this works with class methods...
            // if it's not there we want to add it
            flag = YES;
            const char *types = method_getTypeEncoding(replacement);
            class_addMethod(targetClass,targetSelector,imp,types);
            XLog_FB(red,black,@"Not sure this works...");
        }
    }
    return flag;
}

BOOL
QInstanceMethodOverrideFromClass(Class targetClass, SEL targetSelector,
                                 Class replacementClass, SEL replacementSelector)
{
    BOOL flag = NO;
    if (targetClass && replacementClass) {
        Method om = class_getInstanceMethod(targetClass,targetSelector);
        Method rm = class_getInstanceMethod(replacementClass,replacementSelector);
        flag = _QMethodOverride(targetClass,targetSelector,om,rm);
    }
    return flag;
}


BOOL
QClassMethodOverrideFromClass(Class targetClass, SEL targetSelector,
                              Class replacementClass, SEL replacementSelector)
{
    BOOL flag = NO;
    if (targetClass && replacementClass) {
        Method om = class_getClassMethod(targetClass,targetSelector);
        Method rm = class_getClassMethod(replacementClass,replacementSelector);
        flag = _QMethodOverride(targetClass,targetSelector,om,rm);
    }
    return flag;
}

IMP
QMethodImplementationForSEL(Class aClass, SEL aSelector)
{
    Method method = class_getInstanceMethod(aClass,aSelector);
    if (method) {
        return method_getImplementation(method);
    } else {
        return NULL;
    }
}

IMP
QClassMethodImplementationForSEL(Class aClass, SEL aSelector)
{
    Method method = class_getClassMethod(aClass,aSelector);
    if (method) {
        return method_getImplementation(method);
    } else {
        return NULL;
    }
}

ฉันกำลังคัดลอกและวางไฟล์นี้สองสามไฟล์ตั้งแต่ q-runtime.h เป็นไลบรารีที่ใช้ซ้ำได้ของฉันและนี่เป็นเพียงส่วนหนึ่งของมัน หากสิ่งที่ไม่ได้รวบรวมแจ้งให้ฉันทราบ


คุณไม่โชคดีเมื่อพูดถึงการควบคุมพฤติกรรมของ UIColor ดังที่กล่าวไว้ในคำถามนี้: stackoverflow.com/questions/56487679/…
raven_raven
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.