RORK LABEN
BUILD — Rork Max はクラウド上の実機 Mac に Xcode と iOS SDK を載せ、SwiftUI を書き、ビルドし、エラーを読んで直す反復を回します。コードを吐いて終わりではない点が生成物の質に効いていますNATIVE — 生成されるのは React Native ではなく純粋な Swift / SwiftUI です。AR や Metal、ウィジェットなど React Native からは届かない機能に手が届くことが、他ビルダーとの実質的な差になりますPLATFORMS — 対応は iPhone・iPad・Apple Watch・Apple TV・Vision Pro に加えて iMessage まで含みます。ウォッチや拡張から入る設計を試すのに向いていますCOMPANION — Rork Companion により、有料の Apple Developer アカウントなしで生成したアプリを実機の iPhone で確認できます。最初の一本を試す段階の障壁が一段下がりましたPRICING — 無料で開始でき有料プランは月額25ドルから、Rork Max は月額200ドルの Max プランです。回収できる本数と規模を先に見積もっておく価値がありますDEADLINE — Google Play は2026年8月31日以降、新規アプリと更新の双方に対象 API レベル36 以上を要求します。残り10日で、生成物の targetSdkVersion は自分で確認が必要ですBUILD — Rork Max はクラウド上の実機 Mac に Xcode と iOS SDK を載せ、SwiftUI を書き、ビルドし、エラーを読んで直す反復を回します。コードを吐いて終わりではない点が生成物の質に効いていますNATIVE — 生成されるのは React Native ではなく純粋な Swift / SwiftUI です。AR や Metal、ウィジェットなど React Native からは届かない機能に手が届くことが、他ビルダーとの実質的な差になりますPLATFORMS — 対応は iPhone・iPad・Apple Watch・Apple TV・Vision Pro に加えて iMessage まで含みます。ウォッチや拡張から入る設計を試すのに向いていますCOMPANION — Rork Companion により、有料の Apple Developer アカウントなしで生成したアプリを実機の iPhone で確認できます。最初の一本を試す段階の障壁が一段下がりましたPRICING — 無料で開始でき有料プランは月額25ドルから、Rork Max は月額200ドルの Max プランです。回収できる本数と規模を先に見積もっておく価値がありますDEADLINE — Google Play は2026年8月31日以降、新規アプリと更新の双方に対象 API レベル36 以上を要求します。残り10日で、生成物の targetSdkVersion は自分で確認が必要です
記事一覧/開発ツール
開発ツール/2026-07-04上級

Rork Max のアプリで、選んだ写真が次回起動時に消えている — PHPicker の限定アクセスで URL を握り続けようとする罠

Rork Max が生成したネイティブ Swift アプリで、PHPickerViewController で選んだ写真が再起動後に読めなくなる——限定アクセスの時代に URL や PHAsset を握り続けようとするのが原因でした。選んだ瞬間に自前ストレージへ実体をコピーする設計をまとめます。

Rork Max233PHPickerViewControllerPhotoKit2限定アクセスSwift48iOS109

プレミアム記事

ユーザーが選んだ数枚の写真をコラージュに使うだけの機能を、Rork Max が生成したアプリへ足したときのことです。PHPickerViewController で選んだ写真はその場では問題なく表示され、加工も効きます。ところがアプリを再起動すると、直前に選んだはずの写真が真っ黒、あるいは読み込みに失敗する。選び直せば直りますが、保存したはずの状態が壊れている、という報告に近い挙動でした。エラーらしいエラーは出ません。

原因は、PHPicker が返す一時的な参照を「あとで読めばいい」と握り続けていたことです。限定アクセスが当たり前になった今の iOS では、選択時点で有効だった URL や PHAsset の識別子が、次回には読めなくなる前提で設計する必要があります。個人開発で写真アプリを長く触ってきましたが、この「選んだ瞬間だけ有効」という限定アクセスの性質を取りこぼすと、本番で静かにデータが欠けます。ここでは Rork Max のネイティブアプリに写真取り込みを最小差分で足す前提で、握り続ける罠の避け方と、そのまま使える取り込みレイヤーを順に見ていきます。

PHPicker が「権限を求めない」代わりに渡すものの正体

