2021年3月30日火曜日
Swift・UIBarButtonItemのtitleを変更する。
こんにちは、オフィス狛 技術部のpinoです。
この度、初めてiOSアプリの開発に携わることができました。
まだまだ勉強中の身ですが、今回は「UIBarbuttonItemのtitleを変更する方法」について紹介したいと思います!
方法
早速ですが、UIBarbuttonItemのtitle変更方法です。
private func setBarButtonItem() {
// UIBarbuttonItemのactionを設定
let button = UIBarButtonItem(title: "タイトル", style: .plain, target: self, action: #selector(self.buttonTapped(_:)))
}
@objc func buttonTapped(_ sender: UIBarButtonItem) {
// 変更後のタイトルを設定
sender.title = "変更後のタイトル"
}
タップ時の処理でUIBarButtonItemを引数にとって、
(仮引数名がsenderの場合)sender.title = "hoge"としてあげることでtitleの変更ができます。
...思いのほか、すごく簡単でしたね!
せっかくなので、ここからはこのtitle変更を活かしたものを作ってみたいと思います。
作るもの
以下のようなものを作っていきます。
- ・画面真ん中にTextFieldを配置
- ・TextField押下でキーボード表示。このキーボードの上にUIToolbarを配置
- ・UIToolbar上に並んでいるUIBarButtonItemタップで、キーボードタイプを切り替え
UIBarbuttonItemのtitle変更は、「UIBarButtonItemタップ」で発火するようにしてみます。
準備
Interfaceに「Storyboard」を選択して、プロジェクトを作成します。画面真ん中にTextFieldを置いて、Keyboard Typeを「Number Pad」にしておきます。
ViewControllerで、TextFieldにUIToolbarを追加します。
ViewController.swift
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var sampleTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.setToolbar()
}
private func setToolbar() {
let toolbar = UIToolbar()
toolbar.sizeToFit()
let inputSwitchButton = UIBarButtonItem(title: "英数字入力に切り替え", style: .plain, target: self, action: nil)
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
toolbar.items = [space, inputSwitchButton]
self.sampleTextField.inputAccessoryView = toolbar
}
}
ここまでで、「英数字入力に切り替え」というtitleのUIBarButtonItemが表示されるようになりました。
UIBarbuttonItemのtitle変更
UIBarButtonItemタップ時の処理を定義します。
ViewController.swift
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var sampleTextField: UITextField!
// 中略
private func setToolbar() {
let toolbar = UIToolbar()
toolbar.sizeToFit()
let inputSwitchButton = UIBarButtonItem(title: "英数字入力に切り替え", style: .plain, target: self, action: #selector(self.inputSwitchButtonTapped(_:))) // 🍀変更
let space = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
toolbar.items = [space, inputSwitchButton]
self.sampleTextField.inputAccessoryView = toolbar
}
// 🍀追加
@objc func inputSwitchButtonTapped(_ sender: UIBarButtonItem) {
sender.title = "数字入力に切り替え"
}
}
inputSwitchButtonTapped()を定義して、その中でtitleの変更を行うようにしました。
さらに、inputSwitchButtonの#selectorに
inputSwitchButtonTapped()を設定することで、
ボタンタップ時にtitleが「数字入力に切り替え」へと変更されるようになります。
ここまでで、実際の動きは以下のようになります。
1回タップした後は、特に変化がありませんね。
今回はtitleと一緒にKeyboard Typeも変更したいので、inputSwitchButtonTapped()を以下のように修正します。
@objc func inputSwitchButtonTapped(_ sender: UIBarButtonItem) {
// キーボードが表示されたままだとKeyboard Typeの変更が反映されないのでフォーカスを外す
self.sampleTextField.resignFirstResponder()
// 🍀以下の分岐を追加
if self.sampleTextField.keyboardType == .numberPad {
sender.title = "数字入力に切り替え"
self.sampleTextField.keyboardType = .namePhonePad
} else if self.sampleTextField.keyboardType == .namePhonePad {
sender.title = "英数字入力に切り替え"
self.sampleTextField.keyboardType = .numberPad
}
// Keyboard Typeを切り替えた後に再度フォーカスする
self.sampleTextField.becomeFirstResponder()
}
(フォーカスのつけ外しについては、コメントの通りです)
現在のKeyboard Typeを判定して、titleとKeyboard Typeが切り替わるようにしました。
完成!
完成形は、以下のようになります。
以上、UIBarbuttonItemのtitleを変更する方法について紹介しました。
参考になるとうれしいです。
2021年3月29日月曜日
windows.openを使用した時に、iOSのSafariにて別タブでファイルを開けない場合の対処法。
オフィス狛 技術部のmmm(むー)です。
タイトルの通りですが、windows.open()を使用した際にiOSのSafariにて別タブでファイルを開くことができなかったため、その対処法を書きます。
1. リンクを押下後、APIを呼ぶ
2. API(Express)で、S3にあるPDFデータ(Blob)をレスポンスする
3. フロントにてAPIからのレスポンスを取得した後、別タブを開きPDFを表示する
・PCブラウザ(Chrome、 Firefox、 Sarfari)やiOSブラウザ(Chrome)はリンク押下後に別タブでPDFを開くことができる
observable.subscribe(downloadData => {
const blob = new Blob([downloadData], { type: 'application/pdf' });
const fileURL = window.URL.createObjectURL(blob);
window.open(fileURL, '_blank');
})
this.windowReference = window.open(); // <- 🌟変更
observable.subscribe(downloadData => {
const blob = new Blob([downloadData], { type: 'application/pdf' });
const fileURL = window.URL.createObjectURL(blob);
this.windowReference.location = fileURL; // <- 🌟変更
})
・ただ、別タブで開くか確認するポップアップが表示されますし、デフォルトはONになっています。
設定変更方法:iPhoneの設定 > Safari > ポップアップブロックをOFF
以上となります。
同じようにはまった方の参考になりましたら、幸いです🍭
2021年1月22日金曜日
WindowsでDockerを利用してDynamoDBサーバーをたちあげる時の注意点。
先日「WindowsでDockerを利用してMySQLサーバーを立てる場合の注意点」でも投稿しましたが、WindowsはDockerをVirtualBox経由で起動させているため、Macで起動する場合とは違い、うまく動かない部分があります。
今回は、WindowsでDockerをつかってDynamoDBサーバーをたちあげる時の注意点を記載しようと思います。
※今回DynamoDBはAWSのDynamoDB Localというツールを利用します。
前回投稿した時と同じようにDockerの起動にはdocker-compose.ymlを利用していきます。
docker-compose.ymlには以下のようにDynamoDBの接続設定を記載します。
※今回DBの記述がメインとなるので、API、DB側の記述は割愛します。
version: '3'
services:
api:
build:・・・
・・・
db:
build:・・・
・・・
dynamodb:
image: amazon/dynamodb-local:latest
container_name: elps-client-dynamodb
command: -jar DynamoDBLocal.jar -sharedDb -dbPath . -optimizeDbBeforeStartup
ports:
- "8000:8000"
前回同様上記のように書いて、あとは通常通り上記ymlを使ってDocker起動するだけです。
で、上記方法で、またまたMacでは上手くいくのですが、Windowsではなぜかうまくいきません。
起動はうまくできるのですが、設定したDynamoDBに接続ができないのです。😢
で、またいろいろ調べていくと、やっぱり今回もVirtualBox経由での起動が問題を引き起こしているようでした。。。
今回DynamoDBの接続ポートに8000を指定しているのですが、これはホストマシンのlocalhostで接続しに行きます。
ただ、DockerはVirtualBoxで起動しているため、VirtualBox側の設定でポートフォワーディングが必要なようです。
VirtualBoxのDynamoDBのポートフォワード設定方法
①まずVirtualBoxの「設定」ウィンドウから下記のように「ネットワーク」→「ポートフォワーディング」ボタンを押下します。
②ポートフォワーディングルールの画面の右側の+ボタンを押下して、今回のDynamoDBのポート8000を追加して、「OK」ボタンを押下します。

上記完了後、NoSQL Workbench等のツールや、AWS CLI等を利用してDynamoDBに繋がっているか確認できればOKです。
WindowsユーザーでDockerかつDynamoDBを使う場合には、これ結構ハマりポイントだと思うので、ご参考になれば幸いです。
アピアランスで文字の周りに少し大きい枠線をつくる。
2021年1月8日金曜日
2021年オフィス狛の年賀状の制作秘話。
2020年12月30日水曜日
Angular・Componentのタグにclassを付与したい【HostBinding】
こんにちは、オフィス狛 技術部のpinoです。
早速ですが、皆さんはAngularをやっていて「コンポーネントのタグに直接classを付与したいんだけどなぁ....。」と思った経験はないでしょうか。
今回は、そんな時に使える @HostBinding についてご紹介したいと思います!
準備
まずは、コンポーネントを用意します。app.component.html(親コンポーネント)
<header class="header">
<section class="header__about">
<h1 class="header__title">@HostBinding Sample</h1>
<p class="header__lead">動作確認用のサンプルです</p>
</section>
<nav class="header-nav">
<ul class="header-nav__list">
<app-list-item *ngFor="let name of names" [name]="name"></app-list-item>
</ul>
</nav>
</header>
list-item.component.html
<li class="header-nav__item">
<input type="checkbox" />{{ name }}
</li>
list-item.component.css
.header-nav__item {
width: 120px;
height: 64px;
padding-left: 32px;
line-height: 64px;
}
list-item.component.ts
import { Component, Input, OnInit } from '@angular/core';
@Component({
selector: 'app-list-item',
templateUrl: './list-item.component.html',
styleUrls: ['./list-item.component.scss']
})
export class ListItemComponent implements OnInit {
@Input() name: string;
constructor() { }
ngOnInit(): void {
}
}
ビルド後のイメージ
色味がなく、シンプルで寂しい印象です。
ここから、実際にHostBindingを使ってclassを付与してみたいと思います。
HostBindingの使い方
使い方は1. コンポーネントのタグにclassを付与する
2. 上記1に加えて、動的にclassの付け外しをする
と、主に2つあります。
まずは、1. コンポーネントのタグにclassを付与するについてです。
こちらは、大きく2通りの書き方ができます。
list-item.component.css
import { Component, HostBinding, Input, OnInit } from '@angular/core'; // HostBinding を追加
@Component({
selector: 'app-list-item',
templateUrl: './list-item.component.html',
styleUrls: ['./list-item.component.scss']
})
export class ListItemComponent implements OnInit {
@HostBinding('class') listItem = 'list-item'; // ①
@HostBinding('class.first') first = true; // ②
@Input() name: string;
constructor() { }
ngOnInit(): void {
}
}
ポイントは、@HostBinding()の、()の中です。
①は、「'class'」のみ指定して、なんのclassを付与するかは変数の値が使用されるパターンです。
値部分に定数を使えば、ロジック側にテンプレートの情報をベタ書きすることも避けられますね。
固定のclassであればこれで十分そうです。
②は、「'class.first'」と付与するclass名まで指定するパターンです。
この場合は、後に続いている値がtrueであれば付与、falseであれば付与しない、ということになります。
(※真偽値を固定で設定したい場合は、「@HostBinding('class.first') readonly first = true;」 といった具合に、readonlyをつけるなどの対策が考えられます。)
また、HostBindingの話とはすこし逸れますが、コンポーネントのタグに使用するclassは
グローバルである(style.cssに記述されている等)か、:hostメタデータを使用する必要があります。
今回は、自コンポーネントのCSSに背景色をつけるclassを用意したいと思います。
list-item.component.css
// 以下を追加
:host.list-item.first {
background-color: #7ae5ec;
}
:host.list-item.second {
background-color: #7aecc0;
}
:host.list-item.third {
background-color: #7ab9ec;
}
ここまでのビルド後イメージ
すべてのコンポーネントにclassが付与されて、背景色がつきました。
次は、2. 上記1に加えて、動的にclassの付け外しをするについてです。
list-item.component.css
export class ListItemComponent implements OnInit {
@HostBinding('class')
@Input() name: string; // ①
// 今回formは用意していないので、例としてだけ挙げます
@HostBinding('class.valid') get valid() {
return this.form.valid;
} // ②
@HostBinding('class.list-item') isClick = false; // ③-A
...
onClick(): void {
this.isClick = !this.isClick;
} // ③-B
他にもいろいろな方法があると思うのですが、簡単に思いつくものを挙げてみました。
①は、Input()で受け取った値を使用します。
組み合わせて使うだけで、特別なことをしてる感じがします...!
②について、今回Formは用意していないので記述の例になるのですが、状態など値そのものを監視したい時に使える方法です。
getterってあまり使う機会がなかったのですが、今回試してみたところ使い勝手がいいですね!
また③は、②のようにイベント発生時ではなく、識別子に設定した変数の値を書き換えることによってclassの付け外しをしています。
ここまでで、上記の①と③をプログラムに落とし込んだビルド後のイメージが以下のようになります。
それぞれで別々のclassの付与と、classの付け替えができました!
補足
ここまでclassを付与する使い方を紹介してきましたが、なんとHostBindingはclass以外のバインディングにも使えます。例えば、「@HostBinding('style.display') flex = 'flex';」としてあげればstyle="display: flex;"がバインドされます。
便利!
今回は公式以外に以下サイトも参考にしたのですが、「HostBinding('value') myValue;は[value]="myValue"と全く同じです。」という一文が特にわかりやすかったです。
@HostBindingと@HostListener:彼らは何をし、何のためにいますか?
以上、HostBindingデコレータについて紹介しました。
参考になればうれしいです。
Spring Fest 2020に参加しました。
オフィス狛 技術部のJoeです。
Spring Fest 2020が開催されましたので、昨年に引き続き参加しました。
公式ページ
今年はオンライン開催ということで、昨年のような雰囲気ではありませんでしたが、
質問をチャットで受け付けてセッション後に回答いただけるなど、良かった点もありました。
また、今回は「Advanced Track」と「Beginner track」の2トラックで分かれて配信されていましたので、初めて参加される方も、セッションを選択し易かったかと思います。
(私はどれも聞いてみたく、結構直前まで迷ってしまいました)
今回も、特に気になったセッションの感想を、ブログに残したいと思います。
今こそ知りたいSpringエコシステム
槙 俊明さん(VMWare)セッション資料
Springの歴史から始まり、主なSpring Projectを下記の3つの分類に分けて紹介されていました。
・できることを増やす
・バリエーションを増やす
・使いやすくするプロジェクト
改めて、様々なプロジェクトがあることを認識させられたことと、
最新情報は、書籍ではなく、公式ドキュメントと
プロジェクト開発者のGihub、Twitterで集めることが勉強になりました。
今こそ知りたいSpring DI × AOP
多田 真敏さん(株式会社カサレアル)セッション資料
Springの基礎である、コンテナ、DI、スコープ、プロキシ、AOPについて丁寧に解説されていました。
初心者向けとありましたが、私の勉強不足もあり、なかなか説明に追いつけないところがありましたので、是非、もう一度復習したい内容でした。
CloudNativeな決済サービスの開発と2年間の歩み
鈴木 順也さん(SBペイメントサービス)セッション資料
大規模な決済サービスのシステムを、2年間運用された実績をもとに、
アプリケーション構成とアプリの役割から、
ライブラリの移行と発生した問題、開発体制、CI / CD、テスト、Observabilityといった内容を
実績で紹介されていました。
1つのサービスの歩みという内容がとても面白く、勉強になりました。
また、2年経過してシステム数やアプリ数が増加しているのでに、
プラットフォーム運用者はほぼ変わらないという点にはとても驚きました。
Spring 5.3 & Spring Boot 2.4
槙 俊明さん(VMWare)セッション資料
こちらはSpring 5.3 と Spring Boot 2.4 の新機能の紹介でした。
常に新しいもの、いいものを取り込んで進化しているという印象を受けました。
特に気になったのは、「プロパティ読み込み方法の改善」で、YAMLの定義方法が紹介されていました。
過去にSpring Boot のバージョンアップを行った際に、YAMLの定義方法の変更で、
結構ハマってしまうことがあったので、早めのバージョンアップが必要だなと思いました。
またこちらのセッション後にあった、Springについて色々な観点からの質問コーナー(?)は個人的に面白かったです。
今回はオンラインでの開催で、目的のセッションをゆっくり視聴できました。
今回のセッション動画は、今は非公開になっていますが、
来年に公開される予定とのことですので、今回視聴出来なかったセッションも確認してみたいと思います。

























