きりかノート 3冊め

おあそびプログラミング

RubyCocoa 今日のコミット 2015-09-26

以前に見つかっていたバグがよくわからないけど直った。ひさしぶりにぜんぶテストが通るようになったぜ。。

  • NSArrayController#arragendObjects#eachするとruby-2.xだけNSGenericExceptionが起きるのを修正(beca6d4)

rubycocoa issue#2に書いたとおりなんだけど、

   require 'osx/cocoa'
   ctl = OSX::NSArrayController.alloc.init
   content = [1,2,3,4,5].map {|i| i.to_s}
   ctl.addObjects(content)

   p ctl.arrangedObjects
   # expects ["1", "2", "3", "4", "5"]
   # but ruby-2.0 fail with the following error:
   # /Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/oc_wrapper.r
   # b:55:in `ocm_send': NSGenericException - *** Collection <_NSControllerArrayP
   # roxy: 0x7f8e04a66b00> was mutated while being enumerated. (OSX::OCException)

と、ruby-2.x上でObjective-C側の例外が起きてしまう。もちろんふつうのNSArrayは問題ない。

NSArray#eachは

   iter = self.objectEnumerator
   while obj = iter.nextObject
     yield obj
   end

といった感じで実装されていてenumeraterまわしてるだけなので、コレクションのオブジェクトを変更をしているとは思えない。そもそもruby-1.8のときは問題ないしねえ。。

あれこれ調べてたんだけどけっきょく原因はわからなくて、「動かないよりはいいか」とコレクションかイテレータのクラスかなんかで判定してダメそうな場合は

   self.count do |i|
     yield self[i - 1]
   end

みたいにぐるぐるすればよいかと思って試していたら、iter.classNameを呼び出すと元々の実装でも動くようになったことに気付いた。なんだかわからんけど、Objective-CのメソッドをnextObejctの前に呼び出してやればよさそうなことがわかったのでとりあえずそれで対応した。