Behaviour when local variables pointing to non-auto-retained objects go out of scope?
I just purchased the book Programming Cocoa with Ruby, and am working through the examples using Macruby. This tiny app works fine in rubycocoa, but in macruby the created statusbar item immediately disappears. {{{ #!/usr/bin/env macruby framework 'cocoa' class App def applicationDidFinishLaunching(aNotification) statusbar = NSStatusBar.systemStatusBar status_item = statusbar.statusItemWithLength(NSVariableStatusItemLength) image = NSImage.alloc.initWithContentsOfFile("stretch.tiff") raise "Icon file 'stretch.tiff' is missing." unless image status_item.setImage(image) end end NSApplication.sharedApplication NSApp.delegate = App.new NSApp.run }}} I assumed this had to do with garbage collection because in obj C status_item would have to be retained, and so I changed "status_item" to "@status_item" and then it works fine. However while playing around with it I also noticed that if I leave status_item as a local var and add a "sleep 1" at the end of applicationDidFinishLaunching, it also works fine and the status item never disappears. So now I'm not sure whether there is a bug or not. In general, what is the intended behaviour of Macruby with local variables referring to objects that would have to be retained in obj C when said variables go out of scope? Cheerio, Michael Johnston lastobelus@mac.com
Note that I'm aware {{{ image = NSImage.alloc.initWithContentsOfFile("stretch.tiff") }}} should be {{{ image = NSImage.new.initWithContentsOfFile("stretch.tiff") }}}, I just forgot to change back one of my experiments. It doesn't affect anything in this example though. Cheerio, Michael Johnston lastobelus@mac.com On 5-Jan-10, at 1:30 AM, Michael Johnston wrote:
I just purchased the book Programming Cocoa with Ruby, and am working through the examples using Macruby.
This tiny app works fine in rubycocoa, but in macruby the created statusbar item immediately disappears.
{{{ #!/usr/bin/env macruby framework 'cocoa'
class App def applicationDidFinishLaunching(aNotification) statusbar = NSStatusBar.systemStatusBar status_item = statusbar.statusItemWithLength(NSVariableStatusItemLength)
image = NSImage.alloc.initWithContentsOfFile("stretch.tiff") raise "Icon file 'stretch.tiff' is missing." unless image
status_item.setImage(image) end end
NSApplication.sharedApplication NSApp.delegate = App.new NSApp.run
}}}
I assumed this had to do with garbage collection because in obj C status_item would have to be retained, and so I changed "status_item" to "@status_item" and then it works fine.
However while playing around with it I also noticed that if I leave status_item as a local var and add a "sleep 1" at the end of applicationDidFinishLaunching, it also works fine and the status item never disappears.
So now I'm not sure whether there is a bug or not. In general, what is the intended behaviour of Macruby with local variables referring to objects that would have to be retained in obj C when said variables go out of scope? Cheerio,
Michael Johnston lastobelus@mac.com
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
FYI, the alloc.init pattern is correct in MacRuby too. As in pure Objective-C, calling +new in MacRuby is a shortcut for +alloc and -init. Doing +new then -initWithContentsOfFile will result in initializing the object twice, probably not what you want. Laurent On Jan 5, 2010, at 1:52 AM, Michael Johnston wrote:
Note that I'm aware {{{ image = NSImage.alloc.initWithContentsOfFile ("stretch.tiff") }}} should be {{{ image = NSImage.new.initWithContentsOfFile("stretch.tiff") }}}, I just forgot to change back one of my experiments. It doesn't affect anything in this example though.
Cheerio,
Michael Johnston lastobelus@mac.com
On 5-Jan-10, at 1:30 AM, Michael Johnston wrote:
I just purchased the book Programming Cocoa with Ruby, and am working through the examples using Macruby.
This tiny app works fine in rubycocoa, but in macruby the created statusbar item immediately disappears.
{{{ #!/usr/bin/env macruby framework 'cocoa'
class App def applicationDidFinishLaunching(aNotification) statusbar = NSStatusBar.systemStatusBar status_item = statusbar.statusItemWithLength (NSVariableStatusItemLength)
image = NSImage.alloc.initWithContentsOfFile("stretch.tiff") raise "Icon file 'stretch.tiff' is missing." unless image
status_item.setImage(image) end end
NSApplication.sharedApplication NSApp.delegate = App.new NSApp.run
}}}
I assumed this had to do with garbage collection because in obj C status_item would have to be retained, and so I changed "status_item" to "@status_item" and then it works fine.
However while playing around with it I also noticed that if I leave status_item as a local var and add a "sleep 1" at the end of applicationDidFinishLaunching, it also works fine and the status item never disappears.
So now I'm not sure whether there is a bug or not. In general, what is the intended behaviour of Macruby with local variables referring to objects that would have to be retained in obj C when said variables go out of scope? Cheerio,
Michael Johnston lastobelus@mac.com
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
Hi Michael, I did not give your snippet a try, but looking quickly at the documentation for -[NSStatusBar statusItemWithLength:] I saw: "The receiver does not retain a reference to the status item, so you need to retain it. Otherwise, the object is removed from the status bar when it is deallocated." It's probably what's causing the problem here. Your status item reference is not retained in the program, so it's promoted for garbage collection. Try keeping a reference to it (for example using an instance variable instead of a local variable) :) HTH, Laurent On Jan 5, 2010, at 1:30 AM, Michael Johnston wrote:
I just purchased the book Programming Cocoa with Ruby, and am working through the examples using Macruby.
This tiny app works fine in rubycocoa, but in macruby the created statusbar item immediately disappears.
{{{ #!/usr/bin/env macruby framework 'cocoa'
class App def applicationDidFinishLaunching(aNotification) statusbar = NSStatusBar.systemStatusBar status_item = statusbar.statusItemWithLength (NSVariableStatusItemLength)
image = NSImage.alloc.initWithContentsOfFile("stretch.tiff") raise "Icon file 'stretch.tiff' is missing." unless image
status_item.setImage(image) end end
NSApplication.sharedApplication NSApp.delegate = App.new NSApp.run
}}}
I assumed this had to do with garbage collection because in obj C status_item would have to be retained, and so I changed "status_item" to "@status_item" and then it works fine.
However while playing around with it I also noticed that if I leave status_item as a local var and add a "sleep 1" at the end of applicationDidFinishLaunching, it also works fine and the status item never disappears.
So now I'm not sure whether there is a bug or not. In general, what is the intended behaviour of Macruby with local variables referring to objects that would have to be retained in obj C when said variables go out of scope? Cheerio,
Michael Johnston lastobelus@mac.com
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
I figured that was the case, and that is why I switched to using an instance variable which will stick around after applicationDidFinishLaunching finishes, but I'm still puzzled by why the local variable does not get if I add a "sleep 1". IE, in my original snippet, leaving status_item as a local, which should go out of scope when applicationDidFinishLaunching finishes, if I put a "sleep 1" at the end of applicationDidFinishLaunching, the status item never disappears (or at least it hasn't after much more than 1 second) Cheerio, Michael Johnston lastobelus@mac.com On 6-Jan-10, at 9:24 PM, Laurent Sansonetti wrote:
Hi Michael,
I did not give your snippet a try, but looking quickly at the documentation for -[NSStatusBar statusItemWithLength:] I saw:
"The receiver does not retain a reference to the status item, so you need to retain it. Otherwise, the object is removed from the status bar when it is deallocated."
It's probably what's causing the problem here. Your status item reference is not retained in the program, so it's promoted for garbage collection. Try keeping a reference to it (for example using an instance variable instead of a local variable) :)
HTH, Laurent
On Jan 5, 2010, at 1:30 AM, Michael Johnston wrote:
I just purchased the book Programming Cocoa with Ruby, and am working through the examples using Macruby.
This tiny app works fine in rubycocoa, but in macruby the created statusbar item immediately disappears.
{{{ #!/usr/bin/env macruby framework 'cocoa'
class App def applicationDidFinishLaunching(aNotification) statusbar = NSStatusBar.systemStatusBar status_item = statusbar.statusItemWithLength(NSVariableStatusItemLength)
image = NSImage.alloc.initWithContentsOfFile("stretch.tiff") raise "Icon file 'stretch.tiff' is missing." unless image
status_item.setImage(image) end end
NSApplication.sharedApplication NSApp.delegate = App.new NSApp.run
}}}
I assumed this had to do with garbage collection because in obj C status_item would have to be retained, and so I changed "status_item" to "@status_item" and then it works fine.
However while playing around with it I also noticed that if I leave status_item as a local var and add a "sleep 1" at the end of applicationDidFinishLaunching, it also works fine and the status item never disappears.
So now I'm not sure whether there is a bug or not. In general, what is the intended behaviour of Macruby with local variables referring to objects that would have to be retained in obj C when said variables go out of scope? Cheerio,
Michael Johnston lastobelus@mac.com
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
I believe the reason is because your sleep 1 prevented a non- deterministic garbage collection cycle. In the presence of a Cocoa run loop the GC might be triggered by a few different ways. I believe you're just lucky that it works :) Laurent On Jan 6, 2010, at 10:03 PM, Michael Johnston wrote:
I figured that was the case, and that is why I switched to using an instance variable which will stick around after applicationDidFinishLaunching finishes, but I'm still puzzled by why the local variable does not get if I add a "sleep 1". IE, in my original snippet, leaving status_item as a local, which should go out of scope when applicationDidFinishLaunching finishes, if I put a "sleep 1" at the end of applicationDidFinishLaunching, the status item never disappears (or at least it hasn't after much more than 1 second)
Cheerio,
Michael Johnston lastobelus@mac.com
On 6-Jan-10, at 9:24 PM, Laurent Sansonetti wrote:
Hi Michael,
I did not give your snippet a try, but looking quickly at the documentation for -[NSStatusBar statusItemWithLength:] I saw:
"The receiver does not retain a reference to the status item, so you need to retain it. Otherwise, the object is removed from the status bar when it is deallocated."
It's probably what's causing the problem here. Your status item reference is not retained in the program, so it's promoted for garbage collection. Try keeping a reference to it (for example using an instance variable instead of a local variable) :)
HTH, Laurent
On Jan 5, 2010, at 1:30 AM, Michael Johnston wrote:
I just purchased the book Programming Cocoa with Ruby, and am working through the examples using Macruby.
This tiny app works fine in rubycocoa, but in macruby the created statusbar item immediately disappears.
{{{ #!/usr/bin/env macruby framework 'cocoa'
class App def applicationDidFinishLaunching(aNotification) statusbar = NSStatusBar.systemStatusBar status_item = statusbar.statusItemWithLength (NSVariableStatusItemLength)
image = NSImage.alloc.initWithContentsOfFile("stretch.tiff") raise "Icon file 'stretch.tiff' is missing." unless image
status_item.setImage(image) end end
NSApplication.sharedApplication NSApp.delegate = App.new NSApp.run
}}}
I assumed this had to do with garbage collection because in obj C status_item would have to be retained, and so I changed "status_item" to "@status_item" and then it works fine.
However while playing around with it I also noticed that if I leave status_item as a local var and add a "sleep 1" at the end of applicationDidFinishLaunching, it also works fine and the status item never disappears.
So now I'm not sure whether there is a bug or not. In general, what is the intended behaviour of Macruby with local variables referring to objects that would have to be retained in obj C when said variables go out of scope? Cheerio,
Michael Johnston lastobelus@mac.com
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
_______________________________________________ MacRuby-devel mailing list MacRuby-devel@lists.macosforge.org http://lists.macosforge.org/mailman/listinfo.cgi/macruby-devel
participants (2)
-
Laurent Sansonetti
-
Michael Johnston