Objective-Cで、Method構造体からCレベルの関数ポインタを取得する方法のメモです。

以前は、

   1  Method *method = class_getInstanceMethod(class, selector);
   2  IMP imp = method->method_imp;

という感じで取得出来ていたみたいですが、現在はDeprecatedとなっており、 以下のようにする必要があるようです。

   1  IMP imp = method_getImplementation(method);

posted by Png genki on Thu 9 Oct 2008 at 02:31

Objective-Cで、クラスやプロトコルを前方宣言(前方参照とも呼ばれたりします)をする方法のメモです。

クラスの前方宣言

クラスを前方宣言する場合は、@classに続いてクラス名、セミコロンを書きます。

   1  @class Foo;

プロトコルの前方宣言

クラスのときと同様、プロトコル名のあとにセミコロンでOk。

   1  @protocol Foo;

posted by Png genki on Wed 8 Oct 2008 at 16:56

Objective-Cでオブジェクトを初期化する処理は、-init メソッドなどの初期化メソッドで実装されます。 よく見かけるのはこんな例ですね。

   1  - (id)init
   2  {
   3      [super init];
   4      /* initialization code */
   5      return self;
   6  }

しかしながら、基底クラスの初期化処理[super init]の最中に、 メモリアロケーションの失敗などによって正常に初期化が行われなかった場合に備えて、次のようなエラーハンドリングを行った方が良いでしょう。

   1  - (id)init
   2  {
   3      if(self = [super init]){
   4          /* initialization code */
   5      }
   6      return self;
   7  }

この辺の処理はXcodeなどが生成するひな形にも書かれていますね。

さて、ここからが本題ですが、上述の /* initialization code */ の中で初期化が失敗したときは、どうしたら良いでしょうか。 仕様的には、初期化に失敗したら nil を返す必要がありますが、 その際、途中までの段階で確保したリソースを解放する必要があるでしょう。 つまり、[super init]の中で確保されたであろうリソースを解放する必要があります。

   1  - (id)init
   2  {
   3      if(self = [super init]){
   4          /* initialization code */
   5          if(/* initialization failure */){
   6              /* release all resources */
   7              [super dealloc];
   8              return nil;
   9          }
  10      }
  11      return self;
  12  }

ということで、こんな感じに[super dealloc] を呼び出して nil を返します。 ここで、[super release] を呼び出すと、 参照カウンタが0になり、 [self dealloc] が呼び出されてしまうので注意が必要です。 [self dealloc]を呼び出すようにする場合は、上述の /* release all resources */ の中でリソースを解放せずに、[self dealloc] の中で解放するようにする必要があります。 しかし、失敗した初期化処理の中で中途半端に確保したリソースを、 正しく解放する為には、[self init] の内部で解放処理まで行った方が楽な気がします。 あるいは、以下の様に初期化済みのものだけ解放するようなコードを [self dealloc]に書いておくという手もあるかもしれません。

   1  #define RELEASE(x) if(x) [(x) release]
   2  
   3  - (void)dealloc
   4  {
   5      RELEASE(_something);
   6      [super dealloc];
   7  }

こんなコードを見ると、なんだかノスタルジーを感じます。

ちなみに関係ないですが、このブログシステムでは、 Objective-Cのソースコードを以下のような記法でSyntax highlightさせる事ができます。

   1  objective-c>>
   2  /* Objective-C code */
   3  <<objective-c

posted by Png genki on Mon 6 Oct 2008 at 22:09 with 4 comments

久々にRailsプラグインの紹介です。

Plugins - NamedScope

This is not simple hack of named scope like you might find in WillPaginate. This is a fully backported and tested version of NamedScope that will work on rails 1.2.6 or 2.0.4.

Rails-2.0.4およびRails-1.2.6でNamedScopeが使えるようになるようです。

posted by Png genki on Sun 5 Oct 2008 at 07:29
3rd Fri

My .gitconfig

~/.gitconfigをさらしてみます。[user]は省略。

   1  [color]
   2    status = auto
   3    diff = auto
   4  [alias]
   5    co = checkout
   6    ci = commit -a
   7    st = status
   8    up = pull --rebase

こんな感じ。SVNぽい感じで使えるようにサブコマンドのaliasを設定してます。 色づけはautoで。

posted by Png genki on Fri 3 Oct 2008 at 16:20

いろいろ調べた事をブログに書けなくて、 フラストレーションがたまっていたのですが、 ついにソースコードの開示や解説などが解禁されたようですね。

NDA契約更新が完了次第、iPhoneアプリ開発についても ブログに書いていこうと思います。 今まで通りRailsアプリ開発の話も書いていきます。

See Also

posted by Png genki on Fri 3 Oct 2008 at 03:40

gem update --systemではうまく行かない場合があるようなので、 その場合には以下のようにすればOkです。

   1  # gem install rubygems-update
   2  # update_rubygems

posted by Png genki on Mon 29 Sep 2008 at 19:42

Macのtopコマンドはdebianのものと違って、 Shift+Mではメモリの使用量によるソートができませんでした。 Macの場合は、

   1  % top -orsize

のように、オプションを指定して起動するか、 topが起動している状態で、oキーを押してから、 rsizeと入力すると良いようです。

RSIZEというカラムが使用しているメモリの量を表しています。

posted by Png genki on Mon 29 Sep 2008 at 19:38

config/environment.rbの中で、config.gemによってversion指定したgemを、 rake gems:unpackしようとすると、以下のようなエラーが出るようです。

   1  % rake gems:unpack GEM=genki-pagination_scope 
   2  (in /Users/takiuchi/project/formula)
   3  ERROR:  While executing gem ... (ArgumentError)
   4      Illformed requirement ["\">= 0.0.4\""]

RailsのLightHouseでも報告されていました。

rake gems:unpack version handling broken

ということで、この問題を回避するために、上記Ticketに添付されていた Patchを参考に、以下のようなMonkeyPatchを作ってみました。

config/initializers/fix_gem_unpack_for_2_1_1.rb

   1  module Rails
   2    class GemDependency
   3      def unpack_to(directory)
   4        FileUtils.mkdir_p directory
   5        Dir.chdir directory do
   6          Gem::GemRunner.new.run(
   7            unpack_command.map {|i| i.gsub(/\A["']|["']\z/, '')})
   8        end
   9  
  10        spec_filename = File.join(gem_dir(directory), '.specification')
  11        File.open(spec_filename, 'w') do |file|
  12          file.puts specification.to_yaml
  13        end
  14      end
  15    end
  16  end

これをconfig/initializers/の下に置いておけば、とりあえず正常にunpackする事ができます。

posted by Png genki on Wed 24 Sep 2008 at 02:10

現時点では(version 0.3.1)、macirbを使うときは、LANG=C で利用する必要があるようなので、以下のようにzshrcでaliasを登録してみました。

~/.zshrc

   1  alias macirb='LANG=C macirb'

これで特に問題なくmacirbを使う事ができます。

ちなみに、require "nkf"をしているRubyスクリプトを macrubyで実行する場合も、同様にLANGをCにする必要があるようです。

See Also

posted by Png genki on Mon 22 Sep 2008 at 16:40