RORK LABEN
MAX — Rork MaxはネイティブSwiftアプリを生成し、iPhone・iPad・Apple Watch・Apple TV・Vision Pro・iMessageに対応しますNATIVE — Rork MaxはAR/LiDARスキャン、Metalの3D、ウィジェット、Live Activities、HealthKitなどネイティブ機能を解放しますFUNDING — Rorkはa16zから280万ドルを調達し、月間訪問は74万を超え、成長率は85%に達していますRN — 通常のRorkはReact Native(Expo)でiOSとAndroidアプリをまとめて生成しますFOCUS — Rorkはネイティブモバイルアプリ専業で、Web中心のBoltやLovableと一線を画しますPRICING — 無料で始められ、有料プランは月25ドルから、Rork Maxは月200ドルで2クリックのApp Store公開に対応しますMAX — Rork MaxはネイティブSwiftアプリを生成し、iPhone・iPad・Apple Watch・Apple TV・Vision Pro・iMessageに対応しますNATIVE — Rork MaxはAR/LiDARスキャン、Metalの3D、ウィジェット、Live Activities、HealthKitなどネイティブ機能を解放しますFUNDING — Rorkはa16zから280万ドルを調達し、月間訪問は74万を超え、成長率は85%に達していますRN — 通常のRorkはReact Native(Expo)でiOSとAndroidアプリをまとめて生成しますFOCUS — Rorkはネイティブモバイルアプリ専業で、Web中心のBoltやLovableと一線を画しますPRICING — 無料で始められ、有料プランは月25ドルから、Rork Maxは月200ドルで2クリックのApp Store公開に対応します
記事一覧/アプリ開発
アプリ開発/2026-06-29中級

クリップボード連携のUXを整える — iOSのペースト許可バナーを増やさずに「コピー」と「貼り付け」を成立させる

expo-clipboard で「コピー」と「貼り付け」を実装するとき、iOS のペースト許可バナーが頻発して使い勝手を損なうことがあります。バナーの発生条件を押さえ、hasStringAsync で内容を読まずにボタンを出し分ける設計をまとめました。

Rork475Expo123クリップボードiOS86UX設計6

プレミアム記事

個人開発で運用している壁紙アプリに招待コードの引き換え画面を足したとき、画面を開くたびに「○○からペーストしました」という小さな通知が画面上部に出てしまい、テスターから「これは大丈夫なものなんですか」と何度も尋ねられました。原因はすぐに分かりました。親切心のつもりで、画面が表示されると同時にクリップボードを読み、コード欄へ自動入力していたのです。読んだ瞬間にあのバナーが出ます。私自身、App Store に出している複数のアプリで同じ落とし穴を踏んでおり、これは一度きちんと整理しておく価値のある題材だと考えています。

クリップボード連携は、コードを1行コピーするだけの単純な機能に見えて、iOS の挙動を知らないと「うるさいアプリ」になってしまいます。ここでは expo-clipboard を使いながら、ペースト許可バナーを必要以上に出さず、それでいてコピーと貼り付けが気持ちよく成立する設計を整理します。

ペースト許可バナーはどこで発生するのか

混乱しやすいのですが、コピー(書き込み)とペースト(読み取り)では扱いがまったく違います。

書き込み、つまり Clipboard.setStringAsync() は何の通知も出しません。ユーザーがコピーボタンを押した結果なので、当然といえば当然です。問題は読み取り側です。iOS 16 以降、別アプリがコピーした内容を Clipboard.getStringAsync() で読むと、「○○からペーストしました」というバナーが表示されます。これはユーザーに「いま勝手にクリップボードを覗きましたよ」と知らせるための仕様で、無効化できません。

ここで効いてくるのが「いつ読むか」です。私の失敗は、ユーザーが何も操作していないのに画面表示と同時に読んでしまったことでした。ユーザー自身が「貼り付け」を押した直後の読み取りなら、バナーが出ても文脈と一致しているので不快になりません。逆に、開いた瞬間や数秒おきのポーリングで読むと、身に覚えのないバナーが連発し、不信感につながります。

読むタイミングを決めるときは、次の順序で考えると迷いません。

  1. クリップボードに何か入っているかは、内容を読まずに確認する
  2. 「貼り付け」ボタンは、入っているときだけ押せるようにする
  3. 実際に中身を読むのは、ユーザーがそのボタンを押した直後だけにする

この3点を守るだけで、不要なバナーはほぼ回避できます。

操作APIiOS のバナー
コピー(書き込み)setStringAsync()出ない
内容を読む(貼り付け)getStringAsync()出る(iOS 16+)
有無だけ確認hasStringAsync()出ない

hasStringAsync で内容を読まずにボタンを出し分ける

最後の行が鍵です。hasStringAsync() は「クリップボードに文字列があるか」を真偽値で返すだけで、中身そのものは読みません。そのためバナーも出ません。これを使えば、クリップボードが空のときは「貼り付け」ボタンを無効化し、何か入っているときだけ押せるようにできます。実際に読むのはユーザーがそのボタンを押した瞬間だけです。

import { useEffect, useState } from "react";
import * as Clipboard from "expo-clipboard";
 
function RedeemCodeField({ onPaste }: { onPaste: (value: string) => void }) {
  const [canPaste, setCanPaste] = useState(false);
 
  // 中身は読まず「有無」だけ確認するのでバナーは出ない
  useEffect(() => {
    let mounted = true;
    Clipboard.hasStringAsync().then((has) => {
      if (mounted) setCanPaste(has);
    });
    return () => {
      mounted = false;
    };
  }, []);
 
  // 実際に読むのはユーザーがボタンを押した瞬間だけ
  const handlePaste = async () => {
    const text = await Clipboard.getStringAsync();
    if (text) onPaste(text.trim());
  };
 
  return (
    <PasteButton disabled={!canPaste} onPress={handlePaste} />
  );
}

hasStringAsync() を画面表示時に一度呼ぶだけなら、バナーは出ません。アプリがフォアグラウンドに戻ったタイミングでも確認したい場合は、AppStatechange イベントで active になったときに再度 hasStringAsync() を呼びます。ここでも読むのは有無だけなので安全です。

招待コードのように形式が決まっているなら、貼り付けた文字列をそのまま入れず、text.trim() で前後の空白を落としたうえで、想定する形式に合うかを軽く検証してから反映すると、ユーザーが余計な文字ごとコピーしてしまったときにも破綻しません。

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

この記事の続きを読む

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

この記事で得られること
iOS のペースト許可バナーが発生する正確な条件と、それを増やさずに貼り付け機能を提供する設計
hasStringAsync で内容を読まずに「貼り付け」ボタンを出し分ける実装パターン
コピー成功の確実なフィードバックと、機密データを扱うときの後始末
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

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

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

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

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

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

関連記事

アプリ開発2026-06-27
「本当に削除しますか?」を出す前に — 取り消せる削除という選択肢
リストの項目を消すたびに確認ダイアログを出すと、ユーザーは反射的にOKを押すようになります。Rork(Expo)アプリで「取り消せる削除」を実装し、確認を出すべき場面と出さない場面を切り分ける設計ノートです。
アプリ開発2026-06-29
従量制回線と低データモードを尊重して先読みを止める通信設計
画像中心の Rork(Expo)アプリで、従量制回線や低データモードのときに先読みを抑える通信設計を扱います。NetInfo の details から回線の性質を読み、画質を落とし、プリフェッチを遅延させる適応ロジックを実装コードとともに整理します。
アプリ開発2026-06-27
アップデート後の「新着情報」を、しつこくなく一度だけ出す設計 — バージョン境界とseen状態の作り方
更新後に出すアプリ内「新着情報」画面が、新規インストールにまで出たり毎回出たりして嫌われる問題を、バージョン境界とseen状態の設計で一度だけ確実に届ける。Rork(Expo)の実コードと、複数アプリで使い回す型までまとめます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →