Slide 1

Slide 1 text

"EEEBSLNPEFUPZPVSBQQT QPUBUPUJQT,B[VZB6FPLB!GSPNLL

Slide 2

Slide 2 text

1SPpMF struct Profile { let name = "Kazuya Ueoka" let twitter = "@fromkk" let github = "fromkk" let qiita = "fromkk" let company = "Timers Inc." } • 2

Slide 3

Slide 3 text

%BSLNPEF ❓

Slide 4

Slide 4 text

%BSLNPEF

Slide 5

Slide 5 text

*BEEFEEBSLNPEFGFBUVSFUP# Type

Slide 6

Slide 6 text

)PXUPJNQMFNFOU

Slide 7

Slide 7 text

*GZPVBSFVTJOH3Y4XJGU ZPVDBOJNQMFNFOUFBTJMZ import UIKit import RxSwift import RxCocoa struct ColorSet { static var backgroundColor = BehaviorRelay(value: defaultBackgroundColor) static var theme = BehaviorRelay(value: defaultThemeColor) } // Bind background color ColorSet.backgroundColor.bind(to: view.rx.backgroundColor).disposed(by: disposeBag)
 
 // Change background color ColorSet.backgroundColor.accept(backgroundColorDark)

Slide 8

Slide 8 text

#VU

Slide 9

Slide 9 text

# Type isn’t using RxSwift

Slide 10

Slide 10 text

*USJFEJNQMFNFOUXJUI1VSF4XJGU

Slide 11

Slide 11 text

TU$SFBUFPCTFSWBUJPO import Foundation public class ColorObservation: Equatable { private let observation: NSObjectProtocol weak var notificationCenter: NotificationCenter? init(_ observation: NSObjectProtocol, notificationCenter: NotificationCenter) { self.observation = observation self.notificationCenter = notificationCenter } public func unregister() { notificationCenter?.removeObserver(observation) } public func append(to observationBag: ColorObservationBag) { observationBag.add(self) } public static func == (lhs: ColorObservation, rhs: ColorObservation) -> Bool { return lhs.observation.isEqual(rhs.observation) && (lhs.notificationCenter?.isEqual(rhs.notificationCenter) ?? false) } }

Slide 12

Slide 12 text

OE4UPSFPCTFSWBUJPOTUPCBH import Foundation public class ColorObservationBag { var observations: [ColorObservation] = [] public init() {} deinit { observations.forEach { observation in observation.unregister() } observations = [] } public func add(_ observation: ColorObservation) { observations.append(observation) } public func remove(_ observation: ColorObservation) { guard let index = observations.firstIndex(of: observation) else { return } observation.unregister() observations.remove(at: index) } }

Slide 13

Slide 13 text

SE$SFBUF0CTFSWBCMF public class ColorObservable { let didChange: Notification.Name = .init("me.fromkk.ColorSet.didChange") let notificationCenter: NotificationCenter = .init() public private(set) var value: UIColor { didSet { notificationCenter.post(name: didChange, object: value) } } public init(_ value: UIColor) { self.value = value } /// Change color /// /// - Parameter value: Color public func accept(_ value: UIColor) { self.value = value } }

Slide 14

Slide 14 text

UI*NQMFNFOUTTVCTDSJCFBOECJOE extension ColorObservable { public func subscribe(_ callback: @escaping (UIColor) -> Void) -> ColorObservation { callback(value) return ColorObservation( notificationCenter.addObserver(forName: didChange, object: nil, queue: .main, using: { notification in guard let value = notification.object as? UIColor else { return } callback(value) }), notificationCenter: notificationCenter ) } public func bind(to object: O, keyPath: ReferenceWritableKeyPath) -> ColorObservation { return subscribe { [weak object] value in object?[keyPath: keyPath] = value } } public func bind(to object: O, keyPath: ReferenceWritableKeyPath) -> ColorObservation { return subscribe { [weak object] value in object?[keyPath: keyPath] = value } } }

Slide 15

Slide 15 text

'JOJTI

Slide 16

Slide 16 text

)PXUPVTF

Slide 17

Slide 17 text

)PXUPVTF %FpOFZPVSDPMPSTFU

Slide 18

Slide 18 text

)PXUPVTF #JOEDPMPSUPZPVSQSPQFSUZ class ViewController: UIViewController { @IBOutlet var label: UILabel! @IBOutlet var darkmodeSwitch: UISwitch! let observationBag = ColorObservationBag() override func viewDidLoad() { super.viewDidLoad() MyColorSet.backgroundColor.bind(to: view, keyPath: \.backgroundColor).append(to: observationBag) MyColorSet.textColor.bind(to: label, keyPath: \.textColor).append(to: observationBag) MyColorSet.textColor.subscribe { [weak self] color in self?.label.layer.borderColor = color.cgColor }.append(to: observationBag) } @IBAction func darkmodeSwitchDidChanged(_ sender: UISwitch) { if sender.isOn { MyColorSet.replace(DarkColorSet.self) } else { MyColorSet.replace(DefaultColorSet.self) } } }

Slide 19

Slide 19 text

*NBEF$PMPS4FUBT044MJCSBSZ IUUQTHJUIVCDPNGSPNLL$PMPS4FU (JNFNFBTUBS⭐

Slide 20

Slide 20 text

8SBQVQ w *EFWFMPQFETNBMMMJCSBSZPGTQFDJBMJ[FEDPMPSCJOEJOH w -FU`THFUSFBEZUPP⒏DJBMEBSLNPEF(

Slide 21

Slide 21 text

13

Slide 22

Slide 22 text

• αʔόʔαΠυΤϯδχΞ (PHP, Golang, AWS) • AndroidΤϯδχΞ (Kotlin) • iOSΤϯδχΞ (Swift) TimersͰ͸ݱࡏΤϯδχΞશ৬छ࠾༻தʂ
 ৄ͘͠͸”Timers”Ͱݕࡧ

Slide 23

Slide 23 text

5IBOLZPV)