Commit eb94bb7e by Daniel Dahan

added initial TextField sample project and moved Divider to a UIView extension

parent f00e3eee
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
96090AE81D9CDD2E00709CA6 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96090AE71D9CDD2E00709CA6 /* AppDelegate.swift */; };
96090AEA1D9CDD2E00709CA6 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96090AE91D9CDD2E00709CA6 /* ViewController.swift */; };
96090AEF1D9CDD2E00709CA6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 96090AEE1D9CDD2E00709CA6 /* Assets.xcassets */; };
96090AF21D9CDD2E00709CA6 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 96090AF01D9CDD2E00709CA6 /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
96090AFC1D9CDEB100709CA6 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
96090AE41D9CDD2E00709CA6 /* TextField.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TextField.app; sourceTree = BUILT_PRODUCTS_DIR; };
96090AE71D9CDD2E00709CA6 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
96090AE91D9CDD2E00709CA6 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
96090AEE1D9CDD2E00709CA6 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
96090AF11D9CDD2E00709CA6 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
96090AF31D9CDD2E00709CA6 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
96090AE11D9CDD2E00709CA6 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
96090ADB1D9CDD2E00709CA6 = {
isa = PBXGroup;
children = (
96090AE61D9CDD2E00709CA6 /* TextField */,
96090AE51D9CDD2E00709CA6 /* Products */,
);
sourceTree = "<group>";
};
96090AE51D9CDD2E00709CA6 /* Products */ = {
isa = PBXGroup;
children = (
96090AE41D9CDD2E00709CA6 /* TextField.app */,
);
name = Products;
sourceTree = "<group>";
};
96090AE61D9CDD2E00709CA6 /* TextField */ = {
isa = PBXGroup;
children = (
96090AE71D9CDD2E00709CA6 /* AppDelegate.swift */,
96090AE91D9CDD2E00709CA6 /* ViewController.swift */,
96090AEE1D9CDD2E00709CA6 /* Assets.xcassets */,
96090AF01D9CDD2E00709CA6 /* LaunchScreen.storyboard */,
96090AF31D9CDD2E00709CA6 /* Info.plist */,
);
path = TextField;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
96090AE31D9CDD2E00709CA6 /* TextField */ = {
isa = PBXNativeTarget;
buildConfigurationList = 96090AF61D9CDD2E00709CA6 /* Build configuration list for PBXNativeTarget "TextField" */;
buildPhases = (
96090AE01D9CDD2E00709CA6 /* Sources */,
96090AE11D9CDD2E00709CA6 /* Frameworks */,
96090AE21D9CDD2E00709CA6 /* Resources */,
96090AFC1D9CDEB100709CA6 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = TextField;
productName = TextField;
productReference = 96090AE41D9CDD2E00709CA6 /* TextField.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
96090ADC1D9CDD2E00709CA6 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0800;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = CosmicMind;
TargetAttributes = {
96090AE31D9CDD2E00709CA6 = {
CreatedOnToolsVersion = 8.0;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 96090ADF1D9CDD2E00709CA6 /* Build configuration list for PBXProject "TextField" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 96090ADB1D9CDD2E00709CA6;
productRefGroup = 96090AE51D9CDD2E00709CA6 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
96090AE31D9CDD2E00709CA6 /* TextField */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
96090AE21D9CDD2E00709CA6 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
96090AF21D9CDD2E00709CA6 /* LaunchScreen.storyboard in Resources */,
96090AEF1D9CDD2E00709CA6 /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
96090AE01D9CDD2E00709CA6 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
96090AEA1D9CDD2E00709CA6 /* ViewController.swift in Sources */,
96090AE81D9CDD2E00709CA6 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
96090AF01D9CDD2E00709CA6 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
96090AF11D9CDD2E00709CA6 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
96090AF41D9CDD2E00709CA6 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
96090AF51D9CDD2E00709CA6 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVES = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
96090AF71D9CDD2E00709CA6 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = TextField/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.cosmicmind.TextField;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
96090AF81D9CDD2E00709CA6 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = TextField/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = io.cosmicmind.TextField;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
96090ADF1D9CDD2E00709CA6 /* Build configuration list for PBXProject "TextField" */ = {
isa = XCConfigurationList;
buildConfigurations = (
96090AF41D9CDD2E00709CA6 /* Debug */,
96090AF51D9CDD2E00709CA6 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
96090AF61D9CDD2E00709CA6 /* Build configuration list for PBXNativeTarget "TextField" */ = {
isa = XCConfigurationList;
buildConfigurations = (
96090AF71D9CDD2E00709CA6 /* Debug */,
96090AF81D9CDD2E00709CA6 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 96090ADC1D9CDD2E00709CA6 /* Project object */;
}
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:TextField.xcodeproj">
</FileRef>
</Workspace>
/*
* Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.io>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import UIKit
import Material
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func applicationDidFinishLaunching(_ application: UIApplication) {
window = UIWindow(frame: Device.bounds)
window!.rootViewController = ViewController()
window!.makeKeyAndVisible()
}
}
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="11134" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11106"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
/*
* Copyright (C) 2015 - 2016, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.io>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of CosmicMind nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import UIKit
import Material
class ViewController: UIViewController {
private var nameField: TextField!
private var emailField: ErrorTextField!
private var passwordField: TextField!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = Color.white
prepareNameField()
prepareEmailField()
preparePasswordField()
prepareResignResponderButton()
}
/// Programmatic update for the textField as it rotates.
override func willRotate(to toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval) {
emailField.width = view.bounds.height - 80
}
/// Prepares the resign responder button.
private func prepareResignResponderButton() {
let btn = RaisedButton(title: "Resign", titleColor: Color.blue.base)
btn.addTarget(self, action: #selector(handleResignResponderButton), for: .touchUpInside)
view.layout(btn).width(100).height(50).bottom(24).right(24)
}
/// Handle the resign responder button.
internal func handleResignResponderButton() {
nameField?.resignFirstResponder()
emailField?.resignFirstResponder()
passwordField?.resignFirstResponder()
}
/// Prepares the name TextField.
private func prepareNameField() {
nameField = TextField()
nameField.text = "Daniel Dahan"
nameField.placeholder = "Name"
nameField.detail = "Your given name"
nameField.textAlignment = .center
nameField.clearButtonMode = .whileEditing
// Size the TextField to the maximum width, less 40 pixels on either side
// with a top margin of 40 pixels.
view.layout(nameField).top(40).horizontally(left: 40, right: 40)
}
/// Prepares the email TextField.
private func prepareEmailField() {
emailField = ErrorTextField(frame: CGRect(x: 40, y: 120, width: view.width - 80, height: 32))
emailField.placeholder = "Email"
emailField.detail = "Error, incorrect email"
emailField.isClearIconButtonEnabled = true
emailField.delegate = self
emailField.placeholderColor = Color.amber.darken4
emailField.placeholderActiveColor = Color.pink.base
emailField.dividerColor = Color.cyan.base
view.addSubview(emailField)
}
/// Prepares the password TextField.
private func preparePasswordField() {
passwordField = TextField()
passwordField.placeholder = "Password"
passwordField.detail = "At least 8 characters"
passwordField.clearButtonMode = .whileEditing
passwordField.isVisibilityIconButtonEnabled = true
// Setting the visibilityFlatButton color.
passwordField.visibilityIconButton?.tintColor = Color.green.base.withAlphaComponent(passwordField.isSecureTextEntry ? 0.38 : 0.54)
// Size the TextField to the maximum width, less 40 pixels on either side
// with a top margin of 200 pixels.
view.layout(passwordField).top(200).horizontally(left: 40, right: 40)
}
}
extension UIViewController: TextFieldDelegate {
/// Executed when the 'return' key is pressed when using the emailField.
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
(textField as? ErrorTextField)?.isErrorRevealed = true
return true
}
public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return true
}
public func textFieldDidBeginEditing(_ textField: UITextField) {
}
public func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
return true
}
public func textFieldDidEndEditing(_ textField: UITextField) {
(textField as? ErrorTextField)?.isErrorRevealed = false
}
public func textFieldShouldClear(_ textField: UITextField) -> Bool {
(textField as? ErrorTextField)?.isErrorRevealed = false
return true
}
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
(textField as? ErrorTextField)?.isErrorRevealed = false
return true
}
}
...@@ -68,6 +68,9 @@ ...@@ -68,6 +68,9 @@
location = "group:Examples/Programmatic/TabBar/TabBar.xcodeproj"> location = "group:Examples/Programmatic/TabBar/TabBar.xcodeproj">
</FileRef> </FileRef>
<FileRef <FileRef
location = "group:Examples/Programmatic/TextField/TextField.xcodeproj">
</FileRef>
<FileRef
location = "group:Examples/Programmatic/ToolbarController/ToolbarController.xcodeproj"> location = "group:Examples/Programmatic/ToolbarController/ToolbarController.xcodeproj">
</FileRef> </FileRef>
<FileRef <FileRef
......
...@@ -37,41 +37,6 @@ public enum ContentViewAlignment: Int { ...@@ -37,41 +37,6 @@ public enum ContentViewAlignment: Int {
} }
open class Bar: View { open class Bar: View {
/// Divider layer.
internal private(set) var divider: Divider!
/// Divider color.
@IBInspectable
open var dividerColor: UIColor? {
get {
return divider.color
}
set(value) {
divider.color = value
}
}
/// Divider animation.
open var dividerAlignment: DividerAlignment {
get {
return divider.alignment
}
set(value) {
divider.alignment = value
}
}
/// Divider height.
@IBInspectable
open var dividerHeight: CGFloat {
get {
return divider.height
}
set(value) {
divider.height = value
}
}
/// Should center the contentView. /// Should center the contentView.
open var contentViewAlignment = ContentViewAlignment.any { open var contentViewAlignment = ContentViewAlignment.any {
didSet { didSet {
...@@ -265,16 +230,10 @@ open class Bar: View { ...@@ -265,16 +230,10 @@ open class Bar: View {
open override func prepare() { open override func prepare() {
super.prepare() super.prepare()
prepareContentView() prepareContentView()
prepareDivider()
} }
/// Prepares the contentView. /// Prepares the contentView.
private func prepareContentView() { private func prepareContentView() {
contentView.backgroundColor = nil contentView.backgroundColor = nil
} }
/// Prepares the divider.
private func prepareDivider() {
divider = Divider(view: self)
}
} }
...@@ -131,53 +131,3 @@ open class BottomTabBar: UITabBar { ...@@ -131,53 +131,3 @@ open class BottomTabBar: UITabBar {
backgroundImage = image backgroundImage = image
} }
} }
/// A memory reference to the TabBarItem instance.
private var TabBarKey: UInt8 = 0
extension UITabBar {
/// TabBarItem reference.
internal private(set) var divider: Divider {
get {
return AssociatedObject(base: self, key: &TabBarKey) {
return Divider(view: self)
}
}
set(value) {
AssociateObject(base: self, key: &TabBarKey, value: value)
}
}
/// Divider color.
@IBInspectable
open var dividerColor: UIColor? {
get {
return divider.color
}
set(value) {
divider.color = value
}
}
/// Divider animation.
open var dividerAlignment: DividerAlignment {
get {
return divider.alignment
}
set(value) {
divider.alignment = value
}
}
/// Divider height.
@IBInspectable
open var dividerHeight: CGFloat {
get {
return divider.height
}
set(value) {
divider.height = value
}
}
}
...@@ -32,41 +32,6 @@ import UIKit ...@@ -32,41 +32,6 @@ import UIKit
@objc(CollectionViewCell) @objc(CollectionViewCell)
open class CollectionViewCell: UICollectionViewCell { open class CollectionViewCell: UICollectionViewCell {
/// Divider layer.
internal private(set) var divider: Divider!
/// Divider color.
@IBInspectable
open var dividerColor: UIColor? {
get {
return divider.color
}
set(value) {
divider.color = value
}
}
/// Divider animation.
open var dividerAlignment: DividerAlignment {
get {
return divider.alignment
}
set(value) {
divider.alignment = value
}
}
/// Divider height.
@IBInspectable
open var dividerHeight: CGFloat {
get {
return divider.height
}
set(value) {
divider.height = value
}
}
/** /**
A CAShapeLayer used to manage elements that would be affected by A CAShapeLayer used to manage elements that would be affected by
the clipToBounds property of the backing layer. For example, this the clipToBounds property of the backing layer. For example, this
...@@ -331,7 +296,6 @@ open class CollectionViewCell: UICollectionViewCell { ...@@ -331,7 +296,6 @@ open class CollectionViewCell: UICollectionViewCell {
open func prepare() { open func prepare() {
contentScaleFactor = Device.scale contentScaleFactor = Device.scale
prepareVisualLayer() prepareVisualLayer()
prepareDivider()
} }
/// Prepares the visualLayer property. /// Prepares the visualLayer property.
...@@ -346,9 +310,4 @@ open class CollectionViewCell: UICollectionViewCell { ...@@ -346,9 +310,4 @@ open class CollectionViewCell: UICollectionViewCell {
visualLayer.frame = bounds visualLayer.frame = bounds
visualLayer.cornerRadius = cornerRadius visualLayer.cornerRadius = cornerRadius
} }
/// Prepares the divider.
private func prepareDivider() {
divider = Divider(view: self)
}
} }
...@@ -103,3 +103,53 @@ open class Divider { ...@@ -103,3 +103,53 @@ open class Divider {
} }
} }
} }
/// A memory reference to the Divider instance.
private var DividerKey: UInt8 = 0
extension UIView {
/// TabBarItem reference.
public private(set) var divider: Divider {
get {
return AssociatedObject(base: self, key: &DividerKey) {
return Divider(view: self)
}
}
set(value) {
AssociateObject(base: self, key: &DividerKey, value: value)
}
}
/// Divider color.
@IBInspectable
open var dividerColor: UIColor? {
get {
return divider.color
}
set(value) {
divider.color = value
}
}
/// Divider animation.
open var dividerAlignment: DividerAlignment {
get {
return divider.alignment
}
set(value) {
divider.alignment = value
}
}
/// Divider height.
@IBInspectable
open var dividerHeight: CGFloat {
get {
return divider.height
}
set(value) {
divider.height = value
}
}
}
...@@ -30,11 +30,12 @@ ...@@ -30,11 +30,12 @@
import UIKit import UIKit
public class ErrorTextField: TextField { open class ErrorTextField: TextField {
/// Controls the visibility of detailLabel /// Controls the visibility of detailLabel
@IBInspectable public var revealError: Bool = false { @IBInspectable
open var isErrorRevealed = false {
didSet { didSet {
detailLabel.isHidden = !revealError detailLabel.isHidden = !isErrorRevealed
} }
} }
...@@ -45,9 +46,8 @@ public class ErrorTextField: TextField { ...@@ -45,9 +46,8 @@ public class ErrorTextField: TextField {
The super.prepare method should always be called immediately The super.prepare method should always be called immediately
when subclassing. when subclassing.
*/ */
override public func prepare() { open override func prepare() {
super.prepare() super.prepare()
revealError = false
detailColor = Color.red.base detailColor = Color.red.base
} }
} }
...@@ -39,41 +39,6 @@ public enum NavigationBarStyle: Int { ...@@ -39,41 +39,6 @@ public enum NavigationBarStyle: Int {
} }
open class NavigationBar: UINavigationBar { open class NavigationBar: UINavigationBar {
/// Divider layer.
internal private(set) var divider: Divider!
/// Divider color.
@IBInspectable
open var dividerColor: UIColor? {
get {
return divider.color
}
set(value) {
divider.color = value
}
}
/// Divider animation.
open var dividerAlignment: DividerAlignment {
get {
return divider.alignment
}
set(value) {
divider.alignment = value
}
}
/// Divider height.
@IBInspectable
open var dividerHeight: CGFloat {
get {
return divider.height
}
set(value) {
divider.height = value
}
}
open override var intrinsicContentSize: CGSize { open override var intrinsicContentSize: CGSize {
switch navigationBarStyle { switch navigationBarStyle {
case .small: case .small:
...@@ -324,8 +289,6 @@ open class NavigationBar: UINavigationBar { ...@@ -324,8 +289,6 @@ open class NavigationBar: UINavigationBar {
when subclassing. when subclassing.
*/ */
public func prepare() { public func prepare() {
prepareDivider()
barStyle = .black barStyle = .black
isTranslucent = false isTranslucent = false
depthPreset = .depth1 depthPreset = .depth1
...@@ -358,9 +321,4 @@ open class NavigationBar: UINavigationBar { ...@@ -358,9 +321,4 @@ open class NavigationBar: UINavigationBar {
} }
item.titleView = UIView(frame: .zero) item.titleView = UIView(frame: .zero)
} }
/// Prepares the divider.
private func prepareDivider() {
divider = Divider(view: self)
}
} }
...@@ -49,36 +49,37 @@ open class TextField: UITextField { ...@@ -49,36 +49,37 @@ open class TextField: UITextField {
} }
} }
/// Reference to the divider. /// Divider active state height.
open private(set) var divider: CAShapeLayer!
/// Divider height.
@IBInspectable
open var dividerHeight: CGFloat = 1
/// Divider active state height.
@IBInspectable @IBInspectable
open var dividerActiveHeight: CGFloat = 2 open var dividerActiveHeight: CGFloat = 2
/// Sets the divider. /// Sets the divider.
@IBInspectable @IBInspectable
open var dividerColor: UIColor = Color.darkText.dividers { open override var dividerColor: UIColor? {
didSet { get {
if !isEditing { return super.dividerColor
divider.backgroundColor = dividerColor.cgColor }
} set(value) {
} guard !isEditing else {
} return
}
super.dividerColor = value
}
}
/// Sets the divider. /// Sets the divider.
@IBInspectable @IBInspectable
open var dividerActiveColor: UIColor? { open var dividerActiveColor: UIColor? {
didSet { didSet {
if let v: UIColor = dividerActiveColor { guard isEditing else {
if isEditing { return
divider.backgroundColor = v.cgColor }
}
} guard let v = dividerActiveColor else {
return
}
dividerColor = v
} }
} }
...@@ -198,7 +199,7 @@ open class TextField: UITextField { ...@@ -198,7 +199,7 @@ open class TextField: UITextField {
/// Enables the clearIconButton. /// Enables the clearIconButton.
@IBInspectable @IBInspectable
open var isClearIconButtonEnable: Bool { open var isClearIconButtonEnabled: Bool {
get { get {
return nil != clearIconButton return nil != clearIconButton
} }
...@@ -211,7 +212,7 @@ open class TextField: UITextField { ...@@ -211,7 +212,7 @@ open class TextField: UITextField {
clearButtonMode = .never clearButtonMode = .never
rightViewMode = .whileEditing rightViewMode = .whileEditing
rightView = clearIconButton rightView = clearIconButton
clearIconButtonAutoHandle = clearIconButtonAutoHandle ? true : false isClearIconButtonAutoHandled = isClearIconButtonAutoHandled ? true : false
} }
} else { } else {
clearIconButton?.removeTarget(self, action: #selector(handleClearIconButton), for: .touchUpInside) clearIconButton?.removeTarget(self, action: #selector(handleClearIconButton), for: .touchUpInside)
...@@ -222,10 +223,10 @@ open class TextField: UITextField { ...@@ -222,10 +223,10 @@ open class TextField: UITextField {
/// Enables the automatic handling of the clearIconButton. /// Enables the automatic handling of the clearIconButton.
@IBInspectable @IBInspectable
open var clearIconButtonAutoHandle = true { open var isClearIconButtonAutoHandled = true {
didSet { didSet {
clearIconButton?.removeTarget(self, action: #selector(handleClearIconButton), for: .touchUpInside) clearIconButton?.removeTarget(self, action: #selector(handleClearIconButton), for: .touchUpInside)
if clearIconButtonAutoHandle { if isClearIconButtonAutoHandled {
clearIconButton?.addTarget(self, action: #selector(handleClearIconButton), for: .touchUpInside) clearIconButton?.addTarget(self, action: #selector(handleClearIconButton), for: .touchUpInside)
} }
} }
...@@ -233,7 +234,7 @@ open class TextField: UITextField { ...@@ -233,7 +234,7 @@ open class TextField: UITextField {
/// Enables the visibilityIconButton. /// Enables the visibilityIconButton.
@IBInspectable @IBInspectable
open var isVisibilityIconButtonEnable: Bool { open var isVisibilityIconButtonEnabled: Bool {
get { get {
return nil != visibilityIconButton return nil != visibilityIconButton
} }
...@@ -247,7 +248,7 @@ open class TextField: UITextField { ...@@ -247,7 +248,7 @@ open class TextField: UITextField {
clearButtonMode = .never clearButtonMode = .never
rightViewMode = .whileEditing rightViewMode = .whileEditing
rightView = visibilityIconButton rightView = visibilityIconButton
visibilityIconButtonAutoHandle = visibilityIconButtonAutoHandle ? true : false isVisibilityIconButtonAutoHandled = isVisibilityIconButtonAutoHandled ? true : false
} }
} else { } else {
visibilityIconButton?.removeTarget(self, action: #selector(handleVisibilityIconButton), for: .touchUpInside) visibilityIconButton?.removeTarget(self, action: #selector(handleVisibilityIconButton), for: .touchUpInside)
...@@ -258,10 +259,10 @@ open class TextField: UITextField { ...@@ -258,10 +259,10 @@ open class TextField: UITextField {
/// Enables the automatic handling of the visibilityIconButton. /// Enables the automatic handling of the visibilityIconButton.
@IBInspectable @IBInspectable
open var visibilityIconButtonAutoHandle: Bool = true { open var isVisibilityIconButtonAutoHandled: Bool = true {
didSet { didSet {
visibilityIconButton?.removeTarget(self, action: #selector(handleVisibilityIconButton), for: .touchUpInside) visibilityIconButton?.removeTarget(self, action: #selector(handleVisibilityIconButton), for: .touchUpInside)
if visibilityIconButtonAutoHandle { if isVisibilityIconButtonAutoHandled {
visibilityIconButton?.addTarget(self, action: #selector(handleVisibilityIconButton), for: .touchUpInside) visibilityIconButton?.addTarget(self, action: #selector(handleVisibilityIconButton), for: .touchUpInside)
} }
} }
...@@ -312,13 +313,13 @@ open class TextField: UITextField { ...@@ -312,13 +313,13 @@ open class TextField: UITextField {
open override func layoutSubviews() { open override func layoutSubviews() {
super.layoutSubviews() super.layoutSubviews()
layoutToSize() layoutToSize()
layoutDivider()
} }
open override func layoutSublayers(of layer: CALayer) { open override func layoutSublayers(of layer: CALayer) {
super.layoutSublayers(of: layer) super.layoutSublayers(of: layer)
if self.layer == layer { if self.layer == layer {
layoutShape() layoutShape()
layoutDivider()
} }
} }
...@@ -388,7 +389,7 @@ open class TextField: UITextField { ...@@ -388,7 +389,7 @@ open class TextField: UITextField {
/// Layout the divider. /// Layout the divider.
open func layoutDivider() { open func layoutDivider() {
divider.frame = CGRect(x: 0, y: height, width: width, height: isEditing ? dividerActiveHeight : dividerHeight) divider.reload()
} }
/// Layout the placeholderLabel. /// Layout the placeholderLabel.
...@@ -423,8 +424,11 @@ open class TextField: UITextField { ...@@ -423,8 +424,11 @@ open class TextField: UITextField {
/// Layout the detailLabel. /// Layout the detailLabel.
open func layoutDetailLabel() { open func layoutDetailLabel() {
let h: CGFloat = nil == detail ? 12 : detailLabel.font.stringSize(string: detail!, constrainedToWidth: Double(width)).height guard let v = divider.line else {
detailLabel.frame = CGRect(x: 0, y: divider.y + detailVerticalOffset, width: width, height: h) return
}
let h: CGFloat = nil == detail ? 12 : detailLabel.font.stringSize(string: detail!, constrainedToWidth: Double(width)).height
detailLabel.frame = CGRect(x: 0, y: v.y + detailVerticalOffset, width: width, height: h)
} }
/// Layout the clearIconButton. /// Layout the clearIconButton.
...@@ -448,13 +452,13 @@ open class TextField: UITextField { ...@@ -448,13 +452,13 @@ open class TextField: UITextField {
/// The animation for the divider when editing begins. /// The animation for the divider when editing begins.
open func dividerEditingDidBeginAnimation() { open func dividerEditingDidBeginAnimation() {
dividerHeight = dividerActiveHeight dividerHeight = dividerActiveHeight
divider.backgroundColor = nil == dividerActiveColor ? placeholderActiveColor.cgColor : dividerActiveColor!.cgColor dividerColor = dividerActiveColor ?? placeholderActiveColor
} }
/// The animation for the divider when editing ends. /// The animation for the divider when editing ends.
open func dividerEditingDidEndAnimation() { open func dividerEditingDidEndAnimation() {
divider.frame.size.height = dividerHeight // divider.frame.size.height = dividerHeight
divider.backgroundColor = dividerColor.cgColor // divider.color = dividerColor
} }
/// The animation for the placeholder when editing begins. /// The animation for the placeholder when editing begins.
...@@ -503,9 +507,7 @@ open class TextField: UITextField { ...@@ -503,9 +507,7 @@ open class TextField: UITextField {
/// Prepares the divider. /// Prepares the divider.
private func prepareDivider() { private func prepareDivider() {
divider = CAShapeLayer() dividerColor = Color.darkText.dividers
dividerColor = Color.darkText.dividers
layer.addSublayer(divider)
} }
/// Prepares the placeholderLabel. /// Prepares the placeholderLabel.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment