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

その Swift コード、
こう書き換えてみないか / Polishing your Swift code with me!

その Swift コード、
こう書き換えてみないか / Polishing your Swift code with me!

その Swift コード、
こう書き換えてみないか / Polishing your Swift code with me!

DeNA×STORES×ラクマ iOS Meetup!!
2023/05/22 19:00〜
https://connpass.com/event/283989/

登壇ノートはこちら: https://zenn.dev/treastrain/articles/65f6cae11e0dc7

More Decks by treastrain / Tanaka Ryoga

Other Decks in Programming

Transcript

  1. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. USFBTUSBJO5BOBLB3ZPHB

    ͦͷ4XJGUίʔυɺ 
 ͜͏ॻ͖׵͑ͯΈͳ͍͔ 1PMJTIJOHZPVS4XJGUDPEFXJUINF 1 DeNA × STORES × ϥΫϚ iOS Meetup!! #dena_stores_rakuma
  2. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. "CPVUNF

    USFBTUSBJO5BOBLB3ZPHB 2 4XJGU J04 XBUDI04 $PSF/'$ 044 
 ɹɹJU`TNZNPUIFSUPOHVF 
 ɹɹ࠷ۙ#MVFTLZΛ͸͡Ί·ͨ͠ ɹɹɹɹɹɹɹɹɹɹ!USFBTUSBJOɹɹIUUQTUSFUKQ 
 
 %F/"$P -UE 
 ɹɹJ04"QQ%FWFMPQFSʢ"QSJM$VSSFOUʣ
  3. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. BoolΛ൓స͢Δʹ͸toggle()Λ࢖͏

    flag = !flagΑΓΘ͔Γ΍͍͢ w !Ͱ൓సͰ͖Δ͚Ͳʜʜ 3 var flag = true flag = !flag print(flag) // false
  4. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. BoolΛ൓స͢Δʹ͸toggle()Λ࢖͏

    flag = !flagΑΓΘ͔Γ΍͍͢ 4 struct Hoge { var fuga1 = Fuga(); var fuga2 = Fuga() struct Fuga { var piyo1 = Piyo(); var piyo2 = Piyo() struct Piyo { var flag = true } } } var hoge = Hoge() hoge.fuga1.piyo2.flag = !hoge.fuga2.piyo1.flag // fuga1ɾ2ɺpiyo2ɾ1 ͕ٯʂ
  5. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. BoolΛ൓స͢Δʹ͸toggle()Λ࢖͏

    flag = !flagΑΓΘ͔Γ΍͍͢ w toggle()ͰಡΈ΍͘͢ɺهड़ϛεͷ৺഑΋ݮΔ 5 flag.toggle() hoge.fuga1.piyo2.flag.toggle()
  6. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. isMultiple(of:)Λ࢖͏

    x % 2 == 0͸࢖Θͳ͍ w ӳޠͷจষͷΑ͏ʹಡΊͯɺՄಡੑ͕޲্ 6 let x = 4 print(x % 2 == 0) // true - `%` ԋࢉࢠΛ༻͍Δྫ print(x & 1 == 0) // true - `&` ԋࢉࢠΛ༻͍Δྫ print(x.isMultiple(of: 2)) // true - ӳޠͷจষͷΑ͏ʹಡΊΔ print(x.isMultiple(of: 3)) // false
  7. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ίϨΫγϣϯͷendIndexΛ࢖͏

    countͬΆ͍͚ΕͲ w ʮ࠷ޙͷΠϯσοΫε ʯΛࣔ͢ w count͸0 O ɺendIndex͸0  7 let list = ["DeNA", "STORES", "Rakuten Rakuma”] print(list.count) // 3 print(list.endIndex) // 3
  8. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ίϨΫγϣϯ͕ۭ͔Ͳ͏͔͸isEmptyͰಘΔ

    count == 0͸࢖Θͳ͍ w ಡΈ΍͍͢ w count͸0 O ɺisEmpty͸0  8 let list1 = ["DeNA", "STORES", "Rakuten Rakuma"] print(list1.count == 0) // false print(list1.isEmpty) // false var list2 = list1 list2.removeAll() print(list2.count == 0) // true print(list2.isEmpty) // true
  9. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ίϨΫγϣϯͷΠϯσοΫε͸indexed()ͰಘΔ

    enumerated()΍zip(_:_:)Ͱ͸ͳ͘ w enumerated()͸ཁૉͱҰॹʹʮ0͔Β࢝·Δ࿈൪ʯΛฦ͢ 9 let prefectures = ["Hokkaido", "Aomori", "Iwate", "Miyagi", "Akita", "Yamagata", “Fukushima"] for (offset, prefecture) in prefectures.enumerated() { print(offset, prefecture, prefectures[offset]) /* 0 Hokkaido Hokkaido 1 Aomori Aomori 2 Iwate Iwate 3 Miyagi Miyagi 4 Akita Akita 5 Yamagata Yamagata 6 Fukushima Fukushima */ }
  10. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ίϨΫγϣϯͷΠϯσοΫε͸indexed()ͰಘΔ

    enumerated()΍zip(_:_:)Ͱ͸ͳ͘ w ʮ0͔Β࢝·Δ࿈൪ʯͱʮίϨΫγϣϯͷΠϯσοΫεʯ͸Ұக͠ͳ͍͔΋ 10 let tohoku = prefectures.dropFirst() for (offset, prefecture) in tohoku.enumerated() { print(offset, prefecture, prefectures[offset]) /* 0 Aomori Hokkaido 1 Iwate Aomori 2 Miyagi Iwate 3 Akita Miyagi 4 Yamagata Akita 5 Fukushima Yamagata */ } print(tohoku[0]) // 💥 Fatal error: Index out of bounds
  11. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ίϨΫγϣϯͷΠϯσοΫε͸indexed()ͰಘΔ

    enumerated()΍zip(_:_:)Ͱ͸ͳ͘ w ඪ४తͳ୅ସҊzip(_:_:)͸enumerated()ΑΓύϑΥʔϚϯε͕ѱ͍ 11 for (index, prefecture) in zip(tohoku.indices, tohoku) { print(index, prefecture, prefectures[index]) /* 1 Aomori Aomori 2 Iwate Iwate 3 Miyagi Miyagi 4 Akita Akita 5 Yamagata Yamagata 6 Fukushima Fukushima */ }
  12. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ίϨΫγϣϯͷΠϯσοΫε͸indexed()ͰಘΔ

    enumerated()΍zip(_:_:)Ͱ͸ͳ͘ w 4XJGU"MHPSJUINTͷindexed()͸zip(_:_:)ΑΓ 
 ύϑΥʔϚϯε͕ྑ͍ 12 import Algorithms for (index, prefecture) in tohoku.indexed() { print(index, prefecture, prefectures[index]) /* 1 Aomori Aomori 2 Iwate Iwate 3 Miyagi Miyagi 4 Akita Akita 5 Yamagata Yamagata 6 Fukushima Fukushima */ }
  13. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ೋॏͷϧʔϓ͸product(_:_:)Λ࢖͏

    for-inΛճॻ͘ඞཁ͕ͳ͘ͳΔ 13 let years = [2021, 2022, 2023] let months = ["January", "February", "March", /* ... */] for year in years { for month in months { print(year, month) /* 2021 January 2021 February 2021 March ... 2022 January 2022 February 2022 March ... */ } }
  14. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ೋॏͷϧʔϓ͸product(_:_:)Λ࢖͏

    for-inΛճॻ͘ඞཁ͕ͳ͘ͳΔ w 4XJGU"MHPSJUINTͷproduct(_:_:)ͰωετΛݮΒͤΔ w Ұํ͕ۭͷ৔߹ɺແବͳϧʔϓॲཧ͕ൃੜ͠ͳ͍ 14 import Algorithms for (year, month) in product(years, months) { print(year, month) }
  15. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. for-inͱforEach(_:)ͷ࢖͍෼͚Λߟ͑ͯΈΔ

    forEach(_:)ࣗମ͸for-inͰ࣮૷͞Ε͍ͯΔ͚Ͳ 15 func printWithLowercased(_ value: String) { print(value.lowercased()) } let list = ["DeNA", "STORES", "Rakuten Rakuma"] for name in list { printWithLowercased(name) } // ಉ͡ग़ྗ list.forEach { name in printWithLowercased(name) } // ಉ͡ग़ྗ
  16. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. for-inͱforEach(_:)ͷ࢖͍෼͚Λߟ͑ͯΈΔ

    forEach(_:)ࣗମ͸for-inͰ࣮૷͞Ε͍ͯΔ͚Ͳ 16 for-inϧʔϓ forEach(_:) ϧʔϓΛ్தͰ΍ΊΔ breakΛ࢖͏ Ͱ͖ͳ͍ ॲཧͷ్தͰ࣍ͷཁૉʹҠΔ continueΛ࢖͏ returnΛ࢖͏ SFUVSOจΛ࢖͏ͱ ϧʔϓ͕͋Δείʔϓ͔Βग़Δ ࣍ͷཁૉͷॲཧʹҠΔ ཁૉ໊ͷলུ Ͱ͖ͳ͍ Ͱ͖Δʢ$0ʣ ؔ਺ͳͲΛ௚઀౉͢ Ͱ͖ͳ͍ Ͱ͖ΔʢforEach(someFunc())ʣ ඇಉظʢBTZODBXBJUʣॲཧ Ͱ͖Δ Ͱ͖ͳ͍
  17. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ໊લۭؒʢ/BNFTQBDFTʣʹ͸enumΛ࢖͏

    class΍structͰ͸ͳ͘ w struct΍classΛ࢖͏ͱɺ 
 internalͰ࢖͑ΔΠχγϟϥΠβ͕σϑΥϧτͰ༻ҙ͞Εͯ͠·͏ 17 enum BreakfastMenu { static let rice = "͝൧" static let bread = "ύϯ" // ... } print(BreakfastMenu.rice) // ͝൧
  18. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ϥϯμϜͳ஋ɾཁૉ͕΄͍͠

    arc4random()΍arc4random_uniform(_:)͸࢖Θͳ͍ w 4XJGU͔Β࢖͑ΔΑ͏ʹͳͬͨ 
 random()ɾrandom(in:)ɾrandomElement()Λ࢖͏ 18 let flag = Bool.random() let num = Int.random(in: 0..<10) let area = [1: "Shibuya", 2: "Shinjuku"].randomElement() let player = ["uhooi", "treastrain"].randomElement()
  19. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. Optional.map(_:)Λ࢖͏

    nilͷͱ͖͸nilͷ··ɺnilͰͳ͍ͱ͖͚ͩॲཧΛߦ͏ w nilͷͱ͖͸ʜͷ෼ذΛࣗ෼Ͱॻ͔ͳͯ͘ࡁΉ 19 struct Talk { let title: String } let selectedTalkTitle: String? = nil let selectedTalk: Talk? = selectedTalkTitle.map { Talk(title: $0) } print(selectedTalk) // nil
  20. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ʮOptionalͳvarʯΛʮඇ0QUJPOBMͳletʯʹ

    ʮHFU͢Δͱ͖·Ͱʹ͸ඞͣTFU͞Ε͍ͯΔʯϓϩύςΟͰ 20 enum Area { case osaka, hiroshima } let area: Area = // ... var okonomiyaki: String? switch area { case .osaka: okonomiyaki = "ؔ੢෩" case .hiroshima: okonomiyaki = "޿ౡ෩" } print(okonomiyaki)
  21. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ʮOptionalͳvarʯΛʮඇ0QUJPOBMͳletʯʹ

    ʮHFU͢Δͱ͖·Ͱʹ͸ඞͣTFU͞Ε͍ͯΔʯϓϩύςΟͰ 21 enum Area { case osaka, hiroshima } let area: Area = // ... let okonomiyaki: String switch area { case .osaka: okonomiyaki = "ؔ੢෩" case .hiroshima: okonomiyaki = "޿ౡ෩" } print(okonomiyaki)
  22. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ͋ͱ͔ΒTFU͞ΕΔϓϩύςΟΛOptionalʹ͠ͳ͍

    ඞͣTFU͞ΕΔͳΒpreconditionFailure(_:file:line:)ΛԾஔ͖͢Δ 22 import UIKit final class ViewController: UIViewController { // ͜ͷ collectionView ͸ viewDidLoad() ͷޙʹ࡞Δ͜ͱʹ͍ͯ͠ΔʢͱԾఆʣ private var collectionView: UICollectionView? override func viewDidLoad() { super.viewDidLoad() // collectionView Λ࡞Δ collectionView = UICollectionView(frame: .null) // ... // collectionView Λ࢖͏ view.addSubview(collectionView!) } }
  23. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ͋ͱ͔ΒTFU͞ΕΔϓϩύςΟΛOptionalʹ͠ͳ͍

    ඞͣTFU͞ΕΔͳΒpreconditionFailure(_:file:line:)ΛԾஔ͖͢Δ 23 import UIKit final class ViewController: UIViewController { // ͜ͷ collectionView ͸ viewDidLoad() ͷޙʹ࡞Δ͜ͱʹ͍ͯ͠ΔʢͱԾఆʣ private lazy var collectionView: UICollectionView = { preconditionFailure("collectionView has not been set") }() override func viewDidLoad() { super.viewDidLoad() // collectionView Λ࡞Δ collectionView = UICollectionView(frame: .null) // ... // collectionView Λ࢖͏ view.addSubview(collectionView) } }
  24. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ֦ுʢ&YUFOTJPOTʣ͸ϓϩτίϧʢ1SPUPDPMTʣ͝ͱʹ࡞Δ

    ͦͷϓϩτίϧ΁ͷ४ڌͷͨΊͷ࣮૷͸ͦͷதͰͷΈߦ͏ 24 import Foundation struct Book { let name: String let uuid: UUID } extension Book: Identifiable, Hashable { var id: UUID { uuid } } extension Book { func hash(into hasher: inout Hasher) { hasher.combine(id) } }
  25. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ֦ுʢ&YUFOTJPOTʣ͸ϓϩτίϧʢ1SPUPDPMTʣ͝ͱʹ࡞Δ

    ͦͷϓϩτίϧ΁ͷ४ڌͷͨΊͷ࣮૷͸ͦͷதͰͷΈߦ͏ 25 import Foundation struct Book { let name: String let uuid: UUID } extension Book: Identifiable { var id: UUID { uuid } } extension Book: Hashable { func hash(into hasher: inout Hasher) { hasher.combine(id) } }
  26. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ֦ுʢ&YUFOTJPOTʣ͸ϓϩτίϧʢ1SPUPDPMTʣ͝ͱʹ࡞Δ

    ͦͷϓϩτίϧ΁ͷ४ڌͷͨΊͷ࣮૷͸ͦͷதͰͷΈߦ͏ w 4XJGU6*ͷྫ 26 import SwiftUI struct ContentView: View { let greeting = "Hello, happy world!" var body: some View { // ϓϩτίϧ View ଆͷఆٛͰ @MainActor ʹͳ͍ͬͯΔ Text(greeting) } }
  27. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ֦ுʢ&YUFOTJPOTʣ͸ϓϩτίϧʢ1SPUPDPMTʣ͝ͱʹ࡞Δ

    ͦͷϓϩτίϧ΁ͷ४ڌͷͨΊͷ࣮૷͸ͦͷதͰͷΈߦ͏ w 4XJGU6*ͷྫ 27 import SwiftUI struct ContentView: View { let greeting = "Hello, happy world!" } extension ContentView { var body: some View { // 😫 ҉໧తʹ @MainActor Ͱ͸ͳ͘ͳΓɺ // ϓϩτίϧ View ଆͷఆٛͱ͸ҟͳͬͯ͠·͏ Text(greeting) } }
  28. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ֦ுʢ&YUFOTJPOTʣ͸ϓϩτίϧʢ1SPUPDPMTʣ͝ͱʹ࡞Δ

    ͦͷϓϩτίϧ΁ͷ४ڌͷͨΊͷ࣮૷͸ͦͷதͰͷΈߦ͏ w 4XJGU6*ͷྫ 28 import SwiftUI struct ContentView { let greeting = "Hello, happy world!" } extension ContentView: View { var body: some View { // ✅ ϓϩτίϧ View ଆͷఆٛΑΓ // ҉໧తʹ @MainActor ʹͳΔ Text(greeting) } }
  29. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ͦͷ΄͔఻͔͑ͨͬͨ͜ͱ

    ͕࣌ؒ଍Γͳ͔ͬͨʜʜ w switchจͰͪΌΜͱ໢ཏͯ͠ɺ 
 ݟམͱ͠Λແͨ͘͠Γޙͷมߋʹڧͨ͘͠Γ͢Δ w Resultͱεϩʔؔ਺ʢ5ISPXJOH'VODUJPOTʣͷ૬ޓม׵ w %FMFHBUFɾΫϩʔδϟΛBTZODͳؔ਺ʹ͢Δ w NotificationCenterΛ4XJGU$PODVSSFODZ͔Β࢖͏ w $PNCJOFɾ3Y4XJGUΛ4XJGU$PODVSSFODZ͔Β࢖͏ 29
  30. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved. ɹɹɹɹɹεϥΠυɾൃද಺༰͸IUUQTUSFUKQͰެ։͍ͯ͠·͢ɹ⏩

    ͦͷ4XJGUίʔυɺ 
 ͜͏ॻ͖׵͑ͯΈͳ͍͔ 1PMJTIJOHZPVS4XJGUDPEFXJUINF 31 DeNA × STORES × ϥΫϚ iOS Meetup!! #dena_stores_rakuma