JPEG Image Filer バージョン2.7.0公開

デジカメで撮影した写真などを自動的に撮影日でフォルダに整理するためのアプリケーションです。撮影日はExif情報を利用しています。 動画の振り分けにも対応して欲しいという声が多かったため、v2.0.0よりデジカメ等で撮影したMP4形式の動画も対象になりました。 Read the rest of this entry »

Xcodeで「No signing certificate “iOS Development” found」

Xcodeの新規プロジェクト、または既存プロジェクトを開き、
プロジェクト設定のSigning欄でTeamを選択したら
No signing certificate “iOS Development” found
というエラーが出てしまった場合、
有効な証明書(*.cer)ファイルがキーチェーンに登録されていない
(登録されている証明書が全て期限切れ等)
可能性がある。

Developerサイトの「Certificates, Identifiers & Profiles」にて
新しい証明書を作成し、ダウンロードしたものを
キーチェーンアクセスの証明書のところにドラッグ&ドロップすれば登録され、Xcodeで再読込(Teamを再設定)すればエラーは消える。

Xls/xlsx File Unifier バージョン1.3.0版公開

ダウンロード

◆ これは何か?

  • 拡張子が xls または xlsx であるMicrosoft® Excel®ブック形式のファイルの体裁を統一させるためのアプリケーションです。ブックファイルの全シートの表示形式と表示倍率を揃え、かつ、全シートのA1セルを選択した状態にし、更にはブック中の先頭シートを選択した状態にします。
  • Microsoft® Excel® ブック形式のファイルを納品物や情報資産として利用する場合、ファイルを開いた時に不適切な位置が表示されてしまうと格好悪いので、ドキュメントの最後の仕上げとして体裁を整えたい場合に重宝します。特にそういった利用の仕方をする場合、ブックファイルが1つや2つではないので、それらを1つずつ開いて確認しながら直していくのは大変です。 それをこのアプリケーションでは一括して修整することができます。
  • また、取引先に渡す際にはパスワードをかけて暗号化することが取り決め上必須となっているケースがあります。そうは言っても、内部で管理している物に対してパスワードをかけてしまうと、ちょっとした参照や修正の度にパスワードを入力する必要があるために作業の効率が落ちます。できれば内部ではパスワードをかけない状態で管理しておいて、外部に提出する時にだけパスワードをかけたいところ。ただし、毎回全てのファイルにパスワードをかける作業はしたくない。そんな時、このアプリケーションが役立ちます。
  • 主にドキュメントの納品や管理の責任者の方に使っていただくことを想定しています。これまではこうした修整は別の担当者に手分けして作業をさせていたことが多いと思いますが、これからはその必要が無くなります。私自身もそうした修整作業を、納品間際のドタバタした中で行ってうんざりした経験からこのアプリケーションを開発しました。

◆ 動作環境

.NET Framework 4.0 が動作する環境。

  1. お使いのコンピュータにまだ .NET Framework 4.0 を導入されていない場合は以下のURLからダウンロードしてインストールを行う必要があります。
    https://www.microsoft.com/ja-jp/net/netfx4/download.aspx
  2. Microsoft® Excel® 2007/2010 がインストールされている環境。

◆ 使い方

  • Microsoft® Excel® ブック形式のファイルまたはそれらを含むフォルダをマウス等でドラッグ&ドロップします。フォルダの中にはブック形式以外のファイルが含まれていても構いません。
  • 統一させたい表示形式と表示倍率を指定します。
  • 実行ボタンを押すと確認ダイアログが表示され、OKボタンを押すと処理を開始します。
  • 尚、隠しファイルや読取専用ファイルは処理されません。
  • 「読取パスワード」にパスワードを入力しておくと、パスワードがかかっているファイルも処理することができます。
  • 「設定用」にパスワードを入力しておくと全てのファイルに同じ読取パスワードを設定し、「設定用」のパスワードを空欄にしておくと全てのファイルの読取パスワードを解除します。
  • 尚、「共通」にチェックを入れると、ファイルを開く時のパスワードと同じパスワードを読取パスワードとして設定します。
  • 一度実行後、続けて作業を行いたい場合は「全てクリア」ボタンを押してリストをクリアしてから、再度ファイルまたはフォルダをドロップして作業を行うことができます。

◆ 利用条件

  • 本ソフトウェアはフリーウェアとして公開しています。ご利用に当たり料金は発生いたしません。
  • 著作権はクロスラボラトリーにあります。

◆ 免責事項

  • 本ソフトウェアは無保証です。ご利用によって生じたいかなる損害に対しても作者は責任を負わないものとします。ご自身の責任においてご利用ください。
  • 特に大切な情報資産を取り扱う場合には、バックアップを取得するなど万全の態勢を敷いた上でご利用いただくようにお願いいたします。

更新履歴

  • v0.0.1b (2013-04-14)
    β(ベータ)版公開
    Officeの下位互換性テスト中
  • v0.0.2b (2013-04-17)
    非表示のシートが含まれるブックが処理できない不具合を修正
  • v1.0.0 (2013-05-25)
    アイコンを追加して正式版とする
  • v1.1.0 (2013-07-07)
    ファイル階層の取得方法を変更
  • v1.2.0 (2016-03-07)
    ファイルを開く時のパスワードを指定できるように変更
    タイムスタンプを維持するオプションを追加
    設定を保存できるように変更
  • v1.2.1 (2016-04-12)
    ファイルを開く時のパスワード指定の不具合を修正
    進捗状況をプログレスバーに加えて数値でも表示するように変更
    起動時に表示モードの設定が反映されない不具合を修正
  • v1.3.0 (2018-02-01)
    読取パスワードを設定できる機能を追加

[CakePHP3]2つのファイルアップロードのうちどちらか一方を必須にしたい

複数のファイルアップロードフィールドを配置し、それら全てではなく、そのうち一つが入力されることを保証するバリデーションを行いたいというケースがある。

https://book.cakephp.org/3.0/ja/core-libraries/validation.html#id9
ここにあるように条件付きバリデーションで実装しようとしてnotEmpty()メソッドに on オプションをつけてみたが、$this->Form->file()でレンダリングされた時点で全てのファイルアップロードフィールドに required 属性が付与されてしまって全てが必須になってしまう。

こういう時は時間があればバリデーションクラスを実装する方が美しいが、余裕がなければ標準から外れてしまうが思い切ってバリデータの使用は諦めて、コントローラーで実装してしまった方が早い。

その場合、エラーメッセージはEntityクラスのsetError()メソッドを使って、

1
2
3
4
5
6
7
8
9
10
11
12
$foo = $this->Foos->patchEntity($foo, $this->request->getData());
if ($foo->getErrors()) {
    // 入力チェックエラー
}
else if (!isset($this->request->getData('file1')['name'])
        && !isset($this->request->getData('file2')['name'])) {
    // 独自のバリデーションエラー
    $foo->setError('file1', 'ここにエラーメッセージを書く');
}
else {
    // 保存処理など
}

のような形でセットしてやれば、画面の方で他のバリデーションエラーと同様に表示ができる。

—-

[CakePHP3]ファイルを持つエンティティにpatchEntityメソッドでファイルアップロードフィールドをコピーしたい

Webサイトであれば、アップロードしたファイルをストレージに保存し、ファイルのパスまたはURLをデータベースで管理するといったケースはよく行われるだろう。

とあるBlogエンティティに画像のファイルパスを複数持っているとする。例えばこんな感じ。

  • blog_title
  • blog_image_path_1
  • blog_image_path_2

これを愚直にこのようなフォームにしてしまうとする。

1
2
3
4
5
<?= $this->Form->create($blog, ['enctype' => 'multipart/form-data']) ?>
  <?= $this->Form->text('blog_title') ?>
  <?= $this->Form->file('blog_image_path_1') ?>
  <?= $this->Form->file('blog_image_path_2') ?>
<?= $this->Form->end() ?>

このフォームのリクエストを受け取って

1
2
3
$blog = $this->Blogs->get($id); // DBから取得
$blog = $this->Blogs->patchEntity($blog, $this->request->getData()); // 画面の入力を反映
$this->Blogs->save($blog); // DBに保存

としてしまうのは、2つのファイルが両方とも必須項目であればともかく、片方だけ変更するといったケースでは、指定しなかった方のファイルパスがブランクになってしまって都合が悪い。

そういう場合は、イレギュラーな対応かもしれないが、直接コピーすることをせずに、エンティティにはない項目を一時的に使用して、最終的にエンティティに格納するようにする。そもそもファイルアップロードフィールドには初期値は設定できないのだ。

1
2
3
4
5
<?= $this->Form->create($blog, ['enctype' => 'multipart/form-data']) ?>
  <?= $this->Form->text('blog_title') ?>
  <?= $this->Form->file('blog_image_file_1') ?>
  <?= $this->Form->file('blog_image_file_2') ?>
<?= $this->Form->end() ?>
1
2
3
4
5
6
7
8
9
10
11
$blog = $this->Blogs->get($id);
$blog = $this->Blogs->patchEntity($blog, $this->request->getData());
// 1つ目のファイルが指定されていたら反映
if (isset($this->request->getData('blog_image_file_1')['name'])) {
    $blog->blog_image_path_1 = $this->request->getData('blog_image_file_1')['name'];
}
// 2つ目のファイルが指定されていたら反映
if (isset($this->request->getData('blog_image_file_2')['name'])) {
    $blog->blog_image_path_2 = $this->request->getData('blog_image_file_2')['name'];
}
$this->Blogs->save($blog);

尚、入力チェックや、基本ディレクトリ名の合成などは省略しているので、各々の状況に合わせてアレンジして欲しい。

ファイルアップロードフォームから渡ってくる項目の詳細については以下を参照のこと。
https://secure.php.net/manual/ja/features.file-upload.post-method.php

—-

Quick Password Maker バージョン1.1 公開

パスワードをより強固に、より安全に!

 これは新しいパスワードを勝手に考えてくれるアプリです。

 昨今、パスワードの使い回しによってアカウントに不正にアクセスされてしまう事故が多く発生しています。ここまで世の中にITサービスが増えてくると、それぞれで異なるパスワードを設定することが必要になってきます。しかし、そのためには、自分の頭で考えたのではバリエーションにも限界がありますし、強度にも不安が残ります。そこでこのアプリを使えば、より強固でより安全なパスワードを代わりに考えてくれます。

スクリーンショット

スクリーンショット

◆ 特徴

  • 文字種として英大文字、英小文字、数字の使用・不使用をそれぞれ指定できます。
  • 記号は13種類の中から使用・不使用を個別に指定できます。
  • 全ての文字種を必ず1回以上使うようにできます。
    (記号はいくつ指定されても1種類と数えます。)
  • 同じ文字を2回以上使わないようにできます。
    (文字数と文字種の設定の兼ね合いで出来ない場合もあります。)

◆ 使い方

  1. パスワードに使う文字種を指定します。
  2. パスワードの長さを指定します。
  3. 「パスワードを生成」ボタンを押します。
  4. 必要に応じてコピーして利用します。

◆ 動作環境

iPhone, iPod Touch(iOS 6.0以上)

◆ 利用条件

  • 本ソフトウェアはフリーウェアとして公開しています。ご利用に当たり料金は発生いたしません。
  • 著作権はクロスラボラトリーにあります。

◆ 免責事項

  • 本ソフトウェアは無保証です。ご利用によって生じたいかなる損害に対しても作者は責任を負わないものとします。ご自身の責任においてご利用ください。

◆ オマケ

  • パスワード生成後に端末をシェイクすると生成したパスワードを消去します。

◆ 更新履歴

  • v1.0 (2013-06-22)
    • 公開しました。
  • v1.1 (2016-06-16)
    • iOS 9 に対応しました。

Quick Password Maker ver1.1 Released!

Get Your Password Stronger and Safer!

This app automatically creates a new password.

Recently, many accidents that are unauthorized access to accounts by the recycling of password have occurred. With the increase in IT service, it becomes necessary to set a different password in each. However, to perform it, when a person thinks with one’s head, there is a limit in both the variation and the strength. If you use this application, the application makes stronger and safer password, instead of you.

Screenshot of Quick Password Maker

Screenshot

