『マジ文章書けないんだけど~朝日新聞ベテラン校閲記者が教える一生モノの文章術~』
書店員の友人から「タイトルの割にしっかりした内容で、ためになる」とおすすめされた本。
「マジ文章書けないんだけど」と言うほどひどくはない、…と思いたいけれど、
私も文章が上手く書けないと悩むことが多いので読んでみました。
内容の紹介
就活を控えた女子大生・すずが、文章の達人である謎のおじさんに文章の書き方を教えてもらうストーリー仕立てになっています。
最初は簡単な文法の説明から、だんだんと文章の膨らませ方、エントリーシートの書き方へと進みます。
就活生向けの内容と思いきや、就活に限定した内容は最後の15ページほどなので、意外と万人向けでした。
くだけた会話調で書かれ、可愛いイラストも多いので、本を読むのが苦手という人には読みやすいと思います。
この本が紹介する「文章術」の半分は、
- 助詞の「は」と「が」の違い
- 主語と述語を対応させる
- こそあど言葉
など、とても基本的な文法の説明です。
もう半分は
- 一つの文に一つの内容
- 5W1H、特にWhyが重要
- 結論から先に書く
など、これもまた一度は聞いたことがあるような基本的な内容がほとんど。
タイトル通り「マジ文章書けないんだけど」な人にわかりやすい文章の書き方、書き始め方を教える本なので、ある程度勉強している人には物足りないかもしれません。
私もほとんど聞いたことのある内容ではありましたが、改めて振り返ると結構できていないもので。
文筆のプロのような上手い文章が書けるテクニックの紹介を期待していたので、そういう意味では期待はずれでしたが、上部のテクニックや色気を出す前に、基礎基本をきちんとすることが大事ですね。
この本の良いところは、本当にありそうなダメな文章の例を出して、ダメな原因と改善例が説明されているところです。
例えば
「このバックはブランドものなので、値段と人気が高く、品質とデザインが美しいブランドだ」
という文例。
自分もこんな文を書いている、ダメなのはわかるが何がダメでどう直せばいいのか説明できないという人には一読の価値ありです。
個人的に特に参考になったのは以下のアドバイスです。
- 一つの文に一つの内容
- 「だが」と「ので」などのつなぎ言葉はできるだけ使わない
私は一つの文にいろいろ詰め込んで文が長くなりがちで、結局何が言いたいかが迷子になることがよくあります。
この本を読んでから、意識的に文を短くシンプルにするようになり、少し良くなった実感があります。
文を短くした方が書くのも早いですね。
書かれている内容が根本的であるだけに実践しやすく、普遍的に使える”一生モノの文章術”だと思いました。
【Xcode】XCUITest + fastlane/snapshotで始めるUIテスト(後編)
後編ではfastlane/snapshotを導入して、任意のタイミングでスクリーンショットを取得します。
前編はこちらから。
【Xcode】XCUITest + fastlane/snapshotで始めるUIテスト(前編) - 文系プログラマの勉強ノート
fastlane/snapshotとは
fastlaneは、iOS/Androidアプリのリリース作業を自動化するツール群です。
そのうちの一つであるsnapshotを使うと、UIテストをしながらストア申請時のスクリーンショットを自動作成できます。
開発環境
- Mac OS Sierra
- Xcode8.3
- Swift3
導入手順
1.Xcode command line toolsをインストールする
ターミナルを起動し、Xcode command line toolsをインストールします
$ xcode-select --install
2.fastlaneをインストールする
ターミナルからRubygemsを使ってインストールします。
この他、Homebrew、Zipで入れる方法もあります
$ sudo gem update $ sudo gem install fastlane -NV
3.snapshotを初期化する
snapshotを取りたいアプリの .xcodeproj ファイルがあるディレクトリに移動し、下記のコマンドを実行します。
$ cd /Users/xxx/XCUITestSample $ fastlane snapshot init $ sudo gem install fastlane -NV
下記のファイルが生成されます。
- Snapfile
- SnapshotHelper.swift
4.SnapshotHelper.swiftをプロジェクトに追加する
Xcodeを起動し、生成されたSnapshotHelper.swift をUIテストターゲットに追加します。
SnapshotHelper.swift は移動可なので、私はファイル本体も UIテストディレクトリ以下に移動しました。
5.テストコードを編集する
前編で作成した ***UITests.swift の setUp() を修正します。
//XCUIApplication().launch()
let app = XCUIApplication()
setupSnapshot(app)
app.launch()
UIテストコード(ここではtestExample())のスクリーンショットを取得したい箇所に下記のコードを追加します。
""の文字列は任意の文字列です。画像ファイル名に使用されますので、重複しないようにします。
snapshot("ScreenShot_01")
6.Snapfileを編集する
スクリーンショットを取得したい端末と言語をSnapfileに記載します。
以下は iPhone7 の日本語の場合です。
devices([ "iPhone 7", "iPhone 7 Plus", ]) languages([ "en-US", "ja-JP", ])
7.fastlane/snapshotを実行する
ターミナルから下記のコマンドでfastlane/snapshotを実行します。
(snapshotを取りたいアプリの .xcodeproj ファイルがあるディレクトリで実行してください)
$ fastlane snapshot
設定ファイルやテストコードに問題がなければ、自動的にシミュレータが起動し、テストが実行されます。
完了すると screenshots/screenshots.html が表示されます。
screenshots/screenshots.html には作成されたスクリーンショットが環境別に一覧になっています。
画像は screenshots ディレクトリ以下に保存されます。
公式ドキュメントによると、ストア申請用にデバイスフレームをつけたりもできるようです。
参考URL
【Xcode】XCUITest + fastlane/snapshotで始めるUIテスト(前編)
前編では、XCUITestを導入してUITestを実行してみます。
XCUITestとは
Xcode7から追加されたUIテスト機能です。
UIテストをするためのフレームワークはEarlGreyやappiumなどもありますが、
iOS8以降対応で問題なければ、XCUITestが扱いやすいと思います。
開発環境
- Mac OS Sierra
- Xcode8.3
- Swift3
導入手順
1. UI Testing Bundleを追加する
UITestを追加したいプロジェクトを開き、メニューの File > New > Target... を選択します。
iOS > Test > "iOS UI Testing Bundle" を選択して Next を押します。
Product Name を入力して Finish を押します。
(新規プロジェクトの場合は、作成時にプロジェクト名などを入力する画面で "Inclure UI Tests" にチェックを入れればOK)
2. テスト対象となる機能を作成する(すでにある場合は次へ)
今回はテスト用なので、テキストフィールドに文字を入力して決定ボタンを押すと
入力内容がアラートで表示される機能にしました。
3. Accessibility identiferを設定する(すでにある場合は次へ)
テストコードからコントロールにアクセスするために、Accessibility identiferを設定します。
コードから追加する方法もありますが、ここではIBを開いてコントロールを選び、右側のペインの
Identity inspector(左から3番目) > Accessibility > identifer
に一意の文字列を設定します。
※Accessibility identiferが保存されない場合※
稀にAccessibility identiferを設定しても、実行時に保存されていないことがあります。
その場合、Accessibility identifer設定後に、座標やサイズなどレイアウト情報を変更すると保存されました。
(おそらくXcodeのバグ。保存されたあとはレイアウト情報は戻して大丈夫です。)
4. テストコードを作成する
先程追加したUITestTarget内のswiftファイルにテストコードを書きます。
(デフォルトでは"[ProjectName]UITests.swift"というファイル名になっていると思います。)
初期状態で「testExample()」というメソッドが作成されていますが、
このように「test〜」で始まるメソッドがテスト時に実行されるコードになります。
testExample()内にテストコードを作成します。
"textField"、"decisionButton"は先程設定したAccessibility identiferです。
func testExample() { let app = XCUIApplication() // 文字を入力 let textField = app.textFields["textField"] textField.tap() textField.typeText("UIテストを実行") // 決定ボタンをタップ let button = app.buttons["decisionButton"] button.tap() // 入力内容がアラートに表示される }
5. テストを実行する
メニューの Product > Test を選択するか、テストメソッド名の左側の◇ボタンを押してテストを実行します。
◇ボタンが緑色になれば成功、赤くなれば失敗です。
【Xcode】コードだけでグラデーション作成
下図のようなグラデーションをコードだけで作る方法です。
override func viewDidLoad() { super.viewDidLoad() let colors = [UIColor(red: 112/255, green: 134/255, blue: 241/255, alpha: 1.0).cgColor, UIColor(red: 40/255, green: 169/255, blue: 255/255, alpha: 1.0).cgColor, UIColor(red: 180/255, green: 225/255, blue: 255/255, alpha: 1.0).cgColor] let gradientLayer = gradientLayerWith(frame: view.bounds, colors: colors) view.layer.addSublayer(gradientLayer) } func gradientLayerWith(frame: CGRect, colors: Array<Any>) -> CAGradientLayer { let layer = CAGradientLayer() layer.frame = frame layer.colors = colors // グラデーションの向きを横にしたい場合 layer.startPoint = CGPoint(x: 0, y: 0.5) layer.endPoint = CGPoint(x: 1, y: 0.5) return layer }
【Xcode】UIAlertControllerで簡単進捗ダイアログ作成
カスタムビューを作らず、UIAlertControllerで簡単な進捗ダイアログを表示する方法です。
// インジケータ表示 alert = UIAlertController(title: "Loading...", message: "\n", preferredStyle: .alert) let indicator = UIActivityIndicatorView() indicator.translatesAutoresizingMaskIntoConstraints = false alert.view.addSubview(indicator) let views: [String: UIView] = ["alert": alert.view, "indicator": indicator] var constraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[indicator]-(12)-|", options: [], metrics: nil, views: views) constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|[indicator]|", options: [], metrics: nil, views: views) alert.view.addConstraints(constraints) indicator.isUserInteractionEnabled = false indicator.color = UIColor.lightGray indicator.startAnimating() present(alert, animated: true, completion: { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { self.alert.dismiss(animated: true, completion: { self.alert = nil }) } })
こちらのサイトの回答を参考にSwift3.0の文法で書き直し、インジケータの位置を調整しました。
アラートの高さをmessageの改行で調整しているのが少々ださいですが、
カスタムビューを作らなくて良いのでお手軽ですね。
stackoverflow.com
【Xcode】UIAlertControllerの外側をタップで閉じる & Toast風に一定時間後に閉じる方法
UIAlertControllerの外側をタップで閉じる
UIAlertControllerで、外側(上の図でグレーの部分)をタップすると閉じる方法です。
class ViewController: UIViewController { var alert: UIAlertController! override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // 外側をタップで非表示 alert = UIAlertController(title: "Alert", message: "Tap outside of alert and dismiss", preferredStyle: .alert) present(alert, animated: true, completion: { self.alert.view.superview?.isUserInteractionEnabled = true self.alert.view.superview?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.closeAlert))) }) } func closeAlert() { alert.dismiss(animated: true, completion: nil) alert = nil } }
一定時間後に消えるToast風AlertController
AndroidのToastのように、タップしなくても一定時間後に消える方法です。
class ViewController: UIViewController { var alert: UIAlertController! override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) // 一定時間後に非表示 alert = UIAlertController(title: nil, message: "This alert will disappear after 3 sec", preferredStyle: .alert) present(alert, animated: true, completion: { self.perform(#selector(self.closeAlert), with: nil, afterDelay: 3.0) }) } func closeAlert() { alert.dismiss(animated: true, completion: nil) alert = nil }
Toast風の方はExtension化しておけば使い手がありそう。
Speech Synthesis API を使って動的に音声を読み上げる
Web Speech APIの一つ、Speech Synthesis API を使って動的に音声読み上げさせるサンプルです。
最近の標準的なブラウザで使用でき、音声データを用意することなく読み上げ機能を実現できます。
動作サンプル
サンプルコード
<!DOCTYPE html> <html> <head> <title>音声読み上げサンプル</title> <meta charset="UTF-8"> </head> <body> <p> <input id="text" type="text" size="60" value="吾輩は猫である。名前はまだない。"> <button id="play">音声読み上げ</button> </p> <script> document.getElementById('play').addEventListener('click', function(){ var text = document.getElementById('text').value; speak(text); }); var tmp; function speak(text) { // 再生中の音声をキャンセル speechSynthesis.cancel(tmp); // 日本語音声で読み上げ var speech = new SpeechSynthesisUtterance(); speech.lang = 'ja-JP'; speech.text = text; speechSynthesis.speak(speech); tmp = speech } </script> </body> </html>