Skip to content

Commit 9d33040

Browse files
author
Luc Dion
authored
Merge pull request #43 from mirego/multi_view
Relative positioning methods can now receives one or many relative views
2 parents 27f5518 + dfbc9a9 commit 9d33040

25 files changed

+980
-285
lines changed

CHANGELOG.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<p align="center">
2+
<img src="docs/pinlayout-logo-small.png" alt="PinLayout Performance" width=100/>
3+
</p>
4+
5+
<h1 align="center" style="color: #376C9D; font-family: Arial Black, Gadget, sans-serif; font-size: 1.5em">PinLayout</h1>
6+
7+
8+
# Change Log
9+
10+
## [1.0.14](https://github.com/mirego/PinLayout/releases/tag/1.0.14)
11+
Released on 2017-06-12.
12+
13+
#### Change
14+
15+
* Implementation of **relative positioning using multiple relative views**
16+
* Added by [Luc Dion](https://github.com/lucmirego) in Pull Request [#43](https://github.com/mirego/PinLayout/pull/43)
17+
* The following methods can now receives one or many relative views. Useful to position a view relative to many UIViews.
18+
* `above(of relativeViews: UIView...) `
19+
* `above(of relativeViews: UIView..., aligned: HorizontalAlignment) `
20+
* `below(of relativeViews: UIView...)`
21+
* `below(of relativeViews: UIView..., aligned: HorizontalAlignment)`
22+
* `left(of relativeViews: UIView...) `
23+
* `left(of relativeViews: UIView..., aligned: VerticalAlignment)`
24+
* `right(of relativeViews: UIView...) `
25+
* `right(of relativeViews: UIView..., aligned: VerticalAlignment)`
26+
27+
<br>
28+
29+
## [1.0.11](https://github.com/mirego/PinLayout/releases/tag/1.0.11)
30+
Released on 2017-06-08.
31+
32+
#### Change
33+
34+
* Add **Swift Package Manager** support
35+
* Added by [Luc Dion](https://github.com/lucmirego) in Pull Request [#38](https://github.com/mirego/PinLayout/pull/38
36+
* **`size(…)` methods** now tries to apply the width and the height individually
37+
Previously the size specified was applied only if both the width and height wasn’t specified. Now PinLayout will apply them individually, so if the width has been specified yet, the size’s width will be applied, else a warning will be displayed that indicate that the width won’t be applied. Same thing for the height.
38+
* Doesn’t display a warning anymore if the new specified width or height value is equal to the currently set value. This is coherent with other methods (top, left, hCenter, ….)
39+
* Clean up `size(...)` methods source code
40+
* Add PinLayout's performance documentation
41+
* Add 52 more unit tests. Code coverage is now 95.38%.
42+
43+
### Fixes
44+
- Fix an issue with pin.vCenter() and pin.hCenter()
45+
- Fixed by [Luc Dion](https://github.com/lucmirego) in Pull Request
46+
[#36](https://github.com/mirego/PinLayout/pull/36).
47+
48+
<br>
49+
50+
## [1.0.7](https://github.com/mirego/PinLayout/releases/tag/1.0.7)
51+
Released on 2017-06-06.
52+
53+
### Fixes
54+
- Fix an issue with pin.vCenter() and pin.hCenter()
55+
- Fixed by [Luc Dion](https://github.com/lucmirego) in Pull Request
56+
[#36](https://github.com/mirego/PinLayout/pull/36).

Example/PinLayoutSample.xcodeproj/project.pbxproj

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
2439CC531E665C6B003326FB /* MultiRelativeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2439CC401E665C6B003326FB /* MultiRelativeViewController.swift */; };
1717
2439CC541E665C6B003326FB /* RelativeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2439CC411E665C6B003326FB /* RelativeView.swift */; };
1818
2439CC551E665C6B003326FB /* RelativeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2439CC421E665C6B003326FB /* RelativeViewController.swift */; };
19+
249326891EEEEE3D00BCB814 /* Stylesheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 249326881EEEEE3D00BCB814 /* Stylesheet.swift */; };
20+
2493268C1EEEEFF100BCB814 /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2493268B1EEEEFF100BCB814 /* BaseViewController.swift */; };
21+
2493268E1EEEF02700BCB814 /* BaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2493268D1EEEF02700BCB814 /* BaseView.swift */; };
1922
249EFE431E64FAFE00165E39 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 249EFE421E64FAFE00165E39 /* AppDelegate.swift */; };
2023
249EFE4A1E64FAFE00165E39 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 249EFE491E64FAFE00165E39 /* Assets.xcassets */; };
2124
249EFE4D1E64FAFE00165E39 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 249EFE4B1E64FAFE00165E39 /* LaunchScreen.storyboard */; };
@@ -74,6 +77,9 @@
7477
2439CC401E665C6B003326FB /* MultiRelativeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiRelativeViewController.swift; sourceTree = "<group>"; };
7578
2439CC411E665C6B003326FB /* RelativeView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RelativeView.swift; sourceTree = "<group>"; };
7679
2439CC421E665C6B003326FB /* RelativeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RelativeViewController.swift; sourceTree = "<group>"; };
80+
249326881EEEEE3D00BCB814 /* Stylesheet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Stylesheet.swift; sourceTree = "<group>"; };
81+
2493268B1EEEEFF100BCB814 /* BaseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = "<group>"; };
82+
2493268D1EEEF02700BCB814 /* BaseView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseView.swift; sourceTree = "<group>"; };
7783
249EFE3F1E64FAFE00165E39 /* PinLayoutSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PinLayoutSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
7884
249EFE421E64FAFE00165E39 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7985
249EFE491E64FAFE00165E39 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
@@ -143,7 +149,10 @@
143149
2439CC5E1E665C71003326FB /* Common */ = {
144150
isa = PBXGroup;
145151
children = (
152+
2493268B1EEEEFF100BCB814 /* BaseViewController.swift */,
153+
2493268D1EEEF02700BCB814 /* BaseView.swift */,
146154
2439CC381E665C6B003326FB /* BasicView.swift */,
155+
249326881EEEEE3D00BCB814 /* Stylesheet.swift */,
147156
);
148157
path = Common;
149158
sourceTree = "<group>";
@@ -284,7 +293,7 @@
284293
attributes = {
285294
LastSwiftUpdateCheck = 0820;
286295
LastUpgradeCheck = 0820;
287-
ORGANIZATIONNAME = mcswiftlayyout.mirego.com;
296+
ORGANIZATIONNAME = Mirego;
288297
TargetAttributes = {
289298
249EFE3E1E64FAFE00165E39 = {
290299
CreatedOnToolsVersion = 8.2.1;
@@ -403,7 +412,7 @@
403412
);
404413
runOnlyForDeploymentPostprocessing = 0;
405414
shellPath = /bin/sh;
406-
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
415+
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
407416
showEnvVarsInLog = 0;
408417
};
409418
/* End PBXShellScriptBuildPhase section */
@@ -418,14 +427,17 @@
418427
2439CC541E665C6B003326FB /* RelativeView.swift in Sources */,
419428
2439CC551E665C6B003326FB /* RelativeViewController.swift in Sources */,
420429
2439CC351E665BF6003326FB /* MenuView.swift in Sources */,
430+
2493268C1EEEEFF100BCB814 /* BaseViewController.swift in Sources */,
421431
2439CC4B1E665C6B003326FB /* BasicView.swift in Sources */,
422432
24F75B5B1EE5644E008DB567 /* IntroView.swift in Sources */,
423433
249EFE431E64FAFE00165E39 /* AppDelegate.swift in Sources */,
424434
2439CC361E665BF6003326FB /* MenuViewController.swift in Sources */,
425435
2439CC531E665C6B003326FB /* MultiRelativeViewController.swift in Sources */,
426436
24E654821E69041B00A72A8B /* Expect.swift in Sources */,
437+
249326891EEEEE3D00BCB814 /* Stylesheet.swift in Sources */,
427438
DF66F9DB1E8493E000ADB8D5 /* PinScrollingViewController.swift in Sources */,
428439
2439CC521E665C6B003326FB /* MultiRelativeView.swift in Sources */,
440+
2493268E1EEEF02700BCB814 /* BaseView.swift in Sources */,
429441
);
430442
runOnlyForDeploymentPostprocessing = 0;
431443
};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright (c) 2017, Mirego
2+
// All rights reserved.
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are met:
6+
//
7+
// - Redistributions of source code must retain the above copyright notice,
8+
// this list of conditions and the following disclaimer.
9+
// - Redistributions in binary form must reproduce the above copyright notice,
10+
// this list of conditions and the following disclaimer in the documentation
11+
// and/or other materials provided with the distribution.
12+
// - Neither the name of the Mirego nor the names of its contributors may
13+
// be used to endorse or promote products derived from this software without
14+
// specific prior written permission.
15+
//
16+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
// POSSIBILITY OF SUCH DAMAGE.
27+
28+
import UIKit
29+
30+
class BaseView: UIView {
31+
fileprivate (set) var topLayoutGuide: CGFloat = 0
32+
fileprivate (set) var bottomLayoutGuide: CGFloat = 0
33+
34+
func setLayoutGuides(top: CGFloat, bottom: CGFloat) {
35+
var didChange = false
36+
37+
if top != topLayoutGuide {
38+
topLayoutGuide = top
39+
didChange = true
40+
}
41+
42+
if bottom != bottomLayoutGuide {
43+
bottomLayoutGuide = bottom
44+
didChange = true
45+
}
46+
47+
if didChange {
48+
didChangeLayoutGuides()
49+
}
50+
}
51+
52+
func didChangeLayoutGuides() {
53+
setNeedsLayout()
54+
}
55+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright (c) 2017, Mirego
2+
// All rights reserved.
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are met:
6+
//
7+
// - Redistributions of source code must retain the above copyright notice,
8+
// this list of conditions and the following disclaimer.
9+
// - Redistributions in binary form must reproduce the above copyright notice,
10+
// this list of conditions and the following disclaimer in the documentation
11+
// and/or other materials provided with the distribution.
12+
// - Neither the name of the Mirego nor the names of its contributors may
13+
// be used to endorse or promote products derived from this software without
14+
// specific prior written permission.
15+
//
16+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
// POSSIBILITY OF SUCH DAMAGE.
27+
28+
import UIKit
29+
30+
class BaseViewController: UIViewController {
31+
32+
override func viewWillLayoutSubviews() {
33+
super.viewWillLayoutSubviews()
34+
35+
if let view = view as? BaseView {
36+
view.setLayoutGuides(top: topLayoutGuide.length, bottom: bottomLayoutGuide.length)
37+
}
38+
}
39+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright (c) 2017, Mirego
2+
// All rights reserved.
3+
//
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are met:
6+
//
7+
// - Redistributions of source code must retain the above copyright notice,
8+
// this list of conditions and the following disclaimer.
9+
// - Redistributions in binary form must reproduce the above copyright notice,
10+
// this list of conditions and the following disclaimer in the documentation
11+
// and/or other materials provided with the distribution.
12+
// - Neither the name of the Mirego nor the names of its contributors may
13+
// be used to endorse or promote products derived from this software without
14+
// specific prior written permission.
15+
//
16+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
// POSSIBILITY OF SUCH DAMAGE.
27+
28+
import UIKit
29+
30+
extension UIColor {
31+
class var pinLayoutColor: UIColor { return UIColor(red: 90.0 / 255.0, green: 171.0 / 255.0, blue: 243.0 / 255.0, alpha: 1.0) }
32+
}

Example/PinLayoutSample/UI/Main/MenuView.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ protocol MenuViewDelegate: class {
3131
func didSelect(page: Page)
3232
}
3333

34-
class MenuView: UIView {
34+
class MenuView: BaseView {
3535
weak var delegate: MenuViewDelegate?
3636

3737
fileprivate let tableView = UITableView()

Example/PinLayoutSample/UI/Main/MenuViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ enum Page: Int {
5656
}
5757
}
5858

59-
class MenuViewController: UIViewController {
59+
class MenuViewController: BaseViewController {
6060
fileprivate var mainView: MenuView {
6161
return self.view as! MenuView
6262
}
Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,40 @@
1+
// Copyright (c) 2017, Mirego
2+
// All rights reserved.
13
//
2-
// IntroView.swift
3-
// PinLayoutSample
4+
// Redistribution and use in source and binary forms, with or without
5+
// modification, are permitted provided that the following conditions are met:
46
//
5-
// Created by DION, Luc (MTL) on 2017-06-05.
6-
// Copyright (c) 2017 mcswiftlayyout.mirego.com. All rights reserved.
7+
// - Redistributions of source code must retain the above copyright notice,
8+
// this list of conditions and the following disclaimer.
9+
// - Redistributions in binary form must reproduce the above copyright notice,
10+
// this list of conditions and the following disclaimer in the documentation
11+
// and/or other materials provided with the distribution.
12+
// - Neither the name of the Mirego nor the names of its contributors may
13+
// be used to endorse or promote products derived from this software without
14+
// specific prior written permission.
715
//
16+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
// POSSIBILITY OF SUCH DAMAGE.
27+
828
import UIKit
929
import PinLayout
1030

11-
class IntroView: UIView {
31+
class IntroView: BaseView {
1232

1333
fileprivate let container = UIView()
1434
fileprivate let logo = UIImageView(image: UIImage(named: "PinLayout-logo"))
1535
fileprivate let segmented = UISegmentedControl(items: ["Intro", "1", "2"])
1636
fileprivate let textLabel = UILabel()
37+
fileprivate let separatorView = UIView()
1738

1839
init() {
1940
super.init(frame: .zero)
@@ -23,14 +44,18 @@ class IntroView: UIView {
2344
logo.contentMode = .scaleAspectFit
2445
addSubview(logo)
2546

47+
segmented.tintColor = .pinLayoutColor
2648
addSubview(segmented)
2749

2850
textLabel.text = "Swift manual views layouting without auto layout, no magic, pure code, full control. Concise syntax, readable & chainable.\n\nSwift manual views layouting without auto layout, no magic, pure code, full control. Concise syntax, readable & chainable."
29-
textLabel.font = UIFont.systemFont(ofSize: 14)
51+
textLabel.font = .systemFont(ofSize: 14)
3052
textLabel.numberOfLines = 0
3153
textLabel.lineBreakMode = .byWordWrapping
3254
addSubview(textLabel)
33-
55+
56+
separatorView.pin.height(1)
57+
separatorView.backgroundColor = .pinLayoutColor
58+
addSubview(separatorView)
3459
}
3560

3661
required init?(coder aDecoder: NSCoder) {
@@ -40,8 +65,9 @@ class IntroView: UIView {
4065
override func layoutSubviews() {
4166
super.layoutSubviews()
4267

43-
logo.pin.topLeft().size(100).margin(74, 10, 10)
44-
segmented.pin.right(of: logo, aligned: .top).right().marginHorizontal(20)
68+
logo.pin.topLeft().size(100).margin(topLayoutGuide + 10, 10, 10)
69+
segmented.pin.right(of: logo, aligned: .top).right().marginHorizontal(10)
4570
textLabel.pin.below(of: segmented, aligned: .left).width(of: segmented).pinEdges().marginTop(10).sizeToFit()
71+
separatorView.pin.below(of: logo, textLabel, aligned: .left).right(to: segmented.edge.right).marginTop(10)
4672
}
4773
}

0 commit comments

Comments
 (0)