Skip to content

[feat]: merge ViewEnvironmentPropagatingObject into ViewEnvironmentPropagating #218

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

Merged

Conversation

n8chur
Copy link
Collaborator

@n8chur n8chur commented May 23, 2023

Note:
This PR is targeting the feature/viewenvironmentui branch.
Reviewing this PR by commit may be ideal.

Overview

This PR is part of the larger effort to add support for automatic ViewEnvironment bridging between UIKit propagation and WorkflowUI propagation within WorkflowUI.

See the associated proposal for more information.

Merge ViewEnvironmentPropagatingObject into ViewEnvironmentPropagating

In practice, all graphs attempting to adopt these protocols will be objects—value type systems (like WorkflowUI's propagation of ViewEnvironment through renderings) will not need to maintain nodes.

My adding the restriction to AnyObject on the root protocol, we can perform pointer comparisons of nodes (see below for why that's useful).

This consolidation of protocols likely also makes the system easier to understand.

Only invalidate descendants with a matching ancestor

Updates the descendant invalidation check such that a node will only invalidate descendants if the descendant node's ancestor is set to that node. This prevents invalidating nodes that have their propagation paths overridden (e.g. ViewControllerDescription's custom ancestor node). This should improve performance by reducing unnecessary invalidations.

Square Integration PRs

https://github.com/squareup/market/pull/6286
https://github.com/squareup/ios-register/pull/86301

Checklist

  • Unit Tests
  • UI Tests
  • Snapshot Tests (iOS only)
  • I have made corresponding changes to the documentation

@n8chur n8chur changed the title [feat]: merge ViewEnvironmentPropagatingObject into ViewEnvironmentPropagating [WIP DNR] [feat]: merge ViewEnvironmentPropagatingObject into ViewEnvironmentPropagating May 23, 2023
Base automatically changed from westin/viewenvironmentui-auto-bridge to feature/viewenvironmentui May 31, 2023 15:38
@n8chur n8chur force-pushed the westin/viewenvironment-object-nodes-only branch 2 times, most recently from 965f764 to 4202cc9 Compare May 31, 2023 16:00
// Avoid updating the descendant if this is the case.
guard descendant.environmentAncestor != nil else {
continue
if descendant.environmentAncestor === self {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outside of the more mechanical refactor to merge ViewEnvironmentPropagatingObject into ViewEnvironmentPropagating, this is the most substantial change in the PR.

This change ensures cases like ViewControllerDescription environmentAncestor overrides will prevent invalidations from other nodes who have this node set as a descendant.

@n8chur n8chur changed the title [WIP DNR] [feat]: merge ViewEnvironmentPropagatingObject into ViewEnvironmentPropagating [feat]: merge ViewEnvironmentPropagatingObject into ViewEnvironmentPropagating Jun 1, 2023
@n8chur n8chur marked this pull request as ready for review June 1, 2023 16:34
@n8chur n8chur requested review from a team as code owners June 1, 2023 16:34
assert(
newValue == nil
|| environmentAncestorOverride == nil,
"Attempting to set environment ancestor override when one is already set."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it's a bit odd to require clearing a setter before you set it again. Thoughts?

Copy link
Collaborator Author

@n8chur n8chur Jun 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, it's definitely a bit weird, but we had it in place to ensure folks aren't overriding an existing override without acknowledging that they may be overriding an existing override—this assertion has caught unexpected scenarios like this in the past.

Now that the framework has evolved a bit more, and I think we're more confident in the right shape for how to utilize these types, I don't feel as strongly that it's still necessary. I'm fine with removing it now if other folks agree!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1. Is it intended that we allow this to be nil'd out?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm in favor of leaving it. If the propagation path gets messed up it can cause very subtle bugs downstream that are difficult to diagnose. I think the extra step to unwire existing overrides before wiring new ones is worth it to avoid that kind of mistake.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I'm leaning towards keeping it for now, but let me know if anyone feels strongly that this shouldn't require unwiring before overriding!

assert(
newValue == nil
|| environmentDescendantsOverride == nil,
"Attempting to set environment descendants override when one is already set."
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question/comment

assert(
newValue == nil
|| environmentAncestorOverride == nil,
"Attempting to set environment ancestor override when one is already set."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1. Is it intended that we allow this to be nil'd out?

assert(
newValue == nil
|| environmentAncestorOverride == nil,
"Attempting to set environment ancestor override when one is already set."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm in favor of leaving it. If the propagation path gets messed up it can cause very subtle bugs downstream that are difficult to diagnose. I think the extra step to unwire existing overrides before wiring new ones is worth it to avoid that kind of mistake.

self,
&AssociatedKeys.needsUpdateObservers,
newValue,
.OBJC_ASSOCIATION_RETAIN
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this is UI code, should the nonatomic association be used? i assume this should never run concurrently

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right that this could/should be nonatomic! We should only be accessing this from the main actor/thread.

97b49ca

cc @watt

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(going to merge this PR but will follow up if @watt or others suggest a reason not to do this)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems OK to me! I don't recall any reason it was done this way originally.

@n8chur n8chur merged commit 13c21bd into feature/viewenvironmentui Jun 8, 2023
@n8chur n8chur deleted the westin/viewenvironment-object-nodes-only branch June 8, 2023 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants