[MacRuby-devel] [MacRuby] #484: scoping issues with notification center

MacRuby ruby-noreply at macosforge.org
Fri Dec 4 23:24:50 PST 2009


#484: scoping issues with notification center
-------------------------------------+--------------------------------------
 Reporter:  mattaimonetti@…          |        Owner:  lsansonetti@…        
     Type:  defect                   |       Status:  closed               
 Priority:  blocker                  |    Milestone:                       
Component:  MacRuby                  |   Resolution:  invalid              
 Keywords:                           |  
-------------------------------------+--------------------------------------
Changes (by lsansonetti@…):

  * status:  new => closed
  * resolution:  => invalid
  * milestone:  MacRuby 0.5 =>


Old description:

> Here is a reduction of a bug I encountered today:
>
> {{{
> framework 'Cocoa'
>
> class Foo
>
>   def dataReady(notification)
>     puts "called ok"
>     NSApplication.sharedApplication.terminate(nil)
>   end
> end
>
> nc = NSNotificationCenter.defaultCenter
>
> # foo = nil
>
> Proc.new do
>
>   foo = Foo.new
>   task = NSTask.alloc.init
>   pi = NSPipe.alloc.init
>   po = NSPipe.alloc.init
>
>   task.arguments = []
>   task.currentDirectoryPath = "/bin/"
>   task.launchPath     = "/bin/ls"
>   task.standardInput  = pi
>   task.standardOutput = po
>   task.launch
>
>   file_handle = po.fileHandleForReading
>   file_handle.readInBackgroundAndNotify
>
>   nc.addObserver(foo, selector: "dataReady:", name:
> NSFileHandleReadCompletionNotification, object: file_handle)
>
> end.call
>
> app = NSApplication.sharedApplication
> app.delegate = self
> app.run
> }}}
>
> If you run the code as is, the observer never gets called, however if you
> uncomment the line defining foo before the block everything works fine.
>
> It looks like foo isn't available when the notification center tries to
> call it to send it the notification.

New description:

 Here is a reduction of a bug I encountered today:

 {{{
 framework 'Cocoa'

 class Foo

   def dataReady(notification)
     puts "called ok"
     NSApplication.sharedApplication.terminate(nil)
   end
 end

 nc = NSNotificationCenter.defaultCenter

 # foo = nil

 Proc.new do

   foo = Foo.new
   task = NSTask.alloc.init
   pi = NSPipe.alloc.init
   po = NSPipe.alloc.init

   task.arguments = []
   task.currentDirectoryPath = "/bin/"
   task.launchPath     = "/bin/ls"
   task.standardInput  = pi
   task.standardOutput = po
   task.launch

   file_handle = po.fileHandleForReading
   file_handle.readInBackgroundAndNotify

   nc.addObserver(foo, selector: "dataReady:", name:
 NSFileHandleReadCompletionNotification, object: file_handle)

 end.call

 app = NSApplication.sharedApplication
 app.delegate = self
 app.run
 }}}

 If you run the code as is, the observer never gets called, however if you
 uncomment the line defining foo before the block everything works fine.

 It looks like foo isn't available when the notification center tries to
 call it to send it the notification.

--

Comment:

 NSNotificationCenter doesn't retain the observer. In your example, foo is
 garbage collected before the notification. You must keep a live reference
 to foo.

 This is a common Cocoa pattern. Observers, delegates & friends are always
 weakly referenced.

-- 
Ticket URL: <http://www.macruby.org/trac/ticket/484#comment:1>
MacRuby <http://macruby.org/>



More information about the MacRuby-devel mailing list