Giter VIP home page Giter VIP logo

anchorage's Introduction

Anchorage

Swift 4.2 + 5.0 CircleCI Version Platform Carthage compatible

A lightweight collection of intuitive operators and utilities that simplify Auto Layout code. Anchorage is built directly on top of the NSLayoutAnchor API.

Each expression acts on one or more NSLayoutAnchors, and returns active NSLayoutConstraints. If you want inactive constraints, here's how to do that.

Usage

Alignment

// Pin the button to 12 pt from the leading edge of its container
button.leadingAnchor == container.leadingAnchor + 12

// Pin the button to at least 12 pt from the trailing edge of its container
button.trailingAnchor <= container.trailingAnchor - 12

// Center one or both axes of a view
button.centerXAnchor == container.centerXAnchor
button.centerAnchors == container.centerAnchors

Relative Alignment

// Position a view to be centered at 2/3 of its container's width
view.centerXAnchor == 2 * container.trailingAnchor / 3

// Pin the top of a view at 25% of container's height
view.topAnchor == container.bottomAnchor / 4

Sizing

// Constrain a view's width to be at most 100 pt
view.widthAnchor <= 100

// Constraint a view to a fixed size
imageView.sizeAnchors == CGSize(width: 100, height: 200)

// Constrain two views to be the same size
imageView.sizeAnchors == view.sizeAnchors

// Constrain view to 4:3 aspect ratio
view.widthAnchor == 4 * view.heightAnchor / 3

Composite Anchors

Constrain multiple edges at a time with this syntax:

// Constrain the leading, trailing, top and bottom edges to be equal
imageView.edgeAnchors == container.edgeAnchors

// Inset the edges of a view from another view
let insets = UIEdgeInsets(top: 5, left: 10, bottom: 15, right: 20)
imageView.edgeAnchors == container.edgeAnchors + insets

// Inset the leading and trailing anchors by 10
imageView.horizontalAnchors >= container.horizontalAnchors + 10

// Inset the top and bottom anchors by 10
imageView.verticalAnchors >= container.verticalAnchors + 10

Use leading and trailing

Using leftAnchor and rightAnchor is rarely the right choice. To encourage this, horizontalAnchors and edgeAnchors use the leadingAnchor and trailingAnchor layout anchors.

Inset instead of Shift

When constraining leading/trailing or top/bottom, it is far more common to work in terms of an inset from the edges instead of shifting both edges in the same direction. When building the expression, Anchorage will flip the relationship and invert the constant in the constraint on the far side of the axis. This makes the expressions much more natural to work with.

Priority

The ~ is used to specify priority of the constraint resulting from any Anchorage expression:

// Align view 20 points from the center of its superview, with system-defined low priority
view.centerXAnchor == view.superview.centerXAnchor + 20 ~ .low

// Align view 20 points from the center of its superview, with (required - 1) priority
view.centerXAnchor == view.superview.centerXAnchor + 20 ~ .required - 1

// Align view 20 points from the center of its superview, with custom priority
view.centerXAnchor == view.superview.centerXAnchor + 20 ~ 752

The layout priority is an enum with the following values:

  • .required - UILayoutPriorityRequired (default)
  • .high - UILayoutPriorityDefaultHigh
  • .low - UILayoutPriorityDefaultLow
  • .fittingSize - UILayoutPriorityFittingSizeLevel

Storing Constraints

To store constraints created by Anchorage, simply assign the expression to a variable:

// A single (active) NSLayoutConstraint
let topConstraint = (imageView.topAnchor == container.topAnchor)

// EdgeConstraints represents a collection of constraints
// You can retrieve the NSLayoutConstraints individually,
// or get an [NSLayoutConstraint] via .all, .horizontal, or .vertical
let edgeConstraints = (button.edgeAnchors == container.edgeAnchors).all

Batching Constraints

By default, Anchorage returns active layout constraints. If you'd rather return inactive constraints for use with the NSLayoutConstraint.activate(_:) method for performance reasons, you can do it like this:

let constraints = Anchorage.batch(active: false) {
    view1.widthAnchor == view2.widthAnchor
    view1.heightAnchor == view2.heightAnchor / 2 ~ .low
    // ... as many constraints as you want
}

// Later:
NSLayoutConstraint.activate(constraints)

You can also pass active: true if you want the constraints in the array to be automatically activated in a batch.

Autoresizing Mask

Anchorage sets the translatesAutoresizingMaskIntoConstraints property to false on the left hand side of the expression, so you should never need to set this property manually. This is important to be aware of in case the container view relies on translatesAutoresizingMaskIntoConstraints being set to true. We tend to keep child views on the left hand side of the expression to avoid this problem, especially when constraining to a system-supplied view.

A Note on Compile Times

Anchorage overloads a few Swift operators, which can lead to increased compile times. You can reduce this overhead by surrounding these operators with /, like so:

Operator Faster Alternative
== /==/
<= /<=/
>= />=/

For example, view1.edgeAnchors == view2.edgeAnchors would become view1.edgeAnchors /==/ view2.edgeAnchors.

Installation

CocoaPods

To integrate Anchorage into your Xcode project using CocoaPods, specify it in your Podfile:

pod 'Anchorage'

Carthage

To integrate Anchorage into your Xcode project using Carthage, specify it in your Cartfile:

github "Rightpoint/Anchorage"

Run carthage update to build the framework and drag the built Anchorage.framework into your Xcode project.

License

This code and tool is under the MIT License. See LICENSE file in this repository.

Any ideas and contributions welcome!

anchorage's People

Contributors

ahtierney avatar armcknight avatar chrisballinger avatar colejd avatar irace avatar jdhealy avatar jvisenti avatar jwatson avatar kabiroberai avatar kingofbrian avatar mattprowse avatar mdiep avatar minimusic avatar robcadwallader avatar sanekgusev avatar thejohnlima avatar yonaskolb avatar zeveisenberg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

anchorage's Issues

Question: If I remove the constraint and change the property, do I need to add again?

Hey guys, I have one question. Having this code:

viewTopAnchor = (view_1.topAnchor = view_2.topAnchor)

then at some point I need to updated the viewTopAnchor property

removeConstraint(viewTopAnchor)
viewTopAnchor = (view_1.topAnchor = view_3.bottomAnchor)
addConstraint(viewTopAnchor) // is this optional or mandatory after removeConstraint?

The question is, due to the Anchorage is adding automatically the constraint when you declare it, should I add it manually if I remove and redeclare it again? Because seems that is I don't add it manually the view is broken.

Prevent self-constraint

I just wrote this by mistake:

someView.verticalAnchors == someView.verticalAnchors

I meant to write the similar but distinct:

someView.verticalAnchors == someViewContainer.verticalAnchors

This could be caught at run-time by asserting that the sides of == are not ===.

Shorter anchor properties

I love how concise Anchorage makes constraint equations. But we could do even better by providing view properties that drop the Anchor suffix and alias the anchor properties. For example:

view.top = container.top + 3
view.edges = container.edges

If interested, I could put a PR together.

EXC_BAD_ACCESS switching from 4.0.0 to 4.1.0+

I get a bad access exception by switching the version from 4.0.0 to 4.1.0 (or higher):

Internal.swift
line 155: switch (first, anchors.first, second, anchors.second) {

Full error:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x600100000000)

By calling horizontalAnchors in a custom UIView.

//...
private let containerView: UIView

override init(frame: CGRect) {
    
    //...
    super.init(frame: frame)

    self.addSubview(self.containerView)

    self.containerView.horizontalAnchors == self.horizontalAnchors // Runtime error here.
}
//...

I've tried searching for any associated zombie objects, but couldn't find any.

Everything is working fine prior to version 4.1.

Did something significant change between the versions that I am not aware of? Or am I looking over something trivial?

Relative alignment samples outdated

Hello,

I was trying to do the following:

view.centerXAnchor == 2 * containe.trailingAnchor / 3

but I receive the compiler error:

Binary operator '*' cannot be applied to operands of type 'Int' and 'NSLayoutXAxisAnchor'

Swift Version: 3.2

How can I achieve this relative positioning?

View could not display in full-screen size, black gap on top and also at bottom

Hi, guys,

I met a problem when I was following the tutorial on how to build an IB-free app, https://www.raizlabs.com/dev/2016/08/ib-free-living-without-interface-builder/, after I finish configuring my AppDelegate Info.plist and my VC. The view could not display in full-screen size, there is black gap on top and another on at the bottom.

I check all the files, it seems all right. I created another project and did it again and everything works.

I am just curious where the bug is. So I will really appreciate the help if anyone could spend a couple minutes to look at my code at

https://github.com/InfinityCode777/LearnIBFree

SHA: f52b165905f780c00490c6b037b2d13d6fbb1ea1

The screen snapshot of iPhone8Plus simulator is contained in repo above.

Best

Jing

Operator precedence issue with constraints to constants at priorities

AspectImageCell.swift:25:44: error: binary operator '~' cannot be applied to operands of type 'Int' and 'Float'
                imageView.widthAnchor == 0 ~ UILayoutPriorityRequired - 1
                                         ~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

You can work around this with parentheses and casting, but it would be nice if we could fix it with operator precedence. Here's a workaround:

imageView.widthAnchor == 0 ~ UILayoutPriority(UILayoutPriorityRequired - 1)

Demo Project

It would be great if there was a proper project with a demo app in the repository.

Prevent common accidental type mismatches

viewA.horizontalAnchors == viewB.edgeAnchors
viewA.horizontalAnchors == viewB.verticalAnchors

These both compile, but then crash at runtime because they are invalid constraints. The types exposed by Anchorage should turn these cases into compile errors.

Multi-binding syntax

Not sure if that's the right term for it, but this idea is inspired by SnapKit, which can do this:

someView.snp.makeConstraints { 
    innerView.width.centerX.top.equalToSuperview()
}

I was thinking that an Anchorage-like way to do that would be something more like this:

innerView.anchors([.width, .centerX, .top]) == otherView

As a convenience, we could also supply a constant that means "the superview of the view to the left of the ==:

innerView.anchors([.width, .centerX, .top]) == Anchorage.Superview() // name TBD

Question: would this work with operators that we use to inset/offset things? I think probably not, just to simplify things. We already provide verticalAnchors, horizontalAnchors, edgeAnchors, and centerAnchors for cases where you would want to pin common combinations with an inset/offset. So, I think this should be a compilation error:

innerView.anchors([.width, .centerX, .top]) == otherView + 10

Manual installation instructions

I plan to use Anchorage in an iOS Swift project soon. I'd prefer to avoid CocoaPods or Carthage and simply add the source files to my project manually. It would be useful to include instructions for a manual installation in the README. Thanks!

Remove convenience accessors on UIViewController subclasses

I recently hit a bug where I had a child VC inside a parent VC, and had set the child VC's edge anchors to the parent view's edges. (Not the child VC view, but the child VC itself.) This led to a bug where on X series phones, in a UINavigationController presented modally, when the parent (containing the child) VC was pushed onto the nav controller, the VC's bottom edge appeared to sink lower towards the bottom edge of the screen, and some content wound up underneath the Home Indicator.

Changing the line of code from

childVC.edgeAnchors == parentVC.view.edgeAnchors

to

childVC.view.edgeAnchors == parentVC.view.edgeAnchors

fixed the issue.

I propose removing the convenience accessors for things like edgeAnchors from UIViewController, as it appears to produce different behaviors on different devices, introduces ambiguity to the layout semantics, and can be difficult to spot.

Prevent duplicate constraints.

Adding constraints should probably prevent duplicates.

From basic testing, duplicate constraints do not appear to cause technical problems. However, if those constraints are iterated/manipulated it could cause problems.

ConstraintBatch would need to perform a "union" instead of "append". (See here.) Unfortunately, even though NSLayoutConstraint is Hashable, apparently duplicate constraints still have unique hash values, so Set can't be used to remove duplicates. You would need to do an Equatable based "union" instead. I have some code for that here.

Use of variables

why can't I do this?
let w = 100
view.widthAnchor == w
Compile says

Binary operator '==' cannot be applied to operants of type NSLayoutDimension' and 'Int'

while this is possible
view.widthAnchor == 100

Support optional constraints on either side of operators

If I'm binding to a view's superview, which is a UIView?, I need to unwrap it first. It would be nice if == had an override for (lhs: UIView?, rhs: UIView?) -> NSLayoutConstraint?, so I could write something like:

myView.widthAnchor == myView.superView?.widthAnchor

Swift 3.0

Anchorage should be made compatible with Swift 3.0. There are a few issues that stand in the way of this goal:

  • NSLayoutYAxisAnchor and NSLayoutXAxisAnchor are declared recursively as of Xcode 8 Beta 1. This issue causes the compiler to crash when compiling Anchorage. http://openradar.appspot.com/radar?id=4988511602081792
  • The genericized operators passed into ConstraintBuilder's initializer give an "Ambiguous member reference" error. The compiler fails to infer their type from the initializer's parameter types. This is likely related to the aforementioned issue.
  • Anchorage's AnchorType protocol name collides with that of a protocol newly added to UIKit.

Need operators for optionals

We should to take into consideration the case where one of the layout anchors are optional. If I do this:
view.leftAnchor == view.window?.leftAnchor it uses the equality operator rather than anchorage == operator.

Use custom operators

I love the idea of stating a constraint as an equation. However, using the bare equality and comparison operators for this purpose seems semantically incorrect and is bound to make the code harder to understand than it should be. I would suggest that we surround the equality and comparison operators with vertical bars to indicate "constraint". For example:

   view.topAnchor |>=| container.topAnchor + 5

This also lets us change the operator precedence if we need to.

In order to preserve backward compatibility, we could make the adorned operators the default, but allow bare operators via conditional compilation.

If you are interested in this, I could put a PR together.

Use of `BinaryFloatingPoint` types with custom operators.

I feel like I'm probably just missing something stupid, but the following code demonstrates a problem I'm having:

let n: Double = 44
button.heightAnchor == 44 // works
button.heightAnchor == CGFloat(n) // works
button.heightAnchor == n // Failes with "Binary operator '==' cannot be applied to operands of type 'NSLayoutDimension' and 'Double'"

I feel like it should work without wrapping it because of this operator definition: https://github.com/Raizlabs/Anchorage/blob/master/Source/Anchorage.swift#L45.

Am I doing something wrong?

Add support for system spacing in iOS 11 and High Sierra

From the iOS 11 release notes:

Updated NSLayoutXAxisAnchor and NSLayoutYAxisAnchor to provide factory methods that create constraints using the system spacing between two anchors. Previously the only way to create such a constraint was with the dash (-) in the Visual Format Language.

Anchorage should add some kind of syntactic sugar or named CGFloat value like .system or something. The new API looks like this:

func constraintEqualToSystemSpacingAfter(NSLayoutXAxisAnchor, multiplier: CGFloat)

It might be nice to use it like this:

view2.trailingAnchor == view1.leadingAnchor + SystemSpacing()

Writing ratio position in Anchorage

I want to position an element at 1/3 of the screen's Y axis, which works fine using

        NSLayoutConstraint(
            item: logo,
            attribute: .centerY,
            relatedBy: .equal,
            toItem: self,
            attribute: .bottom,
            multiplier: 0.333,
            constant: 0.0).isActive = true

Is it possible to write this constraint in Anchorage syntax? I tried logo.centerYAnchor == bottomAnchor * 1 / 3 and logo.centerYAnchor == 0.333 * bottomAnchor but both result in compile errors.

First time anchorage-usage confusing

When I was using Anchorage for the first time, I was trying to anchor a label within a UIViewController. I didn't realize the "container" in the docs was in specific reference to the view, so I first did
label.centerAnchors == self.centerAnchors
(instead of label.centerAnchors == self.view.centerAnchors)
which actually worked, adding to my confusion. I realized the issue when I tried to access the UIViewController's leading and trailing anchors, which of course it has none. However, it does have center, edge, size, vertical, and horizontal anchors, which led me in the wrong direction.

Carthage problems on Xcode 12

I'm having a problem using Anchorage with XCode 12 and iOS 14.
Running on a simulator I get - (if using command line tools 11.7 for Carthage) "Building for iOS Simulator, but the linked framework 'Anchorage.framework' was built for iOS."

If I use command line tools 12 for Carthage build fails ("Task failed with exit code 1: ,, This usually indicates that project itself failed to compile."). I checked the xcode logs and they succeeded but with many warnings - "*.pcm: No such file or directory."
If anyone one has any ideas or need more info to investigate that would be great.

My biggest question though is if Anchorage is still supported and if this issue is on my side or should I wait for a fix?
I was also thinking of pulling the Anchorage source, try fix myself and add the framework in the project, but I don't know if that's a good idea?

Any help would be great.

Add a shorthand for accessibilityIdentifier

It would be nice to be able to take any Anchorage expression and add + "someString" to it, and get a constraint that has an identifier. Constraint identifiers show up in debug logs and the Xcode view debugger, and they also appear on wtfautolayout.com.

I’m guessing that overloading func +(lhs: LayoutExpression, rhs: String) might adversely affect compile times, so I’d be OK with exploring other operators, but it’s hard to beat good ol’ + for readability.

Add a logo

Found this in my old photos, circa 2017. Guessing Samantha Broccoli or one of the other Raizlabs designers drew it. Could be the nice basis for a logo.
8A016878-F9DE-42A1-8FDD-84C33139D10F

Order of operation when creating constraint

// Context
let view1 = UIView()
let view2 = UIView()
let window = UIWindow()
window.addSubview(view1)
window.addSubview(view2)
view1.widthAnchor == 50
view2.widthAnchor == (view1.widthAnchor + 150) / 2
// Expectation: (50 + 150) / 2
view2.frame.width == 100
// Actual: (50 / 2) + 150
// <NSLayoutConstraint: UIView.height == 0.5 * UIView.height + 150   (active)>
view2.frame.width == 175

Priority documentation not matching reality

According to the readme the priority can be set with a number like

view.centerXAnchor == view.superview.centerXAnchor + 20 ~ 752

