From 347344ad67975e646bdcca06d6d5fca7ac5b09e8 Mon Sep 17 00:00:00 2001 From: Nikita Ermolenko Date: Mon, 25 Dec 2017 16:53:14 +0600 Subject: [PATCH 1/6] Implement an initial concept --- .../FramezillaExample/ViewController.swift | 46 ++++++++++++------- Sources/Maker.swift | 7 ++- Sources/UIView+Installer.swift | 19 ++++++++ 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/Example/FramezillaExample/ViewController.swift b/Example/FramezillaExample/ViewController.swift index 7d73554..3372515 100644 --- a/Example/FramezillaExample/ViewController.swift +++ b/Example/FramezillaExample/ViewController.swift @@ -14,6 +14,7 @@ class ViewController: UIViewController { let content1 = UIView() let content2 = UIView() let content3 = UIView() + let content4 = UIView() override func viewDidLoad() { super.viewDidLoad() @@ -23,31 +24,44 @@ class ViewController: UIViewController { content1.backgroundColor = .red content2.backgroundColor = .black content3.backgroundColor = .green + content4.backgroundColor = .gray - view.addSubview(content1) - view.addSubview(content2) - view.addSubview(content3) +// view.addSubview(content1) +// view.addSubview(content2) +// view.addSubview(content3) } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() - content3.configureFrame { maker in - maker.size(width: 50, height: 50) - maker.top(inset: 100) - maker.centerX(between: view.nui_left, view.nui_right) - } + let container = [content1, content2, content3, content4].container(in: view) { + content1.configureFrame { maker in + maker.centerX() + maker.top() + maker.size(width: 50, height: 50) + } + + content2.configureFrame { maker in + maker.top(to: content1.nui_bottom, inset: 5) + maker.left() + maker.size(width: 80, height: 80) + } + + content3.configureFrame { maker in + maker.top(to: content1.nui_bottom, inset: 15) + maker.left(to: content2.nui_right, inset: 5) + maker.size(width: 80, height: 80) + } - content1.configureFrame { maker in - maker.bottom(inset: 100) - maker.right().left() - maker.height(10) + content4.configureFrame { maker in + maker.top(to: content3.nui_bottom, inset: 5) + maker.right() + maker.size(width: 20, height: 20) + } } - content2.configureFrame { maker in - maker.size(width: 50, height: 50) - maker.centerX() - maker.centerY(between: content1.nui_bottom, view.nui_bottom) + container.configureFrame { maker in + maker.center() } } } diff --git a/Sources/Maker.swift b/Sources/Maker.swift index 334112c..080563e 100644 --- a/Sources/Maker.swift +++ b/Sources/Maker.swift @@ -374,7 +374,12 @@ public final class Maker { @discardableResult public func container() -> Maker { var frame = CGRect.zero for subview in view.subviews { - frame = frame.union(subview.frame) + let subviewFrame = subview.frame + let x = subviewFrame.origin.x < 0 ? 0 : subviewFrame.origin.x + let y = subviewFrame.origin.y < 0 ? 0 : subviewFrame.origin.y + + let positiveFrame = CGRect(origin: CGPoint(x: x, y: y), size: subviewFrame.size) + frame = frame.union(positiveFrame) } setHighPriorityValue(frame.width, for: .width) setHighPriorityValue(frame.height, for: .height) diff --git a/Sources/UIView+Installer.swift b/Sources/UIView+Installer.swift index 2c4d5c8..601a9d7 100644 --- a/Sources/UIView+Installer.swift +++ b/Sources/UIView+Installer.swift @@ -114,3 +114,22 @@ public extension Sequence where Iterator.Element: UIView { } } } + +public extension Sequence where Iterator.Element: UIView { + + public func container(in view: UIView, installerBlock: () -> Void) -> UIView { + let container = UIView() + container.backgroundColor = .yellow + + for view in self { + container.addSubview(view) + } + view.addSubview(container) + installerBlock() + container.configureFrame { maker in + maker.container() + } + installerBlock() + return container + } +} From 4c2c4d6727b34e7c8ad1c03a2f2a83a7f1892d1c Mon Sep 17 00:00:00 2001 From: Nikita Ermolenko Date: Tue, 26 Dec 2017 10:20:27 +0600 Subject: [PATCH 2/6] Add docs + fix container method in some cases --- Sources/Maker.swift | 30 ++++++++++++++++++++++++------ Sources/UIView+Installer.swift | 26 ++++++++++++++++++++++---- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/Sources/Maker.swift b/Sources/Maker.swift index 080563e..de7db86 100644 --- a/Sources/Maker.swift +++ b/Sources/Maker.swift @@ -369,18 +369,36 @@ public final class Maker { /// - note: Also important to understand, that it's not correct to call 'left' and 'right' relations together by subview, because /// `container` sets width relatively width of subview and here is some ambiguous. /// + /// - warning: Please make note that there is a more flexible container method: + /// + /// ``` + /// let container = [view1, view2].container(in: view) {} + /// ``` + /// /// - returns: `Maker` instance for chaining relations. - + @discardableResult public func container() -> Maker { var frame = CGRect.zero + + var minX: CGFloat = 0 + var minY: CGFloat = 0 + for subview in view.subviews { - let subviewFrame = subview.frame - let x = subviewFrame.origin.x < 0 ? 0 : subviewFrame.origin.x - let y = subviewFrame.origin.y < 0 ? 0 : subviewFrame.origin.y + if subview.frame.origin.x < minX { + minX = subview.frame.origin.x + } + if subview.frame.origin.y < minY { + minY = subview.frame.origin.y + } + } - let positiveFrame = CGRect(origin: CGPoint(x: x, y: y), size: subviewFrame.size) - frame = frame.union(positiveFrame) + for subview in view.subviews { + subview.frame.origin.x -= minX + subview.frame.origin.y -= minY + + frame = frame.union(subview.frame) } + setHighPriorityValue(frame.width, for: .width) setHighPriorityValue(frame.height, for: .height) return self diff --git a/Sources/UIView+Installer.swift b/Sources/UIView+Installer.swift index 601a9d7..7e0c9c1 100644 --- a/Sources/UIView+Installer.swift +++ b/Sources/UIView+Installer.swift @@ -115,16 +115,34 @@ public extension Sequence where Iterator.Element: UIView { } } -public extension Sequence where Iterator.Element: UIView { +public extension Collection where Iterator.Element: UIView, Self.Index == Int, Self.IndexDistance == Int { - public func container(in view: UIView, installerBlock: () -> Void) -> UIView { - let container = UIView() - container.backgroundColor = .yellow + /// Creates сontainer view and configures all subview within this container. + /// + /// Use this method when you want to set `width` and `height` by wrapping all subviews. + /// + /// - note: It atomatically adds all subviews to the container. Don't add subviews manually. + /// - note: Also important to understand, that it's not correct to call 'left' and 'right' relations together by subview, because + /// `container` sets width relatively width of subview and here is some ambiguous. + /// + /// - parameter view: The view where a container will be added. + /// - parameter installerBlock: The installer block within which you should configure frames for all subviews. + /// + /// - returns: Container view. + public func container(in view: UIView, installerBlock: () -> Void) -> UIView { + let container: UIView + if let superView = self.first?.superview { + container = superView + } + else { + container = UIView() + } for view in self { container.addSubview(view) } view.addSubview(container) + installerBlock() container.configureFrame { maker in maker.container() From c4232a270385a1d1ec9b35f08d4a77e88b4fa3f7 Mon Sep 17 00:00:00 2001 From: Nikita Ermolenko Date: Tue, 26 Dec 2017 10:38:55 +0600 Subject: [PATCH 3/6] Add tests for container configuration --- Framezilla.xcodeproj/project.pbxproj | 4 ++ Tests/ContainerInstallerTests.swift | 79 ++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 Tests/ContainerInstallerTests.swift diff --git a/Framezilla.xcodeproj/project.pbxproj b/Framezilla.xcodeproj/project.pbxproj index bb4482f..e25659b 100644 --- a/Framezilla.xcodeproj/project.pbxproj +++ b/Framezilla.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 11FB41471D844F8F00700A40 /* MakerHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11FB41421D844F8F00700A40 /* MakerHelper.swift */; }; 11FB41481D844F8F00700A40 /* UIView+Installer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11FB41431D844F8F00700A40 /* UIView+Installer.swift */; }; 11FB41491D844F8F00700A40 /* UIView+Relations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11FB41441D844F8F00700A40 /* UIView+Relations.swift */; }; + 841192DD1FF205DC00AB255D /* ContainerInstallerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841192DC1FF205DC00AB255D /* ContainerInstallerTests.swift */; }; 842BB7FC1F0638E9000D1CFF /* Parameters.swift in Sources */ = {isa = PBXBuildFile; fileRef = 842BB7FB1F0638E9000D1CFF /* Parameters.swift */; }; 8442F93E1EC75A8500B72551 /* BaseTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8442F9351EC75A8500B72551 /* BaseTest.swift */; }; 8442F9401EC75A8500B72551 /* MakerBothSideRelationsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8442F9381EC75A8500B72551 /* MakerBothSideRelationsTests.swift */; }; @@ -51,6 +52,7 @@ 11FB414A1D844FFA00700A40 /* Framezilla.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Framezilla.podspec; sourceTree = ""; }; 11FB414B1D844FFA00700A40 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 11FB414C1D844FFA00700A40 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; + 841192DC1FF205DC00AB255D /* ContainerInstallerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerInstallerTests.swift; sourceTree = ""; }; 842BB7FB1F0638E9000D1CFF /* Parameters.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Parameters.swift; sourceTree = ""; }; 8442F9351EC75A8500B72551 /* BaseTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseTest.swift; sourceTree = ""; }; 8442F9361EC75A8500B72551 /* FramezillaTests-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "FramezillaTests-Bridging-Header.h"; sourceTree = ""; }; @@ -138,6 +140,7 @@ 84EDCC231F9B3AB10091FAB9 /* MakerSafeAreaTests.swift */, 8442F93D1EC75A8500B72551 /* StateTests.swift */, 845108061EE2F5BC006DC1C8 /* ScrollViewTests.swift */, + 841192DC1FF205DC00AB255D /* ContainerInstallerTests.swift */, ); path = Tests; sourceTree = ""; @@ -273,6 +276,7 @@ files = ( 8442F9441EC75A8500B72551 /* MakerWidthHeightTests.swift in Sources */, 8442F9451EC75A8500B72551 /* StateTests.swift in Sources */, + 841192DD1FF205DC00AB255D /* ContainerInstallerTests.swift in Sources */, 8442F9411EC75A8500B72551 /* MakerCenterTests.swift in Sources */, 8442F9421EC75A8500B72551 /* MakerStackTests.swift in Sources */, 8442F9401EC75A8500B72551 /* MakerBothSideRelationsTests.swift in Sources */, diff --git a/Tests/ContainerInstallerTests.swift b/Tests/ContainerInstallerTests.swift new file mode 100644 index 0000000..cbbbcc0 --- /dev/null +++ b/Tests/ContainerInstallerTests.swift @@ -0,0 +1,79 @@ +// +// ContainerInstallerTests.swift +// FramezillaTests +// +// Created by Nikita Ermolenko on 26/12/2017. +// + +import XCTest + +class ContainerInstallerTests: BaseTest { + + func testContainerConfigurationFromTopToBottom() { + let content1 = UIView() + let content2 = UIView() + let content3 = UIView() + let content4 = UIView() + + _ = [content1, content2, content3, content4].container(in: mainView) { + content1.configureFrame { maker in + maker.centerX() + maker.top() + maker.size(width: 50, height: 50) + } + + content2.configureFrame { maker in + maker.top(to: content1.nui_bottom, inset: 5) + maker.left() + maker.size(width: 80, height: 80) + } + + content3.configureFrame { maker in + maker.top(to: content1.nui_bottom, inset: 15) + maker.left(to: content2.nui_right, inset: 5) + maker.size(width: 80, height: 80) + } + + content4.configureFrame { maker in + maker.top(to: content3.nui_bottom, inset: 5) + maker.right() + maker.size(width: 20, height: 20) + } + } + + XCTAssertEqual(content1.frame, CGRect(x: 70, y: 0, width: 50, height: 50)) + XCTAssertEqual(content2.frame, CGRect(x: 0, y: 55, width: 80, height: 80)) + XCTAssertEqual(content3.frame, CGRect(x: 85, y: 65, width: 80, height: 80)) + XCTAssertEqual(content4.frame, CGRect(x: 170, y: 150, width: 20, height: 20)) + } + + func testContainerConfigurationFromRightToLeft() { + let content1 = UIView() + let content2 = UIView() + let content3 = UIView() + + _ = [content1, content2, content3].container(in: mainView) { + content1.configureFrame { maker in + maker.right() + maker.centerY() + maker.size(width: 50, height: 50) + } + + content2.configureFrame { maker in + maker.right(to: content1.nui_left, inset: 5) + maker.centerY() + maker.size(width: 30, height: 140) + } + + content3.configureFrame { maker in + maker.right(to: content2.nui_left, inset: 15) + maker.centerY() + maker.size(width: 80, height: 80) + } + } + + XCTAssertEqual(content1.frame, CGRect(x: 130, y: 45, width: 50, height: 50)) + XCTAssertEqual(content2.frame, CGRect(x: 95, y: 0, width: 30, height: 140)) + XCTAssertEqual(content3.frame, CGRect(x: 0, y: 30, width: 80, height: 80)) + } +} From 138cf512dedc35f768be8ab10ff7484be737dbc6 Mon Sep 17 00:00:00 2001 From: Nikita Ermolenko Date: Tue, 26 Dec 2017 10:40:44 +0600 Subject: [PATCH 4/6] Some test examples --- .../FramezillaExample/ViewController.swift | 79 ++++++++++++++----- 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/Example/FramezillaExample/ViewController.swift b/Example/FramezillaExample/ViewController.swift index 3372515..2a5ba16 100644 --- a/Example/FramezillaExample/ViewController.swift +++ b/Example/FramezillaExample/ViewController.swift @@ -25,43 +25,84 @@ class ViewController: UIViewController { content2.backgroundColor = .black content3.backgroundColor = .green content4.backgroundColor = .gray - -// view.addSubview(content1) -// view.addSubview(content2) -// view.addSubview(content3) } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() - let container = [content1, content2, content3, content4].container(in: view) { +// let container = [content1, content2, content3, content4].container(in: view) { +// content1.configureFrame { maker in +// maker.centerX() +// maker.top() +// maker.size(width: 50, height: 50) +// } +// +// content2.configureFrame { maker in +// maker.top(to: content1.nui_bottom, inset: 5) +// maker.left() +// maker.size(width: 80, height: 80) +// } +// +// content3.configureFrame { maker in +// maker.top(to: content1.nui_bottom, inset: 15) +// maker.left(to: content2.nui_right, inset: 5) +// maker.size(width: 80, height: 80) +// } +// +// content4.configureFrame { maker in +// maker.top(to: content3.nui_bottom, inset: 5) +// maker.right() +// maker.size(width: 20, height: 20) +// } +// } + + + + let container = [content1, content2, content3].container(in: view) { content1.configureFrame { maker in - maker.centerX() - maker.top() + maker.right() + maker.centerY() maker.size(width: 50, height: 50) } content2.configureFrame { maker in - maker.top(to: content1.nui_bottom, inset: 5) - maker.left() - maker.size(width: 80, height: 80) + maker.right(to: content1.nui_left, inset: 5) + maker.centerY() + maker.size(width: 30, height: 140) } content3.configureFrame { maker in - maker.top(to: content1.nui_bottom, inset: 15) - maker.left(to: content2.nui_right, inset: 5) + maker.right(to: content2.nui_left, inset: 15) + maker.centerY() maker.size(width: 80, height: 80) } - - content4.configureFrame { maker in - maker.top(to: content3.nui_bottom, inset: 5) - maker.right() - maker.size(width: 20, height: 20) - } } + +// let container = [content1, content2, content3].container(in: view) { +// content1.configureFrame { maker in +// maker.bottom() +// maker.centerX() +// maker.size(width: 50, height: 50) +// } +// +// content2.configureFrame { maker in +// maker.bottom(to: content1.nui_top, inset: 5) +// maker.centerX() +// maker.size(width: 30, height: 140) +// } +// +// content3.configureFrame { maker in +// maker.left() +// maker.bottom(to: content2.nui_top, inset: 15) +// maker.size(width: 10, height: 10) +// } +// } + + container.backgroundColor = .yellow container.configureFrame { maker in - maker.center() + maker.centerX() + maker.top() } } } From 653f6b781f59f6924e3df2ef66e360a86a5b9204 Mon Sep 17 00:00:00 2001 From: Nikita Ermolenko Date: Tue, 26 Dec 2017 11:21:30 +0600 Subject: [PATCH 5/6] Update README --- README.md | 181 +++++++++++++++++++++++++--------------------- img/container.png | Bin 8705 -> 8664 bytes 2 files changed, 99 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 192d57a..40c2843 100644 --- a/README.md +++ b/README.md @@ -80,24 +80,27 @@ There're a few methods for working with view's size. You can configure ```width``` and ```height``` separately: ```swift - view.configureFrame { maker in - maker.width(200).and.height(200) - } +view.configureFrame { maker in + maker.width(200).and.height(200) +} ``` + or together with the same result: + ```swift - view.configureFrame { maker in - maker.size(width: 200, height: 200) - } +view.configureFrame { maker in + maker.size(width: 200, height: 200) +} ``` Also in some cases you want to equate the sides of two views with some multiplier. For example: + ```swift - view.configureFrame { maker in - maker.width(to: view1.nui_height, multiplier: 0.5) - maker.height(to: view1.nui_width) // x1 multiplier - default - } +view.configureFrame { maker in + maker.width(to: view1.nui_height, multiplier: 0.5) + maker.height(to: view1.nui_width) // x1 multiplier - default +} ``` ## Edges @@ -109,17 +112,17 @@ Framezilla has two method for comfortable creating edge-relation. Either you can create edge relation so ```swift - view.configureFrame { maker in - maker.edges(insets: UIEdgeInsetsMake(5, 5, 5, 5)) // UIEdgeInsets.zero - default - } +view.configureFrame { maker in + maker.edges(insets: UIEdgeInsetsMake(5, 5, 5, 5)) // UIEdgeInsets.zero - default +} ``` or ```swift - view.configureFrame { maker in - maker.edges(top: 5, left: 5, bottom: 5, right: 5) - } +view.configureFrame { maker in + maker.edges(top: 5, left: 5, bottom: 5, right: 5) +} ``` the second method has optional parameters, so ```maker.edges(top: 5, left: 5, bottom: 5)``` also works correct, but does not create ```right``` relation, that in some cases is very useful. @@ -128,10 +131,10 @@ the second method has optional parameters, so ```maker.edges(top: 5, left: 5, bo You can create edge relation, as shown above, but only use side relations. ```swift - view.configureFrame { maker in - maker.top(inset: 5).and.bottom(inset: 5) - maker.left(inset: 5).and.right(inset: 5) - } +view.configureFrame { maker in + maker.top(inset: 5).and.bottom(inset: 5) + maker.left(inset: 5).and.right(inset: 5) +} ``` Also possible to create relations with another view, not a superview: @@ -139,12 +142,12 @@ Also possible to create relations with another view, not a superview: ![](img/bottomLeftRelation.png) ```swift - // Red view - view.configureFrame { maker in - maker.size(width: 30, height: 30) - maker.left(to: self.view1.nui_right, inset: 5) - maker.bottom(to: self.view1.nui_centerY) - } +// Red view +view.configureFrame { maker in + maker.size(width: 30, height: 30) + maker.left(to: self.view1.nui_right, inset: 5) + maker.bottom(to: self.view1.nui_centerY) +} ``` In iOS 11 Apple has introduced the safe area, similar to `topLayoutGuide` and `bottomLayoutGuide`. Framezilla supports this new api as well: @@ -167,10 +170,10 @@ content.configureFrame { maker in If you just want to center subview relative superview with constant `width` and `height`, this approach specially for you: ```swift - view.configureFrame { maker in - maker.centerY().and.centerX() - maker.size(width: 100, height: 100) - } +view.configureFrame { maker in + maker.centerY().and.centerX() + maker.size(width: 100, height: 100) +} ``` Also possible to set manually centerX and centerY. Just call ```setCenterX``` and ```setCenterY```. @@ -182,11 +185,11 @@ What if you want to join the center point of the view with the top right point o ![](img/centered.png) ```swift - view.configureFrame { maker in - maker.centerX(to: self.view1.nui_right, offset: 0) - maker.centerY(to: self.view1.nui_top) //Zero offset - default - maker.size(width: 50, height: 50) - } +view.configureFrame { maker in + maker.centerX(to: self.view1.nui_right, offset: 0) + maker.centerY(to: self.view1.nui_top) //Zero offset - default + maker.size(width: 50, height: 50) +} ``` ## SizeToFit and SizeThatFits @@ -198,10 +201,10 @@ Very often you should configure labels, so there are some methods for comfortabl ![](img/sizeToFit.png) ```swift - label.configureFrame { maker in - maker.sizeToFit() // Configure width and height by text length no limits - maker.centerX().and.centerY() - } +label.configureFrame { maker in + maker.sizeToFit() // Configure width and height by text length no limits + maker.centerX().and.centerY() +} ``` #### SizeThatFits @@ -211,10 +214,10 @@ But what if you have to specify edges for label? ![](img/sizeThatFits.png) ```swift - label.configureFrame { maker in - maker.sizeThatFits(size: CGSize(width: 200, height: 100)) - maker.centerX().and.centerY() - } +label.configureFrame { maker in + maker.sizeThatFits(size: CGSize(width: 200, height: 100)) + maker.centerX().and.centerY() +} ``` ## Container @@ -223,29 +226,43 @@ Use this method when you want to set `width` and `height` by wrapping all subvie ### NOTE: -**First, you should configure all subviews and then call this method for `container view`.** +**It atomatically adds all subviews to the container. Don't add subviews manually.** **Also important to understand, that it's not correct to call 'left' and 'right' relations together by subview, because `container` sets width relatively width of subview and here is some ambiguous.** ![](img/container.png) ```swift - label1.configureFrame { maker in - maker.sizeToFit() +let container = [content1, content2, content3, content4].container(in: view) { + content1.configureFrame { maker in + maker.centerX() maker.top() - maker.left(inset: 5) + maker.size(width: 50, height: 50) } - - label2.configureFrame { maker in - maker.sizeToFit() - maker.top(to: label1.nui_bottom, inset: 5) - maker.left(inset: 5) + + content2.configureFrame { maker in + maker.top(to: content1.nui_bottom, inset: 5) + maker.left() + maker.size(width: 80, height: 80) } - - view1.configureFrame { maker in - maker.centerY().centerX() - maker.container() + + content3.configureFrame { maker in + maker.top(to: content1.nui_bottom, inset: 15) + maker.left(to: content2.nui_right, inset: 5) + maker.size(width: 80, height: 80) } + + content4.configureFrame { maker in + maker.top(to: content3.nui_bottom, inset: 5) + maker.right() + maker.size(width: 20, height: 20) + } +} + +// width and height are already configured +container.configureFrame { maker in + maker.center() +} ``` ## Cool things: @@ -253,9 +270,9 @@ Use this method when you want to set `width` and `height` by wrapping all subvie Sometimes you want to configure a few views with the same size, for examlple. There is a convinience method: ```swift - [view1, view2].configureFrames { maker in - maker.size(width: 200, height: 100) - } +[view1, view2].configureFrames { maker in + maker.size(width: 200, height: 100) +} ``` ## Stack @@ -265,7 +282,7 @@ Framezilla allows you configure views like stack behaviour. Important to point o ![](img/stack.png) ```swift - [view3, view2, view1].stack(axis: .horizontal, spacing: 3) +[view3, view2, view1].stack(axis: .horizontal, spacing: 3) ``` ## States @@ -275,40 +292,40 @@ It's very convenient use many states for animations, because you can just config ![demo](img/animating.gif) ```swift - override func viewDidLayoutSubviews() { - - super.viewDidLayoutSubviews() - - // state `DEFAULT_STATE` - view1.configureFrame { maker in - maker.centerX().and.centerY() - maker.width(50).and.height(50) - } - - view1.configureFrame(state: 1) { maker in - maker.centerX().and.centerY() - maker.width(100).and.height(100) - } +override func viewDidLayoutSubviews() { + + super.viewDidLayoutSubviews() + + // state `DEFAULT_STATE` + view1.configureFrame { maker in + maker.centerX().and.centerY() + maker.width(50).and.height(50) + } + + view1.configureFrame(state: 1) { maker in + maker.centerX().and.centerY() + maker.width(100).and.height(100) } +} ``` set new state and animate it: ```swift /* Next time when viewDidLayoutSubviews will be called, `view1` will configure frame for state 1. */ - view1.nx_state = 1 // Any hashable value - view.setNeedsLayout() - UIView.animate(withDuration: 1.0) { - self.view.layoutIfNeeded() - } +view1.nx_state = 1 // Any hashable value +view.setNeedsLayout() +UIView.animate(withDuration: 1.0) { + self.view.layoutIfNeeded() +} ``` Also possible to apply many states in a row: ```swift - view1.configureFrame(states: [3, "state"]) { maker in - maker.size(width: 200, height: 100) - } +view1.configureFrame(states: [3, "state"]) { maker in + maker.size(width: 200, height: 100) +} ``` # Author :muscle: diff --git a/img/container.png b/img/container.png index db0bb8d7fe68f112f8baded94af115e802ceee83..fbfc3b023e73d67514c20b0c9caa88a06213b87d 100644 GIT binary patch literal 8664 zcmeHsWmH_vmUiRNKnN1tU4lazZ6GvGkl+M&Z=i8W1A!0-?h@P~!GgOJ+}$B~aQET8 z_s*Snt@$^Kikze*wTd&;!rIOp0MHJK_e2wzURim%@i`1%SoR+IllG_iN^!FWw4_OZ z(Z|{+OA`bM&5wU6C#RWBz|yEr`m6s;;^IMcWgGsGu`f8|3f^{Y9=U58+4sG?Ye865 zp$__t+EE2SMhT9!$8z;Z`=;;VbOb-I!7Wy#)!N+ea5i{sLe@8I1`E3Z^CgT8Uq zLUXR;P1m!m+UIed!mtM4V1)BEUlhRuoIK)56a_{4epeFE zr`}>lm&%?|+rv)X<$_7KnAO{UNSJ`0FLRukv0d{>n0^_~Rr&PeX@X9Xh=jKd3!u0u zH_j`?#T0Nuhxn%&ZiaPYH*Anb?}*63?rLFcLskq86IqS!`kl7lkKLmhDia@9_Q%Ut#y`7Bl3@hs zz`G4h`O#E6qn|mE?@upyYp&Trm{--j^VVPIk0j=|+Cq)sWn4@@#e77X&(GbjGx3@N z4&Y~yGz{#SiklyXgrrs%AE>5&zp|=h*p_ir*3Lc1sKH$OWwLOBf_*Q?s44uAO(NO( z|s`fJ6n)u*e z-Fv1N<_1k)apI)fU_bJJ$}BD zQb;gqugGDZ`%?*Y z{OGZ7;S8sv`9%=ao_r~4)T%Ng5-L#k##z_Q9 z*pV0yo^wypF9h+dv&h%Tf^@~OX!DPURLNYGICJU0u7lE;_+XOwsce;b8Nk5(j38U;2(of999BKwVm zB8fYS%Zw`@JS@JQrJ%y#f^XwTDXyIPap%?fir{oI&_^vNNRM zOMI8xI`Ih;KTJN8{tDHr6ILXdEn#b^W>|w_Ojlx#;EG3YN(>0 z7nnz!N1ZpGml8r1(h*WN6bPd}GC&pSUj$H!tuML^X@#rX{R z%=7uhXBO$#Ip{guIbxreSLV!h&;6LondK~Z zFCT$%ITt#4IOaMnt`n~X3U&+H3*f*KoZVm?&Q35A=OE{_4V&$hZHukx^~>$yHHWSA z4dd0Z)sv0BHS4vTwt=paA+leoBX?2m{*kdGUpNDf@C%o=`&YsXL8@3cL%+_W0BP)JC2 zN;aC50tBtQ+=SHx!9>c$cfGtWyROW`-=hrqbr$^^lPdjKE9OrHSFPjH82!!|^_cmX z=opQdquivt!CbuDy_uT)oBMu_PccAh81_C@~Z(bSspJV1WP>7Z?9aeo7wJAJFg6AJpH;8pf*0O2Qhc z!Cfp=ETfUCuI0vd@M6W+_KJvKt{PBXV)N4*a_MovvcQ`)T&DECH5XjkUb2?&q-v@c zs~nrFlYL{LAU>d0qGv1pL2<$GF6Gjaf`p=SSU=5tX{n*2;fEKqsAMx=Go`PWulK{* zttsj~Di~D*74viG=V0s);at-B(mK+eJ$ldUA-)Hbv7fPm5$9czqW!y()D{pvh%S{s zrE`mMYi``&B+ybAN0&BFLEQxYZK)7rLd`-uD2WICyIZ_;Y8YS8S;<~ine zXU*rEYlx~N%b~DLCr8&p7j3smn8=2}A^ict{`q9`(%eY>GRpS)>ifgWIxRT#aG6C* zYQ}6P%a``<#esKahA({e@ea-EMbwK$x6V4j27T8LOgb_0vR@B-4ucLcDH|v)MZsP+ zo?9Nno<-hiCn+bISKtlN{hY(t1K#bD-PCR2qk?_+<)f0;Xn4hwv!8ieyx)*`Z(9nr zPt*q$NiJVU@#D^yhf$I=4_SCweOVi5?o@-Kb>eRr5`!g-?>hE6Nup)k+ykw;PQJKD zlSZRNi{+4KJ5Xf{6ZjMg>xu~RdolJxV^rgJv+NMG#-*#@ zOu~v<$3-R@#?8mi#%Fj%cp8-Y(+9=sJ^Sy}mGj?k1x?IOv=;HY6!4FY?eX z($n#bKeMrTrT0pe-+kypcg3}N|6(d;D$yp%b{y(Qh6@5Ox-<&944i8&*vBtSxd$E+ zESuM*YGO`F&u~oMOoz`1&s>3$_^SAe`InoST#w}O4b|Fx^Y4;}2!`Z_QrWrLzy8Sj zafahVsaQo}<-K$`3BDe^HC7I`?%j|`5>IPusy`?6Z62&92J zdDR5jKnr}9Tr*e3N5MsrSyVGyv0`JstoN^PZ-$9}a4umgVX7JS8G>5PeJt-jZU%Qm z)<~6fSL9{pRc}^h*om=es%r{qQD|9CXHPrr-;kM*g|{lgo9D3R7qJ+kv)&MemdAWQ1;_JE%`Y8YzMRtFTjW!#cCcw3>)vPC^(OxI<~xX#*IyB3 z2y5tpornEMySeJodccke3f+DA+he?F{-$W4u^F>;;BNW_00hKKZOjd>DF~lIfO1mB zl>Jztgf9b_jYP^Bc1#>izCa77Bwq1AiNSvqu2mo~Gb#1Uth${x;_c2JnMu?5jkt*7 z9$PBjcaDnZ@<6eVB7)lxo&JN#>8iu?tgu=pOC{g_dp9p`+ucEvOOs(6%G=j!kEO8B z+oHe-!Yv{VLo1e#UQWm3vV9)AdUKJ^ldtlDC-P|}r5dU;&ZR5Ghh;Zjv4;uw_6x$s z?#eTo)BMw7R#s5EX7{q)!-tfu{)F-AY_xiN>jN3eTlZP;`#rM*Jx`Ix+}i!IiOWN@ zkrXc*ud}<3TUWF%NFy0USYE9vj5y#6VL$yFJ8$^FU8{7XEhyu5htDZME-OBtKqAjDo^^Hc=Tn`t& zKnc*u7RyI;1A2B(x_v9>YEwxY7|i<-C6laNO#TJ`*OriwUZJ(glNe-NAg=sJR+4oG z8(UJGd4UF#TZ_+vjJg)D2=Q!z3lx{!O7a|@hs`1FU+B&U+Y6; z6wHnqSmxOI**+y~#xBquWxp&%)GBUA+7APINF}2uG(&hf$ZJR;fm=;@!`Ia%GsTbC}zyYYl8{p=8&le8e0+>91Ey zmiy+4Bl5*aqe0MeurIl<`F-L2*25hlDH7W!U;wWq-rGJj{XSh|5o6mmPTEo#Mwxo5 z@yLV_T#-T7K=uTdh)d?no%i>5rurBld{}ID#F4@q!K_4+1bKPkgpYz7V|^8B8N5Ww zoR;kAH|fn$XDsgEqqDh;ZL5(ILS&)@q6@tw=JZAZ*IoO*lJUpN-o(^_)KV7>pN4*| z>LcB?3oZUI&})Z$>Vlbm{UY6whJagt=|Rz;e59*LP+~1#^&7FedAA19OJjAJ`<%hy z?A|#GU;gIFmww1R4jLJL$&h3$xs$9Fq|M|Uhcu${!wpwY75(CC#MIE4L{ zorGiJ^~z(>)7ft5K!3qhi)(Rs^ubLc0Eb3xhv839M>fwG-j0DHmL{oiaAVjNgDk!# za|83&qUlHkK9%t9i z*Ssh(D0D%x9k;Yiv|>_?-J#u`^kHr%avd?S_nqUB=A`Cj{hI^5Y;`Qftj6(P@i2{V z>T~Lb2ORIu7U>EiG^i#Drv@iar=}-xr}L(eyjCtOu|8uRk!+H9C!;5arEaC_q-+c> zu;a0Z|Iq#c)&?z@E!@r*&EX&Pl9vioI`KGJIDg!KUjag{f6}^KTA_lA&tM--E3>-b z9M5jZZ3?ctcHd=2hK@8qzZy2RY68%$utf-S$--V7q6<H`*R@Yh-~T}XwJQ?`?W%)-Xc$Q$|{hES#o$^u2yJ~1W5ToHvI zas#qV=FH!^(#Qo}>39!Z#1qy?Zh0dsuPjEkyMEhj?|yqH7%Y~d$)(ffCQ+(=k-f*z zjko)LjHhM5Zqr4JnH4>r@0a}h)-AUO$i+pw^Kzrf8hDL;>2&fO1+yqXOV6 z{uJQNcT|gaqDM~U?3dDln7|^@x;^?R6#V+ zN`&m0qO!tr+ln&^P;q#ML{L_O6UbCJ7JC92hK!lO5UG(=ojw#`pCB3}nP3|5Gif00 zL%;(B3}BJ-wTKCYea0)$hx5NAZH(iH+`}?&+N1yz&BkIPtr2uZ+x* z!;xW@&TKUkp`JyLCYw?IbaW_5H2BU$GQznBhv7GUGKHZ~bZi6L54z5M0=2D$@0N2p z^{F>a+Zvcd9OQMx`py-0zeCM7yKQ->TPrQxM5am|H3v})k7+h=qjK? z{CPTItH1zp@?VJNnF!|rEaeE?lH*Yrzp)wKGK?bah=zTZGU83b$_QRq<78HfW7$J5 zM&%E&kXgu_7^5IY&xsHWs}I)cwK2i3P1U0<@lZm}kp)n1)FrDjS$7=;QcY5>U4dP@49AUJ zF&->7)?Oq+I!%8<7r)<^zfD|6%0uhdXD!ocEmA#-R;`^rp1_)+wY}RD*d^U7+G8Uw zBqk-L;ELd_H=DPvF={t1g1+)wv=*$fJa9gMk#h*u2>80HE|MMH+KFBHJJuSwBj7+s z^vW8SMZvKxwvU4dr~Ymd(e2xkx{_j1IvrRYbabVV2=eUkH<5iJ_dJ>c9G5#?+!>Jh z+|u921a^BNE-upjED?j3-vjLm^p<|wY)=9wL)E`_b7Uz{#!Dr@^y&?F4Z2 zkA8GFR=UcNroS2E+pmsU=%*TX-4m&wVqZ|31qmIS9`BD14unL{fy9>I9x*c#7a&`P zZJln#x90kC8otom)ltxeu3VqkntMMQn_W#HI8bBo`SBm4R#4+C0+v>hAb#}JurFAf zl0Qb#l1QdMb*?#kAWH@FNHb*Vs*+jpyI?ioHb;#0H$oTpA(wzSe$3}sba^0aT(AMl38rw6>4Bp0JL!Mw zN4NRfu6$;EgGp-vKF&EX?jp6&PDy`o> z>MsPoIRKS848fCXn-(uG5L9;oek2Qv_Z(P&LoC4ayLqZDLux8no^1IEs^4^5+LLe1 z5veW!xZ;q-ancYCe|kDKWKtQ`swKYc1OO1ytktz$wBIQTnL_P3jLo1X<{TdOj?X_B z000pWq35o>xr;HihrOKxOvpo&_8%TX&;7sDoV3*caB;B}rPY3?LM;h(HmBz2;N#$; z1p}$6sYRU4EQH=er2hqfmPBc-TwEN5I62+j-8tNOIiSv#oZNzff}C7DoIE`2&mQbB zPX`xc4|WF_-9JhGlLulBGj+Chbg_myQ2)hiYyx$45v8U5E6~4>e~#1K!}`A>Il%sv z)^mcKe_1%WIk-6g&HW4&`AaLLV(npWrwy^TH+O(N#{l#2af$rH|G!!OE8^dfI)6j* zg8q*Do8@0f5zfC7_*+8%tkyrY&*cIGML7RmdN43nMbrrZK&zI6NT_=t94tzNQuN}X zjLt|?vv+vMi=Mr0M!zUz7m1J#q7G<^mg!Wl=UHED5aD`!I@s9GNEAaxhXC(!1*@|# zUS1oD`}?9J2cQrL2#Dn1s~D{S{EZM$Uc4CDK_-|5iBoHf`+w@>6+%F{#D0lRsIt0x z9H#UPLHb__Ssg%bzuUK8PpK1b;V|}m`jSIMa=l+d)x&u#8^=L2N|)ItTDmN61QGX_ zNz#9tDI@Oht=Ami_Qek|lB+RLJkk&Gs?Lke9~S|I(%22dpArG((CI=Gkq!|k((wlm zQ4|rlxUu&GSsIzZBXEuZ*$bJVu6ODKMi@HtG5Svh^mBA($H8+~f&G{^ORhN~m?_t^d$CHj$ z$Bm`Im_!8rpZWjCvK*V6^ixsc*VcV%^F{pVe>AYz^YwWvP)*XTR~G-Dh|A!QkGsp; z4;RzEL09+!N~`-N&AObeZN1$N)QBU`cSLKxIFCb# q*_}%K5LZ%~nzf#{(f`NAdo&zzN+l9LTl>GBr{tuRAf<1O0{#O8TQu6MQ(utMOqv#P@q_GE?V4*LveTa;;_8Q ze%frZ$xbqJl5-|cp7}7z@0>Z=FgXCCrJ;z4Mur9gfiRVo~-MSeY_Z@n4 zgosp4yMY?VOh=a&SAq&%GXho960u{1BOT$};%NWv3@<4;LP+~n3xGe|9QlupJY@qX z4=XSAJ`$jTHZ>|P!ZdiAc(%3Z0N5lHYU3!38=5GsfE+nEv;{*%x`UIuJhZqjrJj%7 z%Q=sm?Ra^yU>x}}W(x;GqNV5`wJo9zB1?B;r?LQnoclCg>O+OP#cu{a@-8~inJrUtE-J_gqjajq2oi&x9`}po+sHayD}j}w0bX*vCudje z)a0Z?6P49d6L6vY80(NVmprIOaJf|f2kmrpaI1*7_GN7GydyP@HA^y@iFZ&r=oH6R zK8Hpx_v;Cpy}PN@+B=`Q+6M;_?;q{?mVcn2-N`qfQ$(PewY-=2y0 z&VEmWjg!a1JUOLxzTe1TYj1?iou5!`hzgmu=DzhL1YhVx5Z!BD@3c#2|B;@V zVT{0ic|0P%fQ{|Y!J39T>|f z%XbLj4n<`MW7k4-mO|e{uql*uvBb^_Lpg&Bqrs2^B2q(c`;hSqTj=d^eVszB6zcptRXk!*p)E#aR+bb;|6##Nv%Pcxob zg1fYZ{HiQAw0}a9n;;IY57j2x$`Z;A`91@DhgTE%f#rkjgLw(!i@W>OYrS0^XhdEv zBuJJSXBNxRchW6rBlatJj`j!}|^}?jwQp=RDb8^oV$KpIl|$tmEWodq#7seWz2wzmCD`;kM=l zyzr~T=j2)yf>a)*=#u!A8wxG)qU)0Mq(!BhrO6nAX@?Ur2i>=}ZD~J>-J!xF9%CNE zWb*fPvRHTs;OxYT!n`9dvM!9nS*_?g6D?I;6HC52CN;608+@fHrQfH6>F_Gnm|mo8 zQ4aF3gr`)dWD@8)x9O!$8<)bBzH#~q)TR68`DXZ5Uuo}WPFC4^@;38Q@w%o5rAP1@ z+D4Ty|0J4;AA-97pn{qgU=3T_UE7k@4A#ik^xJ`L`?qbk*thAn{toC5nkC{77Hs)# zlU|fwFkZafe%S8d)G^ztVGfySkXMgA;mpv}GVnBrF=WEooB=n{H z$gyv-&#|xF;p2c3nXyTisg>!v0H!8pixy&rE!q#&Sklpz$%VCw#i|ZEhMGb;{$=iE zCv4(K;!);b%nMd@gFm+?heU-`JO?9`!!6VFTINbu(YiX?eYZ8T3+P7`tP$KGIp#Ys zi8FR>`QFm>;XIUQey&$|xM?C_TyCXjjA5*BX6qR5n2|^I1Lywxi|*+meqiP*aUY+L zl#jahUG0b3o1Lf~_Dj~w2O8xx5-==(bpxB7#+dv`aRkw*6# zs``lrNPTGoY2NT;#9r?ec>{@w;UZ?ku3N{P@#32!jfE#C57%64VETDRr>*E*6`O<7 zd)(Jjl)@87WRk*$67V7r0i1++vYoTdgW{aA_c$w|Td|H%0g zjfb;hY;H#p-8ZR8Aq^sAoW;`;ctAqIlH4#lHG@kL*D#9 zgz0YZ#td7&=+}`ZpCXLE80#D78Y-4c)GGvH`m6glSp91_0+J}kvbtR+T#Q}Bd<49O zwy`RGjQuUe>m=NRcabYF@5rNs0^Q12<(5)v_8Z?#wNADsWYP;Y?w0L%{Gndhs4uFP zf`(df|C$ML8PVL!6_&hqt(|M|UrdnsuwFqo1-*cJ^p7$a%$XDZ`)Cseu>$Y0uXO_G&=RV*>qFyQ%A|z&WzOv z#qYwe0^*H~B)^w;n{W$u2p;{=u-KR@;^2KU z@G<^UpLmNi#gxJPPls?Y%kHEcN|nu#_r`YqsD8F)rJNZI5V&<76IgW-ssx*NOm0v5 z?MHRT1D8U_?m2Dp9W#N8_a9Un^>5Nw%R|JbY?i0I`*$=1^x-ORGQ-Rw*;4UXX(?m7rU%uE`ZQ&o3SlN zGxwgv+!NhZZ!+!Q@k~kHms`QCm#-H!L2|)`z&bwV7P#jLk#+Sw)lPn6($Y6ggzlA-cKdH{n4phjw$lt~__&^iS>A?K@E=k7dQfGuw8(c>`*dgaZ_f5N0Yx0K-M>MUcZyl*J+>fXRi2#?XbMmYm0+#-R0)w4z3J z(?mm=$e!4QSfO-%nI+N;p=j$`IMUi*j_-jgaR2^Edd__MJmrTEKSMg^j}Iy@%L4VU z&Gp+Hm_;3namP`APm=(Si2U$a@EIh&n&YTjw0RI|f28XRb?mgQuq$q9DEG(8R9baQa&( zP8#xyT)5_Un{|sddCCRRfN+b96ibjFFmbw{;|Fb{Y6VS2-R`6^Y`7ZJeS4QoY%@{einWI(r~nU z_3cIxA56OprM-TvqLY?Ytu)qr2@8*(lXe%xx$%zuNdeK`swIaWo*Vj-a0iDKJ07cB zEf3#RUk1qY8CLnm!tb4vOWPN1epV81b6EiXPeW;#-#W9SU*^rKBG}7bz#&g!?R@$z z|1?Bg{(ib&+guA&$v6pG-cEBU1?IiAQp=?3-w`|CsT5;A+Btb?JbSWqe*oW3c#_>{ z3Ld@7$U*j-n?-(pw-n-(n_5NwbDmU-QC0M#W)7Z)Vb_lX>o{t!66UZmOmZ?3UVd-D zKHyN@vKu*Xo#pkd2#l(c_=JIyn}2>;D7f5V!um+tx-42X3E85a7)69v1x9-o{5gW| z-*8_bqoe1th1m>8b`K<{xK7Z8n4qR?HfAc2ml)3e9_#QF+;`5~8C;p|b=QOBdWgRkxy>71u;>UaCsynBZY6^`UpG5yFCJvvP% zQ+ay?*rU)>E#v zblT^x1}SB(Cx|lA!lF73rKJAz36v}oWzo8wQ$;5q9h{wDHX}l`|oNZ@+ynu{sigYxO$@^UDXTDD&;0!8)WcL<&U(&WRW8g5n zJa-_h7`s5-To7umIM@Nh7-eFEq-51bZ}|vBtGUC6k3L~YmmH7&wOt%GgtlhjWo`tH zu@QD*EDFRN<2)%Q!iq%_;mTG%bgJPO0IajFg;tD@r2~J{ORN_0u`Z9H(m7O*1@?CU zC}+DT{m#>Z$eP0SD9u{?Uh;)R0dqdT01_6Ft%={qmYM&2BMRhc(?>gT_G_dnpKK-& zw3}kZ}8wF~}0pc`d_Enh!DSI%onzc~cCQ2gFg62GMa{pVA)iDCDVg-8Tx! zA|)>ni9{jTlfa0)b6ut?)L>Wl;zN|~Gpp%N{W^Q~4rSz92R2{Wz&c!b&E6Crv4Z)G zPx{^{B^K?In)z1vho$0lC#ZS0rR(z@w5u;(jh-fgLS^Bkc~P!@GeQPY?j2ec-xrb` zu%Mty3V$L=c=z;rbF+`bTn|ltv#(u2?WJwTLl}9I2T-Xa+*LH5*STI_S6*t;2**0= zDOW(=t|wft?fI0(b@|tH68|}mA`-Q$gwqUqbj9X593AIC4n`FNTPt-T5d~WW$^8#5@Nz1TP*Jhuf#@DMT|~;$cx<|9{QLB0!8*a`h^@cpfFb53J4gxnFCbVzWvR?IPv=JGvFpL$wc z0I>^mw}qVr?`QvyKOE0ywyJp@v6)bl^KOh~F&0Ix6G)5By0PgfX;;U4>k|Aic5&mC z@doUVJ}Bc!s*bHywDkqDqRg307t;q}mL=`Pym zq_+8c?cqR9zV|>_1NT3#ESA$mA((Q;0Tk|DyQEFOlFPkdwL=X!rPIPHq6U=%MOTp< zGvpkt&B7N)I@->HBKfRfR64lk#IEq1HuaP@j=dF&?06AA8~$_GDXffh33gRh%f+MR zx|?$D=4qLO7~4UA>3LoMQF15I}HM7k3L&T&(7!WN({2Tv)O5F2-GUOYtlK(3uuqKlD~?yy9yg!urWwTvX#vn z^sG*?Q+kor$ZA?vH!lX-aw(U_NccWK;PY6XtSrZXQ5f}3!f$iEdboq%14quYCHYDi z8YJmEFTeZJ%ocpc5SWsb=osE&u-0~SyZ>z)LRWeTOqe94+7WAkp|#H8wIB`##~W5X zcj)d-bi+t|V#Iom#XvP;};h z)?j(hzuRsyg(W^4>0hMT04o>h-bKtaUyWxwZfYH{&%Oz}u|#9F_+qKR)>f(Yt((fD z!;(e1vOhABhvp%Pz_>hb0=n%3BDy}U3}4W0{X5=_nkq$R(tr=V{(;KlZHa*-Ur&L6 zE$M81$7^?L6Jx|X@TOZdFwTl^)0>{%_?uFjhUD_Pm#Cj0jXx^qDX@P$Ep69yi-*v0 zcGMv}uZ2&{W|2H-ux4)}@Hv|tzhx>@`+$g%jr3iEhyP^kwc&|Mmg0oVK)suT<)d5< z`ptypUdzJ^67i=^*y>HoB#7%S&uwvUb=eC4BXf&rd zNxfn^nbconTV(i1PW4IX%#|py z;`M)kYM{5jaAC4uxpT-(cCsS7`ri}&r7tSxZsYPb->7LhPLtf8CF3=G zEEzDGSUs{6-yPHae*USZ0uv^?y~S)QfI}jEeUGU`ut10b??jKBj*F%3H;ntN;|29l zObLciuD!V7KiIJ{@ibi?k55c+;|^J{o47xIrc7-%=q1~m>?Ja2ldoq^ZKG7<*9BBV ztea%(J|c=tU~%%v4nUTjA(@WZq?kUrIwbzzY)+d_38%AWW6`=x+U?HE(8k_zprtrf zIw#1x$XU-Yr4&5pqP@C^(nH(-^00wEil?072&u;9nVYDh)(@>I=UE*-IQ7R+u)h79>b#Hq%fz{Ct}9!6$<0n`-*IH@4wi@Is7Hyc^=w51UOPWSZd6+W zp7O%G(ieBcQK!LG5#(k+l=c<)j0*J%*_e-IKZ>;}#YrzBOtFrOb0!M*8{CmJ+&0+b zRZ#vck7SCe!nmAVWLm4Mo2~cC>c}d&k?X2x84^hn2mGPcx9av(v7>(b0MH1t- zuYJO|T|V6={i-fBAJAPT1i)_dnyxxbMOry1Y&uclTQcy;ys3a*ozQZc;sXkaZj z-H-VMz7}czlvycSOrIO7EKF(qHmyI?HbvfkwFEa6b$8xnG(Tio5MaQlUJ`MMirk+n z;A_v%I%$t3E5009t#&Q_m7@X?@(K=l2RYi0!;D{X5Gp62>LpcmBbA0zH z<2U*+qyoYtWZZC`nA6rX>9D@7Z{)}PbKf43=ZIdG?dKeJ4gJ-=%bJnUc_U{k8lL94C;=sV2fJW?`ehA?_#BNYOGfj%)pPzA{yieH*$e?YVT@xByWrl(y z-;p{nM;s*4D$xAjZWAe&o#eTb=po%p3~tDpjzWZkSxBSWO;v%ks##o zjZ$X=;57`Qd9Tzddq#8dEn$^MLUHTV#9J?bgWpP6}FLGApwxku)XS z{{@+8KtdKI01Q05e)Hk4dy98<5)9k;UI*oGF|U5y{S38c$f(20jh0G!8%2L~0~8P_ zr}5D#v_dt%<2+V01=ibiHyMmP`s2?#B-YAV?;iIOdpqTZVF*B~7K@e!3QA^p2FJ2XqAnp4*U47<3^E|lg8yv#wBJx z`ahR}E=i>Abeb4^IlqpK^K~88I-}JVJin|+ml@P^hh*8z*ARbG85EvB!h4(MqLTVK zCjp;M8~|p4Qf^Ps$WjQxQb@6t2@}VO0`gRZ>y_!}E7umM+Agva+5ub_D^qz}7KP!0 zr@(WXOkZo#c_DzZHRUsM#F0Sjzvf<9!1R*uDGC#l!bhzxasT7nB8v{`d`*vxL&h*H zQnaN`Oks7@$k-R{bkZE)Z_V)!B>f5^`K*djK!65}zUt#aTl`ZNLwbEX_?j#Q*7)_h z-Kc?q{ttqC$jzi=dX;JhgW%}D6Qp+Qe(*ly1-U5|B;N~nRe_vw%e>QP%(xSSpMKCR zLYFMy^4W`;!@Xuyn$Co!cuvD*at_kymsx|2QCZwO!b*U}?`%646wx6;3*4xtd*w6% zB3BwOniOFLG8ptxK1Y}Th&2ZvuJj%MmVXMSyZ#N=pZKv`*ILfm~s5Ad}l ztzRjeCTBHAd+&jF2E>R*^mTJDObVM*JekpJvA+)QwAeHC4OvNF=Xnef8DDh&*Az2O zzNw;?64l!K1(~}&?}t$4dp|tXELG*tNl<=9h-<8V3OsHF5u2Q^T@4Xjo7&LAk6FSS z`aA&AnGo~Of#Y?cSJSZX*ZcHJ9cT2=C*#;xt|@m5H1m>tEj`9K0)OdV>BA+{+;A!3 sm7OH%7IN$VLn!~P^Z%6*{J(S_B|#f@V47H`MbPU~me-K0l(7u|FUXxkasU7T From 414c7b377593848631d1ab6fce9a0b95c0123d58 Mon Sep 17 00:00:00 2001 From: Nikita Ermolenko Date: Tue, 26 Dec 2017 11:26:55 +0600 Subject: [PATCH 6/6] Change the podspec version -> 2.6.0 --- Framezilla.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Framezilla.podspec b/Framezilla.podspec index d75a0fa..80b8f47 100644 --- a/Framezilla.podspec +++ b/Framezilla.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = "Framezilla" - spec.version = "2.5.0" + spec.version = "2.6.0" spec.summary = "Comfortable syntax for working with frames." spec.homepage = "https://github.com/Otbivnoe/Framezilla"