Accessing system colors in WatchKit - uikit

I am trying to use UIKit colors for my Apple Watch interface. You can do it in iOS with UIColor class properties like .systemBackground and others. For example:
let myColor = UIColor.systemBlue
Gives me error when compiling watchOS extension target:
Type 'UIColor' has no member 'UIColor.systemBlue'.
I wonder tis there alternative way to get this system colors, and if not — what I need is to get a color of some UI elements, like SwiftUI table view row background which looks very similar to UIColor.systemGray5.
#State private var isActive = false
var body: some View {
List {
Section() {
ForEach(self.dataSource) { item in
CustomCell()
.listRowPlatterColor(self.isActive ? Color(UIColor.systemGray5) : Color(.orange))
}
}
}
}
Code above won't compile because UIColor.systemGray5 is not found in WatchKit. I have tried to create a class which is sued both in iPhone and Watch target and it fixes Xcode autocompletion. But the app breaks when trying to use it the Apple Watch target.
I hope there's a way rather then finding correct color and hard-coding it.

Looking at the documentation, the UIColor.system-ish are only available for iOS, Catalyst and some for tvOS. What you can do is extend UIColor and create you systemGray5:
extension UIColor {
static var mySystemGray5: UIColor {
return .init(red: 229/255, green: 229/255, blue: 234/255, alpha: 1)
}
}
And use on your code like:
ForEach(self.dataSource) { item in
CustomCell()
.listRowPlatterColor(self.isActive ? Color(UIColor.mySystemGray5) : Color(.orange))
}

Since you are using SwiftUI, Color.blue is equivalent to UIColor.systemBlue.
Unfortunately, Color doesn't have a lots of UIColor system colors, hopefully Apple add missing colors on WWDC 2020.
May be use can use something like Color.gray.opacity.opacity(0.25) in the meanwhile?

Related

How to preserve split view divider configuration in Mac Catalyst app?

Mac apps that have a sidebar (Mail, Finder, etc) allow you to resize its width, and that width is preserved across app launches. You enable this behavior in an AppKit app by assigning autosaveName on your NSSplitView. How do you do this in a Mac Catalyst app using UISplitViewController?
By default, my Catalyst app's sidebar is pretty wide, so every time the user opens it they have to resize it.
I reached out to a friend who was able to achieve this in their app. They said you can manually save the current width to UserDefaults and upon creating the split view controller set its preferredPrimaryColumnWidth to the last saved width. Nice!
In my UISplitViewController subclass I added:
init() {
let lastWidth = UserDefaults.standard.integer(forKey: "SidebarWidth")
let initialWidth = lastWidth > 0 ? CGFloat(lastWidth) : 220
preferredPrimaryColumnWidth = initialWidth
//...
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
UserDefaults.standard.setValue(Int(primaryColumnWidth), forKey: "SidebarWidth")
}

SwiftUI NavigationView/Stack if available iOS 15/16

There's something I don't really understand about the transition from NavigationView to NavigationStack for SwiftUI 4 and iOS 16.
I have 2 applications running on the App Store (targeting iOS 15 and above) and of course I'm using NavigationView. This weekend, I was looking for a solution to have them ready for iOS 16 by replacing:
var body: some View {
NavigationView {
ScrollView { /* code here */ }
}
}
To something like this:
var body: some View {
if #available(iOS 16, *) {
NavigationStack {
} else {
NavigationView {
}
ScrollView { /* code here */ }
}
}
But finally, before doing so, I tried them with iOS 16 Beta and they're perfectly fine.
I don't understand, I thought it would be total a mess but finally no. Do you have an explanation? Maybe, deprecated isn't what it should mean?
NavigationView is deprecated, not obsoleted. When a component becomes deprecated, it still can be used until Apple decides to obsolete it which will cause a crash when used. Although it's functional, you shouldn't use it.

Customize background and text color in UIDatePicker in iOS 12

In previous iOS versions, I was able to change the text and background colors using the something like the following:
let datePicker = UIDatePicker()
datePicker.datePickerMode = UIDatePickerMode.date
datePicker.setValue(UIColor.white, forKey: "textColor")
datePicker.backgroundColor = UIColor.black.withAlphaComponent(0.6)
This is no longer working in Xcode 10/iOS 12. The date picker is displayed with its default colors. Has anyone found a solution for customizing the text and background colors in iOS 12?
It seems something is resetting those values between when I set them and when the view is displayed. I was able to solve this by subclassing UIDatePicker and setting the values in layoutSubviews(). There may be a more performant place to set the colors, but this is working for me for now.
class DatePicker: UIDatePicker {
override func layoutSubviews() {
super.layoutSubviews()
backgroundColor = UIColor.black.withAlphaComponent(0.6)
setValue(false, forKey: "highlightsToday")
setValue(UIColor.white, forKey: "textColor")
}
}

