Open amirrajan opened 6 years ago
It’s not a bug. It’s how it should work given the implementation (as far as I understand) doesn’t resolve circular references (yet).
I renamed the code so it should be clearer what’s happening..
class Parent
def dealloc
puts "dealloc: #{self}"
super
end
def initialize
@two = Child.new do
# do callback stuff
end
end
end
class Child
def dealloc
puts "dealloc: #{self}"
super
end
def initialize(&callback)
@callback = callback
#@callback = callback.weak!
end
end
puts "here 1"
@one = Parent.new
puts "here 2"
@one = nil
puts "here 3"
The block retains self — unless
weak!
is invoked on it, like most of said. So Parent retains Child and Child retains Child. Typically, you want to avoid that. The easiest way in this case is to always callweak!
on the block and if the block has explicit references to another object that you don’t want to retain (and hence end up with a cyclic reference), you want to create it outside the block:weak_obj = WeakRef.new(obj)
too and then useweak_obj
instead ofobj
inside that block. But this means the WeakRef may not always be valid. And in those cases, you’d have to check that it is before you use it. In addition, if you pass the WeakRef somewhere else, you sometimes need to passweak_obj.self
instead ofweak_obj
if you ultimately want to store a strong reference to that original object.I think that’s about it for cyclic references/weak references in blocks. Remember them and it should be ok. Otherwise, it’s very very easy to mess this up.
When I do, I add
dealloc
implementations and click around to make sure things I want to be released get released as expected…Probably useful to use this if you like to keep block references (I keep a lot of them): https://github.com/hboon/purplish-accessors/blob/master/lib/purplish-accessors/class.rb#L33-L43 GitHub hboon/purplish-accessors purplish-accessors - Add variations of attr_accessor for RubyMotion for iOS & macOS
This:
def block_attr_accessor(*my_accessors)
my_accessors.each do |accessor|
define_method(accessor) do
instance_variable_get("@#{accessor}")
end
define_method("#{accessor}=") do |accessor_value|
instance_variable_set("@#{accessor}", accessor_value ? accessor_value.weak! : nil)
end
end
end
Ah. Made a typo. Should be: “So Parent retains Child and Child retains Parent too”.
@hboon gave you collaborator access.
From Slack: