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

モジュールの視点からSwiftを読み解く #iosdc

モジュールの視点からSwiftを読み解く #iosdc

Avatar for Shigure Shimotori

Shigure Shimotori

September 13, 2026

More Decks by Shigure Shimotori

Other Decks in Programming

Transcript

  1. UNAuthorizationStatus import UserNotifications // UserNotificationsモジュールを使用 let settings = await UNUserNotificationCenter

    .current().notificationSettings() switch settings.authorizationStatus { case .notDetermined: /* すきなように */ case .denied: /* 結果に応じた */ case .authorized: /* 処理を */ case .provisional: /* 書こう */ case .ephemeral: /* !!! */ } 12
  2. なんかエラー出た ※Swift 6 言語モードの場合 error: switch covers known cases, but

    'UNAuthorizationStatus' may have additional unknown values, possibly added in future versions note: handle unknown values using "@unknown default" 意訳 将来追加される未知の値に対応できてないからエラーにするよ。 @unknown defaultで対応しよう! 13
  3. 言われるがままに修正する import UserNotifications // UserNotificationsモジュールを使用 let settings = await UNUserNotificationCenter

    .current().notificationSettings() switch settings.authorizationStatus { case .notDetermined: /* ... */ case .denied: /* ... */ case .authorized: /* ... */ case .provisional: /* ... */ case .ephemeral: /* ... */ + @unknown default: /* 言われるがままにこれを書き足す…… */ } 14
  4. 毎夏の恒例行事 iOS 14 へのアップデート前 OS 同梱の UserNotifications iOS 13 までを想定して作ったアプリ

    // iOS 13 import UserNotifications enum UNAuthorizationStatus { case notDetermined case denied case authorized case provisional switch settings.authorizationStatus { case .notDetermined: /* ... */ case .denied: /* ... */ case .authorized: /* ... */ case .provisional: /* ... */ } } 17
  5. 毎夏の恒例行事 iOS 14 へのアップデート完了! OS 同梱の UserNotifications // iOS 14

    enum UNAuthorizationStatus { case notDetermined case denied case authorized case provisional + case ephemeral } iOS 13 までを想定して作ったアプリ import UserNotifications switch settings.authorizationStatus { case .notDetermined: /* ... */ case .denied: /* ... */ case .authorized: /* ... */ case .provisional: /* ... */ } 17
  6. 依存モジュールとアプリの間に情報格差があるかも iOS 14が入ってるiPhone: iOS 14 に App Clip が導入された ユーザの選択次第でステータスが.ephemeral

    になる可能性がある。 iOS 13で作ったアプリ: まだ iOS 14 対応していない or アップデートやめた case ephemeral のことは全く知らない。 switch 文にも書いてない。 18
  7. .ephemeral はどこに行けばいいんだ??? iOS 14 対応が済んでないアプリには case ephemeral がない import UserNotifications

    switch authorizationStatus { case .notDetermined: /* ... */ case .denied: /* ... */ case .authorized: /* ... */ case .provisional: /* ... */ } Objective-C の enum なのでクラッシュ。 19
  8. @unknown defaultがあれば安心! 未知の値が来ても対処できる! import UserNotifications switch authorizationStatus { case .notDetermined:

    /* ... */ case .denied: /* ... */ case .authorized: /* ... */ case .provisional: /* ... */ + @unknown default: /* ephemeralを受け取ってごまかす! */ } 20
  9. 補足:実際のところ .ephemeral のせいで意図しない動作をすることはない iOS 13 以前のアプリには App Clip が存在しないのでこいつも飛んでこない 同じ理屈で、

    Apple Glass 仮 ができて UIUserInterfaceIdiom に 新しいものが増えても既存のアプリに影響はないはず きっと互換モードで動いて既存の値が渡されるよたぶん 21
  10. @unknown default を書かされるとき Objective-C 定義の enum の場合: NS_ENUM を使って定義したもの 大多数の

    enum はこれ! Swift 定義の enum の場合: Library Evolution モードを有効にすれば出る SwiftUI は Swift 実装かつ Library Evolution 有効 他にも C 言語の場合とか SE-0487 とかある 22
  11. Library Evolution とは モジュールの作者がモジュールに対して設定できるモード あとから新バージョンに差しかわる前提で話を進めるようになる これがあれば SwiftUI だけを iOS 27

    にアップデートしても安心! 具体的な効果 あとから差しかえる前提でモジュールが生成され、 動作する あとからアップデートされる前提での利用をアプリ側にうながす 例:@unknown default で未知の値を処理するよう強制する 23
  12. SE-0192 と SE-0260 と SE-0487 の違い SE-0192 Handling Future Enum

    Cases (Swift 5.0) このころはまだfrozenの設定手段が限定的だったみたい SE-0260 (Swift 5.1) Library Evolution有効時に出まくるようになった 目的はバイナリ互換性 SE-0487 Nonexhaustive enums (Swift 6.3.2) @nonexhaustive の導入 目的はソース互換性 25
  13. Swift Concurrency の問題です! 非隔離の struct が Sendable って書かなくても勝手に Sendable になるときって

    どんなとき? 答え: その struct が internal 以下で、 プロパティも Sendable なとき! 32
  14. あとから非 Sendable になっちゃうとめんどい! Sendable として運用するつもりのなかった struct かも あとからうっかり非 Sendable プロパティを足しちゃうかも……

    public struct MyStructure { + var value: NonSendableValue } var s = MyStructure() await doOnAnotherActor(s) s.doSomething() error: sending 's' risks causing data races [#SendingRisksDataRace] 34
  15. 暗黙的な Sendable? いろんな struct 暗黙的に Sendable にしていい? internal 直接の影響はないから OK

    public 安易な Sendable 化はリスク高い @frozen public あとから変更しないから迷惑かけない @usableFromInline internal ??? 36
  16. @inlinable と @usableFromInline の設定例 public struct Container<Value> { @usableFromInline internal

    let value: Value @inlinable public func calculate() -> Int { value.doSomething() } } 46
  17. 暗黙的な Sendable? いろんな struct 他のモジュールに 影響ある? internal ない public ある

    @frozen public ない 仕様が変わらない @usableFromInline internal ある インライン化された先で 使われる 暗黙的に Sendable になれる? 47
  18. import したモジュールの中の関数を使う 一般的な理解:import をしても internal 以下のものは使えない internal アクセスにより、 エンティティを定義するモジュールの任意のソース ファイル内で使用できますが、

    そのモジュールの外部のソースファイルでは使用 できません。 by TSPL 日本語版 実際のところ… @usableFromInline internal のものが最適化の一環で使える @testable import すると internal のものが呼べる、 テストできる 52
  19. import したモジュールの中の struct や関数が使える条件 モジュールの核(SwiftUI.tbd)が、対象を他モジュールから利用可能にしている アクセス修飾子の区別なく、外部から使えるか、使わせないか、ただそれだけ AND "取扱説明書 兼 カタログ"の記載通りの使いかたを守る

    アクセス修飾子の制限をかけているのはこちらのファイル 自由に呼べるのは public 以上 @usableFromInline internal を使えるのは最適化のときだけ @testable import が許されているかどうかも書いてある 55
  20. 余談:SwiftUI は @testable import できない SwiftUI.framework 生成時に Apple がテスト機能を有効化しなかった その結果、

    モジュールが @testable import できるように作られない @testable import SwiftUI error: module 'SwiftUI' was not compiled for testing [#ModuleNotTestable] 56
  21. 2 種類の"取扱説明書 兼 カタログ" . .swiftmodule .swiftinterface 生成方法 デフォルト 要フラグ

    形式 バイナリ テキスト 有益な情報の量 たくさん 少ない 互換性 違うコンパイラから読める? のようなエラーが出る error: module compiled with Swift 6.3 cannot be imported by the Swift 6.4 compiler 61
  22. public API と private API アクセス制御の話じゃないよ public API アプリ開発で使っていいAPIのこと Document

    APIとも呼ばれる private API アクセス制御的にはopenやpublicだが使ってはいけない(使えない)API Appleの人しか使えない、無理やり使ったらリジェクトされちゃうかも!? non-public APIとも呼ばれる 64
  23. 厳密には 1+2 種類の"取扱説明書 兼 カタログ" . .swiftmodule .swiftinterface .private.swiftinterface 生成方法

    デフォルト 要フラグ さらにもう 1 つフラグ 形式 バイナリ テキスト テキスト 少ない 同じく少ない が、 裏メニュー付き! 有益な情報の量 たくさん 互換性 67
  24. 参考文献 - モジュール アクセス制御 (Access Control) https://www.swiftlangjp.com/language-guide/access-control.html Introducing Packages https://docs.swift.org/latest/documentation/packagemanagerdocs/introducingpackages/

    Target https://developer.apple.com/documentation/packagedescription/target Swift Compiler https://www.swift.org/documentation/swift-compiler/ Whole-Module Optimization in Swift 3 https://www.swift.org/blog/whole-module-optimizations/ 75
  25. 参考文献 - 互換性と安定性 ABI Stability and More https://www.swift.org/blog/abi-stability-and-more/ [SE-0192] Handling

    Future Enum Cases https://github.com/swiftlang/swift-evolution/blob/main/proposals/0192-non-exhaustive-enums.md Xcode 14+ creates arm64-apple-ios.abi.json by default https://forums.swift.org/t/xcode-14-creates-arm64-apple-ios-abi-json-by-default/65380/2 77
  26. 参考文献 - Library Evolution [SE-0260] Library Evolution for Stable ABIs

    https://github.com/swiftlang/swift-evolution/blob/main/proposals/0260-library-evolution.md Library Evolution in Swift https://www.swift.org/blog/library-evolution/ Library Evolution Support in Swift ("Resilience") https://github.com/swiftlang/swift/blob/main/docs/LibraryEvolution.rst 78
  27. 参考文献 - @unknown default と NS_ENUM Grouping Related Objective-C Constants

    https://developer.apple.com/documentation/Swift/grouping-related-objective-c-constants Foundation Release Notes https://developer.apple.com/documentation/macos-release-notes/foundation-release-notes SE-0487 Nonexhaustive enums https://github.com/swiftlang/swift-evolution/blob/main/proposals/0487-extensible-enums.md 79
  28. 参考文献 - 最適化 SE-0193 Cross-module inlining and specialization https://github.com/swiftlang/swift-evolution/blob/main/proposals/0193-cross-module-inliningand-specialization.md Explore

    Swift performance https://developer.apple.com/videos/play/wwdc2024/10217/ 属性 (Attributes) https://www.swiftlangjp.com/language-reference/attributes.html swift-algorithms https://github.com/apple/swift-algorithms マクロ (Macros) https://www.swiftlangjp.com/language-guide/macros.html 81
  29. 参考文献 - import [SE-0409] Access-level modifiers on import declarations https://github.com/swiftlang/swift-evolution/blob/main/proposals/0409-access-levelon-imports.md

    [SE-0444] Member import visibility https://github.com/swiftlang/swift-evolution/blob/main/proposals/0444-member-importvisibility.md 82
  30. 参考文献 - swiftinterface Plan for module stability https://forums.swift.org/t/plan-for-module-stability/14551 what's in

    the file of .swiftmodule?how to open it? https://forums.swift.org/t/whats-in-the-file-of-swiftmodule-how-to-open-it/1032/2 Underscored Attributes Reference https://github.com/swiftlang/swift/blob/main/docs/ReferenceGuides/UnderscoredAttributes.md A Swift Guide (WebKit Wiki) https://github.com/WebKit/WebKit/wiki/A-Swift-Guide 83
  31. 参考文献 - ライブラリ An Apple Library Primer https://developer.apple.com/forums/thread/715385 Missing librairies

    in /usr/lib on Big Sur? https://developer.apple.com/forums/thread/655588 Dynamic Library Design Guidelines https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/ DynamicLibraries/100-Articles/DynamicLibraryDesignGuidelines.html 84
  32. 参考文献 - Private API Code Naming Basics https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CodingGuidelines/ Articles/NamingBasics.html Try-Swift-Playgrounds

    https://github.com/Private-Playgrounds/Try-Swift-Playgrounds RuntimeViewer https://github.com/MxIris-Reverse-Engineering/RuntimeViewer 86
  33. いつもありがとうございます! mtj0928/SlideKit: SwiftUI framework for presentation slides https://github.com/mtj0928/SlideKit SwiftFiddle -

    Swift Online Playground https://swiftfiddle.com/ いらすとや https://www.irasutoya.com/ twemoji https://github.com/twitter/twemoji 88