Slide 1

Slide 1 text

@S_Shimotori UIColor Cluster ୈ13ճ HAKATA.swift

Slide 2

Slide 2 text

S_Shimotori • Twitter: @S_Shimotori_pub • ண৭৬ਓ • Dark ModeରԠͨ͠ • Objective CϚδͰΘ͔Βͳ͍ • ݟಀͯ͠΄͍͠

Slide 3

Slide 3 text

UIColor Cluster

Slide 4

Slide 4 text

class UIColor • UIKitఏڙͷɺ৭σʔλΛ֨ೲͨ͠ΦϒδΣΫτ • ͨ͘͞ΜΠχγϟϥΠβ͕͋Δ • ϝιου͸ͦΜͳʹͳ͍ • Dark ModeରԠͰΊͬͪΌ͓ੈ࿩ʹͳͬͨɹݟ๞͖ͨʂ

Slide 5

Slide 5 text

var description: String UIColor(white: 1, alpha: 1).description → UIColor(red: 1, green: 1, blue: 1, alpha: 1).description → UIColor(dynamicProvider: { _ in return .white }).description →

Slide 6

Slide 6 text

var description: String UIColor(white: 1, alpha: 1).description → UIExtendedGrayColorSpace 1 1 UIColor(red: 1, green: 1, blue: 1, alpha: 1).description → UIColor(dynamicProvider: { _ in return .white }).description → ↓xcassetsͰͷExtended Gray

Slide 7

Slide 7 text

var description: String UIColor(white: 1, alpha: 1).description → UIExtendedGrayColorSpace 1 1 UIColor(red: 1, green: 1, blue: 1, alpha: 1).description → UIExtendedSRGBColorSpace 1 1 1 1 UIColor(dynamicProvider: { _ in return .white }).description →

Slide 8

Slide 8 text

var description: String UIColor(white: 1, alpha: 1).description → UIExtendedGrayColorSpace 1 1 UIColor(red: 1, green: 1, blue: 1, alpha: 1).description → UIExtendedSRGBColorSpace 1 1 1 1 UIColor(dynamicProvider: { _ in return .white }).description → >

Slide 9

Slide 9 text

?? UIDynamicProviderColor ?? private class͔ͳʁ

Slide 10

Slide 10 text

UIColor૝૾ਤ UIColor UIDynamicProviderColor UIDynamicSystemColor UI??????????Color • init(white:alpha:) • init(red:green:blue:alpha) • systemBackground • label • init(dynamicProvider:) ※ਖ਼֬Ͱ͸ͳ͍ var description: StringͳͲ͸֤ࣗઃఆ͢Δʂ

Slide 11

Slide 11 text

Class Cluster ͔ͳʁ

Slide 12

Slide 12 text

Class Clusterͬͯͳʹ • Foundation framework͕ଟ༻͢ΔσβΠϯύλʔϯɺΒ͍͠ • Abstract FactoryσβΠϯύλʔϯͷ೿ੜ • ෳ਺ͷprivateͳsub classΛɺந৅త͕ͩpublicͳsuper classͷԼʹ഑ஔ • ػೳͷॆ࣮۩߹͸ͦͷ··ʹɺpublicʹͳ͍ͬͯΔॴ͚ͩʹूதͰ͖Δ • super class͸ɺsub classͷΠϯελϯεΛ࡞੒͢ΔϝιουΛ࣋ͭ

Slide 13

Slide 13 text

Class ClusterͷྫʁɿNSNumber NSNumber long long int long int char short int int float double NSNumber͸ɺ֤sub classͷΦϒδΣΫτΛ࡞੒͢ΔͨΊͷϝιουΛ࣋ͭʁ • numberWithChar: • numberWithInt: • ͳͲͳͲʁ

Slide 14

Slide 14 text

ΦʔϓϯιʔεNSNumber͸ʁ • ཪ͸CFNumber • “An object wrapper for primitive scalar numeric values.” • CFNumberCreateͰ୯७ʹbitͱछผΛهԱ͍ͯ͠Δ͚ͩͬΆ͍ʁ • Class ClusterͰ͸ͳͦ͞͏……

Slide 15

Slide 15 text

Class ClusterͷྫʁɿNSArray • ෳ਺ͷsuper class͔Βߏ੒͞Ε͍ͯͯ΋OKͱͷ͜ͱ NSArray NSMutableArray ʁʁʁ privateͳԿ͔ʁ

Slide 16

Slide 16 text

ΦʔϓϯιʔεNSArray͸ʁ • internal var _storage = [AnyObject]() • open class NSMutableArray : NSArray • ΍ͬͺΓClass ClusterͰ͸ͳͦ͞͏……

Slide 17

Slide 17 text

Class ClusterͷσϝϦοτ • sub classΛ௥Ճ͢Δͷ͕໘౗ • FoundationͰClass ClusterΛ࠾༻͍ͯ͠Δ΋ͷ͸ɺsub classΛ࡞Δ༻ࣄ͕ ͋·Γͳͦ͞͏ͳ΋ͷ ௥Ճ͕ΊΜͲ͍͘͞

Slide 18

Slide 18 text

UIColorͷ sub class࡞੒ʹ௅ઓ͢Δ

Slide 19

Slide 19 text

UIColor͕෺଍Γͳ͍ͱࢥͬͨΒ • Ҋ1ɿ͍ͭ΋௨ΓUIColorΛܧঝ͢Δ • Ҋ2ɿUIColorΛϥοϓ͢ΔclassΛ࡞ͬͯޡຐԽ͢ • private var innerColor: UIColor ͳײ͡ͰͲ͏Ͱ͠ΐ͏ • Ҋ3ɿextensionͰϝιουΛੜ΍͢

Slide 20

Slide 20 text

UIColorͷsub class͕ඞཁͳͱ͖ • ৭ۭؒͷछྨ΍৭ͷϞσϧΛ৽͘͠௥Ճ͢Δͱ͖ • UIColor͕ѻ͍ͬͯͳ͍৭ۭؒΛѻ͑ΔΑ͏ʹͯ͠ΈΔͱ͔……ʁ • dynamic providerͰ৭Λܾఆͯ͠ΈΔͱ͔……ʁ

Slide 21

Slide 21 text

UIColorΛܧঝͯ͠ΈΔ • Class ClusterΛܧঝ͢Δͱ͖ͷ஫ҙ఺ΛकΔʂʂ • super classΛܧঝͯ͠࡞Δ͜ͱ • ඞཁͳϓϩύςΟΛએݴ͢Δ͜ͱ • શͯͷΠχγϟϥΠβΛΦʔόʔϥΠυ͢Δ͜ͱ • શͯͷprimitive methodΛΦʔόʔϥΠυ͢Δ͜ͱ • UIColorΛܧঝ͢Δͱ͖ͷ஫ҙ఺ΛकΔʂʂ • ௥Ճ͢Δϝιου΍ϓϩύςΟ͸ɺεϨουηʔϑͰͳ͚Ε͹ͳΒͳ͍

Slide 22

Slide 22 text

primitive methodͱ͸ • ͦͷclassͷΠϯλʔϑΣʔεͷجૅΛ͔ͨͪ࡞Δ΋ͷ • NSArrayͰ͍͏ͳΒcountͱobjectAtIndex • UIColorͰ͍͏ͳΒͲΕ͔ͳ……ʁ • ৭ۭؒͱίϯϙʔωϯτ஋͕ఆ·Βͳ͍ͱࠔΓͦ͏

Slide 23

Slide 23 text

ୈ1஄ɿ
 ಠࣗͷ৭ۭؒΛαϙʔτ

Slide 24

Slide 24 text

ಠࣗͷ৭ۭؒΛαϙʔτ͍ͨ͠ • ಠࣗͷ৭ۭؒΛαϙʔτ͢ΔͨΊͷsub classΛ࡞Δͧʂ • RGBʢίϯϙʔωϯτ3+1ݸʣ͸ΊΜͲ͍͘͞ͷͰɺGrayʢ1+1ݸʣͰ௅ઓ • UIColor(myWhite: CGFloat, alpha: CGFloat)ͳײ͡ͰͰ͖Ε͹࠷ߴ

Slide 25

Slide 25 text

UIColorʹඞཁͳύϥϝʔλΛ౉͢ • UIColorࣗମʹ͸ɺ৭ۭؒ΍ίϯϙʔωϯτ஋ΛهԱͤ͞Δखஈ͕ͳ͍ • 1൪؆୯ͳͷ͸init(cgColor:)ͰCGColorΛ౉ͯ͠͠·͏΍Γํ • CGColorͷΠχγϟϥΠβͳΒ৭ۭؒΛࢦఆՄೳ ↓Πϝʔδ͸͜Μͳײ͡↓ init(myWhite: CGFloat, alpha: CGFloat) {
 super.init(cgColor: CGColor(
 colorSpace: // ここに色空間
 components: // ここにコンポーネント値
 ))!
 }

Slide 26

Slide 26 text

