GithubHelp home page GithubHelp logo

snapkit / masonry Goto Github PK

View Code? Open in Web Editor NEW
18.1K 18.1K 3.1K 767 KB

Harness the power of AutoLayout NSLayoutConstraints with a simplified, chainable and expressive syntax. Supports iOS and OSX Auto Layout

License: MIT License

Objective-C 97.83% Ruby 1.79% Shell 0.38%

masonry's Introduction

SnapKit is a DSL to make Auto Layout easy on both iOS and OS X.

Build Status Platform Cocoapods Compatible Carthage compatible

⚠️ To use with Swift 4.x please ensure you are using >= 4.0.0 ⚠️

⚠️ To use with Swift 5.x please ensure you are using >= 5.0.0 ⚠️

Contents

Requirements

  • iOS 12.0+ / Mac OS X 10.13+ / tvOS 10.0+
  • Xcode 10.0+
  • Swift 4.0+

Migration Guides

Communication

  • If you need help, use Stack Overflow. (Tag 'snapkit')
  • If you'd like to ask a general question, use Stack Overflow.
  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Installation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:

$ gem install cocoapods

CocoaPods 1.1.0+ is required to build SnapKit 4.0.0+.

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

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!

target '<Your Target Name>' do
    pod 'SnapKit', '~> 5.7.0'
end

Then, run the following command:

$ pod install

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

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

github "SnapKit/SnapKit" ~> 5.0.0

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

Swift Package Manager

Swift Package Manager is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.

Xcode 11+ is required to build SnapKit using Swift Package Manager.

To integrate SnapKit into your Xcode project using Swift Package Manager, add it to the dependencies value of your Package.swift:

dependencies: [
    .package(url: "https://github.com/SnapKit/SnapKit.git", .upToNextMajor(from: "5.0.1"))
]

Manually

If you prefer not to use either of the aforementioned dependency managers, you can integrate SnapKit into your project manually.


Usage

Quick Start

import SnapKit

class MyViewController: UIViewController {

    lazy var box = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.addSubview(box)
        box.backgroundColor = .green
        box.snp.makeConstraints { (make) -> Void in
           make.width.height.equalTo(50)
           make.center.equalTo(self.view)
        }
    }

}

Playground

You can try SnapKit in Playground.

Note:

To try SnapKit in playground, open SnapKit.xcworkspace and build SnapKit.framework for any simulator first.

Resources

Credits

License

SnapKit is released under the MIT license. See LICENSE for details.

masonry's People

Contributors

0oneo avatar adempseybox avatar ahti avatar andreyoshev avatar bjallen avatar cloudkite avatar craigsiemens avatar danielrhammond avatar dinosaurdad avatar dlo avatar edoardoc avatar erichoracek avatar fabb avatar game3108 avatar gobetti avatar griffinmacias avatar honood avatar idalink avatar iwill avatar kouky avatar kovpas avatar msqr avatar nickynick avatar pingyourid avatar ploddi avatar rastersize avatar rea-myles-abbott avatar robertjpayne avatar sibljon avatar vascoorey 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  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

masonry's Issues

Can't form weak reference to a NSTextView

As mentioned in Apples Transitioning to ARC Release Notes you can't create a weak reference to instances of class NSTextView. Meaning the app will crash if you are trying to call mas_makeConstraints: on a NSTextView.

Since i love using Masonry, I would love to see this being implemented so that I can use it for my Mac OS X projects as well.

Do you see this feature being implemented or will you go on not supporting this?

Thanks!

Update readme for v0.5

The most recent stuff is not covered yet, but it's too awesome to stay in the shadows :) I may do a PR if you are busy right now.

Animating a view inside a cell : First init

First of all, I don't know if this is really an issue of Masonry or an Auto Layout thing.

I'd been doing some tests animating things with Masonry and after some tweaking it usually works like a charm and is pretty fast. I want to share one of these tests with you which is perfect to show the issue I had and the workaround used.

https://github.com/lluisgerard/Masonry-Animated-Cell

As you can see here. I have a view that starts always at width 0 and grows to the pixel equivalent percentage (from 0 to 300 px).

The basic code for this animation is where self.animateConstraint is animated:

        float width = self.frame.size.width / grade;
        self.animateConstraint.equalTo(@(width));
        [UIView animateWithDuration:1.0f
                              delay:0.0f
             usingSpringWithDamping:0.4f
              initialSpringVelocity:0.9f
                            options:UIViewAnimationOptionCurveEaseInOut
                         animations:^{
                             [self layoutIfNeeded];
                         } completion:^(BOOL finished) {

                         }];

What happens is that when you start the app for the first time (aka load the tableview) the growing view doesn't animate at all. It just appears on the cell with the end state of the animation.

I don't know the best way to approach this, maybe there is something that I'm missing like a trigger when the view is completely loaded and constraints are set (delegates?). I even found other issues that I cannot replicate now, like the bar started to grow while the whole view was being set by autolayout (I think I was using updateConstraints then).

