-
-
Notifications
You must be signed in to change notification settings - Fork 684
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rubicon update #2978
base: main
Are you sure you want to change the base?
Rubicon update #2978
Conversation
cocoa/src/toga_cocoa/icons.py
Outdated
self.native = image.initWithContentsOfFile(str(path)) | ||
if self.native is None: | ||
raise ValueError(f"Unable to load icon from {path}") | ||
image.release() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an interesting one: Since a manual release
call no longer disables Rubicon's release-on-delete logic, we can now only call image.release()
manually when indeed a additional release is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree this is one case where manual reference management is still required. beeware/rubicon-objc#26 (comment) is a proposal for how Rubicon could handle this automatically.
As mentioned at beeware/rubicon-objc#543 (comment), once the new Rubicon version has been released, this PR should update the pyproject.toml files of toga-cocoa and toga-ios to use it. Apart from the similar code in |
That method is indeed a bit hacky and I am wondering whether it should be implemented by returning an actual copy instead. @freakboy3742, have you tried that and do you know if there would be significant performance impact to this? In the current state, callers will think they receive a new object which they own due to the method name. While it is true that they own the returned object, because of the manual |
Those were used to prevent rubicon from releasing an object immediately when going out of scope and delaying this instead until after ObjC can take ownership.
702f35e
to
147a1a2
Compare
I thought the same thing, but then I found that the
The NSCopying docs say that the caller of |
By the way, I think it's better not to do a force push altering commits which have already been reviewed, because it breaks the "show changes since your last review" feature in GitHub. Updates from the main branch can be brought in with a normal merge. |
I'll be completely honest - I've never 100% understood what is going on with this copy method. It's not a method that we ever call... and it's not doing anything with any data that we are adding... so I'm not entirely clear why we need to override anything. But, every time I've thought "Oh, we can just remove it", things start exploding. The explosions are probably an indication that I should spend some time to work out why and how it's working, I guess :-) |
Thanks for digging that up! A reference to that would indeed be great.
Yes, unless Rubicon is the one calling Since this copy behavior is allowed, the implementation from beeware/rubicon-objc#543 can still cause memory leaks in some corner cases which will be very hard to debug. Edit: Added a failing test to demonstrate this in beeware/rubicon-objc@30e4277. |
I think the sequence of events is:
I think this falls under the category of "if you call |
But it's not only our from rubicon.objc import *
from rubicon.objc.runtime import autoreleasepool
with autoreleasepool():
obj0 = NSString.stringWithString("some unique string")
obj1 = obj0.copy()
obj2 = obj0.copy()
assert obj0 is obj1
assert obj0 is obj2
assert obj0.retainCount() == 3 The caller should not need to figure out how |
OK, I see what you mean. Let's discuss this in beeware/rubicon-objc#543. |
Something else to check - does this fix the remaining memory issues in #2853? |
While this is in draft state, would it be worth modifying the pyproject.toml references to rubicon to the PR branch? That will obviously need to be replaced with >= 0.5.0 references before it's merged, but it would give us a good multi-platform confirmation of the PR's impact. |
Done. CI tests on a wider range of Python and platform versions than I can do locally. |
iOS/src/toga_iOS/widgets/slider.py
Outdated
@@ -81,7 +81,7 @@ def get_value(self): | |||
|
|||
def set_value(self, value): | |||
self.value = value | |||
self.native.setValue(value, animated=True) | |||
self.native.setValue_animated_(value, True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm definitely still a noob about Rubicon and ObjC... what's the functional difference between these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Theoretically none at all.
The Objective-C method is setValue:Animated:
, in Rubicon Objective-C this translates to calling setValue_animated_()
.
Rubicon has some additional "magic" to accept a more Pythonic syntax setValue(value, *, animated)
which relies loading and caching all method names of an object and its superclasses. It appears that the planned Rubicon update breaks this logic under some circumstances.
The last commit, i.e., this change, won't be permanent. It is only to confirm that the old syntax still works and narrow down the possible issues.
This reverts commit e4a29f1.
This PR demonstrates changes required for toga to work with beeware/rubicon-objc#543. It also removes a few no longer needed manual retain / release pairs.