Named colors via storyboard - ios

For my MacOS app, I created a colors Asset catalog.
The Deployment target for my project is 10.11.
When I set colors at the storyboard, I can choose from the colors asset. But when I try to set one of the named colors programmatically, I need to wrap it in
if #available(OSX 10.13, *) {
view.backgroundColor = NSColor(named: "someColor")
} else {
// Fallback on earlier versions
}
ORIGINAL QUESTION:
So the question is why I'm not getting any warnings for choosing those colors via the storyboard?
I guess I need to replace them with a custom color, or my app will crash on OS < 10.13, but I would expect the storyboard not to let me choose those colors because of the deployment target..
EDITED:
So the question is what happens when I'm using those colors via Storyboard?
Would it crash the app? or maybe the storyboard can handle named colors even for OS versions < 10.13 ? Because I tried to use the named colors via the Storyboard, and I installed the app on a Mac with OS 10.12, and the app worked just fine. So I'm wondering what's the reason for that..
P.S
This question is also relevant to iOS, where the min version for named colors is iOS 11

It will not crash your app. With Colors from Assets Catalog you have two options:
Only use it with storyboards.
Using UIColor(named: <#String #>) like you're trying to do in your question.
The only problem is that UIColor(named:) is available in iOS 11.0+ (See documentation)
So if you'd like to use it every time you need to think about fallback to the oldest version and that may be not quite right what you want.
But there is an other solution build in into Xcode in Media library:
You can drag&drop colors from assets catalog and Xcode will create for you reference for this color that will work in iOS 10.0 as well.
The actual line of code hidden in this color is:
colorLiteral(red: 0.9411764706, green: 0.07843137255, blue: 0.07843137255, alpha: 1)
So you can write a script that will generate this color for you.
Some time ago I need similar solution so I did wrote a script that scan my whole project for assets catalogs and inside them find a colors sets and create UIColor extension containing all the colors from assets:
You can find it here: https://github.com/JakubMazur/SwiftColorsGenerator and it's available to use through Marathon (https://github.com/JohnSundell/Marathon)

By using Jakub's method, color will not work for different appearances (light/dark mode).
Creating color like this worked for me.
extension UIColor {
static var testColor: UIColor = {
return UIColor(named: "TestColor", in: Bundle(for: AppDelegate.self), compatibleWith: nil)!
}()
}

Related

How to use image contained in Resource framework from main module?

I made embed framework Resources.framework to encapsulate Resources like images and colors.
When I put image resources to main module's storyboard,
InterfaceBuilder present all images correctly, But compiled application didn't present Images. Why? Color resources are presented. Images only.
Can I use image resources from embed frameworks?
As of Xcode 12.1, I do not believe there is a way to do this.
The reason is that when you configure an images using storyboards Xcode defaults to assuming those images are located in the bundle for the current module, and the Attributes inspector does not provide a way to specify an alternate module, as it does in the case of view controller classes:
View controller attribute inspector with Module property
But in code this is easy to accomplish using the in:Bundle? parameter for initializing a UIImage, which tells the app to look in a specific bundle for the image resource at runtime.
guard
let bundleURL = Bundle.main.url(forResource: "[bundle filename without extension]", withExtension: "bundle"),
let bundle = Bundle(url: bundleURL) else { return }
let image = UIImage.init(named: "[image name]", in: bundle, compatibleWith: nil)
It is likely an oversight on Apple's part to allow Xcode to show image resources from other modules in the image name field, but not properly link them when compiling storyboards. I hope they fix this.
Beware of using color assets from other modules as well:
While they appear to work, it is only because when you assign color assets in a storyboard, Xcode actually encodes the color information from the asset in the storyboard file itself. One sign this is not intended to work is that if you define a Color Set asset with a variation for Dark Appearance, only the Any Appearance color will be used (even in dark mode). Color Set assets in the same module, however, work normally.
Color Set Asset with Any Appearance and Dark Appearance

How can I access UIImage dark appearance pre iOS13

I've just added dark mode to my app.
Asset catalogs support multiple appearances for each asset, on iOS 13 this means the correct asset is used when the system is running in dark or light mode.
These are not my real assets
I'm trying to support dark mode on older iOS versions.
In my attempts to do so, I have added an override to force dark mode which works for my custom colours and theming but not for the images.
Is it possible to access the dark appearance of an image programatically before iOS13?
For iOS12 I have tried using the following:
if #available(iOS 12.0, *) {
let traits = UITraitCollection(userInterfaceStyle: .dark)
let image = UIImage(
named: "Image",
in: bundle,
compatibleWith: traits
)
}
This only returns the normal appearance, and the method naming seems to suggest this only checks that the trait collection I've passed is compatible with the image.
As far as I know, there's no way to do that with just one asset. Below iOS 13 the system will always take the Any appearance. You would need to create two different image sets with different names and choose either one of them.
It is a bit confusing since UIUserInterfaceStyle is available in iOS 12+, but this is likely because macOS got Dark Mode that year.