Ok, the solution (or workaround) I found was to do this only the first init:

        double delayInSeconds = 0.0;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            growBlock(); // this block is the above animation code
        });

As you can see, delay is set to 0 seconds but the dispatch_after is enough to activate the first animation. You can download my example project, comment the dispatch, you will see that nothing is animated on the first load then.

You can see the whole code here https://github.com/lluisgerard/Masonry-Animated-Cell/blob/master/AnimateLayouts/LLGAnimatedView.m

I'm sure I'm missing something here to know when the autolayout finished doing it's job (maybe tracking self.frame width and height?). Anyway, I hope that at least somebody can enjoy my example :)

updateConstraints installs two width constraints instead of updating it

When setting a constraint equalTo a NSNumber, and afterwards setting it to equalTo(self) in an updateConstraints block, the constraint is not recognised as needed to be updated, and instead two constraints are added and an autolayout error (cannot satisfy constraints) is thrown, which shows two simultaneously installed width constraints.

Example:

[self.containerView mas_updateConstraints:^(MASConstraintMaker *make) {
        if (something) {
            make.width.equalTo(@760);
        } else {
            make.width.equalTo(self);
        }
}];

A workaround i had to use was to take the width of self manually and wrap it in a NSNumber like this:

[self.containerView mas_updateConstraints:^(MASConstraintMaker *make) {
        if (something) {
            make.width.equalTo(@760);
        } else {
            make.width.equalTo(@(self.bounds.size.width));
        }
}];

Incorporating top layout guide

I am using a transparent UINavigationBar and UITextField. I want it to be 20px under the navigation bar, so I'm using the following commands:

[self.emailTextField mas_makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo((self.view).mas_top).with.offset(20);
}];

However, my text field appears beneath the navigation bar, 20px from the top of the screen.

-- iOS 7 SPOILER ALERT --

In iOS 7 there is a topLayoutGuide property on UIViewController. How can I incorporate it using Masonry, so my text field appears under the navigation bar (84px from the top of the screen) both in iOS 7 with transparent navigation bar and in iOS 6?

I know that it can be done using NSLayoutConstraints. Taken from the documentation:

id topGuide = myViewController.topLayoutGuide;
// "button" is a UIButton object specified elsewhere
[myViewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[topGuide]-20-[button]"]];

Expose MASConstraintMaker's view property

First off, thanks for the amazing library! You've successfully made writing autolayout code a breeze.

It would be helpful to have MASConstraintMaker's view property exposed so that the following code could be written:

[view mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(make.view.superview);
}];

This way, constraints could be defined relative to the view's superview, regardless of if the superview is changed down the line in your implementation.

Additionally, this means that copy-pasting layout code when writing it would result in less occurrences of:

[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(view1.superview);
}];
[view2 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(view1.superview);
}];

Where view2 is constrained to view1's superview, which is an easy to miss but hard to debug error.

Animate a UIView to another location

If I have a view with constraints:

[self.summaryView makeConstraints:^(MASConstraintMaker *make) {

    self.animatableConstraint = make.edges.equalTo(self.view).with.insets(UIEdgeInsetsMake(80, 10, 10, 10));
}];

And later I want to animate to another point like:

// TODO: Set new position here.

[UIView animateWithDuration:2.5
                 animations:^{
                     [self.summaryView layoutIfNeeded];
                 }
                 completion:^(BOOL finished) {
                 }];

How can I do this?

Breaking Objective-C language conventions

I love Masonry to bits. It makes a ton of difference for me and enjoy using it on a daily basis. In that light I'd like to offer some constructive feedback.

I have an issue with the implementation: The MASConstraintMaker design and syntax violates basic Objective-C conventions. Obj-C properties are used in ways they were not intended to be used. I think it's wrong to fight the language because although immediate readability may increase, it decreases implementation transparancy; the implicit conventions and expectation management between an API developer and the API user vanishes and it generally clutters the code if developers create their own conventions instead of following the ones given by the language. Moreover, you're not only fighting the language, you're also fighting the IDE.

Of course, this is what I'm talking about:

[someView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(otherView).with.offset(someOffset);
}
  • The object 'make' is a verb. Object names should be nouns as their classes to indicate their role
  • 'left' is a property representing a constraint. It is vaguely named to increase readability but doesn't tell me what it is.
  • equalTo() can't really be considered a property although it's defined as such. It relates two objects (left and otherView) which is not the job of a property.
  • 'with' does nothing other than increase readability of the 'sentence' and it's a property on the 'equalTo' object. By now I've lost track of what kind of objects I'm actually working on.
  • etc...

Instead I suggest a syntax more like this:

[someView mas_makeConstraints:^(MASConstraintMaker *maker) {
    [maker setLeftEqualTo:otherView withOffset:someOffset];
}

Of course this would require a lot of new methods to cover all cases, but I think its more in line with language conventions and any Objective-C programmer with minimal experience will read this just as easily as the current syntax. An added benefit is that this syntax autocompletes much nicer in Xcode because you don't have to interrupt the auto completion with dots all the time.

I'd just like to start a discussion regarding this issue. I hope we can come up with a great solution that is more in line with the Obj-C language conventions while maintaining Masonry's simplicity and elegance.

Issue with animating constraints

I'm having a strange issue with animating a certain constraint.

I created a very simple project to demonstrate the issue:
https://github.com/mobitar/MasonryTest

In ListViewController.m, there's a method called addSampleView. If you uncomment this method, and hit the "Toggle" button, the list controller slides out with an animation, as intended.

If however you leave this line in, and the sample view is added, for some reason the list controller slides out and in when you hit the toggle button, but without animation.

Any idea why?

Centering not work as expected

I have a UIView (hegiht=80), and as subviews a label and a edit.

I have tried to center both in the Y axis. However, the heigth of both subviews change to be the same of the superview.

I expected to both controls to be centered.

   [self.view addSubview:scroll];
    self.view.backgroundColor = [UIColor darkGrayColor];

    UIEdgeInsets paddingInsets = UIEdgeInsetsMake(self.navigationController.navigationBar.frame.size.height + 30, self.padding, self.padding, self.padding);

    [scroll keepInsets:paddingInsets];

    UIView *back = [[UIView alloc] init];
    back.backgroundColor = [UIColor lightGrayColor];

    [scroll addSubview:back];

    [back mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(@0);
        make.left.equalTo(@0);
        make.width.equalTo(scroll.mas_width);
        make.height.equalTo(@80);
    }];

    [label mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(back);
        make.left.equalTo(@0);

        make.width.equalTo(@200);
        make.centerY.equalTo(back.mas_centerY);
    }];

    [edit mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(back);
        make.right.equalTo(back.mas_right);

        make.width.equalTo(label.mas_width);
        make.centerY.equalTo(back.mas_centerY);
    }];

implicit superview offset not working correctly

Hi Jonas,

I'm seeing a strange issue which I think I should raise.

I've been quite happily using the shortcut in my project for mapping against a superview's offset,

e.g. inside a UIView subclass, when adding a subview, for configuring its constraints instead of writing

make.top.equalTo(self).with.offset(20)

I'd just write

make.top.offset(20)

which adds the same constraint. This has been working great except for a case i've came across - where the view is a UITableViewCell. I've uploaded an example project here which outlines exactly where it works for one case, and not for the other.

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        UILabel *label = [UILabel new];
        label.text = @"Label";

        [self addSubview:label];

        [label mas_makeConstraints:^(MASConstraintMaker *make){
//            /* Broken */
//            make.top.offset(20);
//            make.right.offset(-20);

            /* Works */
            make.top.equalTo(self).with.offset(20);
            make.right.equalTo(self).with.offset(-20);
        }];
    }
    return self;
}

I'm unsure whether it's a fault in Masonry or UIKit, but I figured you're better at debugging this than me so I'd ask you first!

Using mixture of existing views for constraint

I don't quite understand this from the readme:

An array of a mixture of any of the previous types

make.height.equalTo(@[view1.mas_height, view2.mas_height]);

Does make.height.equalTo(@[view1.mas_height, view2.mas_height]); make the height of what ever view we're adding constraints to the average of the view1 and view2 heights?

Masonry built with Swift Support

Currently when trying to set constraints in Swift using the objc Masonry files, an error is generated: Cannot convert the expression's type '$T6' to type '() -> ((AnyObject!) -> MASContraint!)!'

Animating constraints?

It'd be nice if the documentation gave an example about how to animate constraints. I'd submit a pull if I knew how to form such documentation.

Animator proxy on OS X seems to have some problem

Hi!

I use Masonry in my real cocoa project. All things are cool before adding support for the animator proxy on OS X #41 .

Arter #41 All my teammate except me have the following problem:
9qs4 rxufg8vrce6t __yj

So I do some test:

  1. I build a new Cocoa Application
  2. add the podfile with single line: pod 'Masonry'
  3. run 'pod install' with cocoapods 0.29.0
  4. this project still work fine on my computer and the same problem on my teammate's computer.

Problem with UIView in UIScrollView

Hi there

First of all, thanks for Masonry, it looks really awesome! Unfortunately though, I have the following problem: I created a UIScrollView inside the UIView of my UIViewController and added some constraints to keep the scroll view the size of the view:

self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
_scrollView.backgroundColor = [UIColor redColor];
[self.view addSubview:_scrollView];

[_scrollView makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(self.view);
}];

This seems to work, but then I added a UIView inside the scroll view and tried to make it stick to the top:

UIView *view = [[UIView alloc] initWithFrame:CGRectZero];
view.backgroundColor = [UIColor blueColor];
[_scrollView addSubview:view];

[view makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(@0);
    make.left.equalTo(@0);
    make.right.equalTo(@0);
    make.height.equalTo(@100);
}]; 

However, this second view never shows up! Any idea on what I'm doing wrong?

How do I add constraint with flipped relationship ?

How do I add constraint with flipped relationship ?

I have following constraint

[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:scrollView_
  attribute:NSLayoutAttributeLeft
  relatedBy:NSLayoutRelationEqual
  toItem:self.contentView
  attribute:NSLayoutAttributeLeft
  multiplier:1
  constant:JSMessageCellPadding]];

my understanding is that following DSL

[self.contentView mas_makeConstraints:^(MASConstraintMaker *make)
{
  make.left.equalTo(scrollView_.mas_left).with.offset(JSMessageCellPadding);
}];

will be equal to

[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.contentView
  attribute:NSLayoutAttributeLeft
  relatedBy:NSLayoutRelationEqual
  toItem:scrollView_
  attribute:NSLayoutAttributeLeft
  multiplier:1
  constant:JSMessageCellPadding]];

How can I do it ?

Thanks!

iOS 7.1 :: View that adds subviews while the view is not entirely on the screen

I'm having some issues with the app that I'm developing right now. Not sure where is the problem but I can replicate it whenever I want. Not sure if this is a Masonry issue though. So far, I tested the drawer menu without autolayout on iOS7.1 and I'm not having the same problems there, that's why I think that at least autolayout is involved here.

I'm using this "drawer" menu:
https://github.com/monospacecollective/MSDynamicsDrawerViewController

