Darkened overlay while user is typing - ios

When the user taps on a text field, I wanted to darken the rest of the screen (everything below the text box, above the keyboard) to make it clear what they should be doing. I believe it involved putting a transparent UI view down and adding a gesture recognizer to it, but I'm not quite sure how to do that.
I've got the following code for when the user arrives on the screen. Is this where I would add the new UI View?
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
textField.becomeFirstResponder()
}
Thanks!

I created a subclass of UIView for two reasons:
you can add a gesture recogniser to it
you can add a delegate to it
Since the last subview added to a view is on top I first add the dark layer and then call bringSubviewToFront(textview) this will put the dark layer between the textview in question and everything else.
I created a protocol with one function. This function get's called by the gesture recogniser and returns the instance of DarkView to the delegate. The delegate (your ViewController) can then remove it from it's superview.
This you can do without a delegate function, but you also have to call resignFirstResponder() on the textfield.
Don't forget to set up the delegate of the DarkView in your ViewController.
Just a VC with some textfields.
class FirstViewController: UIViewController, DarkViewDelegate, UITextFieldDelegate {
var masterView : UIView!
override func viewDidLoad() {
super.viewDidLoad()
masterView = UIView(frame: self.view.frame)
masterView.backgroundColor = UIColor.whiteColor()
let textField1 = UITextField(frame: CGRect(x: 50, y: 20, width: 300, height: 20))
let textField2 = UITextField(frame: CGRect(x: 50, y: 60, width: 300, height: 20))
let textField3 = UITextField(frame: CGRect(x: 50, y: 100, width: 300, height: 20))
let textField4 = UITextField(frame: CGRect(x: 50, y: 140, width: 300, height: 20))
func styleTextField(field : UITextField) {
field.layer.borderColor = UIColor.blackColor().CGColor
field.layer.borderWidth = 2
field.layer.cornerRadius = field.frame.size.height / 2
field.backgroundColor = UIColor.whiteColor()
field.delegate = self
masterView.addSubview(field)
}
styleTextField(textField1)
styleTextField(textField2)
styleTextField(textField3)
styleTextField(textField4)
self.view.addSubview(masterView)
// Do any additional setup after loading the view, typically from a nib.
}
// delegate function of a textfield
func textFieldDidBeginEditing(textField: UITextField) {
focusUserOn(textField) // darken everything else
}
// delegate function of DarkView undarken everything
func tappedDark(view: DarkView) {
guard let superV = view.superview else {
return
}
if let textField = superV.subviews.last as? UITextField {
textField.resignFirstResponder() // also stop editing
}
view.removeFromSuperview()
}
func focusUserOn(textfield: UITextField) {
guard let superV = textfield.superview else {
return
}
let darkArea = DarkView(frame: superV.bounds)
darkArea.delegate = self
superV.addSubview(darkArea)// add DarkView (everything is dark now)
superV.bringSubviewToFront(textfield) // bring the textview back to the front.
}
}
simple subclass of UIView with a gesture recogniser
class DarkView : UIView, UIGestureRecognizerDelegate {
weak var delegate : DarkViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.4)
let tap = UITapGestureRecognizer(target: self, action: Selector("tapped"))
tap.delegate = self
self.addGestureRecognizer(tap)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
print("deinit dark")
}
func tapped() {
guard let del = self.delegate else {
return
}
del.tappedDark(self)
}
}
Protocol to pass the DarkView when it is tapped to a VC
protocol DarkViewDelegate : class {
func tappedDark(view:DarkView)
}
After thought
func textFieldDidEndEditing(textField: UITextField) {
guard let superV = view.superview else {
return
}
for subview in superV.subviews {
if subview is DarkView {
subview.removeFromSuperview()
}
}
}