iOS dark mode - image assets not redrawn

I'm implementing the dark mode for iOS. The problem occurs with the images:
I've opened the Assets.xcassets and changed the "appearances" "to Any, Dark"
Of course I've added the new image.
Unfortunately the images are not being redrawn when overriding the environment interface style in xcode.
I've tried catching the traitCollectionDidChange method in my viewController and it is properly called. I could set the new image (origImage_dark), but shouldn't it be automatic? That's what the asset settings are made for. I'm using the .alwaysOriginal rendering of the image.
Running the app with dynamic resolve of the image helped:
let image = UIImage(named: "someImage")
let asset = image?.imageAsset
let resolvedImage = asset?.image(with: traitCollection)
After this, reverting back to the original way of setting the images seemed to work. Xcode, thanks a lot!

iOS overrides the `navBarButtonColor` when using PNGs

Issue Description
In my application I have a navigation bar search button set up as follows:
static navigatorButtons = {
leftButtons: [
{
id: 'back-nav-button',
icon: require('../assets/images/icons/arrow-left.png')
}
]
};
The button works as intended on both iOS and Android, but the button is blue on iOS. I understand that this is the desired behavior and that the color can be overridden by setting navBarButtonColor, but the problem is that it's a multi-colored button - meaning I want then button to simply contain the PNG image's colors, and not the navBarButtonColor.
I've tried setting navBarButtonColor to null, transparent, but nothing seems to work.
So my question is, is there a way to make navigation bar icons take on the color of the PNG provided, as is the case on Android?
Steps to Reproduce / Code Snippets / Screenshots
Simply run any RNN app on iOS with a simple static navigatorButtons = ... using a local multi-colored PNG and you'll see the colors of the icon get overwritten.
Environment
React Native Navigation version: 1.1.473
React Native version: 0.55.3
Platform(s) (iOS, Android, or both?): iOS
Device info (Simulator/Device? OS version? Debug/Release?): Android Emulator on Debug
On iOS, UIBarButtonItem uses images created with source image's alpha channel. To display the actual image (not an alpha channel mask of it) you need to change your image's rendering mode to alwaysOriginal
Although, looking at React Native Image class documentation I can't see renderingMode property
We've managed to find a workaround for this. By setting the disableIconTint button property to true, it disables the icon color override. See the following example:
static navigatorButtons = {
leftButtons: [
{
id: 'back-nav-button',
icon: require('../assets/images/icons/arrow-left.png'),
disableIconTint: true // Add this line to use the PNG's color
}
]
};

Using svg or font icon in the ios applications

In my iOS application we need to change the color of the icons based on the user configuration. It is one of our important business option.
One of my friend advised me for using .svg or font icon. And shared me this link
They are creating web applications while I am developing iOS application. Does iOS support this technique too? If yes, how can I use it?
Edit
I found SVGKit that is used for the iPhone/iPad apps. Is there any binding library for using it on the monotouch?
SVG fonts (paths) are kind of easy to convert into source code. Once you have this it's very simple to render them in different colours, sizes (iphone/ipad) or resolutions (e.g. retina).
That's what I did here. That's for an older version of FontAwesome, but it could be used as is (or updated to the latest) for your application.
you can use FontAwesome+iOS
all the icons available here: link
If you just need to change color of icons, you probably can solve this without svg. Just use tint colors.
Create a template image:
let templateImage = UIImage(named: "bla_bla")?.withRenderingMode(.alwaysTemplate)
Then add it to a button or an image view and set the tintColor:
button.setImage(templateImage, for: .normal)
button.setImage(templateImage, for: .highlighted)
button.tintColor = UIColor.blue
This solution works only for monochromatic icons!
Besides, if you want .svg, you can use WKWebView, it's really fast and will not cause overhead if you have limited amount of icons.

Resources