Created
January 20, 2016 17:43
-
-
Save MosheBerman/d65408b75dc28a7046e0 to your computer and use it in GitHub Desktop.
A broken agreement view class that its supposed to interpolate text fields with the form text.
This file contains hidden or 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
// | |
// AgreementView.swift | |
// Intake | |
// | |
// Created by Moshe Berman on 12/11/15. | |
// Copyright © 2015 Moshe Berman. All rights reserved. | |
// | |
import UIKit | |
class AgreementView: UITextView, NSLayoutManagerDelegate { | |
var delimiter = "__x__" | |
var indices : [NSRange] = [] | |
var textFields : [AgreementTextField] = [] | |
var formfields : [FormField] = [] | |
var agreement : Form? { | |
didSet { | |
self.cleanup() | |
if let agreement = self.agreement { | |
self.text = agreement.agreementText | |
self.formfields = agreement.allFields() | |
self.showTextFields() | |
} | |
} | |
} | |
override init(frame: CGRect, textContainer: NSTextContainer?) { | |
super.init(frame: frame, textContainer: textContainer) | |
self.textContainer.layoutManager?.delegate = self | |
self.font = UIFont(descriptor: UIFontDescriptor.preferredFontDescriptorWithTextStyle(UIFontTextStyleBody), size: 0) | |
} | |
required init?(coder aDecoder: NSCoder) { | |
super.init(coder: aDecoder) | |
self.textContainer.layoutManager?.delegate = self | |
self.font = UIFont(descriptor: UIFontDescriptor.preferredFontDescriptorWithTextStyle(UIFontTextStyleBody), size: 0) | |
} | |
// MARK: - Show the agreement input fields | |
func showTextFields() { | |
self.calculateTextFieldIndices() | |
self.createTextFieldsForFormFields() | |
self.createAndAssignExclusionPathsForInputTextFields() | |
self.installTextFields() | |
} | |
// MARK: - Form Fields | |
func createTextFieldsForFormFields () { | |
self.textFields = [] | |
var index = 0 | |
let count = self.formfields.count | |
while index < count { | |
let formField = self.formfields[index] | |
let textField = AgreementTextField(frame: CGRectZero, formField: formField) | |
textField.placeholder = formField.displayName | |
self.textFields.append(textField) | |
index = index + 1 | |
} | |
} | |
// Calculate where to put the text fields | |
func createAndAssignExclusionPathsForInputTextFields () { | |
var index = 0 | |
let textFieldCount = self.textFields.count | |
var exclusionPaths : [UIBezierPath] = [] | |
while index < textFieldCount { | |
let textField : AgreementTextField = self.textFields[index] | |
let location = self.calculatePositionOfPlaceholderAtIndex(index) | |
let size = textField.intrinsicContentSize() | |
textField.frame = CGRectMake(location.x, location.y, size.width, size.height) | |
exclusionPaths.append(textField.exclusionPath()) | |
self.textContainer.exclusionPaths = exclusionPaths | |
self.layoutManager.ensureLayoutForTextContainer(self.textContainer) | |
index = index + 1 | |
} | |
self.textContainer.exclusionPaths = exclusionPaths | |
} | |
func installTextFields() { | |
for field in self.textFields { | |
self.addSubview(field) | |
} | |
} | |
// MARK: - Helpers | |
// Find the indices of all of the placeholders. | |
func calculateTextFieldIndices () { | |
var indicesOfDelimiters : [NSRange] = [] | |
let searchString = NSString(string: self.textStorage.string) | |
var nextDelimiterRange : NSRange = NSMakeRange(0, searchString.length) | |
while nextDelimiterRange.location != NSNotFound | |
{ | |
nextDelimiterRange = searchString.rangeOfString(self.delimiter, options: [], range: nextDelimiterRange) | |
if nextDelimiterRange.location != NSNotFound { | |
let location = nextDelimiterRange.location - (self.delimiter.characters.count * indicesOfDelimiters.count) | |
let rangeToAppend = NSMakeRange(location, self.delimiter.characters.count) | |
indicesOfDelimiters.append(rangeToAppend) // Grab actual location | |
nextDelimiterRange = NSMakeRange(nextDelimiterRange.location + nextDelimiterRange.length, searchString.length - (nextDelimiterRange.location + nextDelimiterRange.length)) | |
} | |
} | |
self.indices = indicesOfDelimiters | |
} | |
// Figure out where the text container wanted to put the | |
// placeholder glyph and use that to show the text field. | |
func calculatePositionOfPlaceholderAtIndex(textIndex : NSInteger) -> CGPoint { | |
let layoutManager : NSLayoutManager = self.textContainer.layoutManager! | |
let delimiterRange = self.indices[textIndex] | |
let characterIndex = delimiterRange.location | |
let glyphRange = self.layoutManager.glyphRangeForCharacterRange(delimiterRange, actualCharacterRange:nil) | |
let glyphIndex = glyphRange.location | |
let rect = layoutManager.lineFragmentRectForGlyphAtIndex(glyphIndex, effectiveRange: nil, withoutAdditionalLayout: true) | |
let remainingRect : UnsafeMutablePointer<CGRect> = nil | |
let textContainerRect = self.textContainer.lineFragmentRectForProposedRect(rect, atIndex: characterIndex, writingDirection: .LeftToRight, remainingRect: remainingRect) | |
let position = CGPointMake(rect.origin.x, textContainerRect.origin.y) | |
print("Position: \(position) Character Index: \(characterIndex), Manager Rect: \(rect), Text Container Rect: \(textContainerRect)") | |
return position | |
} | |
// MARK: - Cleanup | |
func cleanup() { | |
for textField in self.textFields { | |
textField.removeFromSuperview() | |
} | |
self.textFields.removeAll() | |
self.indices.removeAll() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment