Upgrade to Pro — share decks privately, control downloads, hide ads and more …

How we build our app with minimum 3rd party dep...

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

How we build our app with minimum 3rd party dependencies

bitFlyer Drink Meetup for iOSエンジニア 登壇資料
https://bitflyer.connpass.com/event/100661

Avatar for horimislime

horimislime

October 04, 2018
Tweet

More Decks by horimislime

Other Decks in Programming

Transcript

  1. bitFlyer Wallet • ೔ຊ࠷େͷԾ૝௨՟औҾॴ  CJU'MZFSͷJ04޲͚ΞϓϦ • ೥͔Β։ൃ։࢝ • ίʔυϕʔε͸ສߦ௒

    *1 ௐࠪҕୗઌϚΫϩϛϧʢ2018 ೥ 2 ݄ɺΠϯλʔωοτௐࠪʮԾ૝௨՟ɾ҉߸௨՟औҾ
 αʔϏεʹؔ͢ΔΞϯέʔτʯʣɺBitcoin ೔ຊޠ৘ใαΠτௐ΂ɻ 2016 ೥ 4݄-2018 ೥ 4 ݄ɺࠃ಺औҾॴͷ૯݄ؒग़དྷߴʢݱ෺/ܾࠩۚࡁ/ઌ෺औҾΛؚΉʣ
  2. 1. UITableViewͷѻ͍ʹ͘͞ • ࣌୅͸એݴతUITableView / CollectionViewઓࠃ࣌୅ʁ • RxDataSources Λ࢝ΊɺiOSDCͰ΋࿩୊ʹ •

    ܾఆతͳఆ൪͸·ͩͳ͘ɺͦΕͧΕҰ௕Ұ୹ΞϦ • ѻ͍΍͢͞ͱҾ͖׵͑ʹύϥμΠϜ่յ͕ى͜Δ
  3. ബ͍ϑϨʔϜϫʔΫͷ࣮૷ final class HistoryViewController: UIViewController {
 @IBOutlet private weak var

    tableView: UITableView!
 private var entities = [History]() private let dataSource = TableDataSource() private let entitiesProvider = EntitiesProvider<History>() override func viewDidLoad() { super.viewDidLoad() dataSource.mapper.register("HistoryCell") { (cell: HistoryCell, entity: History) in cell.update(with: entity) } dataSource.provider = entitiesProvider tableView.dataSource = dataSource tableView.delegate = self fetchData() }
  4. ബ͍ϑϨʔϜϫʔΫͷ࣮૷ final class HistoryViewController: UIViewController {
 @IBOutlet private weak var

    tableView: UITableView!
 private var entities = [History]() private let dataSource = TableDataSource() private let entitiesProvider = EntitiesProvider<History>() override func viewDidLoad() { super.viewDidLoad() dataSource.mapper.register("HistoryCell") { (cell: HistoryCell, entity: History) in cell.update(with: entity) } dataSource.provider = entitiesProvider tableView.dataSource = dataSource tableView.delegate = self fetchData() } EntitiesProvider: ίϯςϯπҰཡͷϚωʔδ TableDataSource: UITableViewDataSourceʹ४ڌ
 Provider -> TableView΁ͷڮ౉͠
  5. ബ͍ϑϨʔϜϫʔΫͷ࣮૷ final class HistoryViewController: UIViewController {
 @IBOutlet private weak var

    tableView: UITableView!
 private var entities = [History]() private let dataSource = TableDataSource() private let entitiesProvider = EntitiesProvider<History>() override func viewDidLoad() { super.viewDidLoad() dataSource.mapper.register("HistoryCell") { (cell: HistoryCell, entity: History) in cell.update(with: entity) } dataSource.provider = entitiesProvider tableView.dataSource = dataSource tableView.delegate = self fetchData() } EntitiesProvider: ίϯςϯπҰཡͷϚωʔδ TableDataSource: UITableViewDataSourceʹ४ڌ
 Provider -> TableView΁ͷڮ౉͠
  6. ബ͍ϑϨʔϜϫʔΫͷ࣮૷ final class HistoryViewController: UIViewController {
 @IBOutlet private weak var

    tableView: UITableView!
 private var entities = [History]() private let dataSource = TableDataSource() private let entitiesProvider = EntitiesProvider<History>() override func viewDidLoad() { super.viewDidLoad() dataSource.mapper.register("HistoryCell") { (cell: HistoryCell, entity: History) in cell.update(with: entity) } dataSource.provider = entitiesProvider tableView.dataSource = dataSource tableView.delegate = self fetchData() } reloadData()ͨ͠Βclosure͕ݺ͹ΕΔ (cellForRowAt૬౰)
  7. CellΛ࠶ར༻͠ͳ͍γϯϓϧͳTableView࣮૷ final class InputFormViewController: UIViewController { private lazy var userNameCell:

    TextFieldCell = { ... }() private lazy var preferenceCell: SwitchCell = { ... }()
 private lazy var rows: [UITableViewCell] = { 
 [userNameCell, preferenceCell] }() @IBAction private func doneTapped() { API.send( name: userNameCell.textField.text, preference: preferenceCell.toggle.isOn ) } }
 
 extension InputFormViewController: UITableViewDataSource {
 func tableView(…, cellForRowAt indexPath: IndexPath) -> UITableViewCell { return rows[indexPath.row] } }
  8. CellΛ࠶ར༻͠ͳ͍γϯϓϧͳTableView࣮૷ final class InputFormViewController: UIViewController { private lazy var userNameCell:

    TextFieldCell = { ... }() private lazy var preferenceCell: SwitchCell = { ... }()
 private lazy var rows: [UITableViewCell] = { 
 [userNameCell, preferenceCell] }() @IBAction private func doneTapped() { API.send( name: userNameCell.textField.text, preference: preferenceCell.toggle.isOn ) } }
 
 extension InputFormViewController: UITableViewDataSource {
 func tableView(…, cellForRowAt indexPath: IndexPath) -> UITableViewCell { return rows[indexPath.row] } }
  9. CellΛ࠶ར༻͠ͳ͍γϯϓϧͳTableView࣮૷ final class InputFormViewController: UIViewController { private lazy var userNameCell:

    TextFieldCell = { ... }() private lazy var preferenceCell: SwitchCell = { ... }()
 private lazy var rows: [UITableViewCell] = { 
 [userNameCell, preferenceCell] }() @IBAction private func doneTapped() { API.send( name: userNameCell.textField.text, preference: preferenceCell.toggle.isOn ) } }
 
 extension InputFormViewController: UITableViewDataSource {
 func tableView(…, cellForRowAt indexPath: IndexPath) -> UITableViewCell { return rows[indexPath.row] } }
  10. CellΛ࠶ར༻͠ͳ͍γϯϓϧͳTableView࣮૷ final class InputFormViewController: UIViewController { private lazy var userNameCell:

    TextFieldCell = { ... }() private lazy var preferenceCell: SwitchCell = { ... }()
 private lazy var rows: [UITableViewCell] = { 
 [userNameCell, preferenceCell] }() @IBAction private func doneTapped() { API.send( name: userNameCell.textField.text, preference: preferenceCell.toggle.isOn ) } }
 
 extension InputFormViewController: UITableViewDataSource {
 func tableView(…, cellForRowAt indexPath: IndexPath) -> UITableViewCell { return rows[indexPath.row] } } ֤Form Cell͸໊લͷࢀরΛ͍࣋ͬͯΔ ௚઀UIύʔπ͕͍࣋ͬͯΔσʔλΛݟʹ͍͘
  11. 3. Style΍
 ComponentͷऔΓѻ͍ • 5FYU $PMPSͳͲ޿ൣғʹӨڹ • /4"UUSJCVUFE4USJOH΍ 6*4UPSZCPBSE͕ΠϚΠν •

    ඪ४4%,͕ؤுͬͯ΄͍͠ • 044΋๲େͳ਺ ग़యWTPV[BBXFTPNFJPTUFYU
  12. Color Paletteͷ࣮૷ extension UIColor { private static func bf_blueColor() ->

    UIColor { return UIColor(red: 0.26, green: 0.52, blue: 0.75, alpha: 1.0) } private static func bf_lightBlueColor() -> UIColor { return UIColor(red: 0.16, green: 0.64, blue: 0.89, alpha: 1.0) } …
 static func primaryColor() -> UIColor { return bf_blueColor() } static func secondaryTextColor() -> UIColor { return bf_grayColor() } … }
  13. Color Paletteͷ࣮૷ extension UIColor { private static func bf_blueColor() ->

    UIColor { return UIColor(red: 0.26, green: 0.52, blue: 0.75, alpha: 1.0) } private static func bf_lightBlueColor() -> UIColor { return UIColor(red: 0.16, green: 0.64, blue: 0.89, alpha: 1.0) } …
 static func primaryColor() -> UIColor { return bf_blueColor() } static func secondaryTextColor() -> UIColor { return bf_grayColor() } … }
  14. Color Paletteͷ࣮૷ extension UIColor { private static func bf_blueColor() ->

    UIColor { return UIColor(red: 0.26, green: 0.52, blue: 0.75, alpha: 1.0) } private static func bf_lightBlueColor() -> UIColor { return UIColor(red: 0.16, green: 0.64, blue: 0.89, alpha: 1.0) } …
 static func primaryColor() -> UIColor { return bf_blueColor() } static func secondaryTextColor() -> UIColor { return bf_grayColor() } … } ΞϓϦ಺Ͱ࢖͏৭
  15. Color Paletteͷ࣮૷ extension UIColor { private static func bf_blueColor() ->

    UIColor { return UIColor(red: 0.26, green: 0.52, blue: 0.75, alpha: 1.0) } private static func bf_lightBlueColor() -> UIColor { return UIColor(red: 0.16, green: 0.64, blue: 0.89, alpha: 1.0) } …
 static func primaryColor() -> UIColor { return bf_blueColor() } static func secondaryTextColor() -> UIColor { return bf_grayColor() } … }
  16. Color Paletteͷ࣮૷ extension UIColor { private static func bf_blueColor() ->

    UIColor { return UIColor(red: 0.26, green: 0.52, blue: 0.75, alpha: 1.0) } private static func bf_lightBlueColor() -> UIColor { return UIColor(red: 0.16, green: 0.64, blue: 0.89, alpha: 1.0) } …
 static func primaryColor() -> UIColor { return bf_blueColor() } static func secondaryTextColor() -> UIColor { return bf_grayColor() } … } ίϯςΩετͷఆٛ
  17. Text Stylesͷ࣮૷ class TextStyle { let styleName: String // ελΠϧ໊

    var size: CGFloat // ϑΥϯταΠζ var color: UIColor // จࣈͷ৭ enum Weight { case thin, normal, bold } var weight: Weight // จࣈͷଠ͞ var textAlignment: NSTextAlignment // จࣈἧ͑ var kern: CGFloat // จࣈؒͷڑ཭ enum FontType { case proportional, monospaced, compact, monospacedCompact } var fontType: FontType // ϑΥϯτͷछྨ ...
  18. Text Stylesͷ࣮૷ extension TextStyle { static var body: TextStyle {

    return TextStyle("body", size: 17, color: UIColor.primaryTextColor(), weight: .normal, textAlignment: .left, kern: 0.2) } ... }
  19. Text Stylesͷ࣮૷ extension TextStyle { static var body: TextStyle {

    return TextStyle("body", size: 17, color: UIColor.primaryTextColor(), weight: .normal, textAlignment: .left, kern: 0.2) } ... }
  20. Text Stylesͷ࣮૷ extension TextStyle { static var body: TextStyle {

    return TextStyle("body", size: 17, color: UIColor.primaryTextColor(), weight: .normal, textAlignment: .left, kern: 0.2) } ... }
  21. Text Styleͷద༻ extension NSAttributedString { convenience init(string str: String, style:

    TextStyle, 
 tweak: (_ builder: TextStyle) -> Void) { tweak(style) self.init(string: str, attributes: style.build()) } } message.text = NSAttributedString(string: "Hello!", style: .body) name.text = NSAttributedString(string: "Taro", style: .body) { tweak in tweak.color = UIColor.secondaryTextColor() }
  22. Text Styleͷద༻ extension NSAttributedString { convenience init(string str: String, style:

    TextStyle, 
 tweak: (_ builder: TextStyle) -> Void) { tweak(style) self.init(string: str, attributes: style.build()) } } message.text = NSAttributedString(string: "Hello!", style: .body) name.text = NSAttributedString(string: "Taro", style: .body) { tweak in tweak.color = UIColor.secondaryTextColor() }
  23. Text Styleͷద༻ extension NSAttributedString { convenience init(string str: String, style:

    TextStyle, 
 tweak: (_ builder: TextStyle) -> Void) { tweak(style) self.init(string: str, attributes: style.build()) } } message.text = NSAttributedString(string: "Hello!", style: .body) name.text = NSAttributedString(string: "Taro", style: .body) { tweak in tweak.color = UIColor.secondaryTextColor() }
  24. Text Styleͷద༻ extension NSAttributedString { convenience init(string str: String, style:

    TextStyle, 
 tweak: (_ builder: TextStyle) -> Void) { tweak(style) self.init(string: str, attributes: style.build()) } } message.text = NSAttributedString(string: "Hello!", style: .body) name.text = NSAttributedString(string: "Taro", style: .body) { tweak in tweak.color = UIColor.secondaryTextColor() } Attributes DictionaryΛੜ੒
  25. Text Styleͷద༻ extension NSAttributedString { convenience init(string str: String, style:

    TextStyle, 
 tweak: (_ builder: TextStyle) -> Void) { tweak(style) self.init(string: str, attributes: style.build()) } } message.text = NSAttributedString(string: "Hello!", style: .body) name.text = NSAttributedString(string: "Taro", style: .body) { tweak in tweak.color = UIColor.secondaryTextColor() }
  26. Text Styleͷద༻ extension NSAttributedString { convenience init(string str: String, style:

    TextStyle, 
 tweak: (_ builder: TextStyle) -> Void) { tweak(style) self.init(string: str, attributes: style.build()) } } message.text = NSAttributedString(string: "Hello!", style: .body) name.text = NSAttributedString(string: "Taro", style: .body) { tweak in tweak.color = UIColor.secondaryTextColor() } .bodyʹclosure಺ͷΧελϚΠζΛద༻
  27. Storyboard, Xibͷѻ͍ • SwiftGenͳͲ͸࢖Θͣɺఆ൪ͷprotocol४ڌͷΈ protocol StoryboardInitializable: class { static var

    storyboardName: String { get } static func instantiateStoryboard(storyboardName: String?) -> Self } extension StoryboardInitializable where Self: UIViewController { static var storyboardName: String { return String(describing: self) } static func instantiateStoryboard() -> Self { ... } }