ΠχγϟϥΠβʹ৮Εͳ͍໰୊ • UIColorͷrequired initΛΦʔόʔϥΠυ͠ͳ͚Ε͹ͳΒͳ͍ • UIColorͷrequired initΛΦʔόʔϥΠυͰ͖ͳ͍ʢmethod dispatchͷ౎߹ʣ Overriding non-@objc declarations from extensions is not supported @nonobjc required convenience init( _colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float ) Objective CͳΒͳΜͱ͔ɻ

Slide 27

Slide 27 text

ิ଍ɿmethod dispatch • ͲͷϝιουΛݺͼग़͔͢Λܾఆ͢Δ࢓૊Έͷ͜ͱ • static dispatchʢίϯύΠϧ࣌ʹܾఆʣ • struct΍enum΍finalͱ͍ͬͨΦʔόʔϥΠυෆՄͳ΋ͷ͕ͬͪ͜ • extensionͰ௥Ճͨ͠ϝιου΋ͬͪ͜ • dynamic dispatchʢίϯύΠϧ࣌ʹtable࡞੒ɺ࣮ߦ࣌ʹܾఆʣ • ΦʔόʔϥΠυՄೳͳ΋ͷ͸ͬͪ͜ • extensionͰޙ෇͚ͨ͠ϝιου͸tableʹೖΕͯ΋Β͑ͳ͍ આ໌ؒҧͬͯͨΒ͝ΊΜͳ͍͞ʂ

Slide 28

Slide 28 text

SwiftͰ࣮૷ͯ͠Έͨ(1/2) private class MyCustomColor: UIColor {
 private static let whitePoint: [CGFloat] = [76.04, 80, 87.12]
 private static let blackPoint: [CGFloat] = [0.1901, 0.2, 0.2178] static func create(
 gamma1_5Gray gray: CGFloat, alpha: CGFloat
 ) -> MyCustomColor { // 色空間を新しく定義
 let colorSpace = CGColorSpace(
 calibratedGrayWhitePoint: whitePoint,
 blackPoint: blackPoint,
 gamma: 1.5 // ←この値をカスタムしてみた
 )!
 // 色空間とコンポーネント値を設定
 let cgColor = CGColor(
 colorSpace: colorSpace,
 components: [gamma1_5Gray, alpha]
 )!
 // initしたつもり……
 return MyCustomColor(cgColor: cgColor) }
 }

Slide 29

Slide 29 text

SwiftͰ࣮૷ͯ͠Έͨ(2/2) extension UIColor {
 // publicなイニシャライザのつもり
 static func create(
 gamma1_5Gray gray: CGFloat, alpha: CGFloat
 ) -> UIColor {
 return MyCustomColor.create(gamma1_5Gray: gray, alpha: alpha)
 }
 } // ガンマ値2.2のいつもの白
 let gamma2_2Color = UIColor(white: 1, alpha: 1)
 // ガンマ値1.5の白
 let gamma1_5Color = UIColor.create(gamma1_5Gray: 1, alpha: 1)

Slide 30

Slide 30 text

SwiftͰ࣮ߦͯ͠Έͨ • white = 0.0, 0.1, …, 0.9, 1.0ͷ৭Λฒ΂ͨ • ࠨྻɿΨϯϚ2.2ʢ͍ͭ΋ͷʣ • ӈྻɿΨϯϚ1.5ʢMyCustomColorʣ White: 0.0 → White: 1.0 → White: 0.5→

Slide 31

Slide 31 text

ୈ2஄ɿ UIDynamicProviderColorΛύΫΔ

Slide 32

Slide 32 text

৽͍͠Ϟσϧͬͯ΍ͭΛ࡞Γ͍ͨ • ಈతʹ৭Λܾఆ͢Δɺશ͘৽͍͠ϞσϧͷUIColorΛ࡞Δͧʂ • UIDynamicProviderColorͱಉ͡΋ͷΛ࡞Δ͜ͱʹ௅ઓ • init(myDynamicProvider:)ͳײ͡Ͱ • ࠓճ͸ObjCͰؤுΔʢมͳॻ͖ํͯͨ͠ΒεϛϚηϯʣ ↓Πϝʔδ͸͜Μͳײ͡↓ self = [super init];
 if (self) {
 _myDynamicProvider = myDynamicProvider;
 }
 return self;

Slide 33

Slide 33 text

ຊདྷඞਢͳ৘ใΛൈ͖ʹ࡞͍ͬͯ͘ • طଘΠχγϟϥΠβ΁৭ۭؒ&ίϯϙʔωϯτ஋Λ౉ͣ͞ʹܧঝ͢ΔͳΒɺ
 UIColorͷϓϩύςΟ΍ϝιουΛશͯਖ਼͘͠ΦʔόʔϥΠυ͢Δඞཁ͕͋Δ • ઌ΄Ͳͷ[super init]͚ͩͰ͸ΫϥογϡͷݪҼʹͳΔ • UIColorͷϝιου͚ͩͰͳ͘isEqual:ͷΦʔόʔϥΠυ΋๨Εͣʹ • ৭ͷ౳஋൑ఆॲཧ΋͜ΕΒͷ৘ใʹґଘ͍ͯ͠ΔͨΊ *** -CGColor not defined for the UIColor <ུ>; need to first convert colorspace.

Slide 34

Slide 34 text

Objective CͰ࣮૷ͯ͠Έͨ(1/3) Ұ෦ൈਮ @implementation MyDynamicColor: UIColor - (instancetype _Nonnull)initWithMyDynamicProvider:(UIColor * _Nonnull (^ _Nonnull)(UITraitCollection * _Nonnull traitCollection))myDynamicProvider {
 self = [super init];
 if (self) {
 _myDynamicProvider = myDynamicProvider;
 }
 return self;
 } - (CGColorRef)CGColor {
 return _myDynamicProvider(UITraitCollection.currentTraitCollection).CGColor;
 } // その他のメソッドもオーバーライド @end

Slide 35

Slide 35 text

Objective CͰ࣮૷ͯ͠Έͨ(2/3) Ұ෦ @implementation UIColor(MyColor) + (UIColor * _Nonnull)initWithMyDynamicProvider:(UIColor * _Nonnull (^ _Nonnull)(UITraitCollection * _Nonnull traitCollection))myDynamicProvider { return [[MyDynamicColor alloc] initWithMyDynamicProvider:myDynamicProvider]; } @end

Slide 36

Slide 36 text

Objective CͰ࣮ߦͯ͠Έͨ • Dark Modeʹͯ͠΋৭͕มΘΒͳ͍ɻɻɻ UIColor(myDynamicProvider: {
 $0.userInterfaceStyle == .dark ? .red : .blue
 })

Slide 37

Slide 37 text

Objective CͰ࣮૷ͯ͠Έͨ(3/3) • _isDynamicΛΦʔόʔϥΠυͯ͠ਅʹ͠ͳ͍ͱมԽ͠ͳ͍ • privateͳϓϩύςΟͳΜͰ͚͢Ͳ…… - (BOOL)_isDynamic { return YES; }

Slide 38

Slide 38 text

·ͱΊ

Slide 39

Slide 39 text

Θ͔ͬͨ͜ͱ • Foundation΍UIKitʹ͸ɺClass Clusterͱ͍͏σβΠϯύλʔϯʹଇͬͨΫϥε ͕ଘࡏ͍ͯ͠Δʢ͔΋͠Εͳ͍) • Swiftʹ͸ԑ͕ͳ͍΋ͷ͔΋ɻɻ • Ͳ͏ͯ͠΋sub classΛ࡞Βͳ͚Ε͹͍͚ͳ͍࣌͸৻ॏʹ • UIColorͷsub classΛ࡞Δͷ͸େม • SwiftͰ΍Δͷ͸͞Βʹແཧ͕͋Δ • ৭ۭؒͷઃఆ஋Λ͍͡Δ͘Β͍͕ݶ౓ʁ • ΍Ί͓͍ͯͨ΄͏͕͍͍ͱࢥ͍·͢

Slide 40

Slide 40 text

ങͬͯ΄͍͠ • Dark ModeରԠ͠Α͏ʂ • s-shimotori.booth.pm

Slide 41

Slide 41 text

ࢀߟจݙͱ͔ • https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/ ClassClusters/ClassClusters.html • https://developer.apple.com/library/archive/documentation/General/Conceptual/DevPedia-CocoaCore/ ClassCluster.html • https://developer.apple.com/documentation/uikit/uicolor • http://www.color.org/sRGB.pdf • https://github.com/apple/swift-corelibs-foundation/blob/cfac32b92d5fb62a651967cf22756352179b58ba/ CoreFoundation/NumberDate.subproj/CFNumber.c • https://qiita.com/HaNoHito/items/f40bfc1717c1e922a5b0 • https://stackoverflow.com/questions/55364212/overriding-non-objc-declarations-from-extensions-is-not- supported • https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001922.html • https://github.com/xybp888/iOS-Header/blob/master/13.0/PrivateFrameworks/UIKitCore.framework/UIColor.h