Skip to content

Commit e2dac29

Browse files
committed
1 parent e27f9b4 commit e2dac29

File tree

5 files changed

+107
-6
lines changed

5 files changed

+107
-6
lines changed

Validate/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ A gentle introduction to using Combine to validate user input.
55
See the following blog post for more details:
66

77
+ [Getting Started with Combine](https://useyourloaf.com/blog/getting-started-with-combine/)
8+
9+
For details on using Xcode previews with UIKit view controllers see:
10+
11+
+ [Xcode Previews for View Controllers](https:/useyourloaf.com/blog/xcode-previews-for-view-controllers/)

Validate/Validate.xcodeproj/project.pbxproj

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
532A2F1D2425823D00A0005F /* String+Blank.swift in Sources */ = {isa = PBXBuildFile; fileRef = 532A2F1C2425823D00A0005F /* String+Blank.swift */; };
11+
5371387A243202D6006CB01D /* TermsViewControllerPreviews.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53713879243202D6006CB01D /* TermsViewControllerPreviews.swift */; };
1112
5385DF762427C259001E63E0 /* AdaptiveScroll.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5385DF752427C259001E63E0 /* AdaptiveScroll.swift */; };
1213
539CD53024250D75000E2699 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539CD52F24250D75000E2699 /* AppDelegate.swift */; };
1314
539CD53224250D75000E2699 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 539CD53124250D75000E2699 /* SceneDelegate.swift */; };
@@ -19,6 +20,7 @@
1920

2021
/* Begin PBXFileReference section */
2122
532A2F1C2425823D00A0005F /* String+Blank.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Blank.swift"; sourceTree = "<group>"; };
23+
53713879243202D6006CB01D /* TermsViewControllerPreviews.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsViewControllerPreviews.swift; sourceTree = "<group>"; };
2224
5385DF752427C259001E63E0 /* AdaptiveScroll.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdaptiveScroll.swift; sourceTree = "<group>"; };
2325
539CD52C24250D75000E2699 /* Validate.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Validate.app; sourceTree = BUILT_PRODUCTS_DIR; };
2426
539CD52F24250D75000E2699 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@@ -63,6 +65,7 @@
6365
isa = PBXGroup;
6466
children = (
6567
539CD5432425109F000E2699 /* TermsViewController.swift */,
68+
53713879243202D6006CB01D /* TermsViewControllerPreviews.swift */,
6669
5385DF752427C259001E63E0 /* AdaptiveScroll.swift */,
6770
532A2F1C2425823D00A0005F /* String+Blank.swift */,
6871
539CD52F24250D75000E2699 /* AppDelegate.swift */,
@@ -147,6 +150,7 @@
147150
buildActionMask = 2147483647;
148151
files = (
149152
539CD53024250D75000E2699 /* AppDelegate.swift in Sources */,
153+
5371387A243202D6006CB01D /* TermsViewControllerPreviews.swift in Sources */,
150154
5385DF762427C259001E63E0 /* AdaptiveScroll.swift in Sources */,
151155
539CD5442425109F000E2699 /* TermsViewController.swift in Sources */,
152156
539CD53224250D75000E2699 /* SceneDelegate.swift in Sources */,

Validate/Validate/Base.lproj/Main.storyboard

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16095" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ucF-KU-dDs">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16096" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ucF-KU-dDs">
33
<device id="retina4_7" orientation="portrait" appearance="light"/>
44
<dependencies>
5-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16084.1"/>
5+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16086"/>
66
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
77
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
88
</dependencies>
@@ -34,7 +34,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec posuere nul
3434
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ojs-m8-Ph8" userLabel="AcceptTerms Control">
3535
<rect key="frame" x="8" y="200" width="359" height="47"/>
3636
<subviews>
37-
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="I accept the terms and conditions" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rNb-V2-xsx">
37+
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" verticalCompressionResistancePriority="751" text="I accept the terms and conditions" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rNb-V2-xsx">
3838
<rect key="frame" x="8" y="8" width="286" height="31"/>
3939
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
4040
<nil key="textColor"/>
@@ -48,6 +48,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec posuere nul
4848
</switch>
4949
</subviews>
5050
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
51+
<accessibility key="accessibilityConfiguration" identifier="UYL-Terms"/>
5152
<constraints>
5253
<constraint firstAttribute="leadingMargin" secondItem="rNb-V2-xsx" secondAttribute="leading" id="GAL-dM-qv3"/>
5354
<constraint firstItem="UK3-Vd-NdR" firstAttribute="top" secondItem="Ojs-m8-Ph8" secondAttribute="topMargin" id="X7n-Ph-yxk"/>
@@ -58,10 +59,10 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec posuere nul
5859
<constraint firstItem="UK3-Vd-NdR" firstAttribute="leading" secondItem="rNb-V2-xsx" secondAttribute="trailing" constant="8" symbolic="YES" id="sSv-hm-MMF"/>
5960
</constraints>
6061
</view>
61-
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pLT-ws-O8U" userLabel="AcceptPrivacy Control">
62+
<view contentMode="scaleToFill" verticalCompressionResistancePriority="751" translatesAutoresizingMaskIntoConstraints="NO" id="pLT-ws-O8U" userLabel="AcceptPrivacy Control">
6263
<rect key="frame" x="8" y="255" width="359" height="47"/>
6364
<subviews>
64-
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="I accept the privacy policy" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Exk-YM-B1E">
65+
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" verticalCompressionResistancePriority="751" text="I accept the privacy policy" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Exk-YM-B1E">
6566
<rect key="frame" x="8" y="8" width="286" height="31"/>
6667
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
6768
<nil key="textColor"/>
@@ -75,6 +76,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec posuere nul
7576
</switch>
7677
</subviews>
7778
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
79+
<accessibility key="accessibilityConfiguration" identifier="UYL-Privacy"/>
7880
<constraints>
7981
<constraint firstAttribute="trailingMargin" secondItem="o3m-iT-XzI" secondAttribute="trailing" id="227-JY-wXN"/>
8082
<constraint firstItem="Exk-YM-B1E" firstAttribute="top" secondItem="pLT-ws-O8U" secondAttribute="topMargin" id="4y4-uA-sEu"/>
@@ -104,6 +106,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec posuere nul
104106
</textField>
105107
</subviews>
106108
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
109+
<accessibility key="accessibilityConfiguration" identifier="UYL-Name"/>
107110
<constraints>
108111
<constraint firstAttribute="trailingMargin" secondItem="wrf-eZ-eZE" secondAttribute="trailing" id="05B-Ze-ZJN"/>
109112
<constraint firstItem="wrf-eZ-eZE" firstAttribute="top" secondItem="Q40-by-Mbm" secondAttribute="bottom" constant="8" symbolic="YES" id="1Nu-Gc-gqt"/>
@@ -128,6 +131,7 @@ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec posuere nul
128131
</connections>
129132
</button>
130133
</subviews>
134+
<accessibility key="accessibilityConfiguration" identifier="UYL-ContainerView"/>
131135
<constraints>
132136
<constraint firstAttribute="trailingMargin" secondItem="mqc-dX-EpF" secondAttribute="trailing" id="5W9-Oy-xVv"/>
133137
<constraint firstAttribute="trailingMargin" secondItem="mX0-FW-J5u" secondAttribute="trailing" id="84q-4x-rox"/>

Validate/Validate/TermsViewController.swift

+19-1
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,14 @@ final class TermsViewController: UIViewController {
6363

6464
@IBAction private func submitAction(_ sender: UIButton) {
6565
print("Submit... \(name)")
66+
print(view.value(forKey: "_autolayoutTrace")!)
6667
}
6768

6869
private var validToSubmit: AnyPublisher<Bool, Never> {
6970
return Publishers.CombineLatest3($acceptedTerms, $acceptedPrivacy, $name)
7071
.map { terms, privacy, name in
7172
terms && privacy && !name.isBlank
72-
}.eraseToAnyPublisher()
73+
}.eraseToAnyPublisher()
7374
}
7475

7576
// A longer approach just for fun:
@@ -95,3 +96,20 @@ final class TermsViewController: UIViewController {
9596
// }.eraseToAnyPublisher()
9697
// }
9798
}
99+
100+
#if DEBUG
101+
import SwiftUI
102+
103+
extension TermsViewController: UIViewControllerRepresentable {
104+
func makeUIViewController(context: Context) -> TermsViewController {
105+
let storyboard = UIStoryboard(name: "Main", bundle: nil)
106+
guard let viewController = storyboard.instantiateViewController(identifier: "TermsViewController") as? TermsViewController else {
107+
fatalError("Cannot load from storyboard")
108+
}
109+
return viewController
110+
}
111+
112+
func updateUIViewController(_ uiViewController: TermsViewController, context: Context) {
113+
}
114+
}
115+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// Created by Keith Harrison https://useyourloaf.com
2+
// Copyright © 2020 Keith Harrison. 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+
// 1. Redistributions of source code must retain the above copyright
8+
// notice, this list of conditions and the following disclaimer.
9+
//
10+
// 2. Redistributions in binary form must reproduce the above copyright
11+
// notice, this list of conditions and the following disclaimer in the
12+
// documentation and/or other materials provided with the distribution.
13+
//
14+
// 3. Neither the name of the copyright holder nor the names of its
15+
// contributors may be used to endorse or promote products derived from
16+
// this software without specific prior written permission.
17+
//
18+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19+
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21+
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22+
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24+
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25+
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26+
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27+
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28+
// POSSIBILITY OF SUCH DAMAGE.
29+
30+
#if DEBUG
31+
import SwiftUI
32+
33+
let devices = [
34+
"iPhone SE",
35+
"iPhone 11",
36+
"iPad Pro (11-inch) (2nd generation)"
37+
]
38+
39+
let sizeCategories: [ContentSizeCategory] = [
40+
.extraSmall,
41+
.extraExtraExtraLarge,
42+
.accessibilityExtraExtraExtraLarge
43+
]
44+
45+
struct TermsViewControllerPreviews: PreviewProvider {
46+
static var previews: some View {
47+
Group {
48+
TermsViewController()
49+
.previewDisplayName("Default")
50+
51+
ForEach(devices, id: \.self) { name in
52+
TermsViewController()
53+
.previewDevice(PreviewDevice(rawValue: name))
54+
.previewDisplayName(name)
55+
}
56+
57+
ForEach(ColorScheme.allCases, id: \.self) { scheme in
58+
TermsViewController()
59+
.environment(\.colorScheme, scheme)
60+
.previewDisplayName("\(scheme)")
61+
}
62+
63+
ForEach(sizeCategories, id: \.self) { size in
64+
TermsViewController()
65+
.environment(\.sizeCategory, size)
66+
.previewDisplayName("\(size)")
67+
}
68+
}
69+
}
70+
}
71+
#endif

0 commit comments

Comments
 (0)