View in English

  • メニューを開く メニューを閉じる
  • Apple Developer
検索
検索を終了
  • Apple Developer
  • ニュース
  • 見つける
  • デザイン
  • 開発
  • 配信
  • サポート
  • アカウント
次の内容に検索結果を絞り込む

クイックリンク

5 クイックリンク

ビデオ

メニューを開く メニューを閉じる
  • コレクション
  • トピック
  • すべてのビデオ
  • 利用方法

WWDC23に戻る

ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。

  • 概要
  • トランスクリプト
  • コード
  • Core Dataの新機能

    Core Dataの改善によって、アプリのデータ永続性を改善させましょう。複合属性を使用して、より直感的なデータモデルを作成する方法について学びましょう。また、大幅な変更を伴うスキーマの移行方法、負荷のかかる移行のタイミングを遅らせたり、およびユーザーのデバイスに対する負荷を避ける方法も紹介します。このセッションを最大限に活用するためには、Core Dataで異なるデータ型を扱う方法と、軽量マイグレーションの基本を理解していることが望ましいです。

    関連する章

    • 0:00 - Intro
    • 0:56 - Composite attributes
    • 6:31 - Stage your migrations
    • 18:23 - Defer your migrations
    • 22:33 - Wrap-up

    リソース

    • Core Data
    • Migrating your data model automatically
      • HDビデオ
      • SDビデオ

    関連ビデオ

    WWDC22

    • Core Dataスキーマを進化させる
  • このビデオを検索

    ♪ ♪

    David:「Core Dataの新機能」へようこそ 私 David Stitesは Core Dataチームのエンジニアです このセッションでは アプリ内の Core Dataデータモデルを より迅速かつ簡単に設計 クエリ 更新および移行する際に役立つ Core Dataの新技術を学びます

    まず アプリのモデルで 構造化データを整理する 優れた新方法である 複合属性についてお話しします 次に軽量なマイグレーションを 使用するために 最も複雑なモデルマイグレーションを 段階的なものに変える方法をお伝えします 最後に アプリの応答性を保つために モデルの移行を 延期する方法についてお話しします 複合属性は新しいタイプの属性です

    複合属性によって単一の属性内に 複雑なカスタムデータ型の カプセル化が可能になります

    各複合属性は String Float Int Dataなど すでにお馴染みの 組み込みCore Data型の 属性で構成されます

    複合属性は最上位の複合属性が さらに複合属性を含むように 互いに入れ子にすることができます

    Xcode Core Dataモデルエディタは モデルの複合属性の定義と管理を 容易にするため更新されました

    複合属性は 耐久性のあるカスタムデータ型を 作成するために 変換可能な型属性を 使用するための説得力のある代替手段です 属性の値を変換するコードを 書く必要はありません 変換可能な属性とは異なり 複合属性は 複合属性の名前空間付きキーパスで 構成されたNSPredicatesを持つ NSFetchRequestsを許可します

    複合属性はフラット化された属性の拡張を カプセル化するために 使用することができ 保守性と可読性の向上につながります

    複合属性はアプリのパフォーマンス 向上にも使用できます データモデルが あるエンティティを取得することで ほかのエンティティへの関連アクセスが 生じるように構成されている場合 その関連をコンポジット属性を使用して リファクタリングすることができます 複合属性を最初のエンティティに 埋め込むことにより リレーションシップを越えたオブジェクトの 不具合を防ぐことができます

    複合属性クラスは NSComposite AttributeDescription です NSCompositeAttribute Descriptionの属性タイプは NSCompositeAttributeTypeです

    NSComposite AttributeDescriptionクラスは NSAttributeDescriptionまたは ほかの入れ子になった NSCompositeAttribute Descriptionの配列 要素を含みます

    要素配列は NSRelationship Descriptionのような ほかのタイプのプロパティ記述を 含むことはできません 無効な要素を設定しようとするとNSInvalid ArgumentExceptionが発生します

    複合属性の実装方法について コードを使って説明します

    この基本的なデータモデルを 航空機のエンティティで考えてみましょう 多くの属性を有し 中でもcolors属性は 変形可能なタイプです そのタイプのトランスフォーマーは 航空機のprimary secondary tertiaryの色を記述する文字列を 格納し 解析します

    このエンティティを改良するために colors属性を colorSchemeという 複合属性に置き換えて 航空機の塗装色を保存します

    colorSchemeは次の要素を持つ 複合属性です primary secondary tertiaryは それぞれString属性です

    Xcodeで飛行時間を記録するために 使用しているアプリの プロジェクトを開きます

    このアプリのデータモデルには 先ほど説明した Aircraftエンティティとその他の エンティティがいくつか設定されています

    変換を始めるために Core Dataモデルエディタで colorSchemeという 新しい複合属性を追加します

    そのコンポジット内にprimary secondary tertiaryの 3つの文字列属性を追加しています

    Aircraftエンティティに composite属性を追加し その属性のタイプを colorSchemeに設定します

    モデル内の作業は完了したので コードを更新する番です

    Aircraftの実装では @NSManaged var colorSchemeという 新しいプロパティを追加しています コード全体で この複合属性を使用しているため 属性名をキーとして 辞書記法で値にアクセスしています primar secondary tertiaryという 文字列のキーを使用して 航空機の colorScheme属性を設定しています

    同様に、NSFetchRequestを NSPredicateで構成すると 複合属性の要素は名前空間付きキーパスを 介してアクセスされます

    ここではcolorScheme.primaryで その属性をフィルタリングしています

    アプリケーションが進化するにつれて データモデル変更を要する可能性があります

    データモデルを更新するには その変更を基礎となる ストレージスキーマに 具体化する必要があります

    モデルにnumPassengers属性が 追加された場合 対応するストレージを 更新する必要があります

    スキーマの変更を行うプロセスを マイグレーションと呼びます

    マイグレーション後 変更は 基礎となるストレージに完全に反映されます

    Core Dataにはアプリケーションの データストレージを最新データモデルに 保つためのマイグレーションツールセットが 組み込まれています これらのツールを総称して 「軽量マイグレーション」と呼びます

    軽量なマイグレーションについては WWDC 2022の「Evolve your app's schema」をご覧ください

    データモデルへの複合的な変更が 軽量マイグレーションの能力を 超えることもあります この問題の解決策は 段階的な移行です

    段階的移行用のAPIはいくつかの目標を 念頭に置いて設計されています 軽量のスキーマ変更に適合しない 複雑なデータモデルの移行を支援し 移行と移行インフラストラクチャに関連する 数千行のコードを削除する可能性があるため アプリケーションを簡素化できます また 移行プロセス中に アプリが実行状態をコントロールできるため さまざまな他のタスクを 実行する機会を提供します

    このAPIを使用するにはいくつか ステップを踏む必要があります まず モデルの変更が 軽量マイグレーションで サポートできない規模であることを 判断します 軽量マイグレーションに合っていないモデル変更を 軽量マイグレーションで実行できる程度の モデル変更の規模に分解します 新しい段階的移行の API を使用した NSManagedObjectModelの Core Dataへの完全な 順序付けについて説明します Core Dataがイベントループを実行し 未処理の各モデルを 直列順序で繰り返し処理し ストアをマイグレーションします マイグレーション中の特定の時点で 実行制御があなたの アプリケーションに与えられ 移行に関連する必要なタスクが実行されます

    軽量マイグレーションで対応できるモデル変更かを 判断するには いくつかの選択肢があります 最初の選択肢は スキーマの変更を手作業で確認し 各変更が軽量移行の対象であることを 確認するものです

    2つ目の選択肢は新しいモデルと 軽量マイグレーションオプションである NSMigratePersistentStores AutomaticallyOption および NSInferMappingModel AutomaticallyOptionをtrueに 設定して 永続ストアを開くことです 変更が軽量マイグレーションの 対象でない場合は NSPersistentStore Incompatible VersionHashErrorが発生します

    最後の選択肢はNSMappingModel. inferredMappingModel (forSourceModel:destinationModel:)を 使用することです このメソッドは、もしCore Dataが実行できる場合、 推論モデルを返します。 そうでない場合はnilを返します

    Aircraftモデルを再度考慮すると 新属性である flightDataを有しており バイナリ形式でデータを保存します

    仮にこのモデルを非正規化し すべてのフライトデータを 独自のエンティティタイプに 分離する必要があり 同時に既存のデータとそれが生成された 航空機との関係を保持する場合を考えます これは非常に複雑なモデルチェンジであり 軽量マイグレーションの対象になりません 段階的マイグレーションを使用するには これらの変更を分解する必要があります 軽量でない変更を分解する場合 目標は軽量マイグレーションの対象外の マイグレーションタスクを 軽量マイグレーションの 対象となる最小限の一連の マイグレーションに変換することです

    複雑な変更を実現するために 導入された各モデルは 軽量マイグレーションの能力で対応可能なレベルで 1つ以上のオペレーションを 持つことになります その結果 各モデルが 軽量マイグレーション可能ですが 複雑なマイグレーションと同等の結果をする 一連のマイグレーションとなります

    元のモデルにModelV1という ラベルを付けました

    このモデル移行はModelV2と ModelV3という2つの新しい モデルバージョンを 導入することで分解できます

    ModelV2ではAircraftエンティティは 新作成のFlightDataエンティティの コレクションであるflightParameters リレーションシップを獲得します FlightData エンティティは バイナリ型の属性データと Aircraft との関係を持ちます 既存データを保持するため 移行ステージでデータを Aircraftエンティティから 新しいFlightDataエンティティに コピーしてAircraftに関連付けます

    最終的なモデルは ModelV2から作られたModelV3です ModelV3では Aircraftエンティティから 古いflightData属性が削除され モデルの非正規化に成功し 既存のデータはすべて保持されます 説明した各ステップは 軽量マイグレーションの能力の範囲内です

    モデルの全体的な順序を記述するために Core Dataフレームワークレベルの サポートは 以下のクラスで構成されます NSStagedMigrationManager NSCustomMigrationStage NSLightweightMigrationStage および NSManagedObject ModelReferenceです

    NSStagedMigrationManager クラスは NSCustomMigrationStageと あなたが記述したNSLightweight MigrationStageの 補足の合計順序をカプセル化します 段階的移行マネージャーは 移行イベントループも管理し NSPersistentContainerを介して 移行ストアへのアクセスも提供します マネージャーを ストアオプションに追加する際は NSPersistentStoreStaged MigrationManagerOptionKeyを使います

    移行ステージはモデルのバージョン間の 移行の基礎を形成します

    段階的移行を採用する場合 NSCustomMigrationStageまたは NSLightweight MigrationStageを使用して 各モデルのバージョンを Core Dataに記述します NSLightweight MigrationStageクラスは 分解を必要とせず 軽量マイグレーションが可能な 一連のモデルを記述します これはおそらくあなたのモデルの 大部分を占めるでしょう これらの軽量な移行ステージは コアデータに記述された― モデルの総順序を 補足するために使用されます すべての軽量モデルのバージョンは 1つ以上の NSLightweightMigrationStageで 表現する必要があります

    作成したモデルの各分解バージョンは NSCustomMigrationStag を 使って表現され ソースおよびデスティネーション モデルリファレンスを含みます

    NSCustomMigrationStageは 移行ステージの直前と直後に実行される オプションのハンドラを提供します これらのハンドラーは移行処理中に カスタムコードを実行する機能を提供します

    段階的移行はNSManagedObjectModel Reference クラスを使用します このクラスは NSManagedObject Modelの実行計画を表します 移行中 Core Dataが この実行を果たします NSManagedObjectModel Referenceは柔軟性があり さまざまな方法で作成ができます

    すべての NSManagedObject ModelReferenceを 初期化する必要があります これによりモデルが不注意に 変更されていないことを確認します チェックサムの取得には NSManagedObjectModel .versionChecksumメソッドを使います

    あるいは Xcode のビルドログの 「Compile data model」から バージョンチェックサムを 取得することもできます 「version checksum」という 文字列を検索するのです

    バージョン管理されたモデルの場合 チェックサムは NSManagedObjectModelバンドルの VersionInfo.plistでも利用可能です

    例に戻って 段階的移行を使い始めるために 3つのモデルそれぞれに モデル参照を作成することから始めます 私はモデル名とバンドルリファレンスを 受け取るイニシャライザを 使用していますが ほかの選択肢もあります

    次のステップは 必要な移行段階を説明することです 最初のステージでは flightData属性が追加されただけなので 属性の追加は軽量な変更であるため 軽量なステージで表すことができます

    しかし、次の段階は カスタムステージになります モデルの変更が2つのモデルの バージョンに分解されたため 既存のデータを保持するために カスタムコードを実行する必要があります カスタム移行ステージはModelV2と ModelV3で初期化されます

    willMigrateHandlerでは flightDataが nilでないエンティティ行を フェッチしています 汎用 NSManagedObjectおよび NSFetchRequestResult型は Aircraft管理オブジェクトの サブクラス代わりに使われています 移行中にAircraftクラスが 期待通りに 存在しない可能性があるためです

    フェッチされた Aircraftエンティティごとに データはFlightDataの 新しいインスタンスにコピーされ 2つのエンティティは関連付けられ 永続化されます この移行ステージの実行が終了すると ストアのスキーマは 最新のモデルに更新され 既存のデータは保持されます

    段階的移行を完了するため 軽量な移行ステージと カスタム移行ステージを持つNSStaged MigrationManagerを作成します

    NSStagedMigrationManagerは NSPersistentStore Staged MigrationManagerOptionKeyを持つ NSPersistentStoreDescription オプションに追加されます

    そのあと 永続ストアがロードされて 移行プロセスが開始し ストアスキーマに影響を与えます 以上です Core Dataは 自動的に必要なステージを適用し ストアスキーマを移行します

    軽量移行の中には アプリケーションがフォアグラウンドで 提供できないような追加のランタイムを 必要とするものがあります

    軽量移行でユーザーデータを 変換するプロセスは 即座に完了するものではありません 例えば あるカラムから別のカラムへ またはあるテーブルから別のテーブルへ データをコピーするような移行であれば 時間がかかるかもしれません

    特に起動時に移行が行われる場合 じれったいような ユーザーエクスペリエンスに つながる可能性があります

    移行延期はこの問題の解決に役立ちます このAPIを使えば 軽量移行中に行われる 作業の一部を延期し 延期した作業を 後日完了させることができます 軽量移行中 エンティティにインデックスを更新したり テーブルコピーを実行したあとに 列を削除したりするなど クリーンアップが必要な マイグレーション変換がある場合 このテーブル変換は テーブル変換を実行するためのリソースが 利用可能と判断されるまで 延期することができます 軽量マイグレーションは依然として同期的で 正常に行われます スキーマのクリーンアップだけが 延期されます アプリケーションは通常通り 最新のスキーマを使用します Deferredマイグレーションを選択する際は NSPersistentStoreDeferred LightweightMigrationOptionKeyを ストアオプションでtrueに設定します

    DeferredマイグレーションAPIは macOS Big Surと SurとiOS 14までさかのぼり ランタイム互換性があります

    Deferredマイグレーションは SQLiteストアタイプでのみ利用可能です

    Deferredマイグレーションが有用な例を いくつか挙げてみます エンティティからの属性や リレーションシップの削除 エンティティ階層が存在しなくなった リレーションシップの変更 リレーションシップを順序付きから 非順序付きに変更する

    延期した移行タスクを終了するには 永続ストアのメタデータを確認します NSPersistentStore DeferredLight weightMigrationOptionKeyが 含まれている場合は 完了すべきマイグレーション作業が 遅延していることを示しています Deferredマイグレーションは NSPersistentStoreCoordinator.finishDeferredLightweightMigrationを 呼び出すと処理できます

    アプリケーションで 軽量マイグレーションを延期するには コーディネータに永続ストアを追加する際に ストアオプションで NSPersistentStoreDeferredLightweight MigrationOptionKeyをTrueに設定します

    Deferredマイグレーションを終了する 適切なタイミングになると ストアのメタデータをチェックすることで 保留中の延期作業の有無を確認できます NSPersistentStoreDeferred LightweightMigrationOptionKeyが true設定の場合はfinishDeferred LightweightMigration()を呼び出します

    Deferredマイグレーションのタスクを スケジュールするには Background Tasks APIの使用を 検討してください BGProcessingTaskは 長時間のデータ更新やアプリケーションの メンテナンスなど 時間のかかる操作のためのものです タスクの実行に最適な時間を システムが判断します しかし 一般的に処理タスクは デバイスがアイドル状態の時にのみ実行され ユーザーがデバイスを使い始めると バックグラウンド処理タスクは終了します

    Deferredおよび段階的移行は 組み合わせることができます 時間を要するような複雑な移行がある場合は 両APIの機能を利用する ステージの設計を検討してください 例のモデルに戻ると ModelV3で flightData属性を削除する場合 これは良いDeferredマイグレーションの 候補になるかもしれません

    Core Dataには 3つの素晴らしい新技術があります コンポジット属性を使用して ネスト可能で構造化された方法で カスタムデータ型をカプセル化し モデルの変更を分解して 段階的移行を使用し 複雑なモデル移行を実行し Deferredマイグレーションを使用して 一部の移行作業を遅延させることで アプリケーションのパフォーマンスを 向上させます 3つのテクノロジーはすべて調和して機能し アプリケーションを改善します

    私たちのチームは皆さんがこの新技術を どのように使用するか楽しみです ご視聴ありがとうございます 引き続き WWDCをお楽しみください ♪ ♪

    • 5:39 - Adding a composite attribute

      enum PaintColor: String, CaseIterable, Identifiable {
          case none, white, blue, orange, red, gray, green, gold, yellow, black
          var id: Self { self }
      }
      
      extension Aircraft {
      
          @nonobjc public class func fetchRequest() -> NSFetchRequest<Aircraft> {
              return NSFetchRequest<Aircraft>(entityName: "Aircraft")
          }
      
          @NSManaged public var aircraftCategory: String?
          @NSManaged public var aircraftClass: String?
          @NSManaged public var aircraftType: String?
          @NSManaged public var colorScheme: [String: Any]?
          @NSManaged public var photo: Data?
          @NSManaged public var tailNumber: String?
          @NSManaged public var logEntries: NSSet?
      
      }
    • 5:53 - Setting a composite attribute

      private func addAircraft() {
          viewContext.performAndWait {
              let newAircraft = Aircraft(context: viewContext)
              
              newAircraft.tailNumber = tailNumber
              newAircraft.aircraftType = aircraftType
              newAircraft.aircraftClass = aircraftClass
              newAircraft.aircraftCategory = aircraftCategory
              
              newAircraft.colorScheme = [
                  "primary": primaryColor.rawValue,
                  "secondary": secondaryColor.rawValue,
                  "tertiary": tertiaryColor.rawValue
              ]
              
              do {
                  try viewContext.save()
              } catch {
                  // ...
              }
          }
      }
    • 6:11 - Fetching a composite attribute

      private func findAircraft(with color: String) {
          viewContext.performAndWait {
              let fetchRequest = Aircraft.fetchRequest()
              fetchRequest.predicate = NSPredicate(format: "colorScheme.primary == %@", color)
              
              do {
                  var fetchedResults: [Aircraft]
                  fetchedResults = try viewContext.fetch(fetchRequest)
                  
                  // ...
              } catch {
                  // Handle any errors that may occur
              }
          }
      }
    • 16:00 - Creating managed object model references for staged migration

      let v1ModelChecksum = "kk8XL4OkE7gYLFHTrH6W+EhTw8w14uq1klkVRPiuiAk="
      let v1ModelReference = NSManagedObjectModelReference(
          modelName: "modelV1"
          in: NSBundle.mainBundle
          versionChecksum: v1ModelChecksum
      )
      
      let v2ModelChecksum = "PA0Gbxs46liWKg7/aZMCBtu9vVIF6MlskbhhjrCd7ms="
      let v2ModelReference = NSManagedObjectModelReference(
          modelName: "modelV2"                          
          in: NSBundle.mainBundle                                                 
          versionChecksum: v2ModelChecksum
      )
      
      let v3ModelChecksum = "iWKg7bxs46g7liWkk8XL4OkE7gYL/FHTrH6WF23Jhhs="
      let v3ModelReference = NSManagedObjectModelReference(
          modelName: "modelV3"
          in: NSBundle.mainBundle
          versionChecksum: v3ModelChecksum
      )
    • 16:19 - Creating migration stages for staged migration

      let lightweightStage = NSLightweightMigrationStage([v1ModelChecksum])
      lightweightStage.label = "V1 to V2: Add flightData attribute"
      
      let customStage = NSCustomMigrationStage(
          migratingFrom: v2ModelReference,
          to: v3ModelReference
      )
      
      customStage.label = "V2 to V3: Denormalize model with FlightData entity"
    • 16:54 - willMigrationHandler and didMigrationHandler of NSCustomMigrationStage

      customStage.willMigrateHandler = { migrationManager, currentStage in
          guard let container = migrationManager.container else {
              return
          }
      
          let context = container.newBackgroundContext()
          try context.performAndWait {
              let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Aircraft")
              fetchRequest.predicate = NSPredicate(format: "flightData != nil")
                  
              do {
                 var fetchedResults: [NSManagedObject]
                 fetchedResults = try viewContext.fetch(fetchRequest)
                 
                 for airplane in fetchedResults {
                      let fdEntity = NSEntityDescription.insertNewObject(
                          forEntityName: "FlightData,
                          into: context
                      )
                   
                      let flightData = airplane.value(forKey: "flightData")
                      fdEntity.setValue(flightData, forKey: “data”)
                      fdEntity.setValue(airplane, forKey: "aircraft")
                      airplane.setValue(nil, forKey: "flightData")
                  }
                  try context.save()
              } catch {
                  // Handle any errors that may occur
              }
          }
      }
    • 17:41 - Loading the persistent stores with an NSStagedMigrationManager

      let migrationStages = [lightweightStage, customStage]
      let migrationManager = NSStagedMigrationManager(migrationStages)
      
      let persistentContainer = NSPersistentContainer(
          path: "/path/to/store.sqlite",
          managedObjectModel: myModel
      )
      
      var storeDescription = persistentContainer?.persistentStoreDescriptions.first
      
      storeDescription?.setOption(
          migrationManager,
          forKey: NSPersistentStoreStagedMigrationManagerOptionKey
      )
      
      persistentContainer?.loadPersistentStores { storeDescription, error in
          if let error = error {
              // Handle any errors that may occur
          }
      }
    • 21:01 - Adding a persistent store with NSPersistentStoreDeferredLightweightMigrationOptionKey option

      let options = [
          NSPersistentStoreDeferredLightweightMigrationOptionKey: true,
          NSMigratePersistentStoresAutomaticallyOption: true,
          NSInferMappingModelAutomaticallyOption: true
      ]
      
      let store = try coordinator.addPersistentStore(
          ofType: NSSQLiteStoreType,
          configurationName: nil,
          at: storeURL,
          options: options
      )
    • 21:17 - Executing deferred migrations

      // After using BGProcessingTask to run migration work   
      let metadata = coordinator.metadata(for: store)
      if (metadata[NSPersistentStoreDeferredLightweightMigrationOptionKey] == true) {
          coordinator.finishDeferredLightweightMigration()
      }

Developer Footer

  • ビデオ
  • WWDC23
  • Core Dataの新機能
  • メニューを開く メニューを閉じる
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • SF Symbols
    メニューを開く メニューを閉じる
    • アクセシビリティ
    • アクセサリ
    • App Extension
    • App Store
    • オーディオとビデオ(英語)
    • 拡張現実
    • デザイン
    • 配信
    • 教育
    • フォント(英語)
    • ゲーム
    • ヘルスケアとフィットネス
    • アプリ内課金
    • ローカリゼーション
    • マップと位置情報
    • 機械学習
    • オープンソース(英語)
    • セキュリティ
    • SafariとWeb(英語)
    メニューを開く メニューを閉じる
    • 英語ドキュメント(完全版)
    • 日本語ドキュメント(一部トピック)
    • チュートリアル
    • ダウンロード(英語)
    • フォーラム(英語)
    • ビデオ
    Open Menu Close Menu
    • サポートドキュメント
    • お問い合わせ
    • バグ報告
    • システム状況(英語)
    メニューを開く メニューを閉じる
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles(英語)
    • フィードバックアシスタント
    メニューを開く メニューを閉じる
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program(英語)
    • News Partner Program(英語)
    • Video Partner Program(英語)
    • セキュリティ報奨金プログラム(英語)
    • Security Research Device Program(英語)
    Open Menu Close Menu
    • Appleに相談
    • Apple Developer Center
    • App Store Awards(英語)
    • Apple Design Awards
    • Apple Developer Academy(英語)
    • WWDC
    Apple Developerアプリを入手する
    Copyright © 2025 Apple Inc. All rights reserved.
    利用規約 プライバシーポリシー 契約とガイドライン