◉RORK LABEN
●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…●GPT-6.1 SOL — Rork のモデルメニューに追加(09-29)。Low/Medium/High を選べ、Pro・Max に含まれます●SONNET 5.5 — UI づくりが得意で、Sonnet 5 より出力が速いモデルが選べます(09-28)●SDK 58 — Beta が 09/15 から。stable の案内はまだなく、Expo Go でのプロジェクト実行は 09/03 からログインが必要です●WIDGET — iOS のウィジェットが本番ビルドだけ真っ黒になる原因を追った報告が出ています●OBSERVE — EAS Observe がネイティブクラッシュも記録します(SDK 57.0.21 以降・10/07)●NEW — 起動広告が、背面から戻った回にしか出ていませんでした。「前面に戻った」合図が、…
記事一覧/アプリ開発
◇ アプリ開発/2026-06-29中級

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

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

Rork585Expo219クリップボードiOS115UX設計7

✦ プレミアム記事

個人開発で運用している壁紙アプリに招待コードの引き換え画面を足したとき、画面を開くたびに「○○からペーストしました」という小さな通知が画面上部に出てしまい、テスターから「これは大丈夫なものなんですか」と何度も尋ねられました。原因はすぐに分かりました。親切心のつもりで、画面が表示されると同時にクリップボードを読み、コード欄へ自動入力していたのです。読んだ瞬間にあのバナーが出ます。私自身、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() を画面表示時に一度呼ぶだけなら、バナーは出ません。アプリがフォアグラウンドに戻ったタイミングでも確認したい場合は、AppState の change イベントで active になったときに再度 hasStringAsync() を呼びます。ここでも読むのは有無だけなので安全です。

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

✦

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

この記事の続きを読む

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

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

この記事を購入する

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

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

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

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

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

関連記事

◇ アプリ開発2026-10-15
adjustsFontSizeToFit で特定の1行だけ極小になるとき、疑うのは文字列ではなく枠の高さです
一覧の10行目だけ文字が4ptまで縮む。データも文字列も正常なのに起きる iOS の症状を、Yoga の丸めと縮小判定のソースで確かめ、Node で再現率を数えた記録です。
◇ アプリ開発2026-09-18
prebuild が requires the standard Expo SDK 57 Swift AppDelegate で止まったとき、まず確かめる3行
iOS 27 のために ios.enableSceneSupport を有効にすると prebuild が止まることがあります。原因は SDK の版ではなく AppDelegate.swift の形でした。確かめる3行と、手で書くときに SDK 58 の手順を真似てはいけない理由をまとめます。
◇ アプリ開発2026-09-16
消したはずのトークンが再起動で戻る — SecureStore の削除失敗を検知する設計
サインアウト直後に getItemAsync が null を返しても、Android のディスクには値が残っていることがあります。削除の成否を読み出しで確かめていた実装を、戻り値で判断する形へ書き直した記録です。