Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
Material
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Dmitriy Stepanets
Material
Commits
92bfca28
Commit
92bfca28
authored
Jun 01, 2018
by
Orkhan Alikhanov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added ErrorTextFieldValidator
parent
5cbae5db
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
135 additions
and
0 deletions
+135
-0
Material.xcodeproj/project.pbxproj
+4
-0
Sources/iOS/ErrorTextFieldValidator.swift
+131
-0
No files found.
Material.xcodeproj/project.pbxproj
View file @
92bfca28
...
@@ -180,6 +180,7 @@
...
@@ -180,6 +180,7 @@
9DF352421FED20C900B2A11B
/* BaseIconLayerButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
9DF352411FED20C900B2A11B
/* BaseIconLayerButton.swift */
;
};
9DF352421FED20C900B2A11B
/* BaseIconLayerButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
9DF352411FED20C900B2A11B
/* BaseIconLayerButton.swift */
;
};
9DF352441FED20ED00B2A11B
/* RadioButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
9DF352431FED20ED00B2A11B
/* RadioButton.swift */
;
};
9DF352441FED20ED00B2A11B
/* RadioButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
9DF352431FED20ED00B2A11B
/* RadioButton.swift */
;
};
9DF352461FED210000B2A11B
/* CheckButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
9DF352451FED210000B2A11B
/* CheckButton.swift */
;
};
9DF352461FED210000B2A11B
/* CheckButton.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
9DF352451FED210000B2A11B
/* CheckButton.swift */
;
};
9DF58CEE20C098C60098968D
/* ErrorTextFieldValidator.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
9DF58CED20C098C60098968D
/* ErrorTextFieldValidator.swift */
;
};
/* End PBXBuildFile section */
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
/* Begin PBXContainerItemProxy section */
...
@@ -297,6 +298,7 @@
...
@@ -297,6 +298,7 @@
9DF352411FED20C900B2A11B
/* BaseIconLayerButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
BaseIconLayerButton.swift
;
sourceTree
=
"<group>"
;
};
9DF352411FED20C900B2A11B
/* BaseIconLayerButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
BaseIconLayerButton.swift
;
sourceTree
=
"<group>"
;
};
9DF352431FED20ED00B2A11B
/* RadioButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
RadioButton.swift
;
sourceTree
=
"<group>"
;
};
9DF352431FED20ED00B2A11B
/* RadioButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
RadioButton.swift
;
sourceTree
=
"<group>"
;
};
9DF352451FED210000B2A11B
/* CheckButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CheckButton.swift
;
sourceTree
=
"<group>"
;
};
9DF352451FED210000B2A11B
/* CheckButton.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
CheckButton.swift
;
sourceTree
=
"<group>"
;
};
9DF58CED20C098C60098968D
/* ErrorTextFieldValidator.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
ErrorTextFieldValidator.swift
;
sourceTree
=
"<group>"
;
};
/* End PBXFileReference section */
/* End PBXFileReference section */
/* Begin PBXGroup section */
/* Begin PBXGroup section */
...
@@ -315,6 +317,7 @@
...
@@ -315,6 +317,7 @@
96BCB79E1CB40DC500C806FE
/* TextView.swift */
,
96BCB79E1CB40DC500C806FE
/* TextView.swift */
,
96BCB79C1CB40DC500C806FE
/* TextField.swift */
,
96BCB79C1CB40DC500C806FE
/* TextField.swift */
,
961F18E71CD93E3E008927C5
/* ErrorTextField.swift */
,
961F18E71CD93E3E008927C5
/* ErrorTextField.swift */
,
9DF58CED20C098C60098968D
/* ErrorTextFieldValidator.swift */
,
);
);
name
=
Text
;
name
=
Text
;
sourceTree
=
"<group>"
;
sourceTree
=
"<group>"
;
...
@@ -1005,6 +1008,7 @@
...
@@ -1005,6 +1008,7 @@
965E80CE1DD4C50600D61E4B
/* FABButton.swift in Sources */
,
965E80CE1DD4C50600D61E4B
/* FABButton.swift in Sources */
,
965E80CF1DD4C50600D61E4B
/* FlatButton.swift in Sources */
,
965E80CF1DD4C50600D61E4B
/* FlatButton.swift in Sources */
,
965E80D01DD4C50600D61E4B
/* RaisedButton.swift in Sources */
,
965E80D01DD4C50600D61E4B
/* RaisedButton.swift in Sources */
,
9DF58CEE20C098C60098968D
/* ErrorTextFieldValidator.swift in Sources */
,
96A183631E0C6CE200083C30
/* FABMenu.swift in Sources */
,
96A183631E0C6CE200083C30
/* FABMenu.swift in Sources */
,
965E80D11DD4C50600D61E4B
/* IconButton.swift in Sources */
,
965E80D11DD4C50600D61E4B
/* IconButton.swift in Sources */
,
965E80D21DD4C50600D61E4B
/* Color.swift in Sources */
,
965E80D21DD4C50600D61E4B
/* Color.swift in Sources */
,
...
...
Sources/iOS/ErrorTextFieldValidator.swift
0 → 100644
View file @
92bfca28
//
// ErrorTextFieldValidator.swift
// Material
//
// Created by Orkhan Alikhanov on 30/05/2018.
// Copyright © 2018 CosmicMind, Inc. All rights reserved.
//
import
UIKit
import
Motion
open
class
ErrorTextFieldValidator
:
NSObject
{
public
typealias
ValidationClosure
=
(
String
)
->
Bool
open
var
closures
:
[(
code
:
ValidationClosure
,
msg
:
String
)]
=
[]
open
weak
var
textField
:
ErrorTextField
?
open
var
autoValidationType
:
AutoValidationType
=
.
default
open
var
autoValidateOnlyIfErrorIsShownOnce
=
true
open
var
isErrorShownOnce
=
false
public
init
(
textField
:
ErrorTextField
)
{
self
.
textField
=
textField
super
.
init
()
textField
.
addTarget
(
self
,
action
:
#selector(
checkIfErrorHasGone
)
,
for
:
.
editingChanged
)
}
@objc
private
func
checkIfErrorHasGone
()
{
guard
let
textField
=
textField
else
{
return
}
if
autoValidateOnlyIfErrorIsShownOnce
&&
!
isErrorShownOnce
{
return
}
switch
autoValidationType
{
case
.
none
:
break
case
.
custom
(
let
closure
):
closure
(
textField
)
case
.
default
:
_
=
textField
.
isValid
()
// will hide if needed
}
}
open
func
isValid
(
deferred
:
Bool
)
->
Bool
{
guard
let
textField
=
textField
else
{
return
false
}
if
!
deferred
{
textField
.
isErrorRevealed
=
false
}
for
block
in
closures
{
if
!
block
.
code
(
textField
.
text
??
""
)
{
if
!
deferred
{
textField
.
error
=
block
.
msg
textField
.
isErrorRevealed
=
true
isErrorShownOnce
=
true
}
return
false
}
}
return
true
}
@discardableResult
open
func
validate
(
msg
:
String
,
when
code
:
@escaping
ValidationClosure
)
->
Self
{
closures
.
append
((
code
,
msg
))
return
self
}
public
enum
AutoValidationType
{
case
none
case
`
default
`
case
custom
((
ErrorTextField
)
->
Void
)
}
}
private
var
AssociatedInstanceKey
:
UInt8
=
0
extension
ErrorTextField
{
open
var
validator
:
ErrorTextFieldValidator
{
get
{
return
AssociatedObject
.
get
(
base
:
self
,
key
:
&
AssociatedInstanceKey
)
{
return
ErrorTextFieldValidator
(
textField
:
self
)
}
}
set
(
value
)
{
AssociatedObject
.
set
(
base
:
self
,
key
:
&
AssociatedInstanceKey
,
value
:
value
)
}
}
open
func
isValid
(
deferred
:
Bool
=
false
)
->
Bool
{
return
validator
.
isValid
(
deferred
:
deferred
)
}
}
public
extension
ErrorTextFieldValidator
{
@discardableResult
func
email
(
msg
:
String
)
->
Self
{
return
regex
(
msg
:
msg
,
pattern
:
"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+
\\
.[A-Za-z]{2,64}"
)
}
@discardableResult
func
username
(
msg
:
String
)
->
Self
{
return
regex
(
msg
:
msg
,
pattern
:
"^[a-zA-Z0-9]+([_
\\
s
\\
-
\\
.
\\
']?[a-zA-Z0-9])*$"
)
}
@discardableResult
func
regex
(
msg
:
String
,
pattern
:
String
)
->
Self
{
return
validate
(
msg
:
msg
)
{
let
pred
=
NSPredicate
(
format
:
"SELF MATCHES %@"
,
pattern
)
return
pred
.
evaluate
(
with
:
$0
)
}
}
@discardableResult
func
min
(
length
:
Int
,
msg
:
String
,
trimmingSet
:
CharacterSet
?
=
.
whitespacesAndNewlines
)
->
Self
{
let
trimmingSet
=
trimmingSet
??
.
init
()
return
validate
(
msg
:
msg
)
{
$0
.
trimmingCharacters
(
in
:
trimmingSet
)
.
count
>=
length
}
}
@discardableResult
func
notEmpty
(
msg
:
String
,
trimmingSet
:
CharacterSet
?
=
.
whitespacesAndNewlines
)
->
Self
{
let
trimmingSet
=
trimmingSet
??
.
init
()
return
validate
(
msg
:
msg
)
{
$0
.
trimmingCharacters
(
in
:
trimmingSet
)
.
isEmpty
==
false
}
}
@discardableResult
func
noWhitespaces
(
msg
:
String
)
->
Self
{
return
validate
(
msg
:
msg
)
{
$0
.
rangeOfCharacter
(
from
:
.
whitespaces
)
==
nil
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment