FC2ブログ

頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


Automatorとショートカットを使い文字数を数える

Macで文書作成時に文字数を計測したいと思い、調べたところAutomatorを使うとできそうなので設定した。
作業時の流れは、作成した文書のテキストを選択し、ショートカットで文字数が表示される、という感じ。
なのでAutomatorでサービスを作成し、ショートカットを設定する、という二つのことを行う。

Macで選択中のテキストの文字数をカウントするスクリプト【DL有り】 | くにぽん’ず☆きちめきパラダイス

↑こちらにあるコードを使用させていただいた。感謝、感謝!
ただAutomator初心者の私にはこの記事を読んでもすんなり設定できず異様に苦労した。なので、なるべくAutomatorに慣れていない人にもわかるように書いてみた。


(1) Automator起動

Automatorアプリのアイコン

↑このロボットみたいなアイコンのアプリ。Macにデフォで入ってるはず。

(2) 書類の種類を選択

書類選択画面

↑種類は「サービス」を選択する。
本目的ではワークフローでもアプリケーションでもない。拡張子は.workflowになるが気にしない。

(3) コードをコピペ

ワークフローを作成するには、ここにアクションまたはファイルをドラッグしてくださいというメッセージ

↑デフォだと「ワークフローを作成するには、ここにアクションまたはファイルをドラッグしてください。」なんて出てるがここでもがいてもダメ。
「ライブラリ」の中にある「ユーティリティ」を選択(クリック)し、その右側にある「AppleScriptを実行」をダブルクリックする(クリックじゃない)。

コード入力画面

↑撮影用に小さくしてるけどこんなコードを入力するような画面が出てくるはず。
デフォであるコードは削除して、上記リンク先にあるコードをコピペする。
ここで実行してもちゃんと動かないけど気にしない。

(4) 保存する

サービスの名前入力画面

↑⌘+s等で保存しようとすると「サービスの名前」を入力する画面が出るので好きなのを入力し、保存をクリックでOK。ここでは「文字数を数える」としてる。
保存先は聞かれない。macOSが良きに計らってくれる。

(5) ショートカットを設定する

ショートカット設定画面

↑システム環境設定 / キーボード / ショートカット / サービス
を見ると先ほど設定したサービスの名前があるので、そこで好みのショートカットを設定する。
ただ、簡単なのは他で使われていたりするので、自分の納得できるショートカットを設定しよう。
自分の場合は片手でいけるよう ⌘+control+shift+c とした。
実行結果画面
↑実行時の結果。別ウインドウで表示される。

(6) コードを変更する場合

二本指タップ時の画面

↑ショートカット設定のところでサービスの名前のところで右クリック(?私はトラックパッドなので二本指タップなんですが)すればこのように選択肢が出るので Automatorで開く を選択すれば再度編集ができるし、 Finderに表示 を選択すれば保存先がわかる。



バージョン情報
macOS High Sierra 10.13.6


NSTableViewにNSPopupButtonを置く

macOSでNSPopUpButtonとたわむれる
↑この続き。
上記の記事でNSPopupButtonを使ったがこれは言わば練習で、元々はこれをテーブルで使いたかった。

ところが、単純にstoryboradでNSTableViewのセルのところにNSPopupButtonを置いてもうまくいかない。
テーブルなので複数行のNSPopupButtonオブジェクトができた時にそれぞれのボタンが何を示しているかを得るのが難しい(※1)。
NSpopupButtonの参照を得ようとoutlet繋いでも複数はあかんってエラー出るし。


調べたところ、こういう記事が↓
cocoa - Pop up Button in view based NSTableView - Stack Overflow

このページにあるリンク先のpopTestプロジェクトをダウンロードして動かしてみると、、、

popTestスクショ

そうそう、こういう風にしたいのだよ!

ところが、このプロジェクトをよく見るとxibファイルに記述しててstoryboardを使っていない。

部品構成(xibファイルの場合)

↑xibファイルを選択するとこうなってるんだが、、、
ちょっ、、え?storyboardでやるのはどうすんの?なんか勝手が違うやん、、、?

結局、、、参考ページのプロジェクトと部品の構成を同じにてBindingsの設定をあーでもない、こーでもないと試行錯誤しまくったのだが、、、やっぱりダメ。

ようやく気付いたのが、Array Controller(NSArrayController)をstoryboard上で部品としてLibrary(※2)から追加できること(※3)。

LibraryでArray Controllerを選択

↑arrayとかで見つかるのでこれをドラッグ&ドロップ。

さらに追加したArray Controllerで
1. Connections inspector(※4)でoutletを接続
2. Bindings inspector(※5)のContent Arrayを設定

これで無事参考ページと同等のことができた。

これだとNSTableViewDataSource、NSTableViewDelegateのどちらもコードで設定してない。面白いなあ。

しかもこの方法でも、Connections inspectorでNSPopupButtonのactionを設定(コード内のメソッドへ接続)すれば、ボタンをクリック後にそのメソッドがコールされる。

なお、参考ページではdelegateに接続してるけど、

部品構成(storyboardの場合)

↑ファイル構成はこんな感じなのでViewControllerクラスに接続してる。




※1 苦し紛れの回避策
NSPopupButtonオブジェクトのsuperviewはセルを示すのであらかじめ
-(NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row;
で各行のセルのポインタを得ておけばなんとかわかるのだが、、、そんなの強引すぎるよな。素直にバインドを勉強しようと思いました。


※2 Libraryとは
Storyboardで部品を選ぶ方法


※3 参考リンク
NSTableViewをCocoa Bindingsで使ってみた - takopomm’s diary


※4 Connections inspectorとは
Connections inspector
↑右から3つ目、丸の中に右矢印のあるやつ。


※5 Bindings inspectorとは
Bindings inspector
↑右から2つ目、ラーメン鉢の模様みたいなやつ。


macOSでNSPopUpButtonとたわむれる

macOSにはNSPopUpButtonなるものがあって、いくつかの選択肢から選べるようなボタンだ。

NSPopUpButton選択前

↑見た目はこんなの。

NSPopUpButtonクリック時

↑クリックすると選択肢が現れて選ぶことができるってやつ。

バインドとかもあるんだけど、自分が一番理解しやすかった簡単なやり方を紹介。delegateも設定しない。

まずはstoryboardでpopup buttonを設置する。

Xcode10の部品選択画面

↑部品選択画面でpopupとでも打てばいくつか候補が出てくる。この画面はなんだ?という場合はこちらをどうぞ↓

Storyboardで部品を選ぶ方法

一番上のPop Up Buttonをドラッグ&ドロップ。

このオブジェクトの参照がコード側で欲しいのでつないであげる。
あらかじめコード側に
{
    IBOutlet NSPopUpButton *popupButton;
}
などと用意しといてstoryboardでReferencing Outletsを接続。

デフォだと選択肢として3つほど項目があるけど今回はコード側で設定したいので削除したい。

NSPopUpButtonのクラス構成

↑storyboardのボタンのところの構成を見るとMenuの下にItem 1とかあったりすると思うけど3つとも削除(画像は削除した後)。

選択肢の項目をコード側で設定したいので、viewDidLoad内など適当なところで↓このように追加する。
{
    [popupButton addItemWithTitle:@"Osaka"];
    [popupButton addItemWithTitle:@"Kyoto"];
    [popupButton addItemWithTitle:@"Nara"];
}
設定できない!って場合はもしかしたらまだstoryboardに置いた部品のオブジェクトができていない場所で設定しているのかも。オブジェクトがちゃんとできてるかチェックしてみましょう。
他にも似たような追加、挿入、削除用のメソッドがあるのでリファレンスをどうぞ。

ここで実行すればとりあえず選択はできると思う。popupButtonのプロパティからどれが現在選択されているかわかるはず。

でもやっぱり、ボタンで何か選択した場合にコールされるようにしておきたい。
{
-(IBAction)tappedPopupButton:(id)sender
{
    NSPopUpButton *button = (NSPopUpButton *)sender;
    
    NSLog(@"titleOfSelectedItem=%@", button.titleOfSelectedItem);
    NSLog(@"indexOfSelectedItem=%ld",(long)button.indexOfSelectedItem);
}
↑こんなコードを作っておいて、、、

outlet接続

↑storyboardのactionのところでつなぐ。

実行結果のログ

↑これで一応ボタンを閉じた時にこのメソッドがコールされる。画像は実行時のログ。
ただし、変更がなくてもコールされるのでそのあたりは実装時に注意する、ということで。





学習後パラメータをファイルからMPSで読み込む(CNNの場合)

Kerasの学習後パラメータを保存する(CNNの場合)

↑この続き。
この方法で出力した係数のファイルをmacOSアプリのMetal Performance Shadersで使いたい。
なお、今回の話は係数ファイルがすでにできてしまっているのでTensorFlowもKerasも関係ない。

APPLEのサンプルコードだとSwiftのみ(やめてーっ!!)の
MPSCNNHelloWorld: Simple Digit Detection Convolution Neural Networks (CNN)
というサンプルコードがある。
ダウンロードするページを見てみると、、、

サンプルコードMPSCNNHelloWorldのダウンロードページスクショ

↑全然メンテされてない、、、😅
ダウンロードしてもエラーでてビルドできないんだが。
Update to recommended settings ってのが出るのでそれをしてやるとできるのかもしれないけど、知らない、Swiftだし(なげやり)。

サンプルコードだとバンドルされた係数ファイルを読み込んでるので、これを別なフォルダに置いてるファイルから読み込むようにする。

サンプルコードのSlimMPSCNN.swiftというNNの層を作成する補助クラスみたいなのをObjective-Cで書き換えたのがこんな感じ↓
{
@implementation SlimMPSCNNConvolution

- (instancetype)initWithKernelWidth:(NSUInteger)kernelWidth
                       kernelHeight:(NSUInteger)kernelHeight
               inputFeatureChannels:(NSUInteger)inputFeatureChannels
              outputFeatureChannels:(NSUInteger)outputFeatureChannels
                       neuronFilter:(MPSCNNNeuron *)neuronFilter
                             device:(id<MTLDevice>)device
             kernelParamsBinaryName:(NSString *)kernelParamsBinaryName
{

    NSUInteger nofWeight = inputFeatureChannels*kernelHeight*kernelWidth*outputFeatureChannels;
    NSUInteger nofBias = outputFeatureChannels;
    float *weightP = calloc(nofWeight, sizeof(float));
    float *biasP = calloc(nofBias, sizeof(float));

    //外部ファイルから得る
    //(略)
    NSData *wData = [[NSData alloc] initWithContentsOfFile:filePath_w];
    NSData *bData = [[NSData alloc] initWithContentsOfFile:filePath_b];

    [wData getBytes:weightP length:nofWeight*sizeof(float)];
    [bData getBytes:biasP length:nofBias*sizeof(float)];

    MPSCNNConvolutionDescriptor *convDesc = [MPSCNNConvolutionDescriptor
                                             cnnConvolutionDescriptorWithKernelWidth:kernelWidth
                                             kernelHeight:kernelHeight
                                             inputFeatureChannels:inputFeatureChannels
                                             outputFeatureChannels:outputFeatureChannels ];
    convDesc.strideInPixelsX = 1;
    convDesc.strideInPixelsY = 1;
    convDesc.groups = 1;

    if (@available(macOS 10.13.4, *)) {
        MPSNNNeuronDescriptor *fusedNeuronDescriptor =[MPSNNNeuronDescriptor new];
        fusedNeuronDescriptor.neuronType = MPSCNNNeuronTypeReLU;
        fusedNeuronDescriptor.a = 0.0;
        //    convDesc.neuron = neuronFilter;//deprecated!
        convDesc.fusedNeuronDescriptor = fusedNeuronDescriptor;

    } else {
        // 古いのはダメ
    }

    NSInvocation *invocation;
    NSMethodSignature *signature;
    SEL argSelector =  @selector(initWithDevice:convolutionDescriptor:kernelWeights:biasTerms:flags:);
    
    MPSCNNConvolution *result = [MPSCNNConvolution alloc];
    
    signature = [self methodSignatureForSelector:argSelector];
    invocation = [NSInvocation invocationWithMethodSignature:signature];
    [invocation setTarget:result];
    [invocation setSelector:argSelector];

    NSUInteger n = 0;
    
    [invocation setArgument:&device atIndex:2];
    [invocation setArgument:&convDesc atIndex:3];
    [invocation setArgument:&weightP atIndex:4];
    [invocation setArgument:&biasP atIndex:5];
    [invocation setArgument:&n atIndex:6];
    [invocation invoke];
    [invocation getReturnValue:(void*)&result];

    self = (SlimMPSCNNConvolution *)result;
    
    self.destinationFeatureChannelOffset = 0;

    free(weightP);
    free(biasP);

    return self;
}
↑CNNの方。deprecatedを避けるためにいろいろと記述して長くなってる。もはや説明できないくらいの呪文である。

↓全結合層の場合はすでにこちらに書いてた。
KerasとMPSで同じ計算をする(2)


Storyboardで部品を選ぶ方法

Storyboardで画面にLabelやViewControllerなどの部品を追加しようとしたら、いつも画面右下にあるはずの表示がなくなってる?どこや、どこへ行ったんやーっ?

Xcode10画面右上部分

とりあえず画面右上にあるこのボタンをクリックすると、、、

Xcode10ライブラリの画面

こういうのが別画面で出てくるのでここで希望の部品を選んで置くことができた。Libraryって言うのか、あれ?
そんなとこに行ってたんかい。
Xcode10で変わったんかな。




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad