Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Александр Зимин

Александр Зимин
Uberchord Engineering
Интерфейс по кусочкам: эффективное взаимодействие между iOS разработчиком и дизайнером

  • Als Erste(r) kommentieren

  • Gehören Sie zu den Ersten, denen das gefällt!

Александр Зимин

  1. 1. Интерфейс по кусочкам Зимин Александр
  2. 2. iOS Developer UI Engineer CocoaHeads Russia macOS Developer Co-Founder Организатор Маркетинг, Дизайн, Аналитика, …
  3. 3. VIPER Swift RxFastline Promises MVVM Protocol-Oriented Programming Realm
  4. 4. План • Проблемы
  5. 5. План • Проблемы • Цвета и шрифты Дизайнер Разработчик
  6. 6. План • Проблемы • Цвета и шрифты • Передача ассетов
  7. 7. План • Проблемы • Цвета и шрифты • Передача ассетов • Свизлинг для дизайна
  8. 8. План • Проблемы • Цвета и шрифты • Передача ассетов • Свизлинг для дизайна • Планы на будущее
  9. 9. Проблемы
  10. 10. • Дизайн: • Может поменяться • Много рутины • Не вызывает runtime или compile ошибки
  11. 11. Цвета
  12. 12. 7F98BB 7F98BB 7F98BB 3870BE 3870BE 3870BE &%*k? &%*k?
  13. 13. extension UIColor { static var appBlue: UIColor { return UIColor(hexString: "7F98BB") } }
  14. 14. extension UIColor { static var mainColor: UIColor { return UIColor(hexString: "7F98BB") } }
  15. 15. &%*k?
  16. 16. extension UIColor { enum ColorType: String { case gray = "8C8C8C" case darkGray = "6C6C6C" } convenience init(_ colorType: ColorType) { self.init(hexString: colorType.rawValue) } }
  17. 17. extension UIColor { enum ComponentType { case navigationBar case separator var colorType: ColorType { switch self { case .navigationBar: return .gray case .separator: return .darkGray } } } convenience init(componentType: ComponentType) { self.init(componentType.colorType) } }
  18. 18. extension UIColor { enum ComponentType { case navigationBar case separator var colorType: ColorType { switch self { case .navigationBar: return .gray case .separator: return .darkGray } } } convenience init(componentType: ComponentType) { self.init(componentType.colorType) } } Не может содержать HEX строк!
  19. 19. let grayColor = UIColor(.gray) let separatorColor = UIColor(componentType: .separator)
  20. 20. Шрифты
  21. 21. extension UIFont { enum FontType { case gothamProMedium(size: CGFloat) case gothamPro(size: CGFloat) } convenience init(_ fontType: FontType) { switch fontType { case let .gothamProMedium(size): self.init(name: "GothamPro-Medium", size: size)! case let .gothamPro(size): self.init(name: "GothamPro", size: size)! } } }
  22. 22. https://github.com/krzysztofzablocki/Sourcery
  23. 23. Передача ассетов
  24. 24. x3 Labels Switcher States Label Button
  25. 25. http://utom.design/measure/
  26. 26. https://zeplin.io
  27. 27. https://zeplin.io
  28. 28. Свизлинг
  29. 29. viewDidLoad customViewDidLoad
  30. 30. viewDidLoad customViewDidLoad • При вызове viewDidLoad вызывается customViewDidLoad • При вызове customViewDidLoad вызывается viewDidLoad
  31. 31. private var swizzleTextValue: Void = { swizzleMethods(objectClass: UILabel.self, originalSelector: #selector(setter: UILabel.text), swizzledSelector: #selector(UILabel.setStaticText(_:))) }() extension UILabel { open override class func initialize() { _ = swizzleTextValue } @objc fileprivate func setStaticText(_ text: String?) { setStaticText(text) // You actions } }
  32. 32. private var swizzleTextValue: Void = { swizzleMethods(objectClass: UILabel.self, originalSelector: #selector(setter: UILabel.text), swizzledSelector: #selector(UILabel.setStaticText(_:))) }() extension UILabel { open override class func initialize() { _ = swizzleTextValue } @objc fileprivate func setStaticText(_ text: String?) { setStaticText(text) // You actions } }
  33. 33. private var swizzleTextValue: Void = { swizzleMethods(objectClass: UILabel.self, originalSelector: #selector(setter: UILabel.text), swizzledSelector: #selector(UILabel.setStaticText(_:))) }() extension UILabel { open override class func initialize() { _ = swizzleTextValue } @objc fileprivate func setStaticText(_ text: String?) { setStaticText(text) // You actions } } Плохо!
  34. 34. extension UILabel { static func swizzleText() { _ = swizzleTextValue } @objc fileprivate func setStaticText(_ text: String?) { setStaticText(text) // You actions } }
  35. 35. extension UILabel { static func swizzleText() { _ = swizzleTextValue } // ... } • Вызывать swizzleText(): • Где нибудь в AppDelegate или его проксировании • Вызывать в load() у UILabel в Obj-c
  36. 36. Свизлинг
  37. 37. Это безопасно?
  38. 38. Это быстро?
  39. 39. let value = clock() for i in 0..<1000000 { cell.textLabel?.text = "(i)" } let result = Double(clock() - value) print(result)
  40. 40. До свизлинга Плосле свизлинга 2463609.0 2665523.0 2238332.0 2565639.0 2240086.0 2560924.0 2278225.0 2579298.0 2247269.0 2561646.0 2246613.0 2563499.0 2228041.0 2571111.0 15%
  41. 41. Локализация
  42. 42. private var swizzleTextValue: Void = { swizzleMethods(objectClass: UILabel.self, originalSelector: #selector(setter: UILabel.text), swizzledSelector: #selector(UILabel.setLocalizedText(_:))) }()
  43. 43. extension UILabel { static func swizzleText() { _ = swizzleTextValue } @objc fileprivate func setLocalizedText(_ text: String?) { if let text = text, !isInsideButton { setLocalizedText(text.tripleLengthPseudolanguage) } else { setLocalizedText(text) } } private var isInsideButton: Bool { let superview = self.superview return superview is UIButton } }
  44. 44. Керн
  45. 45. @implementation UINavigationItem (AZTitleConfiguration) + (void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ SwizzleInstanceMethod(self, @selector(setTitle:), @selector(az_setTitleWithConfiguration:)); }); } @end
  46. 46. // We setup view with our own label, because we want to use kern spacing and other appearance staf - (void)az_setTitleWithConfiguration:(NSString *)title { if (title == nil) { title = @""; } [self az_setTitleWithConfiguration:[title uppercaseString]]; NSDictionary *attributes = [[UINavigationBar appearance] titleTextAttributes]; NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:[title uppercaseString] attributes:attributes]; // … fill self.titleView if already UILabel UILabel *titleLabel = [UILabel new]; titleLabel.attributedText = attributedString; [titleLabel sizeToFit]; self.titleView = titleLabel; }
  47. 47. // We setup view with our own label, because we want to use kern spacing and other appearance staf - (void)az_setTitleWithConfiguration:(NSString *)title { if (title == nil) { title = @""; } [self az_setTitleWithConfiguration:[title uppercaseString]]; NSDictionary *attributes = [[UINavigationBar appearance] titleTextAttributes]; NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:[title uppercaseString] attributes:attributes]; // … fill self.titleView if already UILabel UILabel *titleLabel = [UILabel new]; titleLabel.attributedText = attributedString; [titleLabel sizeToFit]; self.titleView = titleLabel; }
  48. 48. // We setup view with our own label, because we want to use kern spacing and other appearance staf - (void)az_setTitleWithConfiguration:(NSString *)title { if (title == nil) { title = @""; } [self az_setTitleWithConfiguration:[title uppercaseString]]; NSDictionary *attributes = [[UINavigationBar appearance] titleTextAttributes]; NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:[title uppercaseString] attributes:attributes]; // … fill self.titleView if already UILabel UILabel *titleLabel = [UILabel new]; titleLabel.attributedText = attributedString; [titleLabel sizeToFit]; self.titleView = titleLabel; }
  49. 49. // We setup view with our own label, because we want to use kern spacing and other appearance staf - (void)az_setTitleWithConfiguration:(NSString *)title { if (title == nil) { title = @""; } [self az_setTitleWithConfiguration:[title uppercaseString]]; NSDictionary *attributes = [[UINavigationBar appearance] titleTextAttributes]; NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:[title uppercaseString] attributes:attributes]; // … fill self.titleView if already UILabel UILabel *titleLabel = [UILabel new]; titleLabel.attributedText = attributedString; [titleLabel sizeToFit]; self.titleView = titleLabel; } if ([self.titleView isKindOfClass:[UILabel class]]) { UILabel *label = (UILabel*)self.titleView; label.attributedText = attributedString; return; }
  50. 50. Лейаут
  51. 51. @interface NSLayoutConstraint (UCConstraintBuild) @property (nonatomic, assign) IBInspectable CGFloat screenWidthPercent; @property (nonatomic, assign) IBInspectable CGFloat screenHeightPercent; @end
  52. 52. @implementation NSLayoutConstraint (UCConstraintBuild) - (void)setScreenWidthPercent:(CGFloat)screenWidthPercent { self.constant = round([self screenBounds].size.width * screenWidthPercent); } - (CGFloat)screenWidthPercent { return (self.constant / [self screenBounds].size.width); } @end
  53. 53. Планы на будущее
  54. 54. https://github.com/krzyzanowskim/Natalie
  55. 55. https://github.com/SwiftGen/SwiftGen
  56. 56. { "colors": [ { "name": "lightWhite", "color": "F5F5F5" } ], "fonts": [ { "name": "bold", "fontName": "ProximaNova-Extrabld" } ] }
  57. 57. "code_templates": { "font": "UIFont(.$name, size: $size)", "textColor": "UIColor(.$)", "backgroundColor": "UIColor(.$)" }
  58. 58. "styles": { "text.default": { "font.size": 20, "font.name": "SFUIText-Light", "textColor": "red" }, "text.title": { "parents": ["text.default"], "font.name": "bold", "textColor": "$themeColor" } }
  59. 59. extension UILabel: Stylable { func apply(style: Style) { // ... } } label.apply(style: Styles.Text.Title)
  60. 60. One more thing
  61. 61. @objc protocol Foo { init() } final class Bar: Foo { init() {} deinit { print("destroying") } } let x: Foo.Type = Bar.self _ = x.init()
  62. 62. @objc protocol Foo { init() } final class Bar: Foo { init() {} deinit { print("destroying") } } let x: Foo.Type = Bar.self _ = x.init()
  63. 63. protocol Foo { init() } final class Bar: Foo { init() {} deinit { print("destroying") } } let x: Foo.Type = Bar.self _ = x.init()
  64. 64. https://bugs.swift.org/browse/SR-3935
  65. 65. Спасибо за внимание! Зимин Александр azimin@me.com @ZiminAlex

    Als Erste(r) kommentieren

    Loggen Sie sich ein, um Kommentare anzuzeigen.

Александр Зимин Uberchord Engineering Интерфейс по кусочкам: эффективное взаимодействие между iOS разработчиком и дизайнером

Aufrufe

Aufrufe insgesamt

309

Auf Slideshare

0

Aus Einbettungen

0

Anzahl der Einbettungen

83

Befehle

Downloads

3

Geteilt

0

Kommentare

0

Likes

0

×