Yes, you have the right idea. Add your UIView (let's call it darkeningView) to your storyboard and set it's background color to 50% opaque black. Position it where you want it and add constraints that position it there.
You can also attach a tap gesture recognizer to the darkeningView in IB and set up it's delegate. (You will probably need to set userInteractionEnabled = true on the darkeningView so that it responds to taps.
Add an IBOutlet to your view. In IB, set it to hidden = true.
In your code, when you activate the text field for editing, also set your darkeningView.hidden = false.

Related

Swift: Changing (translate) a UIView position through a pan gesture in its superview window

Introduction
Context:
In my main ViewController I have a scrollView with a few objects inside (which are UIViews). When one of the UIViews are tapped/selected I animate forward a UITextView in a UIView to go with the selected object. (only one UIView can appear at a time)
This UIView that appears on object selection is separated into a separate class called AdjunctiveTextView.
Issue/goal:
(the example code provided below will clear make this clear, I've also commented where the issue lies in the code)
When an object has been tapped and has an adjacent UIView with a text I want to have that adjacent UIView to follow with the scrollView.
I'm using a UIPanGestureRecognizer to attempt to do this. But I can't figure out how to make it work when the user drags in the scrollview. It only work if the user drags on the actual adjunctiveTextView.
Everything works as expected except that the adjunctiveTextView does not change its position during the panGesture.
I would like (if possible) to have the AdjunctiveTextView as a separate class. My ViewController file is getting rather big.
Question:
Why doesn't the UIPanGestureRecognizer work as expected? What is needed in order for it to translate the backView correctly?
Code
My attempt: (as shown below)
My attempt simply makes the backView itself "dragable" around through the panGesture. Nothing happens to it when I scroll the scrollView.
(I have only included relevant portions of my code)
class ViewController: UIViewController {
let adjunctiveTextView = AdjunctiveTextView()
// this is a delegate method which gets called when an object is tapped in the scrollView
func scrollViewObjectIsTapped(_ objectScrollView: ObjectScrollView, object: AvailableObject) {
** adjunctiveTextView.scrollView = scrollView // **Edited! (scrollView is the name of the scrollView in this class too)
adjunctiveTextView.showView(passInObject: AvailableObject)
}
}
class AdjunctiveTextView: NSObject {
lazy var backView: UIView = {
//backView setup
}
lazy var textView: UITextView = {
//textView setup
}
//additional init and setup
** weak var scrollView : UIScrollView! // **Edited!
func showView(passInObject: AvailableObject) {
if let window = UIApplication.shared.keyWindow {
// the issue must either be here in the PanGesture setup
let panG = UIPanGestureRecognizer(target: self, action: #selector(translateView(sender:)))
panG.cancelsTouchesInView = false
// window.addGestureRecognizer(panG)
** scrollView.addGestureRecognizer(panG) // **Edited!
window.addSubview(backView)
textView.text = passInObject.information
backView.frame = CGRect(x: passInObject.frame.minX, y: passInObject.minY, width: window.frame.width - passInObject.maxX - 6, height: textView.bounds.height + 5)
backView.alpha = 0
//it animates a change of the backViews x position and alpha.
UIView.animate(withDuration: 0.42, delay: 0, options: .curveEaseInOut, animations: {
self.backView.alpha = 1
self.backView.frame = CGRect(x: passInObject.frame.minX + passInObject.frame.width, y: passInObject.minY, width: window.frame.width - passInObject.maxX - 6, height: textView.bounds.height + 5)
}, completion: nil)
}
}
// or the issue is here in the handle function for the PanGesture.
#objc private func translateView(sender: UIPanGestureRecognizer) {
if let window = UIApplication.shared.keyWindow {
let translation = sender.translation(in: window) //Have tried setting this to scrollView also
switch sender.state {
case .began, .changed:
backView.center = CGPoint(x: backView.center.x, y: backView.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: window) //Have tried setting this to sccrollView also
break
case .ended:
break
default:
break
}
}
}
}
Thanks for reading my question.
I just add a weak reference to your scrollView and then add the pan gesture to scrollView. It works as you want. You may consider add another pan gesture to the back view if you want your original behavior.
class AdjunctiveTextView: NSObject {
lazy var backView: UIView = {
//backView setup
return UIView.init()
}()
lazy var textView: UITextView = {
//textView setup
return UITextView.init(frame: CGRect.init(x: 0, y: 0, width: 300, height: 100))
}()
weak var scrollView: UIScrollView!
//additional init and setup
func showView(passInObject: AvailableObject) {
if let window = UIApplication.shared.keyWindow {
// the issue must either be here in the PanGesture setup
let panG = UIPanGestureRecognizer(target: self, action: #selector(translateView(sender:)))
panG.cancelsTouchesInView = false
// passInObject.addGestureRecognizer(panG)
scrollView.addGestureRecognizer(panG)
window.addSubview(backView)
textView.text = passInObject.information
textView.backgroundColor = UIColor.blue
backView.addSubview(textView)
backView.frame = CGRect(x: passInObject.frame.minX, y: passInObject.frame.minY, width: window.frame.width - passInObject.frame.maxX - 6, height: textView.bounds.height + 5)
backView.alpha = 0
//it animates a change of the backViews x position and alpha.
UIView.animate(withDuration: 0.42, delay: 0, options: .curveEaseInOut, animations: {
self.backView.alpha = 1
self.backView.frame = CGRect(x: passInObject.frame.minX + passInObject.frame.width , y: passInObject.frame.minY , width: window.frame.width - passInObject.frame.maxX - 6, height: self.textView.bounds.height + 5)
self.backView.backgroundColor = UIColor.red
}, completion: nil)
}
}
// or the issue is here in the handle function for the PanGesture.
#objc private func translateView(sender: UIPanGestureRecognizer) {
if let window = UIApplication.shared.keyWindow {
let translation = sender.translation(in: window)
switch sender.state {
case .began, .changed:
backView.center = CGPoint(x: backView.center.x, y: backView.center.y + translation.y)
sender.setTranslation(CGPoint.zero, in: window)
break
case .ended:
break
default:
break
}
}
}
}
class ObjectScrollView: UIScrollView{
}
class AvailableObject: UIView{
var information: String!
}
class MySCNViewController: UIViewController {
#IBOutlet weak var oScrollView: ObjectScrollView!
// this is a delegate method which gets called when an object is tapped in the scrollView
func scrollViewObjectIsTapped(_ objectScrollView: ObjectScrollView, object: AvailableObject) {
adjunctiveTextView.showView(passInObject: object)
}
let adjunctiveTextView = AdjunctiveTextView()
let ao = AvailableObject.init(frame: CGRect.init(x: 0, y: 0, width: 200, height: 200))
override func viewDidLoad() {
super.viewDidLoad()
ao.information = "test"
adjunctiveTextView.scrollView = oScrollView
ao.backgroundColor = UIColor.yellow
}
#IBAction func tap(_ sender: Any?){
scrollViewObjectIsTapped(oScrollView, object: ao)}
}

UIButton is not clickable after first click

I am trying to bring a subview from bottom when button is clicked. But only for the first time the button is clickable. For second click after animation button is not clickable.
Here is the code.
class AnimateView: UIView {
var button: UIButton!
var menuView: UIView!
var mainView: UIView!
override init(frame: CGRect) {
super.init(frame: frame)
mainView = UIView(frame: CGRect(x: 0, y: 0, width:
self.frame.size.width, height: self.frame.size.height))
mainView.clipsToBounds = true
mainView.backgroundColor = .clear
mainView.isUserInteractionEnabled = true
mainView.isExclusiveTouch = true
self.addSubview(mainView)
let theRect = CGRect(x: self.frame.size.width / 2 - 44 / 2, y: 0,
width: 44, height: 44)
button = UIButton(frame: theRect)
check.layer.cornerRadius = btnView.frame.size.height / 2
mainView.addSubview(self.check)
mainView.bringSubview(toFront: check)
check.addTarget(self, action: #selector(buttonClick(_:)),
for:.touchUpInside)
let newRect = CGRect(x: 0, y: check.frame.height, width:
self.frame.size.width, height: self.mainView.frame.size.height)
menuView = UIView(frame: newRect)
menuView.backgroundColor = .blue
mainView.addSubview(menuView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func buttonClick(_ sender: UIButton) {
toggleMenu()
}
func toggleMenu() {
if check.transform == CGAffineTransform.identity {
UIView.animate(withDuration: 1, animations: {
self.check.transform = CGAffineTransform(scaleX: 12, y: 12)
self.mainView.transform = CGAffineTransform(translationX: 0, y: -120)
self.check.transform = CGAffineTransform(rotationAngle: self.radians(180)) // 180 is 3.14 radian
self.setNeedsLayout()
}) { (true) in
UIView.animate(withDuration: 0.5, animations: {
})
}
} else {
UIView.animate(withDuration: 1, animations: {
// .identity sets to original position
//self.btnView.transform = .identity
self.mainView.transform = .identity
self.button.transform = .identity
})
}
}
}
This class is called from another UIView class like this
class MainViewClass: UIView {
var animateView: AnimateView!
override init(frame: CGRect) {
animateView = AnimateView(frame: CGRect(x: 0, y: self.frame.size.height - 44 - 44 - 20, width: self.frame.size.width, height: 122+44))
//animateView.clipsToBounds = true
self.addSubview(animateView)
self.bringSubview(toFront: animateView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
When the screen first appears:
Initially the button is clickable and when it is clicked it moves up along with subview.
Now the button is not clickable. When I saw the frame of button it is same as when screen initially appears with button touching the screen bottom even though it moves up.
What I am intending is to show the screen with animation from bottom when button is clicked and move to default position for second time click.
But if I place the button as subview inside self, not as subview for mainView, then the button is clickable but it remains in the same position even after view is animated and moved up.
self.addSubview(button)
So, I finally got the solution of what I was intending to achieve before and after animation.
The reason for the UIButton not receiving any touch event after the animation is that after animation, the UIButton moves upward as it is subview of mainView. Due to this, it is out of bound of its superView and does not respond to any click event. Although I moved button along with its superView which is mainView, but button did not respond to touch event.
Then, I tested the whether the button bound is within mainView using hitTest:
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let pointForTargetView: CGPoint = button.convert(point, from: mainView)
if button.bounds.contains(pointForTargetView) {
print("Button pressed")
return button.hitTest(pointForTargetView, with:event)
}
return super.hitTest(point, with: event)
}
This if condition:
button.bounds.contains(pointForTargetView)
Returns false when button is pressed after animation.
So, I need to capture touch event on subview which is out the its superview frame.
Using hitTest() solves my problem.
Here's the link which helped me. Capturing touches on a subview outside the frame of its superview using hitTest:withEvent:
Swift 3
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
if clipsToBounds || isHidden || alpha == 0 {
return nil
}
for subview in subviews.reversed() {
let subPoint = subview.convert(point, from: self)
if let result = subview.hitTest(subPoint, with: event) {
return result
}
}
return nil
}
The screen shots:
When screen first appears, button is at bottom of screen, subview is hidden below the button.
When the button is clicked, mainView animates upward and button moves upward as it is subview of mainView.
When button is clicked again, mainView goes to previous position so does the button.

UIButton works normally, but not in popoverPresentationController

I have a parent container UIView that has three subviews: 1 UITextView, and 2 buttons (the buttons are on top of the UITextView, but contained as subviews of the container UIView). When I present the parent UIView on screen normally, simply inside of a UIViewController, the buttons trigger their associated action methods perfectly and function correctly. However, when I present the UIView inside a view controller that becomes a popover, the view hierarchy shows up properly, but the buttons don't trigger their associated action methods and nothing happens. Is there something about UIPopoverPresentationControllers and buttons that I don't understand?
Adding the buttons to the parent UIView
func layoutButtons(in parent: UIView) {
let speechButton = UIButton(type: .custom)
speechButton.frame = CGRect(x: parent.frame.width - 35, y: parent.frame.height - 35, width: 30, height: 30)
speechButton.setImage(UIImage(named: "sound_icon"), for: .normal)
speechButton.addTarget(self, action: #selector(Textual.textToSpeech), for: UIControlEvents.touchUpInside)
parent.addSubview(speechButton)
let fontSizeButton = UIButton(type: .custom)
fontSizeButton.frame = CGRect(x: textView.frame.width - 75, y: textView.frame.height - 35, width: 30, height: 30)
fontSizeButton.setImage(UIImage(named: "font_size_icon"), for: .normal)
fontSizeButton.addTarget(self, action: #selector(Textual.toggleFontSize), for: UIControlEvents.touchUpInside)
parent.addSubview(fontSizeButton)
// wrap text around the bottom buttons
let excludeSpeechButton = UIBezierPath(rect: speechButton.frame)
let excludeFontSizeButton = UIBezierPath(rect: fontSizeButton.frame)
self.textView.textContainer.exclusionPaths = [excludeSpeechButton, excludeFontSizeButton]
}
#objc func textToSpeech() {
if synth.isPaused {
synth.continueSpeaking()
} else if synth.isSpeaking {
synth.pauseSpeaking(at: .immediate)
} else {
let speechUtterance = AVSpeechUtterance(string: attributedText.string)
speechUtterance.rate = 0.5
synth.speak(speechUtterance)
}
}
#objc func toggleFontSize() {
if self.smallFontSizeMode == true {
self.smallFontSizeMode = false
} else {
self.smallFontSizeMode = true
}
// for each character, multiply the current font size by fontSizeModifier
// http://stackoverflow.com/questions/19386849/looping-through-nsattributedstring-attributes-to-increase-font-size
self.attributedText.beginEditing()
self.attributedText.enumerateAttribute(NSFontAttributeName, in: NSMakeRange(0, self.attributedText.length), options: NSAttributedString.EnumerationOptions.reverse, using: { (value, range, stop) in
if let oldFont = value as? UIFont {
var newFont: UIFont?
if self.smallFontSizeMode == true { // was big and now toggling to small
newFont = oldFont.withSize(oldFont.pointSize / 2)
} else { // was small and now toggling to big
newFont = oldFont.withSize(oldFont.pointSize * 2)
}
attributedText.removeAttribute(NSFontAttributeName, range: range)
attributedText.addAttribute(NSFontAttributeName, value: newFont!, range: range)
}
})
self.attributedText.endEditing()
self.textView.attributedText = self.attributedText
}
Presenting the UIViewController
func present(viewController: UIViewController, at location: CGRect) {
viewController.modalPresentationStyle = .popover
parentViewController.present(viewController, animated: true, completion: nil)
let popController = viewController.popoverPresentationController
popController?.permittedArrowDirections = .any
popController?.sourceView = parentView
popController?.sourceRect = location
}
UPDATE - I've added popController?.delegate = viewController as the last line of func present(viewController:at:) and below I've added extension UIViewController: UIPopoverPresentationControllerDelegate { }
To answer your question, you will need to tell your presenting view controller who to delegate, so add this below and let me know if it works:
popController?.delegate = viewController

How can I get UIGestureRecognizer to work with manually added subviews

I programmatically made a subview and it shows up in my main view. It also has a separate view controller.
Though my gestureRecognizers work on UIImageViews in the main view, they do not work in my sub view.
Here's what I have in the main view controller:
var hVC: HandViewController = HandViewController()
override func viewDidLoad() {
super.viewDidLoad()
createHandImageView()
}
func createHandImageView() {
addChildViewController(hVC)
let w: CGFloat = cardWidth + ((hVC.maxHandCards-1) * hVC.handCardSep)
let h: CGFloat = cardHeight
let screenWidth = view.frame.size.width
let screenHeight = view.frame.size.height
let x: CGFloat = (screenWidth - w) / 2
let frame = CGRectMake(x, screenHeight - cardHeight - 20, w, h)
hVC.view = UIImageView(frame: frame)
hVC.view.backgroundColor = UIColor(white: 0, alpha: 0.3)
// This is where I add the Hand View that eventually holds the card views
view.addSubview(hVC.view)
hVC.didMoveToParentViewController(self)
}
And the sub view controller:
init() {
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad() // This NEVER fires
NSLog("did load");
}
func updateHandCardsView(cards: [Int]) {
handCardViews = [];
for card in cards {
addNewHandCardImage(card)
}
}
func addNewHandCardImage(card: Int) {
let imageView = UIImageView(frame:CGRectMake(0, 0, cardWidth, cardHeight));
imageView.image = UIImage(named: Deck.getCardName(card))
// This is where I add each Card View to the Hand View
self.view.addSubview(imageView)
handCardViews.append(imageView)
addEventRecognizers(imageView)
}
func addEventRecognizers(view: UIImageView) {
let singleTap = UITapGestureRecognizer(target: self, action: "highlightCard:")
singleTap.numberOfTapsRequired = 1
singleTap.numberOfTouchesRequired = 1
view.userInteractionEnabled = true
view.addGestureRecognizer(singleTap)
let doubleTap = UITapGestureRecognizer(target: self, action: "playCard:")
doubleTap.numberOfTapsRequired = 2
doubleTap.numberOfTouchesRequired = 1
view.userInteractionEnabled = true
view.addGestureRecognizer(doubleTap)
}
All the card views show up in the hand view. All programmatically created.
When I copy and paste the gesture code into the main view and use it on the cards on the table, the action gets called, but not in the sub view (HandView).
What am I missing?
Gesture recognizers only work on views that they belong to. There is a UIView method to add gesture recognizers. Your addEventRecognizers is only adding recognizers to whatever UIImageView passed in. You should change the function call to accept UIView, since UIImageView is just a subclass of UIView, it will still work on your images. Then call
addEventRecognizers(HandView) //Pass in the view that will get set with gesture recognizer.
Alternatively, if you just want to add one gesture recognizer just call HandView.addGestureRecognizer(gesture)

Strange behaviour - instantiating a UITextField in willMoveToSuperview as opposed to didMoveToSuperview

I'm working with XCode 6.3/iOS/Swift 1.2. I've just stumbled upon some strange behaviour that I don't understand (coming from a strong OO background).
Put simply, if I subclass a UIView and use it to instantiate some UITextFields; in the constructor, overriding didMoveToSuperview, on dynamically (ie, with a click event)... the UITextFields work as expected. However, when creating the UITextField object during willMoveToSuperview, it seems fine... but it doesn't respond to touch events.
This is demonstrated in the code below (a UIViewController and the subclassed UIView). I've added a gesture recognizer to the entire view containing the UITextFields. Clicking any of them other than the one creating during willMoveToSuperview, will move the focus to that textfield, and will ignore the touch event (as expected). However, clicking on the one added during willMoveToSuperview fires a touch event. Event without the touch event... this textfield remains unresponsive. Can anyone explain this behaviour?
import UIKit
class RootViewController:UIViewController
{
override func viewDidLoad()
{
super.viewDidLoad()
self.view.frame = CGRectMake(0,0,500,500)
}
override func viewDidAppear(animated: Bool)
{
var uiview = ExtendedUIView()
view.addSubview(uiview)
}
}
class ExtendedUIView:UIView
{
internal var hasMovedToSuperView:Bool = false
override init (frame : CGRect)
{
super.init(frame : frame)
}
convenience init()
{
self.init(frame:CGRectMake(0,0,500,500))
var tf: UITextField = UITextField(frame: CGRect(x: 0, y: 50, width: 300, height: 40))
tf.backgroundColor = UIColor.greenColor()
tf.text = "init // ok"
addSubview(tf)
}
required init(coder aDecoder: NSCoder)
{
fatalError("This class does not support NSCoding")
}
override func willMoveToSuperview(newSuperview: UIView?)
{
if (!hasMovedToSuperView) {
var tf: UITextField = UITextField(frame: CGRect(x: 0, y: 100, width: 300, height: 40))
tf.backgroundColor = UIColor.redColor()
tf.text = "willMoveToSuperview // not ok"
addSubview(tf)
}
}
override func didMoveToSuperview()
{
if (!hasMovedToSuperView) {
var tf: UITextField = UITextField(frame: CGRect(x: 0, y: 150, width: 300, height: 40))
tf.backgroundColor = UIColor.greenColor()
tf.text = "didMoveToSuperview // ok"
addSubview(tf)
hasMovedToSuperView = true
addGestureRecognizer(UITapGestureRecognizer(target:self, action:Selector("createTFDynamically:")))
}
}
func createTFDynamically(value:AnyObject)
{
var tf: UITextField = UITextField(frame: CGRect(x: 0, y: 200, width: 300, height: 40))
tf.backgroundColor = UIColor.greenColor()
tf.text = "createTFDynamically // ok"
addSubview(tf)
}
}

Resources