Google App Scriptでセルを扱う
諸々の集計業務を担当することになって、コピペを効率化しようと思ってGoogle App Scriptを調べたのでまとめます。
内容
- 特定のセルの値を取得
- 特定のセルに値を貼り付け
- 他のファイルのソースコードを参照するときの手順
- 確認用ダイアローグを出す
- シートを開いたときに行う処理
- 参考
特定のセルの値を取得
// 単一の値を取得 SpreadsheetApp.getActive().getSheetByName("SHEET_NAME").getRange("A1").getValue(); // 現在アクティブなシートを取得する場合 SpreadsheetApp.getActiveSpreadsheet()).getRange("A1").getValue(); // 特定の範囲の中の値を取得する場合 // 2次元配列が帰ってきます SpreadsheetApp.getActive().getSheetByName("SHEET_NAME").getRange("A1:B6").getValues();
特定のセルに値を貼り付け
// 単一のセルに貼り付けというのはなく、範囲から範囲への貼り付けとなる var rangeToCopy = sheet.getRange('A:A'); var targetToCopy = sheet.getRange('B1'); // 貼り付け範囲か、一番左上のセルを指定するようにしておく rangeToCopy.copyTo(targetToCopy); // 形式のみ, 値のみのオプションについて rangeToCopy.copyTo(targetToCopy, {formatOnly:true}); // 形式のみ rangeToCopy.copyTo(targetToCopy, {contentsOnly:true}); // 値のみ // 2次元配列を特定の範囲へ貼り付け var copyValues = [[1, 2], [3, 4]]; SpreadsheetApp.getActive().getSheetByName("SHEET_NAME").getRange("A1:B2").setValues(copyValues);
他のファイルのソースコードを参照するときの手順
- 新しいプロジェクトを作成して分割したいソースコードを貼る
- 1のプロジェクトに対して、
ファイル > 版で管理
から、他のプロジェクトに公開するバージョンのコメントを入れて保存 - 2のプロジェクトのソースコードを参照したいプロジェクトを開いて、
リソース > ライブラリ
を選択 - 3で開いたメニューの下の方に、2のプロジェクトのURLの一部
https://script.google.com/macros/d/SomeLooooongRandomString/edit?ui...
のSomeLooooongRandomString
の部分を入れる - 入力した文字列が正しければ、2のプロジェクト名が3のメニューに現れるので、2のプロジェクトを利用する側で使うバージョンと、2のプロジェクトの関数などの前につく識別子を入力して、「保存」を押す
- 2のプロジェクトを利用する側で、5で決めた識別子を頭につけて2のプロジェクト内の関数を利用する
確認用ダイアローグを出す
// メッセージだけでる Browser.msgBox("メッセージが出ます"); // OK/キャンセルのボタンがついたダイアローグが出る Browser.msgBox("これからシートを編集しますか?", Browser.Buttons.OK_CANCEL); // 選択されたボタンを取得 var selections = Browser.msgBox("これからシートを編集しますか?", Browser.Buttons.OK_CANCEL); // キャンセルボタンをクリックした場合は"cancel" Browser.msgBox(selections);
シートを開いたときに行う処理
// シートを開いたときにダイアローグを出す function onOpen(){ Browser.msgBox("これからシートを編集しますか?", Browser.Buttons.OK_CANCEL); } // シートを開いたときに上部にメニューを追加する function onOpen() { var sheet = SpreadsheetApp.getActiveSpreadsheet(); var entries = [ { name : "シートの上部にに追加するメニュー内の項目の名前", functionName : "その項目を選択したとき起動する関数" } ]; sheet.addMenu("シートの上部に追加するメニューの名前", entries); }
参考
- http://itinfo.popotoo.com/gas/39/
- http://www.bmoo.net/archives/2012/07/314383.html
- http://www.bmoo.net/archives/2012/03/313107.html
- http://qiita.com/moonstruckdrops@github/items/d791bc7f0b7a2c2e6b5d
- http://www.bmoo.net/archives/2012/03/312958.html
- http://qiita.com/shibukawa/items/8fee715232e12f183698
結局なのですが、普通にGoogle Spread Sheetの関数を使ってCSVインポートからのコピペ前の整形作業用の単純なシートを何枚か作ったらそれだけで大幅に時間が短縮されてしまい、Google App Scriptの動作が遅かったため、2日程度で0からほとんど動くところまで書いたのに導入までできなかったのが残念です...。
暇なときにもう少し手直ししてリベンジしたい...。
Spinnerのレイアウトをコードで変更する
スタイルを利用した指定がうまく動かなかったり見つけるまでにちょっと時間がかかったりしたので、まあ適当にメモ。
android:id="@android:id/text1"
と@android:id/text1
がidに指定されたTextViewだけのレイアウトリソースを用意- Spinnerの要素をセットする
ArrayAdapter
の引数に渡す - ドロップダウン用のレイアウトは、
ArrayAdapter.setDropDownViewResource
メソッドの引数に渡す
Adapterに手動で要素を追加しているのは、利用する時にスピナーの要素が動的に変わっていたからです。
また、Spinnerの要素の先頭に画像などをセットしたい場合は、BaseAdapter
を継承してgetView
メソッドをオーバーライドして用います。
setContentView(R.layout.activity_main); ArrayAdapter<String> adapter = new ArrayAdapter(this, R.layout.item_in_list); adapter.add("One"); adapter.add("Two"); adapter.add("Three"); adapter.setDropDownViewResource(R.layout.item_in_drop_down_list); AppCompatSpinner spinner = (AppCompatSpinner) findViewById(R.id.imageFolderNameSpinner); spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { } @Override public void onNothingSelected(AdapterView<?> parent) { } });
<!-- res/layout/activity_main.xml --> <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.example.woshidan.myapplication.MainActivity"> <android.support.design.widget.AppBarLayout android:layout_height="wrap_content" android:layout_width="match_parent" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay"> <android.support.v7.widget.AppCompatSpinner android:id="@+id/imageFolderNameSpinner" android:layout_width="match_parent" android:layout_height="wrap_content" /> </android.support.v7.widget.Toolbar> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" /> </android.support.design.widget.CoordinatorLayout>
<!-- item_in_list.xml --> <?xml version="1.0" encoding="utf-8"?> <TextView android:id="@android:id/text1" android:textSize="18dp" android:padding="8dp" android:textColor="#0f0" android:layout_width="match_parent" android:layout_height="wrap_content" android:ellipsize="marquee" android:background="#fff" android:textAlignment="inherit" xmlns:android="http://schemas.android.com/apk/res/android" />
<!-- item_in_drop_down_list.xml --> <?xml version="1.0" encoding="utf-8"?> <TextView android:id="@android:id/text1" android:textSize="18dp" android:padding="8dp" android:textColor="#f00" android:layout_width="match_parent" android:layout_height="wrap_content" android:ellipsize="marquee" android:textAlignment="inherit" xmlns:android="http://schemas.android.com/apk/res/android" />
スタイルで指定できるはずなんだけどなぁ。
SSL/TSLについて少し勉強しました
内容
SSL/TSLで使うプロトコルの設定について
SSL/TSLの利用はApacheやnginxなどのWebサーバのソフトの設定を通して有効にできます。 また、これらのソフトが動くサーバのOSのバージョンによっては一部のプロトコルが利用できない場合があります。
SSL/TSLの暗号化のアルゴリズムの指定は暗号スイートの単位で行います。
暗号スイートというのは、通信の暗号化に使うアルゴリズムはこれ、鍵交換に使うアルゴリズムはこれ、といった風に通信の各部の暗号化プロトコルの組み合わせのことです。
// Apacheの場合 SSLCipherSuite DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-CAMELLIA128-SHA:DHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES128-SHA256:CAMELLIA128-SHA:AES128-SHA:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-SHA256:DHE-RSA-CAMELLIA256-SHA:DHE-RSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:CAMELLIA256-SHA:AES256-SHA
// nginxの場合 ssl_ciphers AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
openssl ciphers
で、そのコンピュータに入っているopensslが利用出来る暗号スイートの一覧が見れます。
$ openssl ciphers -v DHE-RSA-AES256-SHA SSLv3 Kx=DH Au=RSA Enc=AES(256) Mac=SHA1 DHE-DSS-AES256-SHA SSLv3 Kx=DH Au=DSS Enc=AES(256) Mac=SHA1 AES256-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1 EDH-RSA-DES-CBC3-SHA SSLv3 Kx=DH Au=RSA Enc=3DES(168) Mac=SHA1 EDH-DSS-DES-CBC3-SHA SSLv3 Kx=DH Au=DSS Enc=3DES(168) Mac=SHA1 DES-CBC3-SHA SSLv3 Kx=RSA Au=RSA Enc=3DES(168) Mac=SHA1 DES-CBC3-MD5 SSLv2 Kx=RSA Au=RSA Enc=3DES(168) Mac=MD5 DHE-RSA-AES128-SHA SSLv3 Kx=DH Au=RSA Enc=AES(128) Mac=SHA1 DHE-DSS-AES128-SHA SSLv3 Kx=DH Au=DSS Enc=AES(128) Mac=SHA1 AES128-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA1 DHE-RSA-SEED-SHA SSLv3 Kx=DH Au=RSA Enc=SEED(128) Mac=SHA1 DHE-DSS-SEED-SHA SSLv3 Kx=DH Au=DSS Enc=SEED(128) Mac=SHA1 SEED-SHA SSLv3 Kx=RSA Au=RSA Enc=SEED(128) Mac=SHA1 RC2-CBC-MD5 SSLv2 Kx=RSA Au=RSA Enc=RC2(128) Mac=MD5 RC4-SHA SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=SHA1 RC4-MD5 SSLv3 Kx=RSA Au=RSA Enc=RC4(128) Mac=MD5 RC4-MD5 SSLv2 Kx=RSA Au=RSA Enc=RC4(128) Mac=MD5 EDH-RSA-DES-CBC-SHA SSLv3 Kx=DH Au=RSA Enc=DES(56) Mac=SHA1 EDH-DSS-DES-CBC-SHA SSLv3 Kx=DH Au=DSS Enc=DES(56) Mac=SHA1 DES-CBC-SHA SSLv3 Kx=RSA Au=RSA Enc=DES(56) Mac=SHA1 DES-CBC-MD5 SSLv2 Kx=RSA Au=RSA Enc=DES(56) Mac=MD5 EXP-EDH-RSA-DES-CBC-SHA SSLv3 Kx=DH(512) Au=RSA Enc=DES(40) Mac=SHA1 export EXP-EDH-DSS-DES-CBC-SHA SSLv3 Kx=DH(512) Au=DSS Enc=DES(40) Mac=SHA1 export EXP-DES-CBC-SHA SSLv3 Kx=RSA(512) Au=RSA Enc=DES(40) Mac=SHA1 export EXP-RC2-CBC-MD5 SSLv3 Kx=RSA(512) Au=RSA Enc=RC2(40) Mac=MD5 export EXP-RC2-CBC-MD5 SSLv2 Kx=RSA(512) Au=RSA Enc=RC2(40) Mac=MD5 export EXP-RC4-MD5 SSLv3 Kx=RSA(512) Au=RSA Enc=RC4(40) Mac=MD5 export EXP-RC4-MD5 SSLv2 Kx=RSA(512) Au=RSA Enc=RC4(40) Mac=MD5 export
上記の一覧の一行分の内容の意味は、
暗号スイートの名前 プロトコルのバージョン 鍵交換の方法(KeyeXchange) サーバ認証の方法(Authentication) 暗号化の方法(Encryption) HMAC(Message Authentication Code)のハッシュアルゴリズム
となります。
理解してるつもりの SSL/TLS でも、もっと理解したら面白かった話 · けんごのお屋敷
SSL証明書のインストールの大まかな流れ
SSL/TSLを有効にするには、サーバの身元を保証するSSL証明書をサーバにインストールする必要があります。
https://www.cybertrust.ne.jp/sureserver/support/tec_download.html#01
上記の資料を参考におおまかな手順をまとめると、下記のようになります。
openssl genrsa
コマンドで秘密鍵ファイルを作成cf. openssl genrsa -aes256 -out server.key 2048
openssl req
コマンドで秘密鍵ファイルからCSR(公開鍵)ファイルを作成cf. openssl req -new -key server.key -out server.csr
- 作成した公開鍵を証明書を発行する会社に送ります
- 証明書がサーバ証明書の会社から発行されます
- 中間CA証明書とサーバー証明書があります
- サーバー証明書と中間証明書を連結させてpemファイルを作ってサーバーにアップロードします
cf. cat サーバー証明書 中間証明書 > 連結ファイル.pem
- サーバーにアップロードした連結ファイルの場所を
ssl_certificate(nginxの場合)
のディレクティブにフルパスで指定します - 秘密鍵ファイルもサーバーにアップロードして、その場所を
ssl_certificate_key(nginxの場合)
のディレクティブにフルパスで指定します - webサーバ(nginxなど)の再起動をして、SSLで通信できているか確認します
プロトコルのバージョンと利用出来る公開鍵証明書のハッシュ関数について
接続したいサービスごとにこのハッシュ関数で作った証明書でないとだめですよ、とか、このバージョンのプロトコルを使ってはダメですよ、といった設定がされていることがあります。
また、OSやブラウザの設定により、公開証明書のハッシュ関数が古いと正式な証明書でも不正な証明書と表示されたり、URLバーに警告が表示されることがあります。
今なら少し自信を持ってオレオレ証明書が作れそうな気がしてきました...
UI用のクラスのプロトコルとWebViewなどについて
内容
iPhone/iPadプログラミングバイブル iOS9/Xcode7/Swift 対応 (smart phone programming bible)
- 作者: 布留川英一
- 出版社/メーカー: ソシム
- 発売日: 2015/10/27
- メディア: 単行本
- この商品を含むブログ (1件) を見る
上の本を参考にiOSのUIViewと戯れています。
とりあえず、4章までやったので、ここまでで一区切り~~。
- UI用のクラスを使うとき実装するプロトコルについて
- DataSource
- Delegate
- WebViewの使い方について
- ATSの例外のためのInfo.plistの設定
- PlayGround
- TableView
- リサイズマスク
- 行のIndicatorの種類
- NavigationController
- UIPickerViewを使う時に実装するプロトコルについて
UI用のクラスを使うとき実装するプロトコルについて
TableViewやWebView, PickerViewなどのクラスをViewControllerのViewに置く場合、対応するプロトコルを実装する必要があり、クラス名DataSource, クラス名Delegateといった名前をしています。
データの表示の中身やViewから受け取れるイベントのハンドリングをそれを置くViewのViewControllerに委譲する、みたいなのりみたいです。
DataSource
Viewのクラスで扱う行数や行ごとのViewを返すメソッドなどがあるみたいです。 AndroidでいうとAdapterにあたる感じのプロトコルです。
Delegate
Viewをタップした時などのイベントをハンドリングするメソッドを書くプロところです。 AndroidでいうとSwipeRefreshLayoutのコールバックのリスナーみたいな位置付けみたいです。
WebViewの使い方について
- ViewController内でWebViewを生成するなり、StoryBoard上に配置した後ViewControllerとひも付けたり*1する
- WebViewが置いてあるViewのViewControllerでUIWebViewDelegateプロトコルを実装
- カスタマイズが必要なら下記のメソッドなどをオーバーライドする
webView(webView: UIWebView, shouldStartLoadWithRequest: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool
- https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIWebViewDelegate_Protocol/#//apple_ref/occ/intfm/UIWebViewDelegate/webView:shouldStartLoadWithRequest:navigationType:
- 与えられたURLのコンテンツの読み込みを開始しようとした時に呼び出される
- navigationTypeはフォームの投稿やリンクを踏んだなどの遷移の種類を意味する
- 戻り値がfalseならコンテンツの読み込みを開始しない
webViewDidStartLoad(webView: UIWebView)
webView(webView: UIWebView, didFailLoadWithError error: NSError?)
- カスタマイズが必要なら下記のメソッドなどをオーバーライドする
- 読み込みたいURLのリクエストを作成する
let url: NSURL = NSURL(string: "ロード先")
let urlRequest: NSURLRequest = NSURLRequest(URL: url)
- WebViewでリクエストを読み込む
WebView.loadRequest(urlRequest)
読み込み中のIndicatorを出したい場合は
UIApplication.sharedApplication().networkActivityIndicatorVisible = true
のようにする。
ATSの例外のためのInfo.plistの設定
結局 PropertyList
からの編集がうまくいかなくて、ソースコードの編集をしました。
<plist version="1.0"> <dict> <key>NSAppTransportSecurity</key> <dict> <key>NSExceptionDomains</key> <dict> <key>localhost</key><!-- HTTPでの通信を例外的に許可したい「ドメイン名」を入れる --> <!-- ダメな例: http://localhost:3000 --> <!-- ダメな例: localhost:3000 --> <!-- ダメな例: 192.168.56.1 --> <!-- ダメな例: 192.168.56.1:3000 --> <dict> <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> <true/> </dict> </dict> </dict>
PlayGround
アプリ全体のビルドをせずにViewや関数だけを試したりできるSwiftの実行環境です。
ViewをPlayGroundで表示して試したい時は、
import UIKit import XCPlayground class CustomView: UIView { // Viewの実装 } val testView = CustomView() XCPShowView("Some ID", testView)
のように、XCPShowView
メソッドを使います... と書いてあったのですが、 Swift 2.1の頃に XCPlaygroundPage
を使うように変わり、XCPShowView
メソッドはdeprectedになっていました。
参考: http://qiita.com/koishi/items/e78f8b852d5f7ae8d125
実際使っている様子は下記です。
TableView
リサイズマスク
これは実はInterfaceBuilderでやるのでは、と思ったのですが、一応設定をメモします。
let tableView = UITableView() tableView.frame = frame tableView.autoresizingMask = [ UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight, UIViewAutoresizing.FlexibleBottomMargin, UIViewAutoresizing.FlexibleLeftMargin, UIViewAutoresizing.FlexibleRightMargin, UIViewAutoresizing.FlexibleTopMargin ]
行のIndicatorの種類
// cellはUITableViewCellのインスタンス cell.accessoryType = UITableViewCellAccessoryType.None // 何もつけない cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator // そのセルの右側に「 > 」みたいなのをつける cell.accessoryType = UITableViewCellAccessoryType.DetailDisclosureButton // そのセルの右側に「(i) > 」みたいなのをつける cell.accessoryType = UITableViewCellAccessoryType.Checkmark // そのセルの右側にチェックマークをつける. Noneと切り替え?して使う?
NavigationController
- NavigationControllerを使いたいViewControllerはStoryBoardでNavigationControllerを追加
- NavigationControllerの戻るボタンに入る文字はひとつ前のスタックのViewControllerのタイトル
UIPickerViewを使う時に実装するプロトコルについて
UIPickerViewは要素が輪のようになっていてクルクル回して選択するUIです。
UIPickerView - UIKit | Apple Developer Documentation
- UIPickerViewDelegateについて
func pickerView(pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat
で1行の高さfunc pickerView(pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusingView view: UIView?) -> UIView
で1行分のViewを作成func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
でピッカーの要素が
- UIPickerViewDataSourceについて
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
で、行数を返すメソッドを返すfunc numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int
で、コンポーネント数を返すが基本は1でよさそうです
XCodeのデバッガについて少しだけメモ
内容
iPhone/iPadプログラミングバイブル iOS9/Xcode7/Swift 対応 (smart phone programming bible)
- 作者: 布留川英一
- 出版社/メーカー: ソシム
- 発売日: 2015/10/27
- メディア: 単行本
- この商品を含むブログ (1件) を見る
上の本を参考にiOSのUIViewと戯れています。
今日はスライダーなどをいじってみたのですが、そこでは特に書くことがなかったので、デバッガについて。
デバッガ
エディタの左側の灰色の部分をタップしてブレークポイントを設定。
デバッグしているときのメニューについて。
左から
- デバッグ関係のメニューを閉じたり開いたりする
- ブレークポイントで処理を止めるかどうか決める
- 次のブレークポイントorクラッシュ箇所まで進むか、今の処理を一時停止するか
- 処理を一行分進む
- 変数の中身などのステップも1つとして1ステップ次の処理に進む
- よくわからない...
デバッグ用のメニューを開きながらステップ実行していくと変数の中身などが確認出来ます。
エラーの中身について
変数の中身を確認するタブの横にクラッシュなどが発生したときにメッセージがでるのですが、メソッド名などが確認出来るだけで行数がちょっとよくわからない現状です。
メソッド名がわかればブレークポイントを仕込めばいいわけですが。
2016-07-29 00:27:57.697 SliderEx[22451:903197] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modal view controller on itself. Presenting controller is <SliderEx.ViewController: 0x7ff723dad930>.' *** First throw call stack: ( 0 CoreFoundation 0x000000010362dd85 __exceptionPreprocess + 165 1 libobjc.A.dylib 0x00000001053d1deb objc_exception_throw + 48 2 UIKit 0x0000000104003ab9 presentationControllerClassForPresentationStyle + 0 3 UIKit 0x000000010400685c -[UIViewController _performCoordinatedPresentOrDismiss:animated:] + 489 4 UIKit 0x000000010400636b -[UIViewController presentViewController:animated:completion:] + 179 5 SliderEx 0x000000010344572b _TFC8SliderEx14ViewController9showAlertfTGSqSS_4textGSqSS__T_ + 955 6 SliderEx 0x0000000103444fa8 _TFC8SliderEx14ViewController7onClickfCSo8UIButtonT_ + 1352 7 SliderEx 0x000000010344500a _TToFC8SliderEx14ViewController7onClickfCSo8UIButtonT_ + 58 8 UIKit 0x0000000103e57a8d -[UIApplication sendAction:to:from:forEvent:] + 92 9 UIKit 0x0000000103fcae67 -[UIControl sendAction:to:forEvent:] + 67 10 UIKit 0x0000000103fcb143 -[UIControl _sendActionsForEvents:withEvent:] + 327 11 UIKit 0x0000000103fca263 -[UIControl touchesEnded:withEvent:] + 601 12 UIKit 0x0000000103eca99f -[UIWindow _sendTouchesForEvent:] + 835 13 UIKit 0x0000000103ecb6d4 -[UIWindow sendEvent:] + 865 14 UIKit 0x0000000103e76dc6 -[UIApplication sendEvent:] + 263 15 UIKit 0x0000000103e50553 _UIApplicationHandleEventQueue + 6660 16 CoreFoundation 0x0000000103553301 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 17 CoreFoundation 0x000000010354922c __CFRunLoopDoSources0 + 556 18 CoreFoundation 0x00000001035486e3 __CFRunLoopRun + 867 19 CoreFoundation 0x00000001035480f8 CFRunLoopRunSpecific + 488 20 GraphicsServices 0x0000000107cc3ad2 GSEventRunModal + 161 21 UIKit 0x0000000103e55f09 UIApplicationMain + 171 22 SliderEx 0x0000000103447092 main + 114 23 libdyld.dylib 0x0000000105e9592d start + 1 24 ???
UIButton, UIAlertController, UITextView, UITextFieldあたりに触りました
内容
iPhone/iPadプログラミングバイブル iOS9/Xcode7/Swift 対応 (smart phone programming bible)
- 作者: 布留川英一
- 出版社/メーカー: ソシム
- 発売日: 2015/10/27
- メディア: 単行本
- この商品を含むブログ (1件) を見る
上の本を参考にiOSのUIViewと戯れています。
- 最初からSwiftでコードを書きたい時はSwiftでプロジェクトを作成する
- Text用, 画像用のViewがあった話
- Swiftのクラス定数っぽいものの名前
- ボタンの種類
- type: UIButtonType.System
- type: UIButtonType.InfoDark
- type: UIButtonType.InfoLight
- type: UIButtonType.ContactAdd
- type: UIButtonType.DetailClosure
- ボタンを押したときのイベントの設定
- アラートの種類
- アラートのボタンの挙動の設定
- AlertActionのハンドラーの引数としてのクロージャの利用例
- UITextFieldについて
- UITextViewでも文字編集可能にできる
最初からSwiftでコードを書きたい時はSwiftでプロジェクトを作成する
これまでObjective-CのプロジェクトにSwiftのクラスをちょいちょい書いて試してたんですが、プロジェクト作成時にObjective-CかSwiftかを選べるのでSwiftで書きたい時は、この時点で Swiftを選んだ方が楽です。
関連して少し調べてみたのですが、, Objective-CからSwift, SwiftからObjective-Cのクラスの参照については下記ブログ記事が参考になりました。
http://techblog.yahoo.co.jp/ios/swift-from-objc/
上記記事より手順だけ簡単にまとめると、
- SwiftからObjective-Cを参照する場合はBridging Headerを用意して、そこに必要なクラスをimportする
- Objective-CからSwiftを呼ぶ場合はビルド時に自動生成される.hファイルをimportする
となります。
Text用, 画像用のViewがあった話
String.drawAtPoint
メソッドや、UIImage.drawAtPoint
メソッドを見て、ひええ、となっていたのですが、Label
クラスやUIImageView
クラスがちゃんとありました。
少し UIImageView
をカスタマイズしたい時などに UIImage.drawAtPoint
メソッドなどを使うのかな、と思いました。
Swiftのクラス定数っぽいものの名前
タイププロパティといいます。
ボタンの種類
UIButtonはコンストラクタで指定するtypeで見た目が変化します。
type: UIButtonType.System
type: UIButtonType.InfoDark
type: UIButtonType.InfoLight
type: UIButtonType.ContactAdd
type: UIButtonType.DetailClosure
何かミスったかもしれない、という感じなのですが、現場に入っていろいろ見てみようと思います。
Customが画像ボタン作るときに使うみたいでした。
let button = UIButton(type: UIButtonType.Cutom) button.setImage(image, forState: UIControlState.Normal)
また、ボタンに表示される画像やテクストはそれが表示されるときのボタンの状態と一緒に指定します。
ボタンを押したときのイベントの設定
func onClick(sender: UIButton) { if sender.id == BTN_TARGET { // do something } } func makeButton() -> UIButton { let button = UIButton(type: UIButtonType.System) button.tag = BTN_TARGET // 適当なInt button.addTarget(self, action: "onClick:", forControlEvents: UIControlEvents.TouchUpInside) return button }
button.addTarget(self, action: "onClick:", forControlEvents: UIControlEvents.TouchUpInside)
のactionのコロンを忘れてあたふたしたのはいい思い出です。
UIControlEvents.TouchUpInside
はインタフェースビルダーで設定した覚えがあるのですが、どうなのでしょう。
アラートの種類
普通のアラート(コンストラクタで指定するpreferredStyleは UIAlertControllerStyle.Alert
)とアクションシート(コンストラクタで指定するpreferredStyleは UIAlertControllerStyle.ActionSheet
)があります。
アクションシートは下図のようなボタンが縦に並んだシートです。
アラートのボタンの挙動の設定
alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.Default, handler: nil)) // 表示 self.presentViewController(alert, animated: true, completion: nil)
AlertActionのハンドラーの引数としてのクロージャの利用例
慣れるために眺めます。
alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default, handler: {(alert) in self.showAlert(nil, text: "Yesをクリック") }))
{ (クロージャのブロックに渡される変数名) in 計算 }
のような感じです。
UITextFieldについて
HTMLでいうフォーム。ViewControllerにUITextFieldDelegateを実装させることで、フォーム内に入力された文字が変化したときの挙動を設定できます。また、UIKeyboardTypeでキーボードの種類を、returnKeyTypeでreturnキーにあるボタンのスタイルを決定できます。
UITextViewでも文字編集可能にできる
UITextViewでもその内部の文字の編集が可能です。UITextView#becomeFirstResponder()
メソッドで編集を開始させ、UITextView#resignFirstResponder()
で編集を終了させます。
UITextViewで入力された文字が変化したときの挙動を設定したい場合は、 UITextViewDelegate
を実装します。
今日はここまでです。
タッチベントの処理とタイマーの処理について
内容
iPhone/iPadプログラミングバイブル iOS9/Xcode7/Swift 対応 (smart phone programming bible)
- 作者: 布留川英一
- 出版社/メーカー: ソシム
- 発売日: 2015/10/27
- メディア: 単行本
- この商品を含むブログ (1件) を見る
上の本を参考にiOSのUIViewと戯れています。
- タッチベントの処理
- UIResponder
- 画面の再描画
- タッチ位置の取得
- ルートビューコントローラの取得
- タイマーの処理
- UIImageとUIImageViewの違い
- タイマーの設定
タッチベントの処理
UIResponder
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIResponder_Class/
UIViewクラスとUIApplicationクラスのスーパークラスで、タッチ操作に関するイベントを取得、処理できます。
タッチイベントの操作を行いたいときは、このクラスのメソッドをオーバーライドします。
タッチ開始時
func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?)
タッチ移動時
func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?)
タッチ終了時
func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?)
タッチキャンセル時
func touchesCanceld(touches: Set<UITouch>, withEvent event: UIEvent?)
画面の再描画
func setNeedsDisplay()
サンプルでは、タッチイベントを取得 => タッチイベントをプロパティに => 再描画 としていましたが、これ子Viewの一部を再描画などでなくて大丈夫なのかな(いちいち全体再描画するのはちと怖いな)、みたいなことを思ってしまった...。
タッチ位置の取得
UITouch#locationInView(view: UIView?) -> CGPoint
ルートビューコントローラの取得
ルートビューコントローラから3Dタッチが利用可能かの設定が取得できます。
ルートビューコントローラは下記の手順で取得します。
- UIApplicationクラスのsharedApplicationでUIApplicationオブジェクトを取得
- UIApplicationクラスのkeyWindowプロパティ、またはwindowsプロパティからウィンドウを取得
- windowクラスのrootViewControllerプロパティでルートビューコントローラを取得
ルートビューコントローラから3Dタッチが利用可能かなどの設定は、UIViewControllerクラスのtraitCollectionプロパティを通して取得できる、UITraitCollectionクラスのオブジェクトから取得できます。このUITraitCollectionクラスのオブジェクトには端末の特徴的な情報(縦方向, 横方向のサイズ, 画面のスケール, UIの種類...)が入っています。
タイマーの処理
UIImageとUIImageViewの違い
補完でUIImageViewがでてきて、あれ、UIImage
を違うの?と思ったので確認。
UIImage
https://developer.apple.com/reference/uikit/uiimage
画像データをiOSのプラットフォームで取り扱うためのクラス。Immutableなクラスなので利用する時はいつも既存のデータからこのオブジェクトを作成するっぽい。
Drawable的な。
UIImageView
https://developer.apple.com/reference/uikit/uiimageview
一連のアニメする画像あるいは静止画像を表示するためのView.アニメの開始 & 停止のメソッドも生えてるみたいです。
ImageView的な。
タイマーの設定
var _timer = NSTimer.scheduledTimerWithTimeInterval( 定時処理を行う時間の間隔, target: self, selector: "onTick:", // 時間になった時実行するメソッド名 // deprectedみたいな警告出てたので実際使う時は調べ直す userInfo: nil, repeats: true) // 繰り返し処理を行うかどうか
// タイマーの停止 _timer.invalidate() _timer = nil