PHPickerViewController の大きな利点は、フォトライブラリの権限ダイアログを出さずに使えることです。ユーザーがシステム UI の中で選んだ写真だけがアプリに渡るので、アプリはライブラリ全体へのアクセス権を持ちません。ここが従来の UIImagePickerController との決定的な違いです。

渡ってくるのは実体ではなく「取り出し口」

PHPicker が返す NSItemProvider は、写真の実体そのものではなく「今なら取り出せる口」です。loadFileRepresentationloadDataRepresentation でその場で読み出すことはできますが、返ってくる一時ファイルの URL はコールバックを抜けた後には失効します。ここを「URL を保存しておいて後で開けばいい」と考えると、次回起動時に読めない状態に落ちます。

PHAsset の識別子も永続の保証ではない

PHPickerConfigurationpreferredAssetRepresentationMode を調整すれば PHAsset に到達する構成も取れますが、限定アクセス下では、そのときアプリに見えていた asset が次回も見えるとは限りません。ユーザーが後で選択範囲を変えれば、識別子は残っていても実体へ辿れなくなります。私は写真アプリの運用で、asset 識別子の永続化に頼る設計は避けるようになりました。

解決の芯は「選んだ瞬間に実体をコピーする」こと

握り続ける発想をやめて、選択のコールバックの中で実体を自分の永続領域(Application Support など)へコピーしきってしまう。以後はそのローカルファイルだけを参照する。これが限定アクセス時代の素直な設計です。取り込み時に一度だけコストを払い、あとは自前のファイルとして扱うことで、URL 失効も選択範囲変更も無関係になります。

import PhotosUI
import UniformTypeIdentifiers
import os
 
let picLog = Logger(subsystem: "net.rorklab.sample", category: "photo")
 
enum PhotoImportError: Error { case noImageRep, copyFailed }
 
final class PhotoImporter {
    private let dir: URL = {
        let base = FileManager.default.urls(for: .applicationSupportDirectory,
                                            in: .userDomainMask)[0]
        let d = base.appendingPathComponent("imported", isDirectory: true)
        try? FileManager.default.createDirectory(at: d, withIntermediateDirectories: true)
        return d
    }()
 
    // PHPicker の結果を受け取り、永続パスの配列を返す
    func importItems(_ results: [PHPickerResult]) async -> [URL] {
        var saved: [URL] = []
        for result in results {
            do {
                let url = try await copyToLocal(result.itemProvider)
                saved.append(url)
                picLog.info("imported: \(url.lastPathComponent)")
            } catch {
                picLog.error("import failed: \(error.localizedDescription)")
            }
        }
        return saved
    }
}

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
PHPicker で選んだ写真が再起動後に消える症状を、限定アクセス・一時 URL の失効・PHAsset の非永続性のどこが原因か切り分けられるようになります
選択直後に実体を App の永続領域へコピーし、以後はローカルのファイルだけを参照する取り込みレイヤーを、そのまま Rork Max の生成コードに足せる形で手に入ります
限定アクセスでフォトライブラリ権限を求めない PHPicker の強みを保ちつつ、書き出し・向き補正・容量まわりを本番で破綻させない勘所がわかります
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

開発ツール2026-07-13
HealthKitの差分同期でデータを取りこぼす — HKAnchoredObjectQueryのアンカーを設計する
HealthKitの差分同期で歩数や睡眠が二重に数えられたり欠けたりする原因は、HKQueryAnchorの永続化設計にあります。newAnchorとdeletedObjectsを正しく扱い、再インストールやバックグラウンド更新をまたいでも整合するローカル取り込みの実装を、動くSwiftコードでまとめました。
開発ツール2026-07-11
Rork Max で App Clip を実装する — QR を読んだ瞬間にアプリの核だけを届ける設計メモ
Rork Maxが出力するネイティブSwiftを土台に、App Clipを実装する設計メモです。15MB制約を守るターゲット分割、NSUserActivityでの起動URL受け取り、apple-app-site-associationの設定、親アプリへの状態引き継ぎまでを実装ベースで整理します。
開発ツール2026-07-08
Rork Max のジオフェンスが20件で頭打ちになる問題を、動的再登録で解く
Rork Max が生成したネイティブ Swift のアプリで、登録したはずのジオフェンスが途中から反応しなくなる——その多くは iOS の「1アプリ20件」という上限に静かにぶつかっています。近い順に20件だけを登録し直す動的再登録の設計と、そのまま組み込める Swift の実装をまとめます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →