griffin-stewieの日記

2010-10-16

[]XcodeのUserScript

Cocoaの日々: Xcode のマクロ定義

こちらの記事をみて、昔 cocoa 勉強会でちょこっと紹介した内容に似たようなのがあったのを思い出しました。

久しぶりなのでブログに書いてみようかと思いました。

Objective-C 2.0プロパティ定義文を挿入する UserScript

さきの記事ではテキストマクロとしてプロパティ定義文を挿入して実際のプロパティ名は自分入力するような形をとっていました。

私はもっと怠け者なので文字入力なしで済ましたいと思ったので UserScript にしました。

UserScript とは

f:id:griffin-stewie:20101016144310p:image

これ。

ちょっとしたことができる仕組みです。

デフォルトで入っているのものでおそらくみんながお世話になっているだろう

コメントアウトショートカット Cmd+/ は実は Perl で書かれた UserScript が実行されています。

何ができる?

こんなのが実行できます。

入力としては以下のものを受けられます。

出力はこんな感じ。

メニューから " Edit User Scrippts ..." を選べば編集画面が表示されます。

ショートカットキーもここでわりあてられます。

UserScript でプロパティ定義文を挿入する

やりたいことは

以下の2パターン作ったことがありますが、今回はクリップボード拡張を導入していない人向け。

@property を挿入する UserScript
#!/usr/bin/env ruby

lines = `pbpaste`
lines.each { |line|
  if line.match(/([_A-Za-z][_A-Za-z0-9]*\s*)+([\s\*]+)([_A-Za-z][_A-Za-z0-9]*);/)
  
    klas = $1
    star = $2
    ivar = $3  
  
    if klas != nil
      if /\ANSString/ =~ klas
        print "@property (nonatomic, copy) #{klas.strip} #{star.strip}#{ivar};\n"
      elsif /\Aid/ =~ klas
        if /delegate/ =~ ivar
          print "@property (assign) #{klas.strip} #{star.strip}#{ivar};\n"          
        else
          print "@property (nonatomic, retain) #{klas.strip} #{star.strip}#{ivar};\n"
        end
      elsif /\*/ =~ star
        print "@property (nonatomic, retain) #{klas.strip} #{star.strip}#{ivar};\n"
      else
        print "@property (assign) #{klas.strip} #{star.strip}#{ivar};\n"
      end
    elsif star == nil
      
    end
  end
}

使い方は

インスタンス変数定義部分をまとめてコピーして挿入したい場所でこのスクリプトを実行。

すると

として挿入します。

@synthesize を挿入する UserScript
#!/usr/bin/env ruby
lines = `pbpaste`
lines.each { |line|
  if line.match(/([_A-Za-z][_A-Za-z0-9]*\s*)+([\s\*]+)([_A-Za-z][_A-Za-z0-9]*);/)
  
    klas = $1
    star = $2
    ivar = $3
    print "@synthesize #{ivar};\n"
  end
}

使い方は

インスタンス変数定義部分をまとめてコピーして挿入したい場所でこのスクリプトを実行。

release を挿入する UserScript
#!/usr/bin/env ruby

lines = `pbpaste`

def releaseAndNil(variable)
  print "[#{variable} release], #{variable} = nil;\n"
end

lines.each { |line|
  if line.match(/([_A-Za-z][_A-Za-z0-9]*\s*)+([\s\*]+)([_A-Za-z][_A-Za-z0-9]*);/)
  
    klas = $1
    star = $2
    ivar = $3  
  
    if klas != nil
      if /\ANSString/ =~ klas
        releaseAndNil(ivar)
      elsif /\Aid/ =~ klas
        if /delegate/ =~ ivar
          print "delegate = nil;"          
        else
          releaseAndNil(ivar)
        end
      elsif /\*/ =~ star
        releaseAndNil(ivar)
      end
    end    
  end
}

使い方は

インスタンス変数定義部分をまとめてコピーして挿入したい場所でこのスクリプトを実行。

すると

として挿入します。

保存方法

今回紹介したスクリプトは Output を ”Insert after Selection” として保存してください。

f:id:griffin-stewie:20101016153602p:image

使い方の流れとしてはこんな感じで使うとインスタンス変数のリリース漏れなどを起こしにくいと思います。

  1. インスタンス変数をずらっと定義
  2. 定義部分をコピー
  3. プロパティ定義を挿入したい箇所で「@property を挿入する UserScript」を実行
  4. 実行ファイルを開いて@synthesize を挿入したい箇所で「@synthesize を挿入する UserScript」を実行
  5. dealloc メソッド内で「release を挿入する UserScript」を実行

その他