This is how it looks usually (can't share it without hiding some parts):
ios-simulator-screen-shot-11-mar-2014-19 49 06

If you go and change from one view to another and you go "slow", letting the whole view load (sometimes it goes to the API on the background to load content), everything works fine.

The issue comes if you open the drawer menu before its content is entirely loaded, then the view seems that is cut in half and so the menu (sometimes disappears).
ios-simulator-screen-shot-11-mar-2014-19 47 59

I can't share my code but maybe someone has an idea about why this is happening, or you are having also some issues after upgrading to iOS 7.1. If nothing comes up I will try to replicate this on a separated project only for this purpose.

Thank you very much in advance! Sorry if you think that this is not to be posted here, I'm having some degree of desperation right now 👹

uicontrols in a uiview can not receive touch event

I setup a UIView to wrap UIControls, like:
aView
-- UISlider
-- UIImageView
-- UIImageView

in the aView's method: - (id)initWithFrame:(CGRect)frame, I setup all subviews and controls, make masonry layout.
Then add the aView on self.view. But the slider's thumb can not be moved.
Please help me to figure out.

Strange problem with "multipliedBy"

In self.view appeared black strip on the right.
If you delete line in code:

make.width.equalTo(self.mas_width).multipliedBy(multiplier);

problem disappears.

How can this be the reason?

- (void)setItems:(NSArray *)items
{
    _items = items;

    UIView *previousContainerItem;
    for (BarButtonItem *item in _items)
    {
        UIView *containerItem = [[UIView alloc] init];
        [self addSubview:containerItem];
        [containerItem addSubview:item];

        [containerItem mas_makeConstraints:^(MASConstraintMaker *make) {
            MASViewAttribute *left = (previousContainerItem) ? previousContainerItem.mas_right : self.mas_left;
            make.left.equalTo(left);
            make.height.equalTo(self);
            make.top.equalTo(self);
            float multiplier = 1.0 / _items.count;
            make.width.equalTo(self.mas_width).multipliedBy(multiplier); // <===
        }];

        [item mas_makeConstraints:^(MASConstraintMaker *make) {
            make.centerY.equalTo(containerItem);
            make.centerX.equalTo(containerItem);
            make.height.equalTo(@30);
            make.width.equalTo(@30);
        }];
        previousContainerItem = containerItem;
    }
}

picture alt

Screen - http://rghost.ru/50893121/image.png

Calling Masonry methods on root view causes layout problems

It seems that setting translatesAutoresizingMaskIntoConstraints=NO on the root view (i.e., the root view controller's view) has a bad effect on auto layout. Masonry implicitly changes that setting, so if it is used in the wrong way, it can cause nasty bugs.

HOW TO REPRODUCE: (I'll try to provide a toy example later, when time is less desperately tight, if desired)

  1. Set up a root view containing some subviews. Use auto layout to position the subviews relative to the root view.
  2. Set translatesAutoresizingMaskIntoConstraints=NO on window.rootViewController.view.
  3. From the rootViewController, present a modal view controller and then dismiss it.
  4. You will probably see a completely wrecked view layout; specifically, the main view is no longer sized to fit the window.

THE WORKAROUND: If RV is the root view and SV is a subview, then avoid calls of the form:

[RV.makeConstraints  .... {
    ... SV ... 
}]

and instead use:

[SV.makeConstraints ... {
    ... RV ...
}]

Note that this situation doesn't apply to every superview/subview relation, only when the superview is the topmost view.

THE FIX? Probably Masonry should check to see if the view on which the Masonry method is being called is the root view, before setting translatesAutoresizingMaskIntoConstraints to NO.

(This is the second time that implicit property change has bitten me. I'm not sure if it's worth the convenience.)

(P.S. Apologies if this is already reported or even documented. I searched but couldn't find anything.)

Support for UILayoutSupports (topLayoutGuide & bottomLayoutGuide)

Support for building constraints with topLayoutGuide and bottomLayoutGuide would be great. From what I understand, using the length property of the guide to build the constraint would require us to also monitor for status bar frame changes, and reconfigure our constraints.

This looks like it would be difficult to support without a big refactor, but if you have ideas for how you'd like this implemented, I'd be happy to work on it.

Question: necessary to remove existing constraints?

When calling a block like so:

[self.descriptionLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  make.top.equalTo(self.titleLabel.mas_bottom).with.offset(8.f);
  make.left.equalTo(self.contentView.mas_left);
  make.right.equalTo(self.contentView.mas_right);
}];

Is it necessary to remove the existing constraints first?

Idea: make.superview

I often use a pattern as the following:

- (instancetype)init...
UIView * mySubView = [UIView new];
[myView addSubview:mySubView];
[mySubView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(mySubView.superview);
}];

So I refer to myView indirectly using mySubView.superview. This is because it often eases refactoring, for instance if I want to introduce a container view between myView and mySubView.

I wonder if it would make sense to introduce a make.superview? This way, the constraints related to the actual view would be easier to recognize.

Also, I try to use mas_makeConstraints: as often as I can, since in my mind, constraints are almost always immutable, except when animating.

What are your comments to the above points? Are they patterns or anti-patterns? :-)

Live reload possible in some way?

After I started using classy.as for my styling I have quickly become addicted to the live reloading feature. I'm thinking if we could somehow do something similar for Masonry it would be awesome. I don't know how this would work thought.

It's mostly my constant numbers I would like to change live. Today I use DCIntrospect (https://github.com/lukaswelte/DCIntrospect-ARC) to adjust frames in the simulator and then I have to remember the new constant values and change them in the code afterwards.

Could we define all constants in a separate file that is watched by Masonry. So that changes in the constant file would be injected into the running simulator?

No issues

I just wanted to say how insanely useful this has been to me in developing my app. Thank you so much!

(Sorry for creating this issue just for that - but I needed you to read it, and couldn't find elsewhere to contact you...)

how to get view frame

when i use masonry such as this,how can i get the truly frame of imageview

imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
        imageView.contentMode = UIViewContentModeScaleAspectFit;
        [backView addSubview:imageView];
        [imageView makeConstraints:^(MASConstraintMaker *make) {
            make.top.equalTo(backView.mas_top).with.offset(5);
            make.left.equalTo(backView.mas_left).with.offset(5);
            make.width.equalTo(@300);
            make.height.equalTo(@120);
        }];

Issues with multiple views inside a UIScrollView

Hi there,

First of all, I want to say that this library is really awesome and is one of the reasons that I'm using autolayout right now. Been using it for a new project and everything is working like a charm, really appreciate it.

But, I'm trying to use it on a ScrollView and I'm having a lot of trouble. I tried to solve this in multiple ways and different approaches and I'm not having any success at all. The more I try the less I feel I understand how Autolayout and Masonry works. Maybe that's the problem, not Masonry but the way Autolayout works in ScrollViews.

The main issue I have is that the scrollView only scrolls horizontally and not vertically, it's stuck.

Found this issue #12 and tried to always set the width of my subviews. I even copied exactly what he did there, but then I created like 50 views in the same scrollView and it doesn't scroll.

Been reading this https://developer.apple.com/library/ios/technotes/tn2154/_index.html but in this case, they use only one big view, and not multiple ones.

At this point, after so many hours trying, I think that I'd better see an example and start again than try to fix my own one so I created a new ViewController and added this code to the init:

    self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
    _scrollView.backgroundColor = [UIColor grayColor];
    [self.view addSubview:_scrollView];

    [_scrollView makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.view);
    }];

    NSNumber* height = [NSNumber numberWithInt:350];

    UIView *view1 = [[UIView alloc] initWithFrame:CGRectZero];
    view1.backgroundColor = [UIColor blueColor];
    [_scrollView addSubview:view1];


    UIView *view2 = [[UIView alloc] initWithFrame:CGRectZero];
    view2.backgroundColor = [UIColor greenColor];
    [_scrollView addSubview:view2];


    UIView *view3 = [[UIView alloc] initWithFrame:CGRectZero];
    view3.backgroundColor = [UIColor redColor];
    [_scrollView addSubview:view3];

    [view1 makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(@0);
        make.left.equalTo(@0);
        make.width.equalTo(_scrollView.width);
        make.height.equalTo(height);
    }];

    [view2 makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(view1.mas_bottom);
        make.left.equalTo(@0);
        make.width.equalTo(_scrollView.width);
        make.height.equalTo(height);
    }];

    [view3 makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(view2.mas_bottom);
        make.left.equalTo(@0);
        make.width.equalTo(_scrollView.width);
        make.height.equalTo(height);
    }];