Features

  • You can specify each use and non-use uppercase, lowercase, numbers as character types.
  • You can specify individual use / non-use from 13 types as a symbol.
  • You can specify to use one or more times always the character types of all.
    Even if how many symbols are specified, symbol is counted as one kind.
  • You can specify not to use more than once the same character.
    In some cases, you can not specify it in consideration of character types and password length.

Usage

  1. Specify the character types to use for password.
  2. Specify the length of the password.
  3. Press the button “Generate Password”.
  4. Copy and use as needed.

Requirements

iPhone, iPod Touch(iOS 6.0 or later)

License & Copyright

  • This software is FREEWARE. There is NO CHARGE Upon use.
  • CROSS LABORATORY holds the copyright.

Disclaimer

  • This software is NO GUARANTEE. We shall not take responsibility for any damage that occurred because of the use. Please use it in the responsibility of own.

Misc

  • After generate passowrd, Shake your device to erase the password.

History

  • v1.0 (2013-06-22)
    • Released.
  • v1.1 (2016-06-16)
    • Adapted to iOS 9.

Xls/xlsx Names Eraser バージョン1.0.0版公開

ダウンロード

◆ これは何か?

  • 拡張子が xls または xlsx であるMicrosoft® Excel®ブック形式のファイルに定義されている不要な「名前」を削除するためのアプリケーションです。ブックファイルに定義された全ての「名前」を削除することで、結果としてファイルサイズを抑制することができます。削除したくない名前を設定することもできます。
  • Microsoft® Excel® ブック形式のファイルを情報資産として担当者から担当者へと、特にコンテンツは引き継がなくても書式だけ引き継がれるということもあります。その過程で、意図すると意図せざるとにかかわらず名前を定義することがありますが、それがある時は有用であったにせよ、たまたま外部リソースを参照しているなどしてたために別の環境では使えず、よく分かっていない人が元の名前を削除せずに別の名前を再定義して、そうやって再利用を繰り返しているうちにファイルサイズが肥大化してしまうということがあります。
    書式を使いたいなと思うファイルをコピーして、書式だけ残してコンテンツをクリアし、新しいドキュメントとして作成し始めたとします。大したコンテンツを追加していないのに、まっさらな状態から作成した時と比べてやけにファイルサイズが大きいとか、編集時の操作がもたつくといったことに気付いた場合、よくよく調べてみると無用な名前定義が数十個も登録されていたというようなケースがありました。更にはそれらの名前定義が非表示になっており、見える名前だけ削除しても状況があまり改善しないということもあります。
  • 主に既存ドキュメントの書式を流用して別のドキュメントを作成するような管理者や担当者の方に使っていただくことを想定しています。これまではこうしたメンテナンスは行われておらず、あるいはメンテナンスを行ったとしても個別に手作業で不要な名前を削除していたと思いますが、これからはそうした手作業の必要が無くなります。私自身もそうした手作業を、忙しいさなかに行ってうんざりした経験からこのアプリケーションを開発しました。

◆ 動作環境

.NET Framework 4.0 が動作する環境。

  1. お使いのコンピュータにまだ .NET Framework 4.0 を導入されていない場合は以下のURLからダウンロードしてインストールを行う必要があります。
    https://www.microsoft.com/ja-jp/net/netfx4/download.aspx
  2. Microsoft® Excel® 2007 以降がインストールされている環境。

◆ 使い方

  • Microsoft® Excel® ブック形式のファイルまたはそれらを含むフォルダをマウス等でドラッグ&ドロップします。フォルダの中にはブック形式以外のファイルが含まれていても構いません。
  • 削除したくない名前を「削除しない名前」欄に追加します。
  • 実行ボタンを押すと確認ダイアログが表示され、OKボタンを押すと処理を開始します。
  • 尚、隠しファイルや読取専用ファイルは処理されません。
  • 一度実行後、続けて作業を行いたい場合は「全てクリア」ボタンを押してリストをクリアしてから、再度ファイルまたはフォルダをドロップして作業を行うことができます。

◆ 利用条件

  • 本ソフトウェアはフリーウェアとして公開しています。ご利用に当たり料金は発生いたしません。
  • 著作権はクロスラボラトリーにあります。

◆ 免責事項

  • 本ソフトウェアは無保証です。ご利用によって生じたいかなる損害に対しても作者は責任を負わないものとします。ご自身の責任においてご利用ください。
  • 特に大切な情報資産を取り扱う場合には、バックアップを取得するなど万全の態勢を敷いた上でご利用いただくようにお願いいたします。

更新履歴

  • v0.0.1b (2015-07-02)
    β(ベータ)版公開
  • v0.0.2b (2016-02-29)
    ファイルを開くパスワードを指定できるように変更
  • v0.0.3b (2016-03-02)
    パスワードを渡せていなかったバグを解消
  • v1.0.0 (2016-03-07)
    タイムスタンプを維持するオプションを追加
    設定を保存できるように変更

NSFetchedResultsControllerとUISearchDisplayControllerを使ったUITableView検索機能の実装

NSFetchedResultsControllerとUISearchDisplayControllerを使ったUITableViewの検索機能を実現するというトピックはネット上でも幾つか見つかるのだが、複数のクラスが組み合わさって動作するためになかなか思うような動きをするコードを書くことができなかった。

UITableView(ここではMaster-Detail Appとする)にUISearchDisplayControllerを組み合わせ、UISearchBarに検索文字列を入力するとすぐに絞り込まれる(ようにコードを書く)のだが、その時表示される絞り込まれた表はUITableViewではなくUISearchResultTableViewのインスタンスである。だから、現在見えている表がどのクラスのインスタンスなのかを意識しなければ思うようなコードを書けないということを痛感した。

表のデータソースにCore Dataを使用している場合、NSFetchedResultsControllerとUISearchDisplayControllerの両クラスの連携が鍵になる。

よく見かけるサンプルコードは次のようなものである。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView beginUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = self.tableView;
  // (省略)
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView endUpdates];
}

だが、検索して絞り込んだ表から選択して更に編集画面でDBを更新した場合、このcontrollerDidChangeContentメソッドでアベンドしてしまう。

1
2
 Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0.
(以下省略)

こんなメッセージだ。言いたいことは分かるがどう対応して良いか分からない。

1
[self.tableView endUpdates];

の代わりに

1
[self.tableView reloadData];

とやれば、更新時にアベンドはしなくなるが、検索をキャンセルした場合に表示されるオリジナルの表のレンダリングがおかしくなってしまう。(あと、削除できなくなったり詳細画面に遷移できなくなったり。)散々悩んだ挙句、冒頭の書いたことに思い当たった。そう、分かってしまえば何てことはない。NSFetchedResultsControllerの操作も、どのTableViewに対して行うかを判断すれば良かったのだ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    if (self.searchDisplayController.isActive) {
        [self.searchDisplayController.searchResultsTableView beginUpdates];
    }
    else {
        [self.tableView beginUpdates];
    }
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = self.searchDisplayController.isActive ? self.searchDisplayController.searchResultsTableView : self.tableView;
   
    // (省略)
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    if (self.searchDisplayController.isActive) {
        [self.searchDisplayController.searchResultsTableView endUpdates];
    }
    else {
        [self.tableView endUpdates];
    }
}

UITableViewCellの再利用について

iOS 5.x までは
– (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
メソッド内で

1
2
3
4
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TABLE_CELL_NAME];
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:TABLE_CELL_NAME];
}

のようなコードを書く必要があったが、iOS 6.0 からは – (void)viewDidLoad メソッドに

1
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:TABLE_CELL_NAME];

というセットアップをすれば

1
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TABLE_CELL_NAME forIndexPath:indexPath];

と書くだけで良いというのがネットで得られる情報なのだが、UISearchDisplayController を使って検索機能を実装しようとすると検索文字列を入力した途端に落ちてしまう。検索結果は UITableView が使われるのではなく、UISearchResultTableView のインスタンスが(しかも都度)生成されるので、適切な場所でセットアップをしてあげる必要がある。ここではupdateFilteredContentForNameメソッドで検索をした直後に記述したら(5行目)うまくいった。

1
2
3
4
5
6
7
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString
{
    [self updateFilteredContentForName:searchString];
    [self.searchDisplayController.searchResultsTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:TABLE_CELL_NAME];
    return YES;
}
アーカイブ