Skip to content

Commit

Permalink
feat(auth): auto layout with snapkit, form slide if keyboard ✨
Browse files Browse the repository at this point in the history
  • Loading branch information
PierreBrisorgueil committed Oct 22, 2019
1 parent 41a509d commit 6141720
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 12 deletions.
15 changes: 15 additions & 0 deletions waosSwift.xcodeproj/project.pbxproj
Expand Up @@ -71,6 +71,7 @@
BF794D41226856E6000B19F3 /* Differentiator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF794D40226856E6000B19F3 /* Differentiator.framework */; };
BF794D51226880FB000B19F3 /* TasksService.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF794D50226880FB000B19F3 /* TasksService.swift */; };
BF794D532269C4FB000B19F3 /* TasksViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF794D522269C4FB000B19F3 /* TasksViewController.swift */; };
BF8BD5F7235F30660083B912 /* KeyboardConstraints.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8BD5F6235F30660083B912 /* KeyboardConstraints.swift */; };
BF8C6723227C3E1E0012B5A8 /* TasksCellReactor.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8C6722227C3E1E0012B5A8 /* TasksCellReactor.swift */; };
BF8C6725227C3E310012B5A8 /* TasksCellController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8C6724227C3E310012B5A8 /* TasksCellController.swift */; };
BF8C6727227C43E80012B5A8 /* Array+SectionModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF8C6726227C43E80012B5A8 /* Array+SectionModel.swift */; };
Expand Down Expand Up @@ -107,6 +108,8 @@
BFDE2602227B17D4008CBD30 /* AppServicesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDE2601227B17D4008CBD30 /* AppServicesProvider.swift */; };
BFDE2604227B185E008CBD30 /* CoreService.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDE2603227B185E008CBD30 /* CoreService.swift */; };
BFE4BB47226CC7BD00739735 /* TasksViewReactor.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFE4BB46226CC7BD00739735 /* TasksViewReactor.swift */; };
BFE912A22341CDA40074FAAB /* Cartfile in Resources */ = {isa = PBXBuildFile; fileRef = BFE912A02341CDA40074FAAB /* Cartfile */; };
BFE912A32341CDA40074FAAB /* Cartfile.resolved in Resources */ = {isa = PBXBuildFile; fileRef = BFE912A12341CDA40074FAAB /* Cartfile.resolved */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -203,6 +206,7 @@
BF794D40226856E6000B19F3 /* Differentiator.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Differentiator.framework; path = Carthage/Build/iOS/Differentiator.framework; sourceTree = "<group>"; };
BF794D50226880FB000B19F3 /* TasksService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TasksService.swift; sourceTree = "<group>"; };
BF794D522269C4FB000B19F3 /* TasksViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TasksViewController.swift; sourceTree = "<group>"; };
BF8BD5F6235F30660083B912 /* KeyboardConstraints.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardConstraints.swift; sourceTree = "<group>"; };
BF8C6722227C3E1E0012B5A8 /* TasksCellReactor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TasksCellReactor.swift; sourceTree = "<group>"; };
BF8C6724227C3E310012B5A8 /* TasksCellController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TasksCellController.swift; sourceTree = "<group>"; };
BF8C6726227C43E80012B5A8 /* Array+SectionModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Array+SectionModel.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -240,6 +244,8 @@
BFDE2601227B17D4008CBD30 /* AppServicesProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppServicesProvider.swift; sourceTree = "<group>"; };
BFDE2603227B185E008CBD30 /* CoreService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreService.swift; sourceTree = "<group>"; };
BFE4BB46226CC7BD00739735 /* TasksViewReactor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TasksViewReactor.swift; sourceTree = "<group>"; };
BFE912A02341CDA40074FAAB /* Cartfile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Cartfile; sourceTree = "<group>"; };
BFE912A12341CDA40074FAAB /* Cartfile.resolved */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Cartfile.resolved; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -382,6 +388,8 @@
BF425477221EBB9700395AE6 = {
isa = PBXGroup;
children = (
BFE912A02341CDA40074FAAB /* Cartfile */,
BFE912A12341CDA40074FAAB /* Cartfile.resolved */,
BF425482221EBB9700395AE6 /* waosSwift */,
BF425499221EBB9800395AE6 /* waosSwiftTests */,
BF4254A4221EBB9800395AE6 /* waosSwiftUITests */,
Expand Down Expand Up @@ -602,6 +610,7 @@
children = (
BF8C6726227C43E80012B5A8 /* Array+SectionModel.swift */,
BF4A2FD32265F4020001B4CE /* UserDefaults.swift */,
BF8BD5F6235F30660083B912 /* KeyboardConstraints.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -897,6 +906,8 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
BFE912A32341CDA40074FAAB /* Cartfile.resolved in Resources */,
BFE912A22341CDA40074FAAB /* Cartfile in Resources */,
BF9A366C228D5CDA00EE2AB8 /* get.json in Resources */,
BF4A2FCD2264A6810001B4CE /* production.json in Resources */,
BF4A2FCE2264A6810001B4CE /* development.json in Resources */,
Expand Down Expand Up @@ -1059,6 +1070,7 @@
BF8C672A2280176B0012B5A8 /* ReusableKit.swift in Sources */,
BF794D51226880FB000B19F3 /* TasksService.swift in Sources */,
BF78B5F32293CD680057157A /* ObservableType+Extras.swift in Sources */,
BF8BD5F7235F30660083B912 /* KeyboardConstraints.swift in Sources */,
BF78B622229949410057157A /* AuthSignupController.swift in Sources */,
BF9A368322900F7200EE2AB8 /* AuthApi.swift in Sources */,
BF058D772282BCAC00E2A077 /* AuthSigninController.swift in Sources */,
Expand Down Expand Up @@ -1258,6 +1270,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 5TTXU376YU;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
Expand All @@ -1280,6 +1293,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 5TTXU376YU;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
Expand Down Expand Up @@ -1443,6 +1457,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 5TTXU376YU;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
Expand Down
6 changes: 6 additions & 0 deletions waosSwift.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

96 changes: 96 additions & 0 deletions waosSwift/lib/helpers/Extensions/KeyboardConstraints.swift
@@ -0,0 +1,96 @@
//
// KeyboardConstraints.swift
// snapkitkeyboard
//
// Created by Szymon Maślanka on 03/01/2017.
// Copyright © 2017 Szymon Maślanka. All rights reserved.
//

import UIKit
import SnapKit

extension ConstraintMakerEditable {
@discardableResult
func keyboard(_ shown: Bool, in view: UIView) -> ConstraintMakerEditable {
switch view.traitCollection.verticalSizeClass {
case .regular:
if shown { view.shownRegularConstraints.append(constraint) } else { view.hiddenRegularConstraints.append(constraint) }
case .compact:
if shown { view.shownCompactConstraints.append(constraint) } else { view.hiddenCompactConstraints.append(constraint) }
case .unspecified: break
}
return self
}
}

private var ckmShownRegular: UInt8 = 0
private var ckmShownCompact: UInt8 = 1
private var ckmHiddenRegular: UInt8 = 2
private var ckmHiddenCompact: UInt8 = 3
extension UIView {

fileprivate var shownRegularConstraints: [Constraint]! {
get { return objc_getAssociatedObject(self, &ckmShownRegular) as? [Constraint] ?? [Constraint]() }
set(newValue) { objc_setAssociatedObject(self, &ckmShownRegular, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) }
}

fileprivate var shownCompactConstraints: [Constraint]! {
get { return objc_getAssociatedObject(self, &ckmShownCompact) as? [Constraint] ?? [Constraint]() }
set(newValue) { objc_setAssociatedObject(self, &ckmShownCompact, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) }
}

fileprivate var hiddenRegularConstraints: [Constraint]! {
get { return objc_getAssociatedObject(self, &ckmHiddenRegular) as? [Constraint] ?? [Constraint]() }
set(newValue) { objc_setAssociatedObject(self, &ckmHiddenRegular, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) }
}

fileprivate var hiddenCompactConstraints: [Constraint]! {
get { return objc_getAssociatedObject(self, &ckmHiddenCompact) as? [Constraint] ?? [Constraint]() }
set(newValue) { objc_setAssociatedObject(self, &ckmHiddenCompact, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) }
}

@objc private dynamic func keyboardWillShow(notification: Notification) {
let duration = (notification as NSNotification).userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as! TimeInterval
let option = (notification as NSNotification).userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as! NSNumber

switch traitCollection.verticalSizeClass {
case .regular:
hiddenRegularConstraints.forEach { $0.deactivate() }
shownRegularConstraints.forEach { $0.activate() }
case .compact:
hiddenCompactConstraints.forEach { $0.deactivate() }
shownCompactConstraints.forEach { $0.activate() }
case .unspecified: break
}

UIView.animate(withDuration: duration, delay: 0,
options: UIView.AnimationOptions(rawValue: option.uintValue), animations: {
self.layoutIfNeeded()
}, completion: nil)
}

@objc private dynamic func keyboardWillHide(notification: Notification) {
let duration = (notification as NSNotification).userInfo![UIResponder.keyboardAnimationDurationUserInfoKey] as! TimeInterval
let option = (notification as NSNotification).userInfo![UIResponder.keyboardAnimationCurveUserInfoKey] as! NSNumber

switch traitCollection.verticalSizeClass {
case .regular:
shownRegularConstraints.forEach { $0.deactivate() }
hiddenRegularConstraints.forEach { $0.activate() }
case .compact:
shownCompactConstraints.forEach { $0.deactivate() }
hiddenCompactConstraints.forEach { $0.activate() }
case .unspecified: break
}

UIView.animate(withDuration: duration, delay: 0,
options: UIView.AnimationOptions(rawValue: option.uintValue), animations: {
self.layoutIfNeeded()
}, completion: nil)
}

func registerAutomaticKeyboardConstraints() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
}
28 changes: 23 additions & 5 deletions waosSwift/modules/auth/controllers/AuthSigninController.swift
Expand Up @@ -18,6 +18,7 @@ final class AuthSignInController: CoreController, View, Stepper {
$0.borderStyle = .roundedRect
$0.placeholder = "email..."
$0.autocapitalizationType = .none
$0.textContentType = .username
}
let inputPassword = UITextField().then {
$0.autocorrectionType = .no
Expand All @@ -26,6 +27,7 @@ final class AuthSignInController: CoreController, View, Stepper {
$0.autocapitalizationType = .none
$0.returnKeyType = .done
$0.isSecureTextEntry = true
$0.textContentType = .password
}
let buttonSignin = UIButton().then {
$0.setTitle("Sign In", for: .normal)
Expand Down Expand Up @@ -65,6 +67,7 @@ final class AuthSignInController: CoreController, View, Stepper {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
self.view.registerAutomaticKeyboardConstraints() // active layout with snapkit
self.view.addSubview(self.inputEmail)
self.view.addSubview(self.inputPassword)
self.view.addSubview(self.buttonSignin)
Expand All @@ -77,31 +80,46 @@ final class AuthSignInController: CoreController, View, Stepper {
make.width.equalTo(300)
make.height.equalTo(50)
make.centerX.equalTo(self.view)
make.centerY.equalTo(self.view).offset(-60)
make.centerY.equalTo(self.view).offset(-60).keyboard(false, in: self.view)
}
inputEmail.snp.prepareConstraints { (make) -> Void in
make.centerY.equalTo(self.view).offset(-160).keyboard(true, in: self.view)
}
inputPassword.snp.makeConstraints { (make) -> Void in
make.width.equalTo(300)
make.height.equalTo(50)
make.centerX.equalTo(self.view)
make.centerY.equalTo(self.view)
make.centerY.equalTo(self.view).keyboard(false, in: self.view)
}
inputPassword.snp.prepareConstraints { (make) -> Void in
make.centerY.equalTo(self.view).offset(-100).keyboard(true, in: self.view)
}
buttonSignup.snp.makeConstraints { (make) -> Void in
make.width.equalTo(140)
make.height.equalTo(50)
make.centerX.equalTo(self.view).offset(-80)
make.centerY.equalTo(self.view).offset(60)
make.centerY.equalTo(self.view).offset(60).keyboard(false, in: self.view)
}
buttonSignup.snp.prepareConstraints { (make) -> Void in
make.centerY.equalTo(self.view).offset(-40).keyboard(true, in: self.view)
}
buttonSignin.snp.makeConstraints { (make) -> Void in
make.width.equalTo(140)
make.height.equalTo(50)
make.centerX.equalTo(self.view).offset(80)
make.centerY.equalTo(self.view).offset(60)
make.centerY.equalTo(self.view).offset(60).keyboard(false, in: self.view)
}
buttonSignin.snp.prepareConstraints { (make) -> Void in
make.centerY.equalTo(self.view).offset(-40).keyboard(true, in: self.view)
}
labelErrors.snp.makeConstraints { (make) -> Void in
make.left.equalTo(25)
make.right.equalTo(-25)
make.centerX.equalTo(self.view)
make.centerY.equalTo(self.view).offset(160)
make.centerY.equalTo(self.view).offset(120).keyboard(false, in: self.view)
}
labelErrors.snp.prepareConstraints { (make) -> Void in
make.centerY.equalTo(self.view).offset(20).keyboard(true, in: self.view)
}
}

Expand Down
38 changes: 31 additions & 7 deletions waosSwift/modules/auth/controllers/AuthSignupController.swift
Expand Up @@ -27,6 +27,7 @@ final class AuthSignUpController: CoreController, View, Stepper {
$0.borderStyle = .roundedRect
$0.placeholder = "email..."
$0.autocapitalizationType = .none
$0.textContentType = .username
}
let inputPassword = UITextField().then {
$0.autocorrectionType = .no
Expand All @@ -35,6 +36,7 @@ final class AuthSignUpController: CoreController, View, Stepper {
$0.autocapitalizationType = .none
$0.returnKeyType = .done
$0.isSecureTextEntry = true
$0.textContentType = .password
}
let buttonSignin = UIButton().then {
$0.setTitle("Sign In", for: .normal)
Expand Down Expand Up @@ -74,6 +76,7 @@ final class AuthSignUpController: CoreController, View, Stepper {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
self.view.registerAutomaticKeyboardConstraints() // active layout with snapkit
self.view.addSubview(self.inputFirstName)
self.view.addSubview(self.inputLastName)
self.view.addSubview(self.inputEmail)
Expand All @@ -87,44 +90,65 @@ final class AuthSignUpController: CoreController, View, Stepper {
inputFirstName.snp.makeConstraints { (make) -> Void in
make.width.equalTo(300)
make.height.equalTo(50)
make.centerY.equalTo(self.view).offset(-180)
make.centerX.equalTo(self.view)
make.centerY.equalTo(self.view).offset(-140).keyboard(false, in: self.view)
}
inputFirstName.snp.prepareConstraints { (make) -> Void in
make.centerY.equalTo(self.view).offset(-240).keyboard(true, in: self.view)
}
inputLastName.snp.makeConstraints { (make) -> Void in
make.width.equalTo(300)
make.height.equalTo(50)
make.centerY.equalTo(self.view).offset(-120)
make.centerX.equalTo(self.view)
make.centerY.equalTo(self.view).offset(-80).keyboard(false, in: self.view)
}
inputLastName.snp.prepareConstraints { (make) -> Void in
make.centerY.equalTo(self.view).offset(-180).keyboard(true, in: self.view)
}
inputEmail.snp.makeConstraints { (make) -> Void in
make.width.equalTo(300)
make.height.equalTo(50)
make.centerY.equalTo(self.view).offset(-60)
make.centerX.equalTo(self.view)
make.centerY.equalTo(self.view).offset(-20).keyboard(false, in: self.view)
}
inputEmail.snp.prepareConstraints { (make) -> Void in
make.centerY.equalTo(self.view).offset(-120).keyboard(true, in: self.view)
}
inputPassword.snp.makeConstraints { (make) -> Void in
make.width.equalTo(300)
make.height.equalTo(50)
make.centerY.equalTo(self.view).offset(0)
make.centerX.equalTo(self.view)
make.centerY.equalTo(self.view).offset(40).keyboard(false, in: self.view)
}
inputPassword.snp.prepareConstraints { (make) -> Void in
make.centerY.equalTo(self.view).offset(-60).keyboard(true, in: self.view)
}
buttonSignup.snp.makeConstraints { (make) -> Void in
make.width.equalTo(140)
make.height.equalTo(50)
make.centerX.equalTo(self.view).offset(80)
make.centerY.equalTo(self.view).offset(60)
make.centerY.equalTo(self.view).offset(100).keyboard(false, in: self.view)
}
buttonSignup.snp.prepareConstraints { (make) -> Void in
make.centerY.equalTo(self.view).offset(0).keyboard(true, in: self.view)
}
buttonSignin.snp.makeConstraints { (make) -> Void in
make.width.equalTo(140)
make.height.equalTo(50)
make.centerX.equalTo(self.view).offset(-80)
make.centerY.equalTo(self.view).offset(60)
make.centerY.equalTo(self.view).offset(100).keyboard(false, in: self.view)
}
buttonSignin.snp.prepareConstraints { (make) -> Void in
make.centerY.equalTo(self.view).offset(0).keyboard(true, in: self.view)
}
labelErrors.snp.makeConstraints { (make) -> Void in
make.left.equalTo(25)
make.right.equalTo(-25)
make.centerX.equalTo(self.view)
make.centerY.equalTo(self.view).offset(160)
make.centerY.equalTo(self.view).offset(160).keyboard(false, in: self.view)
}
labelErrors.snp.prepareConstraints { (make) -> Void in
make.centerY.equalTo(self.view).offset(60).keyboard(true, in: self.view)
}
}

Expand Down

0 comments on commit 6141720

Please sign in to comment.