「クリップボードのテキストを保存してiTunesのファイル共有で取り出せるようにするiPhoneアプリ」の作り方

私は視覚障害者(全盲)です。Mac OSの画面読み上げ機能「VoiceOver」を使って、iPhoneのアプリの作り方を勉強中です。

必要なキーボードショートカット

画面を見ながらマウスを操作することができないので、キーボード操作を駆使してVoiceOverの読み上げの音声を頼りにXcodeを使います。

次のようなキーボードショートカットを使います。

  • コマンド+シフト+N – 新規プロジェクト
  • Caps(VoiceOverキー)+コマンド+エンド(FN+ミギカーソル) – 画面の最後のオブジェクト(ボタンやリストやテーブルなど)へ
  • Caps+コマンド+ホーム(FN+左カーソル) – 画面の最初のオブジェクトへ
  • コマンド+1 – プロジェクトナビゲータへ
  • Caps+シフト+下カーソル – プロジェクトナビゲータやエディタなど(オブジェクト)を操作できる状態にする
  • Caps+シフト+上カーソル – オブジェクト操作状態をぬける
  • Caps+左カーソル/Caps+右カーソル – 操作したいオブジェクトに移動
  • コントロール+オプション+コマンド+3 – オブジェクトライブラリへ移動
  • Caps+シフト+コマンド+スペース – ドラッグ開始/ドロップ(ドラッグ中に「シュー、シュー、シュー」と音がする)
  • オプション+コマンド+エンター – アシスタントエディタを開く。ソースコードからキャンバスへドラッグ&ドロップするときに必要。
  • Caps+シフト+M – 右クリックメニューを開く
  • Caps+スペース – 選択
  • Caps+コマンド+スペース – コンテキストメニューみたいなものが出てくる

アプリのDocumentsフォルダ(ファイル共有)を使うための設定

「Info.plist」をプロジェクトナビゲータで選び、編集するのですが、今のところうまくできません。

Info.plistをテキストエディタで直接開いて、次のような行を追加します。

<key>UIFileSharingEnabled</key>
<true/>

「円マーク」ではなく「バックスラッシュ」を使う

改行のためやエラーメッセージのために入力する記号は「¥円マーク」ではなく、「バックスラッシュ」で、オプションキーを押しながら0の3つミギのキーを押して入力します。(Windowsとは違いますね)

ラベルとボタンをキャンバスに張り付けてコードと接続する

ボタンやラベルの位置やサイズ、コンストレインツなどの設定はまだよくわかりません。

「stack view」を先に張り付け、そこにラベルとボタンを張ると、とりあえず重ならずにボタンとラベルを配置できます。

下記のコードは、Label1つとButtonを2つ、「vertical stack view」の上に張り付けて作りました。(ラベル、ボタン1、ボタン2が縦に自動的に並びます。)

「ViewController.swift」の内容

import UIKit

class ViewController: UIViewController {
@IBOutlet var messageLabel:UILabel! // メッセージ用ラベル
@IBOutlet var newButton:UIButton! // 「新規保存」ボタン
@IBOutlet var appendButton:UIButton! // 「追加保存」ボタン
let pasteboard = UIPasteboard.general // クリップボード(ペーストボード)を使う
let clipFileName = "clip.txt" // 保存するファイル名
var clipCount = 0 // クリップボードをコピーした回数
@IBAction func newTapped(sender:UIButton) { // 「新規保存」ボタンがタップされたとき
    let initialText = pasteboard.string! + "\n" // 保存する文字列にペーストボードの内容を入れる
    if let documentDirectoryFileUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last {
        let targetTextFilePath = documentDirectoryFileUrl.appendingPathComponent(clipFileName)
        do {
            try initialText.write(to: targetTextFilePath, atomically: true, encoding: String.Encoding.utf8)
            messageLabel.text = "新規保存"
            clipCount = 0 // コピーした回数を0にもどす
        } catch let error as NSError {
            print("書き込み失敗: \(error)")
        }
    }
}
@IBAction func appendTapped(sender:UIButton) { // 「追加保存」ボタンがタップされたとき
    if let documentDirectoryFileUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last {
        let targetTextFilePath = documentDirectoryFileUrl.appendingPathComponent(clipFileName)
        do {
            let fileHandle = try FileHandle(forWritingTo: targetTextFilePath)
            let stringToWrite = "\n\n" + pasteboard.string!
            fileHandle.seekToEndOfFile()
            fileHandle.write(stringToWrite.data(using: String.Encoding.utf8)!)
            clipCount+=1 // 追加した回数
            messageLabel.text = clipCount.description + "回目の追加"
        } catch let error as NSError {
            print("追加失敗: \(error)")
        }
    }
}
override func viewDidLoad() {
    super.viewDidLoad()
    messageLabel.text = "クリップボードを保存します" // ボタンをタップする前のラベルのテキスト
    newButton.setTitle("新規保存", for:UIControlState.normal) // ボタンに表示される名前をセット
    appendButton.setTitle("追加保存", for:UIControlState.normal) // ボタンに表示される名前をセット

    // Do any additional setup after loading the view, typically from a nib.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}
}

参考

関連投稿