CodeFest 2019. Антон Спивак (ВКонтакте) — iOS. Переход на тёмную сторону

16b6c87229eaf58768d25ed7b2bbbf52?s=47 CodeFest
April 06, 2019

CodeFest 2019. Антон Спивак (ВКонтакте) — iOS. Переход на тёмную сторону

У нас было три сотни экранов, страх все сломать, монструозный UIKit, огромная куча старого кода и жгучее желание сделать тёмную тему.

Этот рассказ будет о том, как подружить свою архитектуру с дизайнерами и JS-разработчиками, добавить цветовые схемы, не прогореть по производительности и в итоге, зауважать создателей UIKit.

16b6c87229eaf58768d25ed7b2bbbf52?s=128

CodeFest

April 06, 2019
Tweet

Transcript

  1. 9.

    RGB

  2. 10.

    HUE

  3. 11.

    Автоподбор HUEColor ls = [leftColor HSV]; HUEColor rs = [rightColor

    HSV]; CGFloat dh = fmin(fabs(ls.hue - rs.hue), 360.0f - fabs(ls.hue - rs.hue)) / 180.0f; CGFloat ds = fabs(ls.saturation - rs.saturation); CGFloat dv = fabs(ls.brightness - rs.brightness) / 255.0f; CGFloat distance = sqrtf((dh * dh) + (ds * ds) + (dv * dv));
  4. 15.

    Условия Максимально простое решение Минимум изменений в текущем коде Работа

    с CoreGraphics (CALayer’s and etc.) Работа с TextKit, CoreText (NSAttributedString) Работа с UIKit VKUI (VK Apps, VK Connect) Android (а вдруг?)
  5. 16.

    Ух, что сейчас будет • Быстро подберем формат • Подумаем

    над хранением • Определимся с архитектурой (VIPER) • Чуть-чуть покодим
  6. 22.

    Colors.h @interface UIColor (Palette) @property (nonatomic, readonly, strong, class) UIColor

    *azure300; @end @interface Color (Scheme) @property (nonatomic, readonly, strong, class) Color *accent; @end
  7. 25.

    Библиотеки https://github.com/regexident/Gestalt 
 (много кода, нет поддержки NSAttributedString) https://github.com/draveness/DKNightVersion 


    (много кода, нет поддержки NSAttributedString) И вообще их нужно поддерживать, в топку такое
  8. 27.

    CoreGraphics int CGColorCreate(int space, int components) { rax = (*_CGColorCreate_ptr)(space,

    components); return rax; } void CGContextSetFillColorWithColor(CGContextRef, CGColorRef)
  9. 28.

    UIKit @interface UIDeviceRGBColor : UIColor { double alphaComponent double blueComponent

    double greenComponent double redComponent } @interface UIDeviceWhiteColor : UIColor { double alphaComponent double whiteComponent }
  10. 31.

    NSProxy - (void)forwardInvocation:(NSInvocation *)aInvocation { [aInvocation invokeWithTarget:[self _keyedColor]]; } -

    (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector { return [[self _keyedColor] methodSignatureForSelector:aSelector]; }
  11. 32.

    NSProxy - (UIColor *)_keyedColor { UIColor *color = [self.colors valueForKey:[Appearance

    appearance].palette.name]; // Here we need to cache CGColor for system usage [color CGColor]; return color; }
  12. 35.
  13. 37.

    Независимая палитра! @interface Appearance : NSObject <Painter> @property (nonatomic, strong,

    nullable) Palette *palette; @end @interface UIResponder (Painter) <Painter> @property (nonatomic, strong, nullable) Palette *palette; @end
  14. 39.

    И обновим хитрый цвет - (UIColor *)_keyedColor { UIColor *color

    = [self.colors valueForKey:[self _painter].palette.name]; // Here we need to cache CGColor for system usage [color CGColor]; return color; }
  15. 41.
  16. 42.

    Цвета с сервера? - (instancetype)overridedValues:(NSDictionary<NSString *, UIColor *> *)v {

    NSMutableDictionary *currentColors = [self.colors mutableCopy]; [v enumerateKeysAndObjectsUsingBlock:^(NSString *k, UIColor *o, BOOL *stop) { [currentColors setObject:o forKey:k]; }]; return [[Color alloc] initWithIdentifier:[self.identifier copy] colors:[currentColors copy] alpha:self.alpha painter:self.painter]; }
  17. 44.
  18. 45.

    Другое значение alpha? - (UIColor *)colorWithAlphaComponent:(CGFloat)alpha { Color *color =

    [[Color alloc] initWithIdentifier:[self.identifier copy] colors:[self.colors copy] alpha:alpha painter:self.painter]; return (id)color; }
  19. 46.

    KPACUBO - (UIColor *)_keyedColor { UIColor *color = [self.colors valueForKey:[self

    _painter].palette.name]; color = self.alpha < 1.0 ? [color colorWithAlphaComponent:self.alpha] : color; // Here we need to cache CGColor for system usage [color CGColor]; return color; }
  20. 48.
  21. 49.

    DEBUG void UpdateSchemeColor(SEL selector, UIColor *c, NSString *paletteName) { Color

    *color = (Color *)[Color performSelector:selector]; NSMutableDictionary *colors = [[color colors] mutableCopy]; [colors setValue:color forKey:paletteName]; [color updateColorsWithDictionary:[colors copy]]; }
  22. 51.
  23. 53.

    Ну почти :D • -[UIView backgroundColor] - вычислимое свойство •

    -[UIView tintColor] - нужно дернуть tintColorDidChange • -[UILabel attributedText] - нужно немного зафорсить • И другие небольшие особенности UIKit’а • Дизассемблируй это - https://hopperapp.com