2014年3月17日月曜日

Homebrew環境で最新のxcode5.1にするとはまります

Homebrewで何かやろうとして、

Warning: A newer Command Line Tools release is available
Update them from Software Update in the App Store.

なんて出てきますが、ここでAppStoreから最新のxcodeをインストールしちゃうと面倒になります。

clang: error: unknown argument: '-mno-fused-madd' [-Wunused-command-line-argument-hard-error-in-future]
clang: note: this will be a hard error (cannot be downgraded to a warning) in the future
error: Setup script exited with error: command 'cc' failed with exit status 1

こんなエラーが頻発するようになります。
回避策は下記のようにオプションを上書きするくらいしかありません。

sudo ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future easy_install pil

sudoとeasy_install以降は各自その時のオペレーションに当てはめて下さい。
大事なのはARCHFLAGS以降です。

2014年3月6日木曜日

UITableViewのCellいっぱいにUITextViewを貼付けた時のスクロール処理

これから数回にわたってiOSアプリで日本語サイトでは見つからなかったFAQ系をメモっていきます。

今回はUITableViewのCellいっぱいにUITextViewを貼付けた時のカーソル処理です。自動でセルの大きさを広げたり、カーソルの動きに合わせてスクロールしてくれます。UITableViewにUITextViewを入れて編集出来るようなアプリはそれなりに見受けられますがまだの方は参考にどうぞ。

構造は上記のようになっています。


- (void)textViewDidChange:(UITextView *)textView {
    if(textView == self.textInfomation) {
        UITableView* tableView = (UITableView*)[self.view viewWithTag:10];
        UITableViewCell* cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]];

        // 現在のセルの高さを取得
        CGRect cellRect = [tableView rectForRowAtIndexPath:[tableView indexPathForCell:cell]];
        
        // 現在のテキストの高さを計算し取得
        CGSize size = [textView.text getTextSizeWithFont:textView.font viewWidth:289.0f padding:0.0f];
        size.height = size.height + HEIGHT_SPACER;  // HEIGHT_SPACERは適当な値でマージンとして使用

        // セルの高さとテキストの高さを比較して違っていればセルサイズを変更し再描画
        if(size.height != cellRect.size.height){
            // セルの高さを記憶しておく(- tableView:heightForRowAtIndexPath:で使用する)
            [self.aryHeights replaceObjectAtIndex:2 withObject:[NSNumber numberWithFloat:size.height]];
            [tableView beginUpdates];
            [tableView endUpdates];
            [self updateInset];
        }
    }
}

