-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
91668a0
commit 12571a7
Showing
5 changed files
with
1,007 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,249 @@ | ||
// | ||
// JumpOrder.swift | ||
// UITextFieldExtensions | ||
// | ||
// Created by Andrew Goodwin on 8/19/16. | ||
// Copyright © 2016 Andrew Goodwin. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import UIKit | ||
|
||
private struct AssociatedKeys { | ||
static var fri = "jumpOrder" | ||
static var fra = "firstResponderArray" | ||
static var cfri = "currentjumpOrder" | ||
static var mnd = "moveNextDate" | ||
static var mnt = "moveNextTimer" | ||
static var fj = "formatJump" | ||
static var lj = "lengthJump" | ||
static var fn = "formatNotification" | ||
static var ln = "lengthNotification" | ||
static var tfn = "textFormatNotification" | ||
static var tln = "textLengthNotification" | ||
} | ||
|
||
@IBDesignable | ||
extension UITextField | ||
{ | ||
@IBInspectable | ||
var formatJump: Bool { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.fj) as? Bool ?? false | ||
} | ||
set { | ||
objc_setAssociatedObject(self, &AssociatedKeys.fj, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
|
||
@IBInspectable | ||
var lengthJump: Bool { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.lj) as? Bool ?? false | ||
} | ||
set { | ||
objc_setAssociatedObject(self, &AssociatedKeys.lj, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
|
||
var textLengthNotification: AnyObject? { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.tln) ?? nil | ||
} | ||
set { | ||
objc_setAssociatedObject(self, &AssociatedKeys.tln, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
|
||
var textFormatNotification: AnyObject? { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.tfn) ?? nil | ||
} | ||
set { | ||
objc_setAssociatedObject(self, &AssociatedKeys.tfn, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
|
||
@IBInspectable | ||
var jumpOrder: Int { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.fri) as? Int ?? -1 | ||
} | ||
set { | ||
if textFormatNotification != nil{ | ||
NSNotificationCenter.defaultCenter().removeObserver(textFormatNotification!) | ||
} | ||
textFormatNotification = NSNotificationCenter.defaultCenter().addObserverForName("text.MoveNext.Format", object: nil, queue: NSOperationQueue.mainQueue()) { [weak self](notification) in | ||
if self!.formatJump{ | ||
NSNotificationCenter.defaultCenter().postNotificationName("firstResponder.MoveNext.Format", object: nil) | ||
} | ||
} | ||
if textLengthNotification != nil{ | ||
NSNotificationCenter.defaultCenter().removeObserver(textLengthNotification!) | ||
} | ||
textLengthNotification = NSNotificationCenter.defaultCenter().addObserverForName("text.MoveNext.MaxLength", object: nil, queue: NSOperationQueue.mainQueue()) { [weak self](notification) in | ||
if self!.lengthJump{ | ||
NSNotificationCenter.defaultCenter().postNotificationName("firstResponder.MoveNext.MaxLength", object: nil) | ||
} | ||
} | ||
objc_setAssociatedObject(self, &AssociatedKeys.fri, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
|
||
func getjumpOrder()->Int{ | ||
return jumpOrder | ||
//NSNotificationCenter.defaultCenter().postNotificationName("firstResponder.MoveNext", object: jumpOrder + 1) | ||
} | ||
} | ||
|
||
@IBDesignable | ||
extension UITextView | ||
{ | ||
@IBInspectable | ||
var jumpOrder: Int { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.fri) as? Int ?? -1 | ||
} | ||
set { | ||
objc_setAssociatedObject(self, &AssociatedKeys.fri, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
|
||
func getjumpOrder()->Int{ | ||
return jumpOrder | ||
//NSNotificationCenter.defaultCenter().postNotificationName("firstResponder.MoveNext", object: jumpOrder + 1) | ||
} | ||
} | ||
|
||
extension UIViewController{ | ||
|
||
var currentjumpOrder: Int { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.cfri) as? Int ?? -1 | ||
} | ||
set { | ||
objc_setAssociatedObject(self, &AssociatedKeys.cfri, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
var textInputArray: [UIView] { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.fra) as? [UIView] ?? [UIView]() | ||
} | ||
set { | ||
objc_setAssociatedObject( | ||
self, | ||
&AssociatedKeys.fra, | ||
newValue as [UIView]?, | ||
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC | ||
) | ||
} | ||
} | ||
var moveNextDate: NSDate? { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.mnd) as? NSDate ?? nil | ||
} | ||
set { | ||
objc_setAssociatedObject(self, &AssociatedKeys.mnd, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
var moveNextTimer: NSTimer? { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.mnt) as? NSTimer ?? nil | ||
} | ||
set { | ||
objc_setAssociatedObject(self, &AssociatedKeys.mnt, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
var formatNotification: AnyObject? { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.fn) ?? nil | ||
} | ||
set { | ||
objc_setAssociatedObject(self, &AssociatedKeys.fn, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
var lengthNotification: AnyObject? { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.ln) ?? nil | ||
} | ||
set { | ||
objc_setAssociatedObject(self, &AssociatedKeys.ln, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
|
||
func moveNext(){ | ||
self.moveNextDate = NSDate() | ||
for view in self.textInputArray{ | ||
if view is UITextField{ | ||
let tf = view as! UITextField | ||
if tf.jumpOrder == currentjumpOrder + 1{ | ||
tf.becomeFirstResponder() | ||
currentjumpOrder = tf.jumpOrder | ||
break | ||
} | ||
} | ||
else if view is UITextView{ | ||
let tf = view as! UITextView | ||
if tf.jumpOrder == currentjumpOrder + 1{ | ||
tf.becomeFirstResponder() | ||
currentjumpOrder = tf.jumpOrder | ||
break | ||
} | ||
} | ||
} | ||
} | ||
|
||
func findAllTextInputs(){ | ||
self.textInputArray = [UIView]() | ||
if formatNotification != nil{ | ||
NSNotificationCenter.defaultCenter().removeObserver(formatNotification!) | ||
} | ||
formatNotification = NSNotificationCenter.defaultCenter().addObserverForName("firstResponder.MoveNext.Format", object: nil, queue: NSOperationQueue.mainQueue()) { [weak self](notification) in | ||
if self!.moveNextDate == nil{ | ||
//nothing has fired before | ||
self!.moveNext() | ||
} | ||
else if self!.moveNextDate != nil{ | ||
print(self!.moveNextDate!.timeIntervalSinceNow) | ||
if abs(self!.moveNextDate!.timeIntervalSinceNow) < 0.1{ | ||
//do nothing | ||
} | ||
else{ | ||
self!.moveNext() | ||
} | ||
} | ||
} | ||
if lengthNotification != nil{ | ||
NSNotificationCenter.defaultCenter().removeObserver(lengthNotification!) | ||
} | ||
lengthNotification = NSNotificationCenter.defaultCenter().addObserverForName("firstResponder.MoveNext.MaxLength", object: nil, queue: NSOperationQueue.mainQueue()) { [weak self](notification) in | ||
if self!.moveNextDate == nil{ | ||
//nothing has fired before | ||
self!.moveNext() | ||
} | ||
else if self!.moveNextDate != nil{ | ||
print(self!.moveNextDate!.timeIntervalSinceNow) | ||
if abs(self!.moveNextDate!.timeIntervalSinceNow) < 0.1{ | ||
//do nothing | ||
} | ||
else{ | ||
self!.moveNext() | ||
} | ||
} | ||
} | ||
findAllTextInputsInView(self.view) | ||
} | ||
|
||
private func findAllTextInputsInView(inputView:UIView){ | ||
for view in inputView.subviews{ | ||
if view.respondsToSelector(Selector("getjumpOrder")){ | ||
if view is UITextField{ | ||
textInputArray.append(view) | ||
if view.subviews.count > 0{ | ||
findAllTextInputsInView(view) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// | ||
// Maxlength.swift | ||
// | ||
// Created by Andrew Goodwin on 8/16/16. | ||
// Copyright © 2016 Conway Corporation. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import UIKit | ||
|
||
private struct AssociatedKeys { | ||
static var len = "length" | ||
} | ||
|
||
@IBDesignable | ||
extension UITextField | ||
{ | ||
@IBInspectable | ||
var maxLength: Int { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.len) as? Int ?? Int.max | ||
} | ||
set { | ||
objc_setAssociatedObject(self, &AssociatedKeys.len, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
|
||
func reachedMaxLength(range:NSRange, string:String)->Bool{ | ||
let oldLength = self.text!.characters.count | ||
let replacementLength = string.characters.count | ||
let rangeLength = range.length | ||
let newLength = oldLength - rangeLength + replacementLength | ||
|
||
let returnKey = string.rangeOfString("\n") != nil | ||
let isBackspace = string == "" | ||
let shouldAllow = newLength <= self.maxLength || returnKey || isBackspace | ||
if self.maxLength == newLength{ | ||
//do i support auto first responder | ||
NSTimer.scheduledTimerWithTimeInterval(0.05, target: self, selector: #selector(goNext), userInfo: nil, repeats: false) | ||
} | ||
return !shouldAllow | ||
} | ||
|
||
@objc private func goNext(){ | ||
NSNotificationCenter.defaultCenter().postNotificationName("text.MoveNext.MaxLength", object: nil) | ||
} | ||
|
||
} | ||
|
||
@IBDesignable | ||
extension UITextView | ||
{ | ||
@IBInspectable | ||
var maxLength: Int { | ||
get { | ||
return objc_getAssociatedObject(self, &AssociatedKeys.len) as? Int ?? Int.max | ||
} | ||
set { | ||
objc_setAssociatedObject(self, &AssociatedKeys.len, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) | ||
} | ||
} | ||
|
||
func reachedMaxLength(range:NSRange, string:String)->Bool{ | ||
let oldLength = self.text!.characters.count | ||
let replacementLength = string.characters.count | ||
let rangeLength = range.length | ||
let newLength = oldLength - rangeLength + replacementLength | ||
|
||
let returnKey = string.rangeOfString("\n") != nil | ||
let isBackspace = string == "" | ||
let shouldAllow = newLength <= self.maxLength || returnKey || isBackspace | ||
if self.maxLength == newLength{ | ||
//do i support auto first responder | ||
NSTimer.scheduledTimerWithTimeInterval(0.05, target: self, selector: #selector(goNext), userInfo: nil, repeats: false) | ||
} | ||
return shouldAllow | ||
} | ||
|
||
@objc private func goNext(){ | ||
NSNotificationCenter.defaultCenter().postNotificationName("text.MoveNext.MaxLength", object: nil) | ||
} | ||
|
||
} |
Empty file.
Oops, something went wrong.