Disable ScrollView bounce NativeScript

Looking for a way to disable the ScrollView bounce or overflow that happens when scrolling reaches the top or bottom of the scroll view.
here how to set the settings in android.
Android scrollview remove blue light
Here is a code snippet that might do the trick for you:
if (this.content.ios instanceof UIScrollView) {
this.content.ios.alwaysBounceVertical = false;
}
Of course you need to get an instance of the <ScrollView> component from NativeScript and then the native iOS instance.
I have a small utility library that has this function and some other handy functions baked into it.
https://github.com/TheOriginalJosh/nativescript-swiss-army-knife
import {SwissArmyKnife} from 'nativescript-swiss-army-knife/nativescript-swiss-army-knife';
...
let scrollView = page.getViewById('myScrollView');
SwissArmyKnife.disableScrollBounce(scrollView);
Here is how to do it on iOS and Android.
let scrollView = page.getViewById('myScrollView');
if (app.android) {
scrollView.android.setOverScrollMode(2);
}
else if (app.ios) {
scrollView.ios.bounces = false;
}

OSX NSVisualEffectView Decrease Blur Radius [duplicate]

Is it possible to adjust the blur radius and transparency of an NSVisualEffectView when it's applied to an NSWindow (Swift or Objective-C)? I tried all variations of NSVisualEffectMaterial (dark, medium, light) - but that's not cutting it. In the image below I've used Apple's non-public API with CGSSetWindowBackgroundBlurRadius on the left, and NSVisualEffectView on the right.
I'm trying to achieve the look of what's on the left, but it seems I'm relegated to use the methods of the right.
Here's my code:
blurView.blendingMode = NSVisualEffectBlendingMode.BehindWindow
blurView.material = NSVisualEffectMaterial.Medium
blurView.state = NSVisualEffectState.Active
self.window!.contentView!.addSubview(blurView)
Possibly, related - but doesn't answer my question:
OS X NSVisualEffect decrease blur radius? - no answer
Although I wouldn't recommend this unless you are ready to fall back to it not working in a future release, you can subclass NSVisualEffectView with the following to do what you want:
- (void)updateLayer
{
[super updateLayer];
[CATransaction begin];
[CATransaction setDisableActions:YES];
CALayer *backdropLayer = self.layer.sublayers.firstObject;
if ([backdropLayer.name hasPrefix:#"kCUIVariantMac"]) {
for (CALayer *activeLayer in backdropLayer.sublayers) {
if ([activeLayer.name isEqualToString:#"Active"]) {
for (CALayer *sublayer in activeLayer.sublayers) {
if ([sublayer.name isEqualToString:#"Backdrop"]) {
for (id filter in sublayer.filters) {
if ([filter respondsToSelector:#selector(name)] && [[filter name] isEqualToString:#"blur"]) {
if ([filter respondsToSelector:#selector(setValue:forKey:)]) {
[filter setValue:#5 forKey:#"inputRadius"];
}
}
}
}
}
}
}
}
[CATransaction commit];
}
Although this doesn't use Private APIs per se, it does start to dig into layer hierarchies which you do not own, so be sure to double check that what you are getting back is what you expect, and fail gracefully if not. For instance, on 10.10 Yosemite, the Backdrop layer was a direct decedent of the Visual Effect view, so things are likely to change in the future.
I had the same issue as you had and I have solved it with a little trick seems to do the job that I wanted. I hope that it will also help you.
So in my case, I have added the NSVisualEffectView in storyboards and set its properties as follows:
and my View hierarchy is as follows:
All that reduces the blur is in the NSViewController in:
override func viewWillAppear() {
super.viewWillAppear()
//Adds transparency to the app
view.window?.isOpaque = false
view.window?.alphaValue = 0.98 //tweak the alphaValue for your desired effect
}
Going with your example this code should work in addition with the tweak above:
let blurView = NSVisualEffectView(frame: view.bounds)
blurView.blendingMode = .behindWindow
blurView.material = .fullScreenUI
blurView.state = .active
view.window?.contentView?.addSubview(blurView)
Swift 5 code
For anyone interested here is a link to my repo where I have created a small prank app which uses the code above:
GitHub link

Resources