Mohammad Asgharneya - Big Nerd Ranch Tue, 19 Oct 2021 17:47:08 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.5 Paint It Black: Dark Mode in macOS Mojave https://bignerdranch.com/blog/paint-it-black-dark-mode-in-macos-mojave/ https://bignerdranch.com/blog/paint-it-black-dark-mode-in-macos-mojave/#respond Wed, 06 Jun 2018 10:00:23 +0000 https://nerdranchighq.wpengine.com/blog/paint-it-black-dark-mode-in-macos-mojave/ Starting with macOS Mojave, users can choose to run a system-wide light or dark mode of the Aqua interface. While opting an application into light and/or dark appearance modes is ultimately the choice of the developer, users may come to expect that apps support both. Apple believes some content creation applications may make sense primarily as dark mode only applications.

The post Paint It Black: Dark Mode in macOS Mojave appeared first on Big Nerd Ranch.

]]>

Starting with macOS Mojave, users can choose to run a system-wide light or dark mode of the Aqua interface. While opting an application into light and/or dark appearance modes is ultimately the choice of the developer, users may come to expect that apps support both. Apple believes some content creation applications may make sense primarily as dark mode only applications.

Overview

Standard views and controls are ready for Dark Mode out-of-the-box. And if you’re already using asset catalogs and semantic colors, you’ll be able to make your app ready too with minimal code changes.



Our Astronomical app was designed using just the Aqua interface but we would like to support Dark Mode as well. We first built the app using the macOS 10.14 SDK, but it seems like we have some work to do.

Sample Astronomical app in light mode and Broken Astronomical app in dark mode

Our header text was previously hardcoded to NSColor.black but we can easily achieve the same result using the dynamic .headerTextColor which will now do the right thing when we switch appearances.

Sample Astronomical app in light mode with header text that changes colors properly

Next, we would like to change our sun asset to a moon to represent dark mode. This can be achieved using the Asset Catalog. The Asset Catalog provides a convenient way to return a different resource using the same name that varies based on device attributes. In our case, the device attribute that is changing is the Appearance.

asset catalog screenshot

Note: If you are still targeting 10.13 or earlier, trying to receive a named image asset will only return the “Any Appearance” versions.

Nearly complete dark mode conversion, but emoji text is still not updated

Detecting Appearance Changes Programmatically

There are some cases where you may want to respond to appearance changes programmatically. You may have already noticed that Xcode 10 is nice enough to remember your Source Editor theme preference for each appearance. We would like to use this trigger to update our emoji representation of the Astronomical object we are presenting on screen.

How can we do something like this in our code? We can detect appearance changes by observing effectiveAppearance from the newly formalized NSAppearanceCustomization protocol. This protocol has informally existed for a while, but is now adopted by NSPopover, NSView, NSWindow, and NSApplication (new as of 10.14).

You can use KVO to observe changes to effectiveAppearance.

override func viewDidLoad() {
    super.viewDidLoad()
    appearanceChangeObservation = view.observe(.effectiveAppearance) { [weak self] _, _  in
        self?.updateAppearanceRelatedChanges()
    }
}

Once you detect an appearance change, you will want to figure out which appearance the application is currently in. Switching on effectiveAppearance.name will work, but switching on bestMatch(from:) may be a more future-proof approach. This method will attempt to provide you a good match based on the appearances you provide as the parameter.

private func updateAppearanceRelatedChanges() {
    switch view.effectiveAppearance.bestMatch(from: [.aqua, .darkAqua]) {
    case .aqua?: emojiField.stringValue = "☀️☀️☀️"
    case .darkAqua?: emojiField.stringValue = "🌙🌙🌙"
    default:  emojiField.stringValue = "💫💫💫"
    }
}

Successful dark mode conversion of the Astronomical app

Update Custom Views Using Established Methods

While our Astronomical app didn’t need to override the methods below, it is worth mentioning that these methods are the ideal place to update views when appearances change. Depending on your implementation, some of these NSView methods will be called when an appearance changes:

  • updateLayer()
  • draw(_:)
  • layout()
  • updateConstraints()

You can trigger these methods manually by setting needsLayout, needsDisplay, and needsUpdateConstraints.

We can’t wait to see how great your apps look in dark mode!

The post Paint It Black: Dark Mode in macOS Mojave appeared first on Big Nerd Ranch.

]]>
https://bignerdranch.com/blog/paint-it-black-dark-mode-in-macos-mojave/feed/ 0
WWDC 2017: Large Titles and Safe Area Layout Guides https://bignerdranch.com/blog/wwdc-2017-large-titles-and-safe-area-layout-guides/ https://bignerdranch.com/blog/wwdc-2017-large-titles-and-safe-area-layout-guides/#respond Tue, 06 Jun 2017 10:00:53 +0000 https://nerdranchighq.wpengine.com/blog/wwdc-2017-large-titles-and-safe-area-layout-guides/ iOS 11 added a property to `UINavigationItem` that can enable a large out-of-line title in the navigation bar. Here's how to take advantage of it.

The post WWDC 2017: Large Titles and Safe Area Layout Guides appeared first on Big Nerd Ranch.

]]>

The UI in iOS 11 is mostly unchanged from that of iOS 10, but it does add a new variation to the navigation bar.

Larger Navigation Bar Titles

iOS 11 added a property to UINavigationItem that enables a large, out-of-line title in the navigation bar. Apple recommends that this larger title be enabled for the first view controller in a navigation controller, but you can use it with any view controller.

To display a large title, set the navigation item’s largeTitleDisplayMode to .always:

let vc = UIViewController()
vc.navigationItem.largeTitleDisplayMode = .always

Is That It?

Yes, that’s pretty much it. Now our app went from this:

Regular navigation bar with small title

to this:

Large navigation bar with large title, but content of the view controller is blocked

Oh no, something went wrong. This is what happens when the offset for the content was hardcoded; the taller title breaks the assumed fixed height, and we get unwanted overlap. If we’d used topLayoutGuide, then we’d be fine. But iOS 11 also deprecates topLayoutGuide!

Safe Area Layout Guides

safeAreaLayoutGuide replaces topLayoutGuide and bottomLayoutGuide as a new way to create constraints between your views and a superview. These guides are used in tvOS to help insure that important areas of your view aren’t cut off because of overscan. These guides can also be used as new anchors for your views within a UIViewController to make sure that the UINavigationBar or UITabBar isn’t blocking your content.

If you are familiar with writing programmatic constraints, using these new guides couldn’t be easier. Let’s see if we can fix our app using these new layout guides:

topLabel.topAnchor.constraint(
-  equalTo: view.topAnchor,
-  constant: 64
+  equalTo: view.safeAreaLayoutGuide.topAnchor
).isActive = true

With that fix, our content moves back beneath even the large-titled Navigation Bar:

Large navigation bar and content of the view controller is properly visible after constraint changes

If your constraints were created through Interface Builder, you can also opt into using the new layout guides. Open your Storyboard, view the File Inspector and select “Use Safe Area Layout Guides.”

Whether your project uses hardcoded offsets or topLayoutGuide and bottomLayoutGuide, we recommend using safeAreaLayoutGuide.

Learn more about why you should update your apps for iOS 11 before launch day, or download our ebook for a deeper look into how the changes affect your business.

The post WWDC 2017: Large Titles and Safe Area Layout Guides appeared first on Big Nerd Ranch.

]]>
https://bignerdranch.com/blog/wwdc-2017-large-titles-and-safe-area-layout-guides/feed/ 0