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

    View Slide

  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ʣ

    View Slide

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


    flag = !flag


    print(flag) // false

    View Slide

  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 ͕ٯʂ

    View Slide

  5. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved.
    BoolΛ൓స͢Δʹ͸toggle()Λ࢖͏
    flag = !flagΑΓΘ͔Γ΍͍͢
    w toggle()ͰಡΈ΍͘͢ɺهड़ϛεͷ৺഑΋ݮΔ
    5
    flag.toggle()


    hoge.fuga1.piyo2.flag.toggle()

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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


    */


    }

    View Slide

  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

    View Slide

  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


    */


    }

    View Slide

  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


    */


    }

    View Slide

  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


    ...


    */


    }


    }

    View Slide

  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)


    }

    View Slide

  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)


    }


    // ಉ͡ग़ྗ

    View Slide

  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ʣॲཧ Ͱ͖Δ Ͱ͖ͳ͍

    View Slide

  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) // ͝൧

    View Slide

  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()

    View Slide

  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

    View Slide

  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)

    View Slide

  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)

    View Slide

  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!)


    }


    }

    View Slide

  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)


    }


    }

    View Slide

  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)


    }


    }

    View Slide

  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)


    }


    }

    View Slide

  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)


    }


    }

    View Slide

  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)


    }


    }

    View Slide

  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)


    }


    }

    View Slide

  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

    View Slide

  30. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved.
    ͞ΒʹεςοϓΞοϓ
    6*,JUʢJ04ͳͲʣͰʮͬͪ͜ͷํ͕͍͍Αʯ
    30

    View Slide

  31. Copyright © 2023 treastrain / Tanaka RyogaɹAll rights reserved.
    ɹɹɹɹɹεϥΠυɾൃද಺༰͸IUUQTUSFUKQͰެ։͍ͯ͠·͢ɹ⏩
    ͦͷ4XJGUίʔυɺ

    ͜͏ॻ͖׵͑ͯΈͳ͍͔
    1PMJTIJOHZPVS4XJGUDPEFXJUINF
    31
    DeNA
    ×
    STORES
    ×
    ϥΫϚ iOS Meetup!! #dena_stores_rakuma

    View Slide