Why not login to Qiita and try out its useful features?

We'll deliver articles that match you.

You can read useful information later.

9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SwiftUIとUIKitが共存するアプリにおける色指定の注意点 (sRGB vs Generic RBG)

Last updated at Posted at 2019-10-12

モチベーション

UIKitを併用していて、Color.gray と、 UIColor.gray で指定した部分で色が異なることに気づきました。
SwiftUIでは、色は、 Color UIKitでは、 UIColor と別の型である。

コンソールにprint文出力して確認してもやはり値が異なる。

Gray
Color 0x600002ea6b20
UIColor 0x6000030b1170

そもそも何故、SwiftUIだけではなく、UIKitを併用しないといけなかった理由は後半に書きます。

ColorのデフォルトはsRGB

Colorの宣言部分をみるとデフォルト引数が sRGBになっていることがわかる。

extension Color {

    public enum RGBColorSpace {

        case sRGB

        case sRGBLinear

        case displayP3

        ...
        
        public init(_ colorSpace: Color.RGBColorSpace = .sRGB, red: Double, green: Double, blue: Double, opacity: Double = 1)

    }
}

SwiftUIの色のデフォルトは sRGB指定である。そしてUIColorで指定できる、Generic RGBが選択肢にない。

UIColorで使い方によってRGBの種類が異なるのか?

使用方法 デフォルト
コード sRGB label.backgroundColor = UIColor(red: 245/255.0, green: 84/255.0, blue: 45/255.0, alpha: 1.0)
Color Literal sRGB スクリーンショット 2019-10-12 10.17.00.png
AssetCatalogのColorSet sRGB スクリーンショット 2019-10-12 10.19.53.png

すべて、sRGBがデフォルトであることがわかる。

Appleの公式を読むと
https://developer.apple.com/documentation/uikit/uicolor

For apps linked against the iOS 9 SDK and earlier, or running on iOS 9 and earlier, 
colors use one of two color spaces:

- Device-Dependent Gray

- Device-Dependent RGB

UIColor.gray は iOS9以前から存在したからこれを Generic RGBから sRGBに 色合いを変えることはできなくて取り残されていると考えられる。

みんな大好き16進数色指定extension

今回のようにデフォルトの gray を使用せずに、 個々で色を指定すると思うが、 せっかくなので、 16進数指定できるものを用意した。 Apple 的には Dark Mode対応のため、AssetCatalog で色指定してほしいのかな?なので使いみちはないかもしれないが一応書いておく。

// MARK: - Helper

extension UIColor {
    convenience init(hex: Int, alpha: CGFloat = 1) {
        let components = (
            R: CGFloat((hex >> 16) & 0xff) / 255,
            G: CGFloat((hex >> 08) & 0xff) / 255,
            B: CGFloat((hex >> 00) & 0xff) / 255
        )
        self.init(red: components.R, green: components.G, blue: components.B, alpha: alpha)
    }
}

extension Color {
    init(hex: Int, alpha: Double = 1) {
        let components = (
            R: Double((hex >> 16) & 0xff) / 255,
            G: Double((hex >> 08) & 0xff) / 255,
            B: Double((hex >> 00) & 0xff) / 255
        )
        self.init(
            .sRGB,
            red: components.R,
            green: components.G,
            blue: components.B,
            opacity: alpha
        )
    }
}

使い方

Color(hex: 0xdddddd)

UIColor(hex: 0xdddddd)

ちょっと補足、
UIColorは32bitも使われる時代に作られたものなので、alphaの引数が Doubleではなく、 CGFloatのエイリアスで32bitか64bitかでFloatなのかDoubleなのかを切り替えているが、Colorからは全面的に64bitなので気持ちよくDoubleに振り切っている。(さすがAppleだ)

    /// The native type used to store the CGFloat, which is Float on
    /// 32-bit architectures and Double on 64-bit architectures.
    public typealias NativeType = Double

iOS 11に別れを告げられた悲しき32bitアプリたち

それとalphaを opacity という単語に変えている。

補足

そもそもなぜアプリ内で UIColorを使おうと思ったかというと
以下の図を見てもらうとわかるように、Listを引っ張った時に、背景が白色で表示されてしまうのを対応するため

initの中で、UITableViewのbackgroundColorを指定するためである。これだけのために、UIKitを指定するのは正直イケていないので、Appleが指定できるIFを用意してくれることを望む(もしSwiftUIで指定する方法をご存じの方がいましたら教えて下さい)

    init() {
        UITableView.appearance().backgroundColor = UIColor(hex: 0xdddddd)
    }

    var body: some View {
       List(consoleLogs, id: \.self) { value in
             Text(value)
                  .lineLimit(Int.max)
                  .fixedSize(horizontal: false, vertical: true)  
             }
       }
    }

まとめ

ほとんどのアプリではGeneric RGBを使わずにsRGBを使っていて、UIColor.gray みたいなデフォルトの色を使うことはないと思うので実害はないだろう。

参考

9
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?