- (void)textViewDidChangeSelection:(UITextView *)textView {
    if(textView.selectedRange.location != NSNotFound) {
        
        NSRange range;
        range.location = textView.selectedRange.location;
        range.length = [textView.text length] - range.location;
        
        // 現在のセルの高さを取得
        UITableView* tView = (UITableView*)[self.view viewWithTag:10];
        UITableViewCell* cell = [tView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]];
        CGRect cellRect = [tView rectForRowAtIndexPath:[tView indexPathForCell:cell]];
        
        // 1行分の高さを事前に計算しておく
        CGSize fontsz = [@"あ" getTextSizeWithFont:textView.font viewWidth:100.0f padding:0.0f];
        
        if(range.length != 0) {
            // カーソル位置までの文字を切り出す
            NSString *string = [textView.text stringByReplacingCharactersInRange:range withString:@""];
            
            // 切り出した文字列の高さを計算する
            CGSize size = [string getTextSizeWithFont:textView.font viewWidth:289.0f padding:0.0f];
            
            // 1行多めに上にスクロールの頂上をオフセットしておく
            size.height = size.height - fontsz.height;
            
            // スクロール位置を設定してスクロール開始
            // fontsz.height*2 はスクロールする底辺からの空間量でここでは2行分空けている(実際には1行と半分位)
            CGRect finalRect = CGRectMake(10.f, cellRect.origin.y + size.height, 300.f, fontsz.height*2);
            [tView scrollRectToVisible:finalRect animated:YES];
        }else if(range.location == [textView.text length]){
            // 最後の位置にカーソルがある場合
            // 全文文字列の高さを計算する
            CGSize size = [textView.text getTextSizeWithFont:textView.font viewWidth:289.0f padding:0.0f];
            
            // スクロール位置を設定してスクロール開始
            // fontsz.height*2 はスクロールする底辺からの空間量でここでは2行分空けている(実際には1行と半分位)
            CGRect finalRect = CGRectMake(10.f, cellRect.origin.y + size.height, 300.f, fontsz.height*2);
            [tView scrollRectToVisible:finalRect animated:YES];
        }
    }
}
ソース内にあるメソッドは下記のとおり。
- (CGSize)getTextSizeWithFont:(UIFont *)font viewWidth:(CGFloat)viewWidth padding:(CGFloat)padding {
    
    CGSize size;
    if ([self respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) {
        NSDictionary *attributeDic = @{NSFontAttributeName:font};
        size = [self boundingRectWithSize:CGSizeMake(viewWidth, CGFLOAT_MAX)
                                  options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine
                               attributes:attributeDic
                                  context:nil].size;
    }
    size.height += padding;
    return size;
}

2013年5月31日金曜日

keyboardFinder0.18リリース (8/5更新)



配布先 → http://ux.getuploader.com/keyboardFinder/

Version 0.18.2 (2013/8/5)



  • 一括ファイル名変更ツールを追加


Version 0.18.1.1 (2013/7/30)
Version 0.18.1 根本バグあったので削除
  • 諸々のバグ対応
  • zip/rarアーカイブ処理をunrar/unzipを使用するように変更
  • パッケージ内にunrar/7z/lha/ffmpegを同梱、追々対応予定
  • ファイルコピーに連番ファイルコピー機能追加
 使用者居ないみたいだしこれが最後の公開かもしれんw


Version 0.18.0
  • ブックビューワでのキーアサイン機能追加
  • ブック・イメージビューワでの画像の選択機能追加
  • ブック・イメージビューワで選択ファイルのコピー機能追加

Version 0.17.3
  • 仮想ディレクトリでレートとラベルのフィルタ対応
  • 仮想ディレクトリでの各要素の編集対応
  • 仮想ディレクトリでの未読・既読の色設定対応
  • 仮想ディレクトリでの外部ブックビュワーの対応
  • 仮想ディレクトリでのアーカイブファイル内のカバー編集機能を追加

Version 0.17.2
  • 設定ウィンドウを閉じた際に設定を反映させるように修正
  • 仮想フォルダでのラベルカラー設定を実装
  • 仮想フォルダでのレート設定を実装
  • 仮想フォルダでの既読フラグ・既読ページの未実装を実装
  • ディレクトリの自動更新でカーソルが一番上に移動するバグを修正
  • ルート(/)ディレクトリでさらに親ディレクトリに移動するバグを修正
  • 自動アップデートチェック機能の実装

Version 0.17.1
  • UnRarライブラリのARC対応ビルドが失敗していたのを修正
  • rarアーカイブファイルを選択しても無反応のバグを修正
  • 仮想ディレクトリでジャンルが空の場合選択出来なかったバグを修正




仮想ディレクトリモード
通常ファイラーモード
音楽ファイラーモード

2013年5月16日木曜日

ディレクトリの更新を通知してもらう簡単な方法


全てのディレクトリで更新があった時に呼ばれる方法。
特定のディレクトリじゃないので起動時に一回登録してやればいい。


void fsevents_callback(ConstFSEventStreamRef streamRef, void *userData, size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId eventIds[])
{
    int i;
    char **paths = eventPaths;
    DFAppDelegate *appDelegate = (DFAppDelegate*)[[NSApplication sharedApplication] delegate];

    for (i=0; i
        [appDelegate updateWindowPath:[NSString stringWithCString:paths[i] encoding:NSUTF8StringEncoding]];
    }
}

- (void)checkDirectory:(NSString*)path
{
FSEventStreamEventId lastEventId = kFSEventStreamEventIdSinceNow;
    NSArray* pathsToWatch = [NSArray arrayWithObjects:path, nil];
    void *selfPointer = (__bridge void*)self;
    FSEventStreamContext context = {0, selfPointer, NULL, NULL, NULL};
    FSEventStreamRef stream;
    NSTimeInterval latency = 3.0;
    stream = FSEventStreamCreate(NULL, &fsevents_callback, &context, (__bridge CFArrayRef)pathsToWatch, lastEventId, latency, kFSEventStreamCreateFlagNone);
    FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    FSEventStreamStart(stream);
}


2013年5月14日火曜日

NSAlertの連続呼び出しの注意点 と KeyboardFinder0.16.5リリース。


NSAlertを連続して表示するときは、

    [[alert window] orderOut:nil];

didEndSelectorで設定したメソッド内で呼んでやる必要がある。
そうじゃないと、2度呼びした時に挙動がおかしくなる。

- (void)bipassDelete
{
        NSAlert *alert = [[NSAlert alloc] init];
        [alert addButtonWithTitle:@"OK"];
        [alert addButtonWithTitle:@"Cancel"];
        [alert setMessageText:@"削除確認"];
        [alert setInformativeText:@"選択されたファイルを削除します。"];
        [alert setAlertStyle:NSInformationalAlertStyle];
        [alert beginSheetModalForWindow:[self window] modalDelegate:self didEndSelector:@selector(alertDeleteDidEnd:returnCode:contextInfo:) contextInfo:nil];
}

- (void)alertDeleteDidEnd:(NSAlert*)alert returnCode:(NSInteger)returnCode contextInfo:(void*)contextInfo
{
    DFAppDelegate *appDelegate = (DFAppDelegate*)[[NSApplication sharedApplication] delegate];
    [[alert window] orderOut:nil]; // シートを消す
    if(returnCode == NSAlertFirstButtonReturn) {  // OK

     :
     :

                NSAlert *alert = [[NSAlert alloc] init];
                [alert addButtonWithTitle:@"OK"];
                [alert setMessageText:@"E002"];
                [alert setInformativeText:@"親ディレクトリは削除出来ません。"];
                [alert setAlertStyle:NSWarningAlertStyle];
                [alert beginSheetModalForWindow:[self window] modalDelegate:self didEndSelector:@selector(someMethodDidEnd:returnCode:contextInfo:) contextInfo:nil];

        }
}

- (void)someMethodDidEnd:(NSAlert *)alert returnCode:(int)returnCode contextInfo:(void *)contextInfo
{
    if(returnCode == NSAlertFirstButtonReturn){
    }
    [[alert window] orderOut:nil]; // シートを消す
}


Version0.16.1をリリースしますた。
Version0.16.3をリリースしますた。
Version0.16.4をリリースしますた。
Version0.16.5をリリースしますた。


※相変ず通常ファイラーモード以外でコピーとか削除とか名前変更をしちゃいけません。

配布先変更 → http://ux.getuploader.com/keyboardFinder/

・設定ウィンドウ
 キーアサイン設定が出来るようになりますた。
→初期起動時設定が全く無いのでメニュー「keyboardFinder」→「環境設定」から開いてキーアサイン設定を行って下さい。今後は引き継がれるので今回きりだと思いま・・す・・。
→全般項目では未設定項目はフォントを大きく表示してあります。
→キーアサインでは競合設定項目はフォントを大きく表示してあります。

・仮想フォルダモード
→仮想フォルダモード時、試験的にzipファイルとrarファイルのドラッグ&ドロップに対応させた。投げ込まれたファイルを解析して仮想フォルダに登録します。(キーボードオペレーションが前提のアプリだけど、仮想フォルダを使用する特需にとりあえず対応?)
→仮想フォルダを作ったり消したりする方法。ユーザ名がHogeだったとして、/Users/Hoge/.keyboardFinder/.stacks/にフォルダを追加することで増やす事が出来ます。

・ファイラーモード
→ドラッグ対応。ファイルを選択している時に有効。仕事で使うんで実装・w・
→ドロップにも対応。(Optionキー押しながらでコピー、デフォルトで移動)
→keyboardFinder間のD&Dにも対応させました。
→外部更新があったときにイベントを受信して一覧更新する様にしました。

残りの設定関係も追加していって、
その後未実装の機能を実装していこうかと思っています。

仮想ディレクトリモード
通常ファイラーモード
音楽ファイラーモード

2013年5月11日土曜日

AppleScriptでShellを起動 と keyboardFinder開発メモ


既にTerminalが起動されていればウィンドウを新規に、起動されてなければ新規にはウィンドウを開かないでパスを移動されるやりかたメモ。


        NSString* cmd1 = [NSString stringWithFormat:@"do script \"cd '%@'\"",w.path];
        NSString* cmd2 = [NSString stringWithFormat:@"do script \"cd '%@'\" in front window",w.path];

        NSTask* task2 = [[NSTask alloc] init];
        [task2 setLaunchPath:@"/usr/bin/osascript"];
        [task2 setArguments:[NSArray arrayWithObjects:
                             @"-e", @"if application \"Terminal\" is running then",
                             @"-e", @"tell application \"Terminal\"",
                             @"-e", @"activate",
                             @"-e", cmd1,
                             @"-e", @"end tell",
                             @"-e", @"else",
                             @"-e", @"tell application \"Terminal\"",
                             @"-e", @"activate",
                             @"-e", cmd2,
                             @"-e", @"end tell",
                             @"-e", @"end if",
                             nil]];
        [task2 launch];


こんばんわ。

仕事現場で使い始めたので細々と利便性を上げている今日この頃。
近況としては各種設定ダイアログをしこしこ整備中。


※相変ず通常ファイラーモード以外でコピーとか削除とか名前変更をしちゃいけません。

配布先変更 → http://ux.getuploader.com/keyboardFinder/

・通常ファイラーモード(command+1)
→削除はゴミ箱に入れるように修正(そのうちUndo実装したい)(0.14)
→"-"キーでFinderウィンドウを表示(0.14.2)
→"-"+"SHIFT"キーでPathをクリップボードにコピー(0.14.2)
→"x"キーで起動するアプリを選択して起動(0.14.2)
→"-"+"Command"キーでそのPathでTerminalを起動する(0.16.0)

・画像ビュアー
→画像表示中に画像を他アプリ・Finderへドラッグ&ドロップ可能に(0.16.0)

・テキストビュアー
→"e"キーで"mi.app"がインストールされていればテキスト編集起動(0.14.2)

・mp3タグ表示モード(command+2)
→タグ表示だけ出来た(文字化け対応中)(0.14)
→タグ編集・コピー・削除・移動(未実装)

・動画タグ表示モード(command+3)
・exifタグ表示モード(command+4)
→未実装

・仮想ディレクトリ全種類スタンプ型タグ表示モード(command+5)
→フォルダ構成が変わってもMD5でファイルを再検索してくれる機能(実装中)
→登録してカバーを表示するところまでしか出来ていない(0.14)
→ファイルがzip圧縮画像集ならブックビュアー起動(0.15)
→ブックビュアー表示で読み掛け保存機能(0.15)

・その他
→各ソートにランダムソート機能追加(実装中)


仮想ディレクトリモード
通常ファイラーモード
音楽ファイラーモード

2013年4月24日水曜日

keyboardFinder 開発メモ(2013/5/4更新)


モードを増やして多種対応中・・。

mp3タグ表示モードだけ出来たのでとりあえず現状バイナリ公開(ver 0.14)
コミックビューワ的な機能を追加(ver 0.15)

通常ファイラーモード以外でコピーとか削除とか名前変更をしちゃいけません。

配布先変更 → http://ux.getuploader.com/keyboardFinder/

・通常ファイラーモード(command+1)
→削除はゴミ箱に入れるように修正(そのうちUndo実装したい)(0.14)
→"-"キーでFinderウィンドウを表示(0.14.2)
→"-"+"SHIFT"キーでPathをクリップボードにコピー(0.14.2)
→"x"キーで起動するアプリを選択して起動(0.14.2)

・テキストビュアー
→"e"キーで"mi.app"がインストールされていればテキスト編集起動(0.14.2)

・mp3タグ表示モード(command+2)
→タグ表示だけ出来た(文字化け対応中)(0.14)
→タグ編集・コピー・削除・移動(未実装)

・動画タグ表示モード(command+3)
・exifタグ表示モード(command+4)
→未実装

・仮想ディレクトリ全種類スタンプ型タグ表示モード(command+5)
→フォルダ構成が変わってもMD5でファイルを再検索してくれる機能(実装中)
→登録してカバーを表示するところまでしか出来ていない(0.14)
→ファイルがzip圧縮画像集ならブックビュアー起動(0.15)
→ブックビュアー表示で読み掛け保存機能(0.15)

・その他
→各ソートにランダムソート機能追加(実装中)

もうちょいで公開出来そう・・。
Stackroomのデザインパクリ過ぎてるので手直しもせんとw
ここまで出来たら試しにApp Storeに出してみよう。

全然やることだらけで終わらないぽ。
デバッグ出力多いので以前よりも速度が落ちてます。

使ってる人なんかいないと思うけどね!
どこを優先的に作っていくか迷ってる・・。

仮想ディレクトリモード
通常ファイラーモード
音楽ファイラーモード