Skip to content

Commit

Permalink
Added example project
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewGene committed Aug 23, 2016
1 parent 91668a0 commit 12571a7
Show file tree
Hide file tree
Showing 5 changed files with 1,007 additions and 0 deletions.
249 changes: 249 additions & 0 deletions WASHD/Classes/JumpOrder.swift
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)
}
}
}
}
}
}
83 changes: 83 additions & 0 deletions WASHD/Classes/MaxLength.swift
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 removed WASHD/Classes/ReplaceMe.swift
Empty file.
Loading

0 comments on commit 12571a7

Please sign in to comment.