Swiftpack.co - Package - freshOS/Stevia

Stevia

Documentation Language: Swift 2, 3, 4 and 5 Platform: iOS 8+ Carthage compatible CocoaPods compatible Swift Build Status codebeat badge License: MIT GitHub contributors GitHub tag

Drawing

Winner of Hacking with Swift Recommended award

You + Stevia = πŸ¦„

  • β˜‘ πŸ’‘ Write concise, readable layouts
  • β˜‘ πŸ– Reduce your maintenance time
  • β˜‘ 🎨 Compose your styles, CSS-like
  • β˜‘ πŸ”΄ Plug Live reload and boost your iteration cycles

Reason - Example - Live Reload - Installation - Documentation

πŸ–Ό Visual Layout Api

layout {
    100
    |-email-| ~ 80
    10%
    |-password-forgot-| ~ 80
    >=20
    |login| ~ 80
    0
}

β›“ Chainable Api

email.top(100).left(8).right(8).width(200).height(44)
alignHorizontally(password, forgot)
image.fillContainer()
button.centerInContainer().size(50%)
equalWidths(email, password)
image.width(>=80)

πŸ“ Equation-Based Api

email.Top == 100
password.CenterY == forgot.CenterY
login.Top >= password.Bottom + 20
login.Width == 75 % Width
(image.Height == 100).priority = UILayoutPriority(rawValue: 999)

All Generate native NSLayoutConstraints πŸŽ‰

πŸ‘¨β€πŸ”¬Try it!

Stevia is part of freshOS iOS toolset. Try it in an example App ! Download Starter Project

πŸ’‘ Reason

Because nothing holds more truth than pure code πŸ€“
Xibs and storyboards are heavy, hard to maintain, hard to merge.
They split the view concept into 2 separate files making debugging a nightmare
There must be a better way

How

By creating a tool that makes Auto layout code finally readable by a human being.
By coupling it with live code injection such as injectionForXcode we can design views in real time
View layout becomes fun, concise, maintainable and dare I say, beautiful ❀️

Login View Example

In the project folder, you can find an example of a typical login view laid out in both native and Stevia for you to understand and compare the two approaches.

As a spoiler alert, the number of characters goes from 2380 to 1239 ( ~ divided by 2)

Write Half the code that is actually 10X more expressive and maintainable !

πŸ”΄ Live Reload

Live reload enables you to develop your views live without relaunching the app everytime.

Stevia + InjectionForXcode = #WhoNeedsReactNative?? πŸš€

Just Cmd+S and you can dev live in the simulator !

Learn more about how to set up live reload here.

βš™οΈ Installation

Stevia is installed via the official Swift Package Manager.

Select Xcode>File> Swift Packages>Add Package Dependency...
and add https://github.com/freshOS/Stevia.

The Swift Package Manager (SPM) is now the official way to install stevia. The other package managers are now deprecated as of 4.8.0 and won't be supported in future versions.
For Carthage/Cocoapods support (legacy versions) see documentation here.

πŸ“– Documentation

The following will teach you the gist of Stevia in one minute.
To go further, you can refer to the full documentation here.

Stevia enables you to write readable Auto Layout code. It does so by tackling the 3 main components of layout: view hierarchy, layout and styling.

01 - View hierarchy

email.translatesAutoresizingMaskIntoConstraints = false
password.translatesAutoresizingMaskIntoConstraints = false
login.translatesAutoresizingMaskIntoConstraints = false
addSubview(email)
addSubview(password)
addSubview(login)

becomes

subviews {
    email
    password
    login
}

02 - Layout

email.topAnchor.constraint(equalTo: topAnchor, constant: 100).isActive = true
email.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
email.rightAnchor.constraint(equalTo: rightAnchor, constant: -8).isActive = true
email.heightAnchor.constraint(equalToConstant: 80).isActive = true

password.topAnchor.constraint(equalTo: email.bottomAnchor, constant: 8).isActive = true
password.leftAnchor.constraint(equalTo: leftAnchor, constant: 8).isActive = true
password.rightAnchor.constraint(equalTo: rightAnchor, constant: -8).isActive = true
password.heightAnchor.constraint(equalToConstant: 80).isActive = true

login.topAnchor.constraint(lessThanOrEqualTo: password.bottomAnchor, constant: 20).isActive = true
login.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
login.rightAnchor.constraint(equalTo: rightAnchor).isActive = true
login.heightAnchor.constraint(equalToConstant: 80).isActive = true
login.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0).isActive = true

becomes

layout {
    100
    |-email-| ~ 80
    8
    |-password-| ~ 80
    >=20
    |login| ~ 80
    0
}

03 - Styling

email.borderStyle = .roundedRect
email.autocorrectionType = .no
email.keyboardType = .emailAddress
email.font = UIFont(name: "HelveticaNeue-Light", size: 26)

becomes

email.style { f in
    f.borderStyle = .roundedRect
    f.autocorrectionType = .no
    f.keyboardType = .emailAddress
    f.font = UIFont(name: "HelveticaNeue-Light", size: 26)
    f.returnKeyType = .next
}

πŸ‘¨β€πŸ’» Contributors

YannickDot, S4cha, Damien, Snowcraft, Mathieu-o, Blaz Merela, Theophane Rupin, Jason Liang, liberty4me, Scott Bates, Sai, Mike Gallagher, WaterNotWords, Mick MacCallum, Onur Genes

πŸ‘₯ Backers

Like the project? Offer coffee or support us with a monthly donation and help us continue our activities :)

πŸ“² Apps using Stevia

Many top-notch Apps with millions of users use Stevia to write better Auto Layout code:

You are using Stevia ? Please let me know @sachadso@gmail.com and I'll add you to the list 😍!

πŸ… Sponsors

Become a sponsor and get your logo on our README on Github with a link to your site :)

Swift Version

Github

link
Stars: 2948

Dependencies

Used By

Total: 0

Releases

Fixes CGFloats in Layout blocks - 2020-04-20 07:59:27

Thanks @moliya for noticing CGFloat values were broken in layout blocks, this is now fixed πŸŽ‰

5.0.0 - Function builders, % api, CGFloat, api clean, UIStackViews ! - 2020-04-05 10:08:50

⚠️ A serious bug has been found in this release, please use 5.0.1 instead ⚠️

Bug found that can break your layouts -> https://github.com/freshOS/Stevia/pull/141

  • Adds support for CGFloat for all apis
  • % constraints can now be used in layout blocks for margins, height & spaces
  • sv() is renamed to subviews() for clarity
  • subviews() has now its function builder counterpart: subviews{} (no more commas!)
  • layout() has now its function builder counterpart: layout {}
  • fillVertically(m:) is renamed to fillVertically(padding:)
  • fillHorizontally(m:) is renamed to fillHorizontally(padding:)
  • fillContainer(x) is renamed to fillContainer(padding: x)
  • centerHorizontally(x) is renamed to centerHorizontally(offset: x)
  • Double dash -- operator is renamed in hyphen bullet for better compile times. (auto replace)
  • Adds UIStackView arrangedSubviews {} function builder

Swift Package Manager - 2020-01-06 09:22:00

Swift Package Manager is now the official way to install Stevia πŸŽ‰. In order to use other package managers, see previous versions. Onwards ! ✨

Xcode 11.2.1 & Swift 5.1.2 - 2019-12-10 17:59:43

  • Builds the pre-built framework with Xcode 11.2.1 & Swift 5.2.1

- 2019-11-13 09:48:48

  • Fixes the issue described in #123 where equation api had bugs when using >= & <= with single values. Props @jsonfellin for noticing, thanks @excursus for chiming in πŸ™

Before

view.Width >= 30 β‰  view.width(>=30)
view.Width >= 30 was equivalent to view.Width >= Width + 30 (Wrong)
view.Botton >= 100 was equivalent to view.Bottom >= Bottom + 100 (Wrong)
view.Right >= 100 was equivalent to view.Right >= Right + 100 (Wrong)

Now

view.Width >= 30 == view.width(>=30)
view.Height <= 100 == view.height(<=100)
view.Botton >= 100 == view.Bottom >= Bottom - 100
view.Right >= 100 == view.Right >= Right - 100
  • Big thanks @lukysnupy for his first contribution on improving our SPM integration πŸ‘

Right-to-left language support - 2019-11-04 12:01:55

⚠️ Warning, this release adds support for RTL languages which represents quite a big change. If you use this version, make sure to check you app for any layout issue and please report them :)

  • Visual format now supports right-to-left language meaning |-20-myview means myView is pinned to the right in a right-to-left language environment.
  • Adds leading trailing support in the chainable api.

Debug Tip

You can force RTL rendering by using view.semanticContentAttribute = .forceRightToLeft in your view.

4.6.1 - 2019-10-16 11:05:19

Xcode11 & Swift 5.1 - 2019-09-30 10:32:10

  • Builds framework with Xcode11 & Swift 5.1

Swift 5 ! - 2019-04-02 12:40:29

Updates to swift 5 πŸš€

fillContainer returns self - 2019-03-09 14:42:43

fillContainer now returns self to make it chainable (courtesy of @n13 )

4.4.3 - 2019-01-03 14:18:37

  • Fixes Equation api >= broken operator

4.4.2 - 2019-01-03 10:53:54

Fixes view.bottom/top/right/leftConstraint possibly returning wrong constraint if the one you want is not there yet. (looking for constraint in the view itself after looking for it in the superview) The fix makes sure it only looks for the constraint in the view itself for width and height constraints, that corresponds to constraints added via width/heightAnchors api.

4.4.1 - 2018-12-28 10:00:31

  • Make sure userAddedConstraints doesn't return layout margins. Fixes https://github.com/freshOS/Stevia/pull/104 Kudos @mpsnp πŸ‘
  • Code clean
  • Removing deprecated tap helper (discussion here https://github.com/freshOS/Stevia/issues/42) alternatives : https://github.com/XCEssentials/ViewEvents

Xcode 10 & Swift 4.2 - 2018-09-18 09:22:04

  • Migrates to Swift 4.2 πŸš€

Adds Support for baselines + bug fix - 2018-09-09 20:35:52

  • Adds support for baselines, kudos to @bellebethcooper for bringing this up πŸš€
align(lastBaselines: label, label2, label3)
label.FirstBaseline == label.LastBaseline
  • Fixes #90 Thanks @leidi0129 for spotting the issue πŸ‘

Adds centerXConstraint & centerYConstraint - 2018-09-09 11:00:38

This release adds centerXConstraint & centerYConstraint helpers.

Thanks to @Shadester for pointing this out πŸ‘

Xcode 9.3 & Swift 4.1 - 2018-04-04 21:07:30

Supports Xcode 9.3 & Swift 4.1 πŸŽ‰

"==" operator now supports different view hierarchies! - 2018-01-09 14:38:56

1 - Different view hierarchies

Before the == wasn't working if views weren't on the same Z-index in the view hierarchy. It was blind taking the first argument's superview. Now the == operator is smart enough to grab the closest common ancestor πŸ€“

2 - Reflexivity

The way it was before, the == operator wasn't reflexive. Meaning

view.Width == contentView.Width
contentView.Width == view.Width

were not generating the same constraint behind the hood. Mathematically speaking this was quite misleading.

Thanks to fix we can write interchageably :

avatar.Top == photo.Top + 10
photo.Top + 10 == avatar.Top

3- Re-opening Layout([array]) overload

Some needed it for dynamic layout so it's back :)

UILayoutSupport & UILayoutGuide πŸ“ - 2017-11-20 18:27:12

UILayoutSupport & UILayoutGuide are now supported in Equation base api !

It's time to clean the iPhone X support code :

button.bottomAnchor.constraint(equalTo: bottomLayoutGuide.topAnchor).isActive = true

into

button.Bottom == bottomLayoutGuide.Top

Happy coding πŸŽ‰

Swift4 and xcode9 - 2017-09-29 08:48:29

Migrates to swift 4 \o/

Sizeable Orphan views + getters - 2017-06-14 12:51:46

Kudos to @trupin and @cowgp for this release πŸŽ‰

  • Size constraints such as width and height can now be added without the need for a superview.
  • New leadingConstraint & trailingConstraint property

πŸ‘ πŸ‘

tvOS Support - 2017-06-14 09:08:42

Stevia is now supported on tvOS πŸŽ‰πŸ“Ί

Built with Xcode 8.3.1 - 2017-04-13 10:14:42

- 2017-01-27 13:12:26

Single Element Equations + less/Greater equations - 2017-01-23 17:40:02

Equations, Side Alignments & Percentage-based layouts - 2017-01-21 11:05:00

Equations Support

addConstraint(item: button,
                      attribute: .centerY,
                      toItem: avatar,
                      attribute: .bottom,
                      constant: -4)

Becomes

button.CenterY == avatar.Bottom - 4

Examples

label.Width == button.Width * 3
label.Height == (button.Width / 7) + 3
button.Left == image.Right - 20

Side Alignments

addConstraint(item: label, attribute: .top, toItem: avatar)

Becomes

alignTops(label, avatar)

Examples

alignTops(label, avatar, square)
alignBottoms(v1, v2, v3, v4)
alignLefts(button, image)
alignRights(v1, v2)

Percentage-Based Layout

addConstraint(item: label, attribute: .top, toItem: superview, attribute: .bottom, constant: 0.05)

Becomes

label.top(5%)

Examples

label.top(5%)
view.size(30%)
view.width(50%)
label.Top == 5 % Top

Prebuilt with Swift 3.0.2 - 2017-01-08 19:50:27

- 2016-09-26 10:44:35

Swift 3 support - 2016-09-17 10:26:54

Swift 3 support is here! Be aware this is the first version so make sure to check your layout thoroughly and report any issue that might pop.