iOS で Slack に投稿するアプリを作り実機にインストール
iOS チュートリアルが一通り終わったので、Slack に投稿するアプリを作ってみることにしました。
レポジトリは以下。
元々 Android 版をシュッと作っていたので、iOS 版という位置づけでやってみます。
アプリの機能は非常に単純で、webhook の URL を入力し、ユーザー名、アイコン、文字列を指定して OK を押すと JSON を webhook サーバーに POST するというものです。
UI を作る
Andorid では適当に EditText
を並べたものでしたが、iOS ではそのような UI はあまり見ないので UITableView
に UITextField
を入れることにしました。
↑のようにUIを組み立てていきます。
UITAbleView
で予め表示する要素が決定しているときは Static Cells
を使います。StoryBoard
上で内容を決定しておくとUITableView
で表示する部分のコードを書かなくて済むので楽。
Cell
の内部全体に UITextField
を入れています。
ここで、特に何も設定せずに左端に置くと親の margin がうまく反映されずに左に寄りすぎてしまいました。
これを防ぐには親の Table View Cell
と Content View
の Preserve SuperView Margins
のチェックを入れて、再度 Update Frames
をクリックします。
すると、正しい位置になってくれました。
ここで、本文に複数行入れたいときは UITextField
ではなく UITextView
を使いますが、Static Cells
だと改行した時に上手く Cell が広がってくれなかったので諦めました。*1
あとは Done
ボタンを設置したり、タイトルを設定したりして完成です。
Done ボタンを押した処理を書く
メッセージ送信
次は Done
を押した時にメッセージを送信する処理を書きます。ネットワークを使う場合、AFNetWorking
が著名なようですが、今回は学習の意味を兼ねてライブラリを使わずに POST することにします。
swift で POST するには以下の記事の通りに行えばよいです。
プログレス表示のために CocoaPods を導入
さて、何も表示しないと不安なのでプログレスダイアログを表示することにします。iOS のプログレスダイアログといえば MBProgressHUD
が有名みたいなので、それを使うことにしました。*2
ライブラリを簡単に管理するために Swift / Obj-C の依存性管理ツールである CocoaPods
を導入します。
まずは bundle の Gemfile
と同じように Podfile
を書きます。
platform :ios, '9.0' use_frameworks! pod 'MBProgressHUD', '~> 0.9.2'
そして pod install
すると {MyApp}.xcworkspace
というフォルダが作られるので、一旦 Xcode を閉じて xcworkspace
を開きます。
すると CocoaPods
経由でインストールしたライブラリが使えるようになります 🎉
プログレス表示
MBProgressHUD
を使ってプログレスを出し、投稿できたらチェックマークを出します。ダメなら Alert を出すというコードを書きました。
// show progress let progress = MBProgressHUD.showHUDAddedTo(self.view, animated: true) progress.mode = .Indeterminate progress.labelText = "Sending" NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: {data, response, error in // main thread dispatch_async(dispatch_get_main_queue(), { var errorMessage: String? if let error = error { errorMessage = error.localizedDescription } else if (response as! NSHTTPURLResponse).statusCode / 100 != 2 { errorMessage = NSString(data: data!, encoding: NSUTF8StringEncoding)! as String } if let message = errorMessage { progress.hide(true) // show error alert let alert = UIAlertController(title: "Message not sent", message: message, preferredStyle: .Alert) alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil)) self.presentViewController(alert, animated: true, completion: nil) } else { // show check mark progress.customView = UIImageView(image: UIImage(named: "CheckMark")) progress.mode = .CustomView progress.labelText = "Message sent" progress.hide(true, afterDelay: 1) } }) }).resume()
こうしてエラーハンドリングとプログレスができました。
Slack にもちゃんと投稿されています。
アプリ再開時にURLなどを入れておく
毎回立ち上げるたびに URL を入力するのはやや面倒なので、NSUserDefaults
を使って入力データを保存します。
struct Key { static let textKey = "text" static let userKey = "user" static let iconKey = "icon" static let webHookKey = "webhook" } override func viewDidLoad() { super.viewDidLoad() // recover data let userDefaults = NSUserDefaults.standardUserDefaults() textTextField.text = userDefaults.stringForKey(Key.textKey) userTextField.text = userDefaults.stringForKey(Key.userKey) iconTextField.text = userDefaults.stringForKey(Key.iconKey) webHookTextField.text = userDefaults.stringForKey(Key.webHookKey) } @IBAction func sendMessage(sender: UIBarButtonItem) { // save data let text = textTextField.text ?? "" let icon = iconTextField.text ?? "" let username = userTextField.text ?? "" let url = webHookTextField.text ?? "" let userDefaults = NSUserDefaults.standardUserDefaults() userDefaults.setObject(text, forKey: Key.textKey) userDefaults.setObject(username, forKey: Key.userKey) userDefaults.setObject(icon, forKey: Key.iconKey) userDefaults.setObject(url, forKey: Key.webHookKey) ~~~ }
こうして、再開時にも送信時のデータが復元されるようになりました。
実機でデバッグしてみる
特に目立った機能もないので AppStore に申請する気はないですが実機で動かしたいですね。実機で動かすのは Xcode 7 から無料化されたということなので動かしました。
.xcodeproj
を開くと Identity
に Team
の欄があるのですが、実機を特に登録していない場合 Fix issue
というボタンが表示されています。
実機を mac につなぎ、 Fix issue
を押せば実機の登録が始まります。Processing Symbol Files...
とバーに出てくるので数分待つと登録が完了し、実機へのインストールができるようになります。
そしてデバイス欄で実機を選択し、インストールします。
ここで特に設定していない場合、実機で Your device management settings do not allow ~
というエラーが出て起動できないのですが、
設定アプリ -> General
-> Profiles & Device Management
を開くと開発者を承認する画面が出てくるので、ここで承認すると起動できるようになります。
ライセンス画面を作る
最後にライセンス画面を作成します。CococaPods
にはライセンスの plist
を作る機能があり、それを利用することで簡単にできました。
下の記事の通りにすると良いです。
こうしてアプリは完成しました!やっぱり無料でも実機で動かせるとだいぶ違いますね。
感想・その他
- iOS、検索すると obj-C のコードが割りと出てくるのですが obj-C 全然わからないのでちょっとつらかった。まぁこの程度なら swift を検索ワードに入れれば出てくるので良いのですが。
- obj-C 思ったよりよく分からん…
- CocoaPods はだいぶ楽で良いですね。bundle と同じようなインターフェースで使いやすい。
UITextField
をTableView
に入れると時々項目が選択されたかのように項目の背景色が変化してフォーカスが移らない時がありました。これはUITextField
ではなく周りのmargin
部分をタップしたことが原因で、本来は全体をタップしてもフォーカスが合うようにしたほうが良いのですが、
override func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool { return false }
とすることによって背景色を変化させないようするとマシになりました。
- Swift は最高👌
- といっても多分冗長なコードになっているんだろうなあ…
- Android だと一時間ぐらいでつくれたけどなんだかんだ五時間ぐらいかかりました。iOS プログラミング、結構おもしろい*3し他のライブラリとかも触ってみたい。他にも何か作ってみたいです。