Swiftで遊ぼう! - 977 - Good design is not easy
- Swiftで遊ぼう!の前書き-> Life-LOG OtherSide
- 初心者はここから!-> 50オヤジでもできるiOS開発
- 私の本業、オフィシャルなブログ-> Life-LOG
- Swift 3 対応
WWDC 2017が来月開催されるというのに私はWWDC 2016のビデオを見て勉強しています。昨日berrymuchさんからiOSユーザーインターフェイスガイドラインの説明を受けたので次のビデオを見ました。
おおお、なんとKeynoteでデザインしているんですね。Keynoteは私もプレゼンテーションで使いまくっているので慣れています。これから作るアプリもKeynoteを使ってデザインしてみます。KeynoteのデザインをKeynoteでするほどアップルの人間はKeynote好きなんですね。
Design mattersです。やっぱりデザインの勉強もしないといけませんね。
ということで今日からデザインに目覚めます(笑)
では。
Swiftで遊ぼう! - 976 - セグエに関するコメントの返事
- Swiftで遊ぼう!の前書き-> Life-LOG OtherSide
- 初心者はここから!-> 50オヤジでもできるiOS開発
- 私の本業、オフィシャルなブログ-> Life-LOG
- Swift 3 対応
久しぶりに下記のエントリーにコメントが入りました!
私がブログを続けている理由の1つは読者からのコメントです。berrymuchさん、本当にありがとうございます!
今日の記事は上記ブログの内容の続きです。
berrymuchさんから2つ指摘を受けました。まず最初のprepareメソッドに関して詳しく説明します。
私の理解している範囲でセグエの説明をします。
セグエのインスタンス化には以下の2つの方法があります。
- ストーリーボードで視覚的に生成(Ctrl + ドラッグ)
- コードで生成(performSegueを書く)
このどちらを利用してセグエを生成しても、遷移先のViewController生成メソッドは「prepare(for segue: UIStoryboardSegue, sender: Any?) 」です。そのため、このメソッドをoverrideしなければいけません。
私は最初に、ストーリーボードで視覚的にセグエを設定しました。つまりTextFieldから「Ctrl + ドラッグ」して遷移先のViewControllerに繋いで、Identifierの設定をしたということです。
そして遷延元のViewControllerに次のコードを加えました。
override func prepare(for segue:UIStoryboardSegue, sender:Any!) { if let identifier = segue.identifier { switch identifier { case "Show Datepopover": if let dateController = segue.destination as? DatePopoverController { dateController.delegate = self let widthX = birthTextField.bounds.midX if let popoverController = dateController.popoverPresentationController { popoverController.delegate = self popoverController.sourceRect = CGRect(x: widthX, y: self.view.frame.minY + 30, width: 0, height: 0) } } case "Show Numpadpopover": if let numpadPopover = segue.destination as? NumpadViewController { numpadPopover.delegate = self let widthX = idField.bounds.midX if let popoverController = numpadPopover.popoverPresentationController { popoverController.delegate = self popoverController.sourceRect = CGRect(x: widthX, y: self.view.frame.minY + 30, width: 0, height: 0) } } default: break } } }
これでシュミレーションを実行させてテキストフィールドをタッチすると、デフォルトのキーボードが出現するんです。このデフォルトのキーボードをマニュアルで閉じると遷移先ののPopoverが出現します。
どうしてもデフォルトのキーボードが最初に立ちあがるのを止めることができません。色々試していて上手く動いたのが先日お話したperformSegueの利用だったと言うわけです。
デフォルトのキーボードの消し方も色々あることは分かりました。resignFirstResponder()やtextFieldShouldBeginEditing(_ textField: UITextField)を色々使って、試していたらperformSegueで上手く動いたということです。
キーボードの制御に関して考えていると、berrymuchさんの2つめのアドバイスで「は!」と気がつきました。私の考えているデザインは、インターフェイスのガイドラインに全く準じていませんでした。
ユーザインターフェイスのデザインのヒント - Apple Developer
このページも全く知らなかったです。berrymuchさん、情報ありがとうございます。
カスタムPopoverを使おうと考えたのは、私のアプリはiPad専用を考えていたからです。iPhoneで「Number Pad」を利用すれば数字だけの入力ができるのですが、iPadでは「Number Pad」の利用ができません。そこで独自にPopoverからの入力を思いついた訳です。
しかし、ガイドラインを読むと、そういう勝手なインターフェイスは許されていないようですね。「TextFieldからPopoverのコントロールはガイドライン違反」と考えていいんでしょう。それで実装しにくいんじゃないかと思います。
そして思いついたんです。iPadで用意されていないのならカスタムキーボードを用意して入力すればガイドラインに準じていると思いました。
berrymuchさんのコメントでまた少し成長できました。ありがとうございました。
通りすがりの読者の皆さん、何でもいいのでコメントをお願いしますm(_ _)m
では。
Swiftで遊ぼう! - 975 - Numpad Popoverの実装に関して
- Swiftで遊ぼう!の前書き-> Life-LOG OtherSide
- 初心者はここから!-> 50オヤジでもできるiOS開発
- 私の本業、オフィシャルなブログ-> Life-LOG
- Swift 3 対応
誕生日を入力するためのDate PopoveはViewControllerに値を渡さないといけないのでProtocolを用意しました。ViewControllerはこのプロトコールに準拠することで値を表示することができます。このやり方だと準拠すべきプロトコールがクラス宣言の後に並びます。UITextFieldDelegateやUIPopoverPresentationControllerDelegateも並ぶので長々しく見た目はよくありません。
カスタムPopoverを1つ作るたびにProtocolに準拠させるというコーディングスタイルは正しいのでしょうか?かなり疑問に思っています。
Numpad Popoverという新たなカスタムPopoverを用意しました。この入力値をViewControllerに渡すためにProtocolを用意しました。渡す値の型もDate Popoverと異なるので共通化はできないと思います。ということで今回はExtensionを使ってみました。
Numpad Popoverで数字をタップするとリアルタイムにテキストフィールドに表示されるようにできました。
こういう場合Protocolに準拠させるのとExtensionを追加するのとどちらがふさわしいのでしょう?
悩みはつきません(^_^;)
Swiftで遊ぼう! - 974 - Popoverのサイズ考察
- Swiftで遊ぼう!の前書き-> Life-LOG OtherSide
- 初心者はここから!-> 50オヤジでもできるiOS開発
- 私の本業、オフィシャルなブログ-> Life-LOG
- Swift 3 対応
Popoverのサイズの調整もできるようになりました。
また一歩前進。
先日まで無駄に大きく広がっていたPopoverのウインドウサイズを次のように変更できました。
しかし、適当にレイアウトを調整しただけでは駄目なんでしょうね。ボタンの大きさやレイアウトをどうすればいいのかちょっと調べました。
なるほど、ちょっとしたレイアウト調整でもちゃんと考えて設定した方がいいようですね。上の崩れたレイアウトを次のように変更しました。
なんかすっきりしました。
Swiftで遊ぼう! - 973 - Popoverのまとめを改訂
- Swiftで遊ぼう!の前書き-> Life-LOG OtherSide
- 初心者はここから!-> 50オヤジでもできるiOS開発
- 私の本業、オフィシャルなブログ-> Life-LOG
- Swift 3 対応
「Swiftで遊ぼう!」シリーズ最初の記事を振り返ってみた。
Swiftで遊ぼう! - 1 class and structure:Life-LOG OtherSide
この記事は2104年7月9日に書かれていますが、あの頃は本当に何も分からず超ド素人でした。
今までコツコツ勉強を続けてここまで理解できたのが不思議です。
「継続は力なり」を実践しているだけ。「毎日ブログ更新」も目標にしてきましたが、これは先日潰えてしまいました(T_T)
しかし、「継続は力なり」の本質は「諦めない」意気込みです。たとえ失敗しても突き進むのみ。当初はアプリ発表に3年という期間を目標に立てましたが、どうも7月9日までにアプリを発表できそうにもありません(T_T)
それでも続けるだけです!
ということでPopoverの復習をしました。
Swiftで遊ぼう! - 972 - 分かった気でいるけど本当はどうなんだろう?
- Swiftで遊ぼう!の前書き-> Life-LOG OtherSide
- 初心者はここから!-> 50オヤジでもできるiOS開発
- 私の本業、オフィシャルなブログ-> Life-LOG
- Swift 3 対応
昨日「複数のTextFieldからセグエの切り替えができるようになった!」なんて偉そうな事言っていましたが、本質は理解していないんで、本当に理解できている人がいらっしゃれば教えてもらいたいです。
私の書いたコーディングの概要を説明します。
ストーリーボード上のベースになるView Controllerに2つのUITextViewを設置します。ストーリーボードに設置したオブジェクトからViewController.swiftに「Ctrl + ドラッグ」して@IBOutletプロパティを作ります。それぞれ「birthTextField」と「idField」と名前をつけます。次に2つのUIViewControllerをオブジェクト・ライブラからストーリーボードに設置して「Date Popover Controller」と「Numpad View Controller」に変更します。カスタムUIViewControllerはSwiftで遊ぼう! - 270 - カスタムViewControllerの作成法 - Swiftで遊ぼう! on Hatenaで説明しているように用意します。
次にそれぞれのTextFieldからViewControllerに「Ctrl + ドラッグ」してセグエを作ります。Popoverを使いたいので、表示されるメニューから「Present As Popover」を選ぶだけです。ストーリーボードのSegueを選択してIdentifierを「Show Datepopover」と「Show Numpadpopover」にするだけでセグエのインスタンス化がされます。そうなんです。ストーリーボードを使った場合はコードを書かなくてもこれでセグエが作られることになります。
ViewController.swiftで「prepare(for segue:UIStoryboardSegue, sender:Any!) 」をオーバーライドするだけでPopoverをインスタンス化できます。
しかし、実際のところ奇妙な現象が生じるんです。
このままランしてシュミレーションを実行します。birthTextFieldとidFieldのどちらかをクリックすると、基本的にデフォルトのキーボードが画面下部からせり出してきます。デフォルトの状態ではキーボードの制御もできません。さらにどちらかのテキストフィールドを選択するとランダムにどちらかのセグエが実行されるためどのTextFieldがクリックされているのか判断させることができないんです。
クリックされたTextFieldを判断させるには以下のデリゲーション・メソッドを使用する必要があります。
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { switch textField { case birthTextField: performSegue(withIdentifier: "Show Datepopover", sender: self) print("Birth Text Field was selected") case idField: performSegue(withIdentifier: "Show Numpadpopover", sender: self) print("Id Field was selected") default: break } return false }
これでTextFieldを選別することができます。
しかし、ここで疑問が1つ生じます。「 performSegue(withIdentifier: String, sender: Any?)」はコーディングでセグエを生成する方法であり、ストリーボードを使ってセグエを生成している場合は必要無いはずです。とすれば重複していることになるのですが、performSegueを使用しないでTextFieldを選別できないんでしょうか?
Swiftで遊ぼう! - 971 - UITextFieldを考える
- Swiftで遊ぼう!の前書き-> Life-LOG OtherSide
- 初心者はここから!-> 50オヤジでもできるiOS開発
- 私の本業、オフィシャルなブログ-> Life-LOG
- Swift 3 対応
いままで勉強のためにチュートリアルに取り組んでいましたが、いくらチュートリアルをこなしても実践的な能力は身につきませんね。
オリジナルプロジェクトを立ち上げてプログラミングをはじめると、チュートリアルで学んだiOSフレームワークの知識だけでは太刀打ちできず初っぱなから行き詰まってます(T_T)
UITextFieldクラス利用も色々と知らなければならないことがあります。
UITextFieldはUILabelと異なりユーザーからの入力を受け付けて反応することができ、そういう流れからUITextFieldにはデリゲーション・メソッドが用意されています。
プログラミング初心者は「デリゲーション・メソッド」と言われてもちんぷんかんぷんだと思います。今まで基本概念を学んできた私は違和感なく理解できるんですが、それはコツコツとチュートリアルを勉強してきたからです。
デリゲーションは日本語で言えば「委譲」です。委譲はOOP(オブジェクト指向プログラミング)の中核概念の1つです。
- 作者: 平澤章
- 出版社/メーカー: 日経BP社
- 発売日: 2011/04/07
- メディア: 単行本
- 購入: 6人 クリック: 92回
- この商品を含むブログ (19件) を見る
クラス継承を超えたつながりを作るための概念がポリモーフィズムで、Swift言語では「プロトコール&デリゲーション」と「エクステンション」が用意されています。特にプロトコール&デリゲーションは基本中の基本にあたります。
yataiblue.hatenablog.com
デリゲーション・メソッドを利用するためにUITextFieldとViewControllerの繋がりを用意する必要があります。
この準備の仕方にも基本的にストーリーボードの利用とコーディングによる方法があるので混乱しないように注意が必要です。
教科書を読んでチュートリアルをこなせばここまでの基本的な流れは理解できます。しかし、これだけで実践的なコーディングができないんです。
TextFieldからPopoverへのセグエ、入力した値をTextFieldに戻すためにデリゲーションが大活躍します。ここらの詳しい解説をしていませんがグーグルで調べてなんとか自分で解決しました。
そして悩んでいたのが、複数のTextFieldからどうやって1つだけ用意されているデリゲーションメソッドを利用すればいいのか分からなくなっていました。
やっぱりグーグルって素晴らしいですね。調べていると解決できました!
誕生日フィールドをタップするとDatePickerが表示されたPopoverが出現します。IDフィールドをタップするとNumberパッドのPopoverが表示されるようになりました。
分かっています。Popoverのレイアウトがむちゃくちゃです。まだStack Viewの絡んだレイアウト調整がちゃんと理解できてないんです。こういう実践的なコーディングの勉強がまだ不十分なんです。
まだまだですね(^_^;)