今回のスクリプトは普段使っていて特に問題はありませんでしたが、結構適当なのでコーディングスタイルが違う人は使えない代物かもしれません。ご利用は自己責任でお願いします。

2010-01-20

[][] デバッグ中にXcodeエディタブレイクポイントに移動しない問題

Snow Leopardにしたころくらいからデバッグ中にXcodeエディタブレイクポイントに移動しないなぁと思っていました。

移動しないっていうのは、例えば

  1. Hogeクラスのfugaメソッドブレイクポイントをセット
  2. エディタではFooクラスbarメソッドあたりを表示
  3. この状態でBuild & Debug を開始

この状況の場合、今まではブレイクポイントに来たときには、エディタで表示される場所がHogeクラスのfugaメソッドに変わっていました。

しかし、たまに移動しないままブレイクポイントで止まっていたり、全然関係のない行にハイライトがついたりする問題が起こっていました。


毎回必ずこの状況になるのならまだしも正常に動くプロジェクトファイルもあったので困っていました。


昨晩、 @sonson_twit さんが同様の問題にハマっていたようで、ついに原因を突き止めてくれました。

原因は日本語を含むパスプロジェクトファイルがあったから


うそ〜? って思いながら自分の問題が発生しているプロジェクトファイルパスを見ると日本語が入っていました orz

問題なく動いていたプロジェクトファイルはすべてアルファベットのみのパスでした。


普段から日本語ファイル名とかディレクトリ名を極力使わないようにしていたのですが、まさかでした。

2009-11-03

[][] Group 分け

今さっき気づいたXcodeのGroup分けのことをちょっと書きます。

Twitterに書くには長いので、じゃあもう2ヶ月近くブログを書いてなかったし、ブログに書きます。


Xcodeでは左の縦長のペイン"Groups & Files"があります。

いつもはざっくりとファイルを突っ込んでるんですが、一定量のリソースの数になってくるとGroup分けしたくなります。


今まで

まず最初に任意の場所でコンテキストメニューを出して Add > New Group して、名前をつけてそのGroupにファイルをD&Dでぼこぼこ放り込んでいました。

さっき気づいた方法

分類したいファイル群を Cmd + クリック とかで複数選択していきます。

選択が終わったらコンテキストメニューを出して Group を選びます。

新規のGroupが作られるので名前を付けます。

完成したGroupの中をみるとさっき選択したファイル群が中に入っています。

おわり

別に特に便利というわけじゃないですけど、へぇ〜と思ったので書いてみました。


この方法は Detail View *1 でもできます。

"Groups & Files"ペインにごちゃごちゃに突っ込んでいたイメージを名前順でソートして整頓したいってときには、


  1. "Groups & Files"ペインで並び替えて見たいファイル群の親Groupを選択。
  2. 右上のペインでソート。

っていう使い方もできますね。


おまけ

エントリを書いていてさらに気づいたこと。

個人的に「別にGroup分けしたいわけじゃないけど、"Groups & Files" ペイン内の任意のGroupに入っているファイルを名前でソートしたい」ということがよくあります。

上で書いた方法で強引に実行できます。


  1. ソートしたいファイル群を"Groups & Files"ペインで選択
  2. Detail Viewでソートをかける
  3. Detail Viewでファイルを全選択し、コンテキストメニューからGroupを選択
  4. Group名は適当につける(すぐ消すのでデフォ値でOK)
  5. "Groups & Files"ペインにできたGroupをコンテキストメニューから UnGroupを選択
  6. ソート済みのファイル群がならぶ

どうでもいいことですが、個人的にはうれしい発見でした。

*1Xcodeの右上(エディタの上)のペイン

2009-08-02

[][]SIMBL Plugin 開発でデバッガを使う方法

もう2ヶ月くらい前になるかもしれませんが、Xcode関連で調べ物をしていたときに偶然見つけた方法をちょっと弄ったらうまい具合に SIMBL plugin 向けにも動いたよっという話です。

超ニッチな情報ですが、僕は超テンションが上がりましたのでご紹介。


Custom Executable を追加

メニューバーから ”Project” > ”New Custom Executable” をクリック


f:id:griffin-stewie:20090802190917p:image:w400


出てきたウインドウに適当な名前を付けて、プラグインの対象となるアプリを選択。


f:id:griffin-stewie:20090802191300p:image:w400


Run Script Build Phase を追加

メニューバーから ”Project” > ”New Build Phase” > ”New Run Script Build Phase” をクリック


f:id:griffin-stewie:20090802191447p:image:w400


出てきたウインドウに以下のスクリプトをコピペ。


f:id:griffin-stewie:20090802191559p:image:w400

# clean up any previous products/symbolic links in the SIMBL Plugins folder
if [ -a "${USER_LIBRARY_DIR}/Application Support/SIMBL/Plugins/${FULL_PRODUCT_NAME}" ]; then
  rm -Rf "${USER_LIBRARY_DIR}/Application Support/SIMBL/Plugins/${FULL_PRODUCT_NAME}"
fi

# Depending on the build configuration, either copy or link to the most recent product
if [ "${CONFIGURATION}" == "Debug" ]; then
  # if we're debugging, add a symbolic link to the plug-in
  ln -sf "${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}" \
    "${USER_LIBRARY_DIR}/Application Support/SIMBL/Plugins/${FULL_PRODUCT_NAME}"
elif [ "${CONFIGURATION}" == "Release" ]; then
  # if we're compiling for release, just copy the plugin to the SIMBL Plugins folder
  cp -Rfv "${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}" \
    "${USER_LIBRARY_DIR}/Application Support/SIMBL/Plugins/${FULL_PRODUCT_NAME}"
fi

Build設定を変更

僕の環境では弄る必要がありませんでしたが、

Target の コンテキストメニュー ”Get Info” > ”Build” タブ で 各項目を変更。

  • "Strip Debug Symbols During Copy" ・・・ Off 
  • "Generate Debug Symbols" ・・・ On
  • ”Optimization level” ・・・ None

f:id:griffin-stewie:20090802191649p:image:w400


おしまい

これでDebugビルド時にBreakePointが有効になって普通のCocoaアプリやiPhoneアプリみたいにデバッグができるようになると思います。実は今までこの方法を知らなかったので地道にNSLog & Console.app でやってました。


問題点として複数のプラグインを平行して作ったりしてると別プラグインのブレイクポイントで止まる事がありました。

あとデバッグを終わらせるとSafariも終了します。


でも、この方法でだいぶ開発が楽になりそうです。




Snow Leopard では SIMBL が使えなくなるそうですが、また誰かが同等な手段で穴を開けてくれると期待しています。


参考URL

Technical Q&A QA1500: Debugging a WebKit Plug-in in Xcode

http://developer.apple.com/qa/qa2006/qa1500.html#//apple_ref/doc/uid/DTS10004165

2009-06-28

[][] Xcode でのコーディング支援アプリ「accessorizer」

たまたま見つけた Xcode でのコーディング支援アプリを適当にご紹介。


accessorizer

http://www.kevincallahan.org/software/accessorizer.html


accessorizer はXcodeプロパティとか Keyed Archiving に対応させるとか copy に対応させるなど、「ほぼ定型で自力で書くのが面倒くさいようなコード」をパコっとコピペできるようにしてくれるコーディング支援アプリ*1っぽいです。


詳細は配布元のビデオとか見て下さい。

いろいろと結構細かい設定もできる見たいです。


使い方

使い方の流れ的には

  1. あらかじめ自分コーディングスタイルを設定しておく
  2. accessorizer を起動したままXcodeでコード書く。
  3. @interface 内のインスタンス変数を書く最初のブレースをダブルクリックしてインスタンス変数を選択。
  4. Cmd+1とか*2を押す。
  5. accessorizer が前面に出てくるからCmd+TAB でXcode に戻る。
  6. クリップボードにコードが入っているので任意の箇所にペースト

f:id:griffin-stewie:20090628164239j:image


使ってみた

なぜかわからないけど、設定したものが反映されない。レジストしてないから?

ショートカットキーを押した後にaccessorizerが前面に出てくるのがちょっと好きじゃないです。

これってUserScriptでできるよね

XcodeのUserScriptを使えば、選択文字列をShellScriptとかLL言語でごにょごにょできます。

Cocoaを書くようなMacな人ならLL言語が書ける人が多いような気がしますし、自分専用ならある程度決め打ちでもOKでしょう。

UserScriptと PTHPasteboardClipMenu などのクリップボードユーティリティを使えば、


  1. インスタンス変数をガガッと書く
  2. それらを選択して@property,@synthesize,release 用のコードをそれぞれ個別にクリップボードに格納するようなUserScriptを実行
  3. 任意の箇所へクリップボードユーティリティの履歴機能を使ってペタペタと貼っていく

って事ができますね。

まとめ

クリップボードを活用するアイディアをあたえてくれたaccessorizerに感謝。

お陰様で3分ほどコーディング時間が短縮できそうです。

*1:シェアウェア

*2:accessorizerの機能はServiceメニューに登録されている

プロフィール

griffin-stewie

griffin-stewie

遂にプログラマの端くれに。ここで述べられていることは私の個人的な意見に基づくものであり、私の雇用者には一切関係ありません。