カテゴリー: テクノロジー

UIPickerViewの使い方と改善ヒント

Apple-Swift

iOSアプリを開発すると、UIPickerViewはとても便利なものです。
指のフリックだけで、ユーザに多くのデータを提示することができるため、沢山のアプリで使われていています。

UIPickerViewを使うには、以下のステップが必要です。

  1. UIPickerViewのインスタンスを作成する
  2. データ自体を用意する
  3. UIPickerViewのデータを扱うオブジェクト(DataSource)を定義
  4. UIPickerViewの表示などを扱うオブジェクト(Delegate)を定義
  5. DataSourceでComponent(区切り)数やRow(行)数を返すファンクションを用意する
  6. Delegateで各項目のタイトルを返すファンクションを用意する
  7. UIPickerViewのデータをロードする

簡単な実例を以下に貼り付けいたしました。
生物のリストをUIPickerViewで表示させる簡単なアプリだけです。

ご覧の通り、
生物の順番が作成した順番となって、生物の種類(Kingdom(哺乳類、鳥類、昆虫類、など))を見分けられないのはあまりよくないと思います。
以下の改善に取り組みましょう!

  1. 生物を種類にまとめる
  2. 生物の種類によって文字色を設定する

生物を種類にまとめる

これは一行でできることです!
データで使われるArrayにsortInPlaceファンクションを掛けて、Animalのkingdom値で順番を変更する。

Animal.Species.sortInPlace { $0.kingdom.hashValue < $1.kingdom.hashValue }

生物の種類によって文字色を設定する

これを実現するには、UIPickerViewDelegateの”titleForRow”のファンクションを消去し、”attributedTitleForRow”のファンクションを設置する必要があります。

例は以下に貼り付けています。

Extensionで変数(Stored Property)を定義する方法

Apple-Swift1_201603151208394f1.jpg
Swiftの基本のルールですが、Extensionで
・Method (メソッド、即ちファンクション)
・Computed Properties(計算型変数)
は定義できまるのに対して、
・Stored Property(保持型変数)
は定義することができません。

保持型変数と計算型変数の違いを簡単に説明しますと、保持型プロパティとは、データを保持してくれる、とても一般的な変数です。
計算型プロパティとは、すでに定義されている保持型プロパティを操る、getとsetのある、ファンクションに近い変数です。新たなデータを保持することはできません。

つまり、普通の保持型変数をクラスに追加したい場合、Extensionでではなく、クラスの中で定義しなければなりません。

けれども、Appleのライブラリのクラス(UIViewなど)のコードはアクセスできないため、そのようなクラスに新たな変数を定義することはできません。

もちろん、こういうようなクラスにサブクラスを作って、変数をサブクラスで定義できますので、問題はありません。
例えば、UIView の背景色が何回変わったかを記録する変数を付け加えようと思ったら、ColorChangingUIViewというSubclassを作って、そのクラスに変数を入れたら、解決されます。

SubclassでUIViewに変数を加える方法

 
上記の例では、単純に3つのColorChangingUIViewを作りましたので、問題はありませんでしたが、同じように、背景色が何回変わったかを記録する変数を持つUITableViewやUIButtonやUILabelなどを用意しようと思ったら、それぞれ、ColorChangingUITableView、ColorChangingUIButton、ColorChangingUILabelをつくる必要があります。
 
なお、同じ変数名を定義しても、ColorChangingUIViewとColorChangingUITableViewとColorChangingUILabelなどをループで取り扱う際、if is でそれぞれのタイプを確認しないと、colorChangesの変数がアクセスできないため、コードは複雑になり、大混乱になりやすい状態です。
 
それぞれのUIViewのSubclassにSubclassを作る場合のカオス

やっぱり、全てのクラスが親クラスとして共有しているUIViewのコードに変数入れることができたら、解決されますね。
それで、以下は、UIViewに保持型変数を入れる方法となります。

UIViewに保持型変数を入れる場合

わかりやすい上、重複を防げた簡潔なコードになりましたね。
これからも、Swiftの開発、頑張りましょう!

キーボードとともに、UIViewをずらす方法

Apple-Swift1.jpg

SwiftでiOSアプリを開発していますが、キーボードが表示される時のレイアウトで困っている方は少なくないと思います。
キーボードが表示されると、ページの下部が見えなくなったりなどの問題が発生し、エンドユーザに迷惑を掛けないように、キーボードの表示・非表示に反応するアプリを作れたらいいなと思います。

ところで、本日は、iOSのUITextFieldなどのキーボード表示とともに、UIViewをずらす方法を紹介したいと思います!
まずは、とても簡単なSingleViewアプリを用意させていただきました。


 
はるかにシンプルなアプリですが、ページの真ん中あたりに、グレー色なUITextField (文字入力欄)があり、押すとキーボードが開きます。
ページの下にオレンジ色なUIView(長方形)もあり、それをタップすると、キーボードが閉じます。
 
swiftKeyboard1.png
 
けれども、問題!
キーボードが開くと、下のオレンジ色のUIViewが見えなくなり、キーボードを閉じることができません。
 
swiftKeyboard2.png
 
それを修正するには、NSNotificationは使えます!
NSNotificationとは、引き金のようなものとイメージしたらいいと思いますです。
 
キーボードのフレームが変わった時に、オレンジ色のUIViewの位置をずらしたいと思うので、今回の例で引きたい引き金は「UIKeyboardWillChangeFrameNotification」となります。
 
では、この「UIKeyboardWillChangeFrameNotification」が引かれたら、「UIViewを適切にずらす」というコードを書きましょう!
他にも、様々なやり方はあると思いますが、解りやすい例として、以下の方法を紹介したいと思います。
 
1. まず、UIKeyboardWillChangeFrameNotificationが引かれたら、keyboardWillChangeファンクションを呼ぶ
NSNotificationCenter.defaultCenter().addObserver(self, selector: “keyboardWillChange:”, name: UIKeyboardWillChangeFrameNotification, object: nil)
 
2. このファンクションで、キーボードフレームの上部(minY)を取る
var keyboardTop = self.view.frame.height – (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)!.CGRectValue().minY
 
3. その新しい高さをどこかに保存する(今回は別クラスのstatic varに保存する)
KeyboardOverlay.newTop = keyboardTop
 
4. UIViewの位置をキーボードの新しい位置と以前の位置の差異の分で引き足しする。
footer.frame.origin.y = footer.frame.origin.y + (KeyboardOverlay.currentTop – KeyboardOverlay.newTop)
 
5. キーボードの現在の位置を保存する。
KeyboardOverlay.currentTop = keyboardTop
 
合わせたら、コードは以下のようになります。
 

試しましょう〜

 

動いています!
これからも、Swiftの開発、頑張ります!

Swift2でUISearchBarの背景透過

UNIQLOのヒートテックタイツを履いたら怖いものがなくなりました。
マエダです。

Apple-Swift1.jpg

Swift2でiOSアプリを開発してますがUISearchBarの背景透過について紹介します。
# あまり情報なくバッドノウハウだったらすみません。。

Swift1系でも同じことをしたい方は多数いらっしゃったようです。
参考
http://ja.stackoverflow.com/questions/7315/uisearchbar%E3%81%AE%E8%83%8C%E6%99%AF%E3%81%AEview%E3%82%92%E9%80%8F%E6%98%8E%E3%81%AB%E3%81%97%E3%81%9F%E3%81%84

Swift2になるとSubViewアクセスできない風じゃないですか。。。
そこで参考サイトにインスパイアされて以下のようにすると実現できました。

setBackgroundImageで空のUIImageを設定してあげてます。

そもそもなんでUISearchBarの背景色指定させてくれないんだろう。。教えてエロいヒト。

Docker使ってみました

突然寒くなりましたね。
開発担当のノリフミです。

最近サーバーサイドを少し触らせてもらってるのですが
Dockerという素晴らしいのに得体の知れないものを手懐けようと奮闘してる日々です。

自分なりにこうしたらいいのでは?
っと思ったこと残しておこうかと。

そもそも、Dockerって?

docker.png

「Docker」とは、Docker社(旧dotCloud)が開発するオープンソースのコンテナー管理ソフトウェアの1つです。

なんて記述をみつけましたが、分かる人には分かりますが、分からない人はさっぱりですよね。

簡単にいうと、「皆んなが使えて、目に見えないパソコンを簡単に管理(作成・編集・削除等)できるソフトウェア」という感じでしょか(逆にわからない)

前置きはこれくらいにして、ここから本題…

マウントでコンテナ生成してみた

wordpressの公式イメージをpull

docker pull wordpress:latest

コンテナ生成

docker run –name container-name -it
–link container-mysql:mysql
-p 8080:80
-v /home/user/html:/var/www/html
-v /home/user/conf/apache2/sites-available/000-default.conf:/etc/apache2/sites-available/000-default.conf
-v /home/user/conf/php/php.ini:/usr/local/etc/php/php.ini
-e ‘WORDPRESS_DB_HOST=mysql’
-e ‘WORDPRESS_DB_USER=user’
-e ‘WORDPRESS_DB_PASSWORD=password’
-e ‘WORDPRESS_DB_NAME=db_name’
wordpress:latest bash

※ここで問題発生!
カスタマイズすればするほど-vが
増える!
増える!!

そこで考えるノリフミ…
「そうかDockerfileにしてしまえば!」

※ここでまたまた問題発生!!
DockerfileでCOPYしてコンテナ生成しても、起動後のホスト側での編集がコンテナに反映されない…

そこでノリフミは思いました。
「-vとDockerfileってどっちがいいんだ?」

-vとDockerfileどっちが良いのか

要点整理
-vでマウントいっぱい

    • ホストから設定書き換えれる!
    • imageも公式wordpressだけで済むし簡単!
    • 生成コマンド(run)が度々変わる
    • 生成後にもコンテナ内作業がいる場合がある

 

Dockerfileでまとめる

    • COPYなりで設定ファイル追加すると、設定変えたらimage作り直し
    • 環境ごとにimage増える
    • 生成はimageからだから生成コマンドが簡単!
    • 生成後に作業がいらない!

 

色々と記事を探していると、こんなのみつけました。

Dockerが提供するのは、アプリケーションの実行環境を「Dockerイメージ」としてイメージ化する機能、そして、Dockerイメージから実際にアプリケーションを起動する実行環境を提供するという機能です。この「実行環境のイメージ化」こそが、Dockerの中心となる機能です。

なるほど。
imageどんどん作ってけよってことですよね。

それではDockerの考え方に基づいて、構築しよう。

Docker build時の仕様

その前に、Dockerのbuildする時に注意点が何点かあります。

    • COPYとADDの違い
      COPYは純粋にコピーするだけADDはzipなどの解凍もします。
      なのでコピーするだけであればCOPYを使いましょう。

 

    • コンテキスト(読み込めるファイルとか)
      読み込むDockerfileのある階層のファイルorディレクトリか
      設定しているコンテキスト内しかアクセスできません。
      なので、COPYしたいファイル等はDockerfileと同じ階層に設置しましょう。
      逆にコンテキスト内に不要ファイル(重いファイルとか)を設置していると
      勝手に読み込まれるので整理しましょう。

 

Dockerfileでコンテナ生成してみた

上記を踏まえてファイル構成はこんな形に

├── Dockerfile
└── conf
├── apache2
|  └── sites-available
|     └── 000-default.conf
├── docker-entrypoint-initdb.d
└── php
└── php.ini

Dockerfile生成

vi Dockerfile
FROM wordpress
MAINTAINER user
COPY conf/docker-entrypoint-initdb.d /docker-entrypoint-initdb.d/
COPY conf/apache2/sites-available/000-default.conf /etc/apache2/sites-available/
COPY conf/php/php.ini /usr/local/etc/php/
RUN a2ensite 000-default
RUN a2enmod headers
RUN a2enconf security

image生成

docker build image_name ./

コンテナ生成

docker run –name container_name -it
–link container-mysql:mysql
-p 8080:80
-e ‘WORDPRESS_DB_HOST=mysql’
-e ‘WORDPRESS_DB_USER=user’
-e ‘WORDPRESS_DB_PASSWORD=password’
-e ‘WORDPRESS_DB_NAME=db_name’
-v /home/user/html:/var/www/html
image_name:latest bash

無事コンテナ生成終了しましたm(_ _)m

まとめ

Dockerでコンテナ生成するときは最低限のマウントで
後はDockerfileに書いて、どんどんimage作っていこう。
というお話でした。

よくよく考えると当たり前な気もしますが、今でもimageいっぱい作るの抵抗あります…