but that doesn't seem to work. The compiler always complains about it with the message Cannot convert value of type 'Int' to expected argument type 'Priority'.

However, using an instance of Priority works:

view.centerXAnchor == view.superview.centerXAnchor + 20 ~ .init(752)

So either the documentation is wrong or there is a bug which doesn't allow to use an Integer directly.

horizontalEdge operator math shifts constraints

horizontalEdge operator shifts the constraint, so:

view.horizontalAnchors == horizontalAnchors + 10

This shifts the leading and trailing constraint right by 10. This makes sense, but isn't overly useful in practice. It feels like EdgeAnchors or horizontal / vertical anchors should inset the anchors so +10 would shift the leading left and the trailing right.

Improved demo for new users?

In the Anchorage demo app, nothing in the root view controller is pinned using Anchorage. I'm trying to make my first app using Anchorage, and if I try using it to pin stuff I added to the root view that was automatically created by IB, I just get a big mess. Surely I'm doing it wrong or making my configureLayout() call too early. In any case, a demo using Anchorage in every view, including the root view controller, would really help.

Constructing an `AnchorPair` outside of Anchorage will be impossible

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.

Please Update for Swift 5.2

Anchorage won't work after updating xcode to 11.4 which is using swift 5.2.

import Anchorage cause an error :
Module compiled with Swift 5.1.2 cannot be imported by the Swift 5.2 compiler.

Add convenience syntax for .low + 1

With the new enumerations provided in #33, it would be nice to add some extra operators so that you can do:

view1.leadingAnchor == view2.trailingAnchor ~ .low + 1

Instead, you have to do:

view1.leadingAnchor == view2.trailingAnchor ~ .custom(UILayoutPriorityLow + 1)

Mark invalid combinations of anchors as deprecated

label.leadingAnchor == view.topAnchor

Expected behavior: a compile-time error, telling you that this combination is invalid.

Actual behavior: a warning telling you that the result of == is unused.

The current behavior is that, in the absence of an override of == for <NSLayoutXAxisAnchor, NSLayoutYAxisAnchor>, it’s falling back to the global ==Equatable conformance for NSObject.

Ideally, we could write the appropriate overrides and mark them as @available(*, unavailable), but unfortunately, Swift is too clever for that. It realizes that there’s no point in choosing that implementation, so it again falls back to the NSObject version.

We can mark the methods as @available(*, deprecated, message: "It’s invalid to mix X and Y axes in this way") and then fatalError or -> Never (or both). But we still get a compile-time warning, not error.

One more sweeping workaround would be to stop using built-in UIKit anchors in favor of custom shorthand anchors, like .leading and .top instead of .leadingAnchor and .topAnchor. Those types can do whatever we want, which in this case would be to not inherit from NSObject, so then we would have more control over which operators are valid. It’s the nuclear option, but it might make layout expressions a little nicer to use.

As a stopgap, we should probably implement and deprecate the invalid combinations, just to improve error messaging.

Use precedence operator without parentheses

someView.topAnchor == otherView.bottomAnchor + 50 ~ UILayoutPriorityDefaultHigh

Gives this error in Swift 3:

 error: adjacent operators are in unordered precedence groups 'AdditionPrecedence' and 'PriorityPrecedence'
someView.topAnchor == otherView.bottomAnchor + 50 ~ UILayoutPriorityDefaultHigh
                                             ^    ~

If this is fixed, it should be fixed in the readme as well.

Update for Swift 5.0

On top of fixing up the podspec to include swift_version (#68) and fixing Xcode 10.2+ warnings (#73), this project should be updated to Swift 5.0.

I took a quick pass at this and it appears to only require a few minor changes. However, someone with access needs to fix the CI build (it currently points to an inaccessible CircleCI page).

Type-checking Performance

We're using anchorage in our app and have something akin to this in our xcconfig:

OTHER_SWIFT_FLAGS = -Xfrontend -warn-long-function-bodies=400 -Xfrontend -warn-long-expression-type-checking=400

We compile Anchorage from source due to needing a static lib and Anchorage code as well as our app are consistently causing warnings.

For Anchorage, it's the performInBatch(closure:) call in func constraints(forAnchors:, firstConstant c1:, secondConstant:, priority:, builder:) (Internal.swift).

In our app, functions that have numerous calls to Anchorage.batch(active:closure:) ini the same function tends to also fail this check.

Expose .centerAnchors property

On the pattern of horizontalAnchors and verticalAnchors:

view1.centerAnchors == view2.centerAnchors
// same as:
view1.centerXAnchor == view2.centerXAnchor
view1.centerYAnchor == view2.centerYAnchor

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.