Skip to content

MisterFusion is Swift DSL for AutoLayout. It is the extremely clear, but concise syntax, in addition, can be used in both Swift and Objective-C. And support Size Class.

License

Notifications You must be signed in to change notification settings

kotalab/MisterFusion

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

30 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MisterFusion

Platform Language Version Carthage compatible License

ManiacDev.com referred.
https://maniacdev.com/2015/12/open-source-auto-layout-library-with-a-simple-and-concise-syntax

MisterFusion makes more easier to use AutoLayout in Swift & Objective-C code.

Features

  • Simple And Concise Syntax
  • Use in Swift and Objective-C
  • Support Size Class
  • Support Swift3 (If you want to use it in Swift3, please use 2.0.0-beta)

MisterFusion Code for Swift

let view = UIView()
self.view.addLayoutSubview(view, andConstraints:
    view.Top    |+| 10,
    view.Right  |-| 10,
    view.Left   |+| 10,
    view.Bottom |-| 10
)

Ordinary Code for Swift

This is same implementation as above code, but this is hard to see.

let view = UIView()
self.view.addSubview(view)
view.translatesAutoresizingMaskIntoConstraints = false
self.view.addConstraints([
    NSLayoutConstraint(item: view, attribute: .Top,    relatedBy: .Equal, toItem: self.view, attribute: .Top,    multiplier: 1, constant:  10),
    NSLayoutConstraint(item: view, attribute: .Right,  relatedBy: .Equal, toItem: self.view, attribute: .Right,  multiplier: 1, constant: -10),
    NSLayoutConstraint(item: view, attribute: .Left,   relatedBy: .Equal, toItem: self.view, attribute: .Left,   multiplier: 1, constant:  10),
    NSLayoutConstraint(item: view, attribute: .Bottom, relatedBy: .Equal, toItem: self.view, attribute: .Bottom, multiplier: 1, constant: -10),
])

MisterFusion Code for Objective-C

UIView *view = [UIView new];
[self.view addLayoutSubview:view andConstraints:@[
    view.Top   .Constant(10.0f),
    view.Right .Constant(-10.0f),
    view.Left  .Constant(10.0f),
    view.Bottom.Constant(-10.0f)
]];

Ordinary Code for Objective-C

This is same implementation as above code, but this is hard to see.

UIView *view = [UIView new];
view.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview: view];
[self.view addConstraints:@[
    [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop    relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop    multiplier:1.0f constant:10.0f],
    [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeRight  relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight  multiplier:1.0f constant:-10.0f],
    [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeft   relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft   multiplier:1.0f constant:10.0f],
    [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeHeight multiplier:0.5f constant:-15.0f]
]];

Sample Layout

If you want to realize layout like a above image, needed code is only this.

let redView = UIView()
redView.backgroundColor = .redColor()
self.view.addLayoutSubview(redView, andConstraints:
    redView.Top   |+| 10,
    redView.Right |-| 10,
    redView.Left  |+| 10
)

let yellowView = UIView()
yellowView.backgroundColor = .yellowColor()
self.view.addLayoutSubview(yellowView, andConstraints:
    yellowView.Top    |==| redView.Bottom |+| 10,
    yellowView.Left   |+|  10,
    yellowView.Bottom |-|  10,
    yellowView.Height |==| redView.Height
)

let greenView = UIView()
greenView.backgroundColor = .greenColor()
self.view.addLayoutSubview(greenView, andConstraints:
    greenView.Top    |==| redView.Bottom    |+| 10,
    greenView.Left   |==| yellowView.Right  |+| 10,
    greenView.Bottom |-|  10,
    greenView.Right  |-|  10,
    greenView.Width  |==| yellowView.Width,
    greenView.Height |==| yellowView.Height
)

Installation

CocoaPods

MisterFusion is available through CocoaPods. If you have cocoapods 0.39.0 or greater, you can install it, simply add the following line to your Podfile:

pod "MisterFusion"

In addtion, import MisterFusion like this.

Swift
import MisterFusion
Objective-C
#import <MisterFusion/MisterFusion-Swift.h>

Carthage

If you’re using Carthage, simply add MisterFusion to your Cartfile:

github "szk-atmosphere/MisterFusion"

Make sure to add MisterFusion.framework to "Linked Frameworks and Libraries" and "copy-frameworks" Build Phases.

Advanced Setting

You can set multiplier, constant and priority like this. (This is same implementation as first example.)

Swift

self.view.addLayoutSubview(view, andConstraints:
    view.Top    |==| self.view.Top    |*| 1 |+| 10 |<>| UILayoutPriorityRequired,
    view.Right  |==| self.view.Right  |*| 1 |-| 10 |<>| UILayoutPriorityRequired,
    view.Left   |==| self.view.Left   |*| 1 |+| 10 |<>| UILayoutPriorityRequired,
    view.Bottom |==| self.view.Bottom |*| 1 |-| 10 |<>| UILayoutPriorityRequired
)

Objective-C

[self.view addLayoutSubview:view andConstraints:@[
    view.Top   .Equal(self.view.Top)   .Multiplier(1.0f).Constant(10.0f) .Priority(UILayoutPriorityRequired),
    view.Right .Equal(self.view.Right) .Multiplier(1.0f).Constant(-10.0f).Priority(UILayoutPriorityRequired),
    view.Left  .Equal(self.view.Left)  .Multiplier(1.0f).Constant(10.0f) .Priority(UILayoutPriorityRequired),
    view.Bottom.Equal(self.view.Bottom).Multiplier(1.0f).Constant(-10.0f).Priority(UILayoutPriorityRequired)
]];

For Swift

Operators

  • |==|, |<=|, |>=| ... NSLayoutRelation and fixed Height and Width
  • |*|, |/| ... multiplier
  • |+|, |-| ... constant
  • |<>| ... UILayoutPriority
  • |=| ... For fixed Height and Width (deprecated since 1.1.0, use |==|)
  • <|> ... UIUserInterfaceSizeClass for VerticalSizeClass
  • <-> ... UIUserInterfaceSizeClass for VerticalSizeClass
  • -=- ... Identifier

UIView Extensions

public func addLayoutConstraint(misterFusion: MisterFusion) -> NSLayoutConstraint?
public func addLayoutConstraints(misterFusions: MisterFusion...) -> [NSLayoutConstraint]
public func addLayoutConstraints(misterFusions: [MisterFusion]) -> [NSLayoutConstraint]
public func addLayoutSubview(subview: UIView, andConstraint misterFusion: MisterFusion) -> NSLayoutConstraint?
public func addLayoutSubview(subview: UIView, andConstraints misterFusions: [MisterFusion]) -> [NSLayoutConstraint]
public func addLayoutSubview(subview: UIView, andConstraints misterFusions: MisterFusion...) -> [NSLayoutConstraint]
public func insertLayoutSubview(subview: UIView, atIndex index: Int, andConstraint misterFusion: MisterFusion) -> NSLayoutConstraint?
public func insertLayoutSubview(subview: UIView, atIndex index: Int, andConstraints misterFusions: [MisterFusion]) -> [NSLayoutConstraint]
public func insertLayoutSubview(subview: UIView, atIndex index: Int, andConstraints misterFusions: MisterFusion...) -> [NSLayoutConstraint]
public func insertLayoutSubview(subview: UIView, belowSubview siblingSubview: UIView, andConstraint misterFusion: MisterFusion) -> NSLayoutConstraint?
public func insertLayoutSubview(subview: UIView, belowSubview siblingSubview: UIView, andConstraints misterFusions: [MisterFusion]) -> [NSLayoutConstraint]
public func insertLayoutSubview(subview: UIView, belowSubview siblingSubview: UIView, andConstraints misterFusions: MisterFusion...) -> [NSLayoutConstraint]
public func insertLayoutSubview(subview: UIView, aboveSubview siblingSubview: UIView, andConstraint misterFusion: MisterFusion) -> NSLayoutConstraint?
public func insertLayoutSubview(subview: UIView, aboveSubview siblingSubview: UIView, andConstraints misterFusions: [MisterFusion]) -> [NSLayoutConstraint]
public func insertLayoutSubview(subview: UIView, aboveSubview siblingSubview: UIView, andConstraints misterFusions: MisterFusion...) -> [NSLayoutConstraint]

Array Extensions

public func firstItem(view: UIView) -> [NSLayoutConstraint]    
public func firstAttribute(attribute: NSLayoutAttribute) -> [NSLayoutConstraint]   
public func relation(relation: NSLayoutRelation) -> [NSLayoutConstraint]  
public func secondItem(view: UIView) -> [NSLayoutConstraint]    
public func secondAttribute(attribute: NSLayoutAttribute) -> [NSLayoutConstraint]

You can get added NSLayoutConstraint with those functions. This is a example.

let bottomConstraint: NSLayoutConstraint = self.view.addLayoutSubview(view, andConstraints:
    view.Top    |+| 10,
    view.Right  |-| 10,
    view.Left   |+| 10,
    view.Bottom |-| 10
).firstAttribute(.Bottom).first

You can use Size Class with func traitCollectionDidChange(previousTraitCollection: UITraitCollection?).

This is an example Regular, Compact size for iPhone6s+.

override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
    guard let whiteView = whiteView, redView = redView else { return }
    if let whiteViewHeightConstraint = whiteViewWidthConstraint {
        redView.removeConstraint(whiteViewHeightConstraint)
    }
    self.whiteViewWidthConstraint = redView.addLayoutConstraints(
        whiteView.Width |-| 20 <|> .Compact <-> .Regular,
        whiteView.Width |*| 0.5 |-| 10 <|> .Regular <-> .Compact
    ).firstAttribute(.Width).first
}
  • A detail sample is here

For Objective-C

Readonly Blocks

@interface MisterFusion : NSObject
//NSLayoutRelation
@property (nonatomic, readonly, copy) MisterFusion * __nullable (^ __nonnull Equal)(MisterFusion * __nonnull);
@property (nonatomic, readonly, copy) MisterFusion * __nullable (^ __nonnull LessThanOrEqual)(MisterFusion * __nonnull);
@property (nonatomic, readonly, copy) MisterFusion * __nullable (^ __nonnull GreaterThanOrEqual)(MisterFusion * __nonnull);
//multiplier
@property (nonatomic, readonly, copy) MisterFusion * __nullable (^ __nonnull Multiplier)(CGFloat);
//constant
@property (nonatomic, readonly, copy) MisterFusion * __nullable (^ __nonnull Constant)(CGFloat);
@property (nonatomic, readonly, copy) MisterFusion * __nullable (^ __nonnull NotRelatedEqualConstant)(CGFloat);
@property (nonatomic, readonly, copy) MisterFusion * __nullable (^ __nonnull NotRelatedLessThanOrEqualConstant)(CGFloat);
@property (nonatomic, readonly, copy) MisterFusion * __nullable (^ __nonnull NotRelatedGreaterThanOrEqualConstant)(CGFloat);
//@property (nonatomic, readonly, copy) MisterFusion * __nullable (^ __nonnull NotRelatedConstant)(CGFloat); (deprecated since 1.1.0, use NotRelatedEqualConstant)
//UILayoutPriority
@property (nonatomic, readonly, copy) MisterFusion * __nullable (^ __nonnull Priority)(UILayoutPriority);
//UIUserInterfaceSizeClass for HorizontalSizeClass
@property (nonatomic, readonly, copy) MisterFusion * __nullable (^ __nonnull HorizontalSizeClass)(UIUserInterfaceSizeClass);
//UIUserInterfaceSizeClass for VerticalSizeClass
@property (nonatomic, readonly, copy) MisterFusion * __nullable (^ __nonnull VerticalSizeClass)(UIUserInterfaceSizeClass);
//Identifier
@property (nonatomic, readonly, copy) MisterFusion * _Nullable (^ _Nonnull Identifier)(NSString * _Nonnull);
@end

UIView Category

- (NSLayoutConstraint * _Nullable)addLayoutConstraint:(MisterFusion * _Nonnull)misterFusion;
- (NSArray<NSLayoutConstraint *> * _Nonnull)addLayoutConstraints:(NSArray<MisterFusion *> * _Nonnull)misterFusions;
- (NSLayoutConstraint * _Nullable)addLayoutSubview:(UIView * _Nonnull)subview andConstraint:(MisterFusion * _Nonnull)misterFusion;
- (NSArray<NSLayoutConstraint *> * _Nonnull)addLayoutSubview:(UIView * _Nonnull)subview andConstraints:(NSArray<MisterFusion *> * _Nonnull)misterFusions;
- (NSLayoutConstraint * _Nullable)insertLayoutSubview:(UIView * _Nonnull)subview atIndex:(NSInteger)index andConstraint:(MisterFusion * _Nonnull)misterFusion;
- (NSArray<NSLayoutConstraint *> * _Nonnull)insertLayoutSubview:(UIView * _Nonnull)subview atIndex:(NSInteger)index andConstraints:(NSArray<MisterFusion *> * _Nonnull)misterFusions;
- (NSLayoutConstraint * _Nullable)insertLayoutSubview:(UIView * _Nonnull)subview belowSubview:(UIView * _Nonnull)siblingSubview andConstraint:(MisterFusion * _Nonnull)misterFusion;
- (NSArray<NSLayoutConstraint *> * _Nonnull)insertLayoutSubview:(UIView * _Nonnull)subview belowSubview:(UIView * _Nonnull)siblingSubview andConstraints:(NSArray<MisterFusion *> * _Nonnull)misterFusions;
- (NSLayoutConstraint * _Nullable)insertLayoutSubview:(UIView * _Nonnull)subview aboveSubview:(UIView * _Nonnull)siblingSubview andConstraint:(MisterFusion * _Nonnull)misterFusion;
- (NSArray<NSLayoutConstraint *> * _Nonnull)insertLayoutSubview:(UIView * _Nonnull)subview aboveSubview:(UIView * _Nonnull)siblingSubview andConstraints:(NSArray<MisterFusion *> * _Nonnull)misterFusions;

NSArray Category

@property (nonatomic, readonly, copy) NSArray * __nonnull (^ __nonnull FirstItem)(UIView * __nonnull);
@property (nonatomic, readonly, copy) NSArray * __nonnull (^ __nonnull FirstAttribute)(NSLayoutAttribute);
@property (nonatomic, readonly, copy) NSArray * __nonnull (^ __nonnull SecondItem)(UIView * __nonnull);
@property (nonatomic, readonly, copy) NSArray * __nonnull (^ __nonnull SecondAttribute)(NSLayoutAttribute);
@property (nonatomic, readonly, copy) NSArray * __nonnull (^ __nonnull Reration)(NSLayoutRelation);

You can get added NSLayoutConstraint with those properties. This is a example.

NSLayoutConstraint *bottomConstraint = [self.view addLayoutSubview:view andConstraints:@[
    view.Top   .Constant(10.0f),
    view.Right .Constant(-10.0f),
    view.Left  .Constant(10.0f),
    view.Bottom.Constant(-10.0f)
]].FirstAttribute(NSLayoutAttributeBottom).firstObject;

You can use Size Class with - (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection.

This is an example Regular, Compact size for iPhone6s+.

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
    [self.redView removeConstraint:self.whiteViewWidthConstraint];
    self.whiteViewWidthConstraint = [self.redView addLayoutConstraints:@[
        self.whiteView.Width.Multiplier(0.5f).Constant(-10).VerticalSizeClass(UIUserInterfaceSizeClassRegular).HorizontalSizeClass(UIUserInterfaceSizeClassCompact),
        self.whiteView.Width.Constant(-20).VerticalSizeClass(UIUserInterfaceSizeClassCompact).HorizontalSizeClass(UIUserInterfaceSizeClassRegular)
    ]].FirstAttribute(NSLayoutAttributeWidth).firstObject;
}
  • A detail sample is here

Requirements

  • Xcode 7.0 or greater
  • iOS 8.0 or greater

Author

Taiki Suzuki, s1180183@gmail.com

License

MisterFusion is available under the MIT license. See the LICENSE file for more info.

About

MisterFusion is Swift DSL for AutoLayout. It is the extremely clear, but concise syntax, in addition, can be used in both Swift and Objective-C. And support Size Class.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Swift 69.0%
  • Shell 17.4%
  • Objective-C 11.0%
  • Ruby 2.6%