This code adds the first view and the next two correctly, one using the bottom as a top reference, but the UISCrollView is not scrolling at all. I also tried to add everything inside a UIView. I even tried to get the last object Y position, but I get a very high number that doesn't make sense.

Should I have to set the contentSize of the scrollView ? but that's why I wanted the Y position for, I'm feeling that this is the wrong direction.

At this point I hope that somebody can help me, I will really appreciate it, and even better, seeing some example. I think I'm missing something here.

Thanks in advance :)

Memory leak

I am applying the constrains over the subview that is tableview of viewcontroller HelpDetailVC and i found that dealloc method is not called if we keep constrain.

__weak UIView *superview = self.view;
[self.tableview mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(superview);
}];

So if now i comment the make.edges part it start calling dealloc method.
__weak UIView *superview = self.view;
[self.tableview mas_makeConstraints:^(MASConstraintMaker *make) {
//make.edges.equalTo(superview);
}];

So can you please verify this it is an issue?

MasonryTestLoader generated build phase uses a full path to the script

Since Pods are out of .gitignore now, Pods.xcodeproj is now included in the repo. However, Podfile specifies a build phase generation which involves a full path to the script:

export | egrep '( BUILT_PRODUCTS_DIR)|(CURRENT_ARCH)|(OBJECT_FILE_DIR_normal)|(SRCROOT)|(OBJROOT)' > /Users/jonas/Projects/Masonry/script/env.sh

So you can't run tests unless you run pod to regenerate it for yourself.

I'm not quite sure how to fix this properly, so leaving it here for now :)

The documentation and examples for updateConstraints contradict each other

The documentation shows the following example for the updateConstraints methods. The updateConstraints method is called at the top of the method.

- (void)updateConstraints {
    [super updateConstraints];

    [self.growingButton mas_updateConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self);
        make.width.equalTo(@(self.buttonSize.width)).priorityLow();
        make.height.equalTo(@(self.buttonSize.height)).priorityLow();
        make.width.lessThanOrEqualTo(self);
        make.height.lessThanOrEqualTo(self);
    }];
}

The updateConstraints method in MASExampleUpdateView.m calls the updateConstraints method at the bottom of the method.

// this is Apple's recommended place for adding/updating constraints
- (void)updateConstraints {

    [self.growingButton updateConstraints:^(MASConstraintMaker *make) {
        make.center.equalTo(self);
        make.width.equalTo(@(self.buttonSize.width)).priorityLow();
        make.height.equalTo(@(self.buttonSize.height)).priorityLow();
        make.width.lessThanOrEqualTo(self);
        make.height.lessThanOrEqualTo(self);
    }];

    //according to apple super should be called at end of method
    [super updateConstraints];
}

I believe the updateConstraints method in MASExampleUpdateView.m is correct, but the documentation and MASExampleUpdateView.m should use the same method to update constraints.

Examples don't compile 'out of the box'

So, I downloaded a zip of your archive, ran pod install, opened up the workspace, and switched my target to the example project. When I hit Run, it gave me a compile error saying that Masonry.h couldn't be found (from the example project's PCH file).

I had to modify the import line to be:

#import "Masonry/Masonry.h"

for it to work.

This is in Xcode 4.6.3.

Constraints strangely breaking

Hey I have some constraints that are oddly breaking and am hoping you can help me out.

Here's the scenario. I have a UIViewController with a custom toolbar at the bottom. The toolbar has 4 buttons, all equal height, and when switching between portrait and landscape mode the button widths will adjust equally to fill the view width. This works great when I test this in a ViewController that only has this custom toolbar.

However, in one of my more complex UIViewControllers that has many subviews with constraints, the toolbar constraint is breaking on the button widths.

I've tested on these devices.

iPhone 4 iOS 6 - breaks
iPad Mini iOS 6 - does not break
iPhone Simulator iOS 6 - breaks
iPhone Simulator iOS 7 - does not break

Here's my init function in my custom toolbar class. At the bottom of the function is where I do the auto layout for my toolbar. I must not be creating equal widths properly?

  • (id)init
    {
    self = [super init];
    if (self) {
    // Initialization code here.

    BOOL isIphone = [UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone;
    CGSize screenSize = [UIScreen mainScreen].bounds.size;
    
    CGFloat viewHeight;
    if (isIphone)
    {
        viewHeight = 80.0f;
    }
    else//iPad
    {
        viewHeight = 100.0f;
    }
    
    self.view = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, screenSize.width, viewHeight)];
    self.view.backgroundColor = [UIColor grayColor];
    
    //add buttons
    
    _buttons = [[NSMutableArray alloc] init];
    
    UIButton *button;
    //CGFloat buttonWidth = screenSize.width / 4.0f;
    CGFloat buttonHeight = viewHeight;
    
    for (NSUInteger i = 0; i < 4; ++i)
    {
        button = [UIButton buttonWithType:UIButtonTypeCustom];
    
        [_buttons addObject:button];
    
        [self.view addSubview:button];
    }
    
    //auto layout
    UIButton *button0 = [_buttons objectAtIndex:0];
    UIButton *button1 = [_buttons objectAtIndex:1];
    UIButton *button2 = [_buttons objectAtIndex:2];
    UIButton *button3 = [_buttons objectAtIndex:3];
    
    self.view.mas_key = @"self.view";
    button0.mas_key = @"button0";
    button1.mas_key = @"button1";
    button2.mas_key = @"button2";
    button3.mas_key = @"button3";
    
    [button0 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.equalTo(self.view.mas_left);
        make.bottom.equalTo(self.view.mas_bottom);
        make.right.equalTo(button1.mas_left);
    
        make.width.equalTo(button1.mas_width);
        make.height.equalTo([NSNumber numberWithFloat:buttonHeight]);
    }];
    
    [button1 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(self.view.mas_bottom);
        make.left.equalTo(button0.mas_right);
        make.right.equalTo(self.view.mas_centerX);
    
        make.width.equalTo(button0.mas_width);
        make.height.equalTo([NSNumber numberWithFloat:buttonHeight]);
    }];
    
    [button2 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(self.view.mas_bottom);
        make.left.equalTo(self.view.mas_centerX);
        make.right.equalTo(button3.mas_left);
    
        make.width.equalTo(button3.mas_width);
        make.height.equalTo([NSNumber numberWithFloat:buttonHeight]);
    }];
    
    [button3 mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(self.view.mas_bottom);
        make.left.equalTo(button2.mas_right);
        make.right.equalTo(self.view.mas_right);
    
        make.width.equalTo(button2.mas_width);
        make.height.equalTo([NSNumber numberWithFloat:buttonHeight]);
    }];
    

    }

    return self;
    }

Example for calculating a width or height

HI,
i've been using Masonry now for the past week and it's awesome.

But i have a question and perhaps you could add it to the examples. How do you do calculations in the equalTo function?

I want to do something like have a view which has a width the same as its superview but, the height should only be a third. Normally i would do CGRectGetWidth(superView.bounds) / 3, but how should i do it with Masonry?

[myView mas_makeConstraints:^(MASConstraintMaker *make) {
    make.center.equalTo(superView);
    make.width.equalTo(superView.mas_width);
    make.height.equalTo(superView.mas_width); //It needs to be a third of the width
}];

thx!

Ignoring titleEdgeInsets on UIButton

If I add titleEdgeInsets to UIButton whole width of a button stays the same as it would without inset and titleLabelText just doesn't display properly

Insufficient examples

I plan to use masonery to build forms. I try to follow the examples but found it not enough.

For example, if I try to recreate

https://stripe.com/docs/checkout

(click in pay with card), I need to:

  • Add several rows of controls
  • Align the control to the left & center
  • Put the labels on top of each control
  • Keep the separation between them, and build the relations

So far, I have only work by trial and error and mainly things work with exact values (defeating the use of a layout manager).

I'm sure I have not get the library (neither with https://github.com/iMartinKiss/KeepLayout) so some more complete examples could help

-[MASConstraint and] prevents compilation under Xcode 6 Beta 3

- (MASConstraint *)and;

When compiling my Swift project with this project included in my bridging header, I get a compilation error due to this line above. The error is as follows:

<unknown>:0: error:
    /path/to/Pods/Headers/Masonry/MASConstraint.h:113:
    expected selector for Objective-C method

When I comment out the line, compilation proceeds quite happily.

This is based off of head, latest commit being bec7297 (so this includes the fix from #84). Am I doing something wrong, or missing something?

Code that worked with 0.3.0 now throws runtime exceptions

My use case is pretty simple: call mas_makeConstraints: on some views. I do this in several places and everything worked perfectly with 0.3.0. As soon as I updated to 0.4.0, I started seeing these exceptions:

-[UILabel mas_makeConstraints:]: unrecognized selector sent to instance 0x14989a80                                                                                      
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UILabel mas_makeConstraints:]: unrecognized selector sent to instance 0x14989a80'

No code has changed. I am importing <Masonry/Masonry.h> and the project builds just fine. Were there breaking changes that weren't mentioned in the README?

MAS_ATTR_FORWARD(attribute) raises a warning if mismatched-return-types is enabled

If the flag -Wmismatched-return-types is set, the new property attribute from MASShorthandAdditions introduced in v0.5.0 will raise a warning when forwarding it to the non-shorthand equivalent.

This is the output from the compiler:

conflicting return type in implementation of 'attribute': 'MASViewAttribute *(^)(NSLayoutAttribute)' vs 'MASViewAttribute *' [-Wmismatched-return-types]
MAS_ATTR_FORWARD(attribute);

How to update the constraint when keyboard shows up.

I have been working on login module. I have created the login view like this.

[loginview mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(@(kLoginContainerYPosition));
make.centerX.equalTo(self.view.mas_centerX);
make.width.equalTo(@(kLoginContainerViewWidth));
make.height.equalTo(@(kLoginContainerViewHeight));
}];

When keyboard pops up I tried to update login view y position like below. But could not able update view position.

pragma mark -

pragma Keyboard Notification method

  • (void)keyboardWillBeShown {

    [loginCompanyViewController.view mas_updateConstraints:^(MASConstraintMaker *make) {

    CGFloat kContentPaddingForIPad = kLoginContainerYPosition - 100;
    make.centerY.equalTo(@(kContentPaddingForIPad));

    }];
    }

Can you please help me out.

iOS7: Calling -makeConstraints: order seems to matter

iOS7 Bug?

Maybe it is my misunderstanding about how AutoLayout or Masonry work, but it seems to me like the order of calling -makeContraints: in iOS7 is somehow order dependant.

Here is a very simple example:

Expected Result

A very simple view, with a yellow view on top and a blue view on bottom:
Expected Result (Gist)

screenshot 2013 11 25 10 29 00

[blueView makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(yellowView.bottom).offset(padding);
    make.bottom.equalTo(superview.bottom).offset(-padding);
    make.left.equalTo(superview.left).offset(padding);
    make.right.equalTo(superview.right).offset(-padding);
  }];

[yellowView makeConstraints:^(MASConstraintMaker *make) {
    make.top.greaterThanOrEqualTo(superview.top).offset(padding);
    make.left.equalTo(superview.left).offset(padding);
    make.right.equalTo(superview.right).offset(-padding);
    make.height.equalTo(@100);
}];

Possible Bug

All I do is switch the order -makeContraints: is called, calling yellowView first :
Possible Bug Result (Gist)

screenshot 2013 11 25 10 05 13

[yellowView makeConstraints:^(MASConstraintMaker *make) {
    make.top.greaterThanOrEqualTo(superview.top).offset(padding);
    make.left.equalTo(superview.left).offset(padding);
    make.right.equalTo(superview.right).offset(-padding);
    make.height.equalTo(@100);
}]

[blueView makeConstraints:^(MASConstraintMaker *make) {
    make.top.equalTo(yellowView.bottom).offset(padding);
    make.bottom.equalTo(superview.bottom).offset(-padding);
    make.left.equalTo(superview.left).offset(padding);
    make.right.equalTo(superview.right).offset(-padding);
}];

On iOS6 this seems to work fine.
So is this a bug or am I missing something?

Priority doesn't work

Hello, i've code like this

self.nameLabel.text = "super long long long long text";
[self.nameLabel makeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(self.contentView.left).offset(10);
    make.top.equalTo(self.contentView.top).offset(10);
    make.right.equalTo(self.contentView.right).offset(-10).priorityLow();
}];

As you can see it has the constraint make the the label all the way to right - 10px.
But when you add priority after offset it doesn't work, the label just overflow and ignore the right and offset.

In other words it's behaving the same like you don't specify any right constraint like code below

self.nameLabel.text = "super long long long long text";
[self.nameLabel makeConstraints:^(MASConstraintMaker *make) {
    make.left.equalTo(self.contentView.left).offset(10);
    make.top.equalTo(self.contentView.top).offset(10);
}];

Thank you

Using the animator proxy on OSX

I noticed you can't get to the animator proxy on OSX using Masonry. I was thinking of adding this feature, but before I do, do you have any idea on the best way to expose this?

This is a OSX only feature, and I don't want to sprinkle the code with #ifdefs, and also don't want to expose the underlying NSLayoutConstraint(s) on the MASConstraint protocol.

I thought about adding a delegate method, but that's far from elegant.

Maybe adding this to MASConstraint protocol:

#ifdef TARGET_OS_MAC && !TARGET_OS_IPHONE
@property (nonatomic, copy, readonly) id<MASConstraint> (^animated)(BOOL useAnimator);
#endif
- (void)update:(void (^)(id<MASConstraint>)block; 

After installing a constraint, updating it would be something like:

[self.heightConstraint update:^(id<MASConstraint> constraint){
    constraint.equalTo(@(100)).animated(YES);
}];

What do you think?

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.