Skip to content
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

Constructing an AnchorPair outside of Anchorage will be impossible #59

Closed
rlwimi opened this issue Apr 15, 2018 · 4 comments
Closed

Constructing an AnchorPair outside of Anchorage will be impossible #59

rlwimi opened this issue Apr 15, 2018 · 4 comments

Comments

@rlwimi
Copy link

rlwimi commented Apr 15, 2018

To extend Anchorage in an application-specific way, one might create convenience methods to return an AnchorPair, make new AnchorGroupProviding conformers, or extend AnchorGroupProviding to specify new groups. These approaches start with being able to construct an AnchorPair outside of the Anchorage module.

I'm not sure this qualifies as the most "practical" example, but here is my real-world use case. I've implemented a vertical columns-based layout system in order to match the way my designer works, to support handling devices with different widths by scaling the UI rather than implementing (and designing) a responsive design or doing nothing.

So for example, I'd like to be express a layout like

titleLabel.horizontalAnchors == AnchorPair(first: columnOne.leadingAnchor, second: columnTwo.trailingAnchor)

That's pretty raw, and you might imagine a convenience method to make this

titleLabel.horizontalAnchors == anchorsSpanningColumns(.one, .two)

The AnchorPair initializer is marked internal, so I can't use it directly. I've hobbled by with a hack of replicating the internal initializer with slightly different parameter labels, intending to bring this very question in front of this group. With Swift 4.1 and SE-0189, this is now explicitly deprecated.

What is the reasoning behind disallowing AnchorPair construction outside of Anchorage? Is there a downside or complication to making its initializer public that I'm not seeing?

Obviously, I have alternatives. I can always use Anchorage as the implementation for layout convenience methods, but integration with the DSL is so much nicer than mixing it with method calls.

I'd love to hear what you think. In the event that there aren't objections – maybe this initializer was just very conservatively marked internal – I'll post a PR. In that case, I'd have some organizational questions around the Internal.swift file.

@ZevEisenberg
Copy link
Collaborator

My guess is that it wasn't marked as public because we didn't see a use case, but yours is definitely intriguing. @jvisenti should make the call, but this seems like a reasonable request to me.

@jvisenti
Copy link
Contributor

jvisenti commented Apr 16, 2018

@rlwimi @ZevEisenberg I believe AnchorPair is essentially an internal type because exposing the initializer publicly could allow for unsafe usage of the API. Consider this function:

func == <T, U>(lhs: AnchorPair<T, U>, rhs: AnchorPair<T, U>) -> ConstraintPair

If you were to construct two AnchorPair<NSLayoutAnchor, NSLayoutAnchor>, you could mix NSLayoutXAxisAnchor and NSLayoutYAxisAnchor however you wanted, which would result in a crash if you attempted to use this operator on mismatched types, i.e. trying to constraint an XAxisAnchor to a YAxisAnchor. The current API forbids this by construction.

That said, the existence of a valid use case may outweigh the pretty minor risk that comes with it. Happy to take a look at a PR if you have something put together already, and see how it could fit in.

@ZevEisenberg
Copy link
Collaborator

I was just reading through some code that I wrote in a project, and found what I believe is a valid use case:

var safeCenterAnchors: AnchorPair<NSLayoutXAxisAnchor, NSLayoutYAxisAnchor> {
    if #available(iOS 11.0, *) {
        return AnchorPair(first: safeAreaLayoutGuide.centerXAnchor, second: safeAreaLayoutGuide.centerYAnchor)
    }
    else {
        return centerAnchors
    }
}

@rlwimi
Copy link
Author

rlwimi commented Jul 10, 2018

Thanks, everyone! Much appreciated.

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

No branches or pull requests

3 participants