How to change a variable UITextView after clicking the button? - swift

I create UITextView with a random tag and text, but it is created with one variable, is it possible to update the variable after creation UITextView (by clicking the add button)? Maybe add a random number to it, for example newText1, newText2.. etc.
So that the next UITextView is already created with a new variable?
P.S Sorry, if the question is silly, I just recently started to study Swift
#IBOutlet weak var addTextButton: UIButton!
#IBOutlet weak var StoriesView: UIView!
var newText = UITextView()
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func addTextButton(_ sender: Any) {
let maxNumber = 10000
let i = Int(arc4random_uniform(UInt32(maxNumber)))
newText = UITextView(frame: CGRect(x: self.StoriesView.frame.origin.x + 40, y: self.StoriesView.frame.origin.y + 40, width: 380, height: 80))
self.StoriesView.addSubview(newText)
newText.font = UIFont(name: "Verdana", size: 11)
newText.text = "TAP TO EDIT #\(i)"
newText.sizeToFit()
newText.textColor = UIColor.black
newText.backgroundColor = UIColor.clear
newText.tag = i
newText.isEditable = true
newText.isSelectable = true
newText.isUserInteractionEnabled = true
newText.allowsEditingTextAttributes = true
newText.translatesAutoresizingMaskIntoConstraints = true
newText.enablesReturnKeyAutomatically = true
newText.delegate = self
}
UPD:
let fontToolbar = UIToolbar(frame:CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
fontToolbar.barStyle = .default
fontToolbar.items = [
UIBarButtonItem(title: "Green", style: .plain, target: self, action: #selector(greenColor)),
UIBarButtonItem(title: "Blue", style: .plain, target: self, action: #selector(blueColor)),
UIBarButtonItem(title: "Red", style: .plain, target: self, action: #selector(redColor)),
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
UIBarButtonItem(title: "Close Keyboard", style: .plain, target: self, action: #selector(dismissKeyboard))]
fontToolbar.sizeToFit()
newText.inputAccessoryView = fontToolbar
in the toolBar above the keyboard I have buttons, here we change the color
#objc func redColor() {
newText.textColor = UIColor.red}
#objc func blueColor() {
newText.textColor = UIColor.blue}
#objc func greenColor() {
newText.textColor = UIColor.green}
So the color changes only in the newly created UITextView

On click of button, create a new texView and assign it a tag value. Once it is added, update the value of i to +1, so that every textView added has a new tag value.
var i = 1
var newText = UITextView()
#IBAction func addTextButton(_ sender: Any) {
newText = UITextView(frame: CGRect(x: self.StoriesView.frame.origin.x + 40, y: self.StoriesView.frame.origin.y + 40, width: 380, height: 80))
self.StoriesView.addSubview(newText)
newText.font = UIFont(name: "Verdana", size: 11)
newText.text = "TAP TO EDIT #\(i)"
newText.sizeToFit()
newText.textColor = UIColor.black
newText.backgroundColor = UIColor.clear
newText.tag = i
newText.isEditable = true
newText.isSelectable = true
newText.isUserInteractionEnabled = true
newText.allowsEditingTextAttributes = true
newText.translatesAutoresizingMaskIntoConstraints = true
newText.enablesReturnKeyAutomatically = true
newText.delegate = self
//increment i
i+=1
}
then you can access your textField via tag values like this:
if let textView = self.StoriesView.viewWithTag(i) as? UITextView {
// textView.text = "change it"
}
UPDATE:
Add textView Delegate method, and once a textView starts editing, change the newText value to the currently editing textView
class ViewController : UIViewController, UITextViewDelegate {
func textViewDidBeginEditing(_ textView: UITextView) {
newText = textView
}
}

I have modified your code a bit to have new UITextView object with button click
import UIKit
class ScannerViewController: UIViewController, UITextViewDelegate {
#IBOutlet weak var StoriesView: UIView!
#IBOutlet weak var addTextButton: UIButton!
var yposition: CGFloat!
var textFieldTag: [Int]! = []
override func viewDidLoad() {
super.viewDidLoad()
yposition = 20
}
#IBAction func addTextButton(_ sender: Any) {
let xposition = self.StoriesView.frame.origin.x
let maxNumber = 10000
let i = Int(arc4random_uniform(UInt32(maxNumber)))
textFieldTag.append(i)
let newText = UITextView(frame: CGRect(x: xposition , y: yposition , width: 380, height: 40))
self.StoriesView.addSubview(newText)
newText.font = UIFont(name: "Verdana", size: 11)
newText.text = "TAP TO EDIT #\(i)"
newText.sizeToFit()
newText.textColor = UIColor.black
newText.backgroundColor = UIColor.yellow
newText.tag = i
newText.isEditable = true
newText.isSelectable = true
newText.isUserInteractionEnabled = true
newText.allowsEditingTextAttributes = true
newText.translatesAutoresizingMaskIntoConstraints = true
newText.enablesReturnKeyAutomatically = true
newText.delegate = self
yposition = yposition + 45
}
#IBAction func accessTextFields(_ sender: Any) {
//access all text fields
for tag in textFieldTag {
if let textField = self.StoriesView.viewWithTag(tag) as? UITextView {
//change properties here
textField.backgroundColor = .cyan
}
}
//access specific text fields
if let textField = self.StoriesView.viewWithTag(textFieldTag.first!) as? UITextView {
//change properties here
textField.backgroundColor = .orange
}
if let textField = self.StoriesView.viewWithTag(textFieldTag[textFieldTag.count - 1]) as? UITextView {
//change properties here
textField.backgroundColor = .green
}
}
}
It will have an output as this!!

Related

Present a Popover view from UIToolbar barButtonItem

Screenshot of the gap
I need to present a popover view from a UIBarbuttonItem in a UIToolbar. But there exists a gap between the popover view and the toolbar.
private func addToolbar() {
let toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.size.width, height: 50))
let item1 = UIBarButtonItem(image: UIImage(systemName: "pencil"), style: .plain, target: self, action: #selector(item1Pressed(_:)))
let item2 = UIBarButtonItem(image: UIImage(systemName: "house"), style: .plain, target: self, action: #selector(item2Pressed(_:)))
toolBar.sizeToFit()
toolBar.items = [item1, item2]
textField.inputAccessoryView = toolBar
}
class SearchViewController: UIViewController {
let searchBar = UISearchBar()
weak var viewControllerDelegate: SearchViewControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
setupView()
setupSearchbar()
}
private func setupView() {
view.backgroundColor = .white
navigationController?.navigationBar.prefersLargeTitles = true
self.title = "Search"
}
private func setupSearchbar() {
searchBar.sizeToFit()
searchBar.placeholder = "Search test"
searchBar.showsCancelButton = true
searchBar.delegate = self
self.navigationItem.titleView = searchBar
}
}
I tried setting the sourceRect of the presented popover view, but the popover view doesn't move down below a certain point.
#objc private func item1Pressed(_ sender: UIBarButtonItem) {
let vc = SearchViewController()
vc.viewControllerDelegate = self
let navVC = UINavigationController(rootViewController: vc)
navVC.modalPresentationStyle = .popover
navVC.popoverPresentationController?.delegate = self
navVC.popoverPresentationController?.permittedArrowDirections = .any
navVC.preferredContentSize = CGSize(width: 500, height: 200)
navVC.popoverPresentationController?.sourceItem = sender
var location = CGPoint(x: 0, y: 0)
if let barItemView = sender.value(forKey: "view") as? UIView {
let barFrame = barItemView.frame
let rect = barItemView.convert(barFrame, to: view)
location = rect.origin
}
navVC.popoverPresentationController?.sourceRect = CGRect(x: location.x, y: location.y+100, width: 0, height: 0)
present(navVC, animated: true)
}

UIToolbar doesn't show again in view when dismissing keyboard in Swift

I have an UIToolbar containing a UITextField. I want to show the toolbar above the keyboard and then display it again when I finish editing inside the textfield.
The issue is that it is working when selecting the textfield. However, the toolbar is disappearing from the view when hiding the keyboard.
What should be done to redisplay it again to my view?
My Swift code is:
Add UITextFieldDelegate
class ATCChatThreadViewController: MessagesViewController, MessagesDataSource, MessageInputBarDelegate, UITextFieldDelegate {
Create ToolBar is as below
func createToolbar(){
//Fixed space
let fixed = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.fixedSpace, target: self, action: nil)
fixed.width = 10
//Camera
//let img = UIImage(named: "camera-filled-icon")!.withRenderingMode(UIImage.RenderingMode.alwaysOriginal)
let img = UIImage.localImage("camera-filled-icon", template: true)
let iconSize = CGRect(origin: CGPoint.zero, size: CGSize(width: 30, height: 30))
let iconButton = UIButton(frame: iconSize)
iconButton.setTitleColor(uiConfig.primaryColor, for: .normal)
iconButton.setBackgroundImage(img, for: .normal)
let cameraItem = UIBarButtonItem(customView: iconButton)
cameraItem.tintColor = uiConfig.primaryColor
iconButton.addTarget(self, action: #selector(cameraButtonPressed), for: .touchUpInside)
//TextField true
textFieldChat = UITextField(frame: CGRectMake(0,0,(self.view.frame.size.width - 100) ,30))
textFieldChat.tintColor = uiConfig.primaryColor
textFieldChat.textColor = uiConfig.inputTextViewTextColor
textFieldChat.backgroundColor = uiConfig.inputTextViewBgColor
textFieldChat.layer.cornerRadius = 14.0
textFieldChat.layer.borderWidth = 0.0
textFieldChat.font = UIFont.systemFont(ofSize: 16.0)
textFieldChat.delegate = self
textFieldChat.attributedPlaceholder = NSAttributedString(string: "Start typing...".localized(), attributes: [NSAttributedString.Key.foregroundColor: uiConfig.inputPlaceholderTextColor])
let paddingView: UIView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 20))
textFieldChat.leftView = paddingView
textFieldChat.leftViewMode = .always
let textFieldButton = UIBarButtonItem(customView: textFieldChat)
//Fixed space
let fixedTwo = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.fixedSpace, target: self, action: nil)
fixedTwo.width = 10
//Send Button
let imgSend = UIImage.localImage("share-icon", template: true)
let iconSendSize = CGRect(origin: CGPoint.zero, size: CGSize(width: 30, height: 30))
let sendButton = UIButton(frame: iconSendSize)
sendButton.setTitleColor(uiConfig.primaryColor, for: .normal)
sendButton.setBackgroundImage(imgSend, for: .normal)
let sendItem = UIBarButtonItem(customView: sendButton)
sendItem
.tintColor = uiConfig.primaryColor
sendButton.addTarget(self, action: #selector(sendBtnPressedWith), for: .touchUpInside)
//Flexible Space
// let flexible = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.flexibleSpace, target: self, action: nil)
let flexible = UIBarButtonItem(barButtonSystemItem: UIBarButtonItem.SystemItem.fixedSpace, target: self, action: nil)
flexible.width = 10
//Toolbar
var bottomsafeAreaHeight: CGFloat?
if #available(iOS 11.0, *) {
bottomsafeAreaHeight = UIApplication.shared.windows.first{$0.isKeyWindow }?.safeAreaInsets.bottom ?? 0
} else {
// Fallback on earlier versions
bottomsafeAreaHeight = bottomLayoutGuide.length
bottomsafeAreaHeight = UIApplication.shared.keyWindow?.rootViewController?.bottomLayoutGuide.length ?? 0
}
toolbar = UIToolbar(frame: CGRectMake(0,(self.view.frame.size.height - 116 - (bottomsafeAreaHeight ?? 0)),view.frame.width,50))
toolbar.sizeToFit()
toolbar.barTintColor = UIColor.f5f5f5ColorBg()
toolbar.isTranslucent = false
toolbar.tintColor = uiConfig.primaryColor
toolbar.items = [fixed, cameraItem, fixed, textFieldButton,fixedTwo, sendItem,flexible]
view.addSubview(toolbar)
}
// MARK: - UITextFieldDelegate
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
textFieldChat.inputAccessoryView = toolbar
return true
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
view.addSubview(toolbar)
self.toolbar.isHidden = false
return true
}
if only chat etxfield is using toolbar then replace line:
view.addSubview(toolbar)
with
textFieldChat.inputAccessoryView = toolbar
remove both methods textFieldShouldBeginEditing and textFieldShouldEndEditing

Use Uitapgesture recognizer on multiple image views that are not declared

My swift code uses func addBox to add and append image views to the uiview controller. All I want to do is when one of the image views are tapped is for func viewClicked to be activated. Right now nothing is happening and nothing is being written into the debug area.
import UIKit
class ViewController: UIViewController {
var ht = -90
var ww = 80
var hw = 80
var arrTextFields = [UIImageView]()
var b7 = UIButton()
override func viewDidLoad() {
[b7].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
$0.backgroundColor = .systemOrange
}
b7.frame = CGRect(x: view.center.x-115, y: view.center.y + 200, width: 70, height: 40)
b7.addTarget(self, action: #selector(addBOx), for: .touchUpInside)
for view in self.arrTextFields {
view.isUserInteractionEnabled = true
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(viewClicked)))
}
}
#objc func viewClicked(_ recognizer: UITapGestureRecognizer) {
print("tap")
}
//func that adds imageview.
#objc func addBOx() {
let subview = UIImageView()
subview.isUserInteractionEnabled = true
arrTextFields.append(subview)
view.addSubview(subview)
subview.frame = CGRect(x: view.bounds.midX - 0, y: view.bounds.midY + CGFloat(ht), width: CGFloat(ww), height: 35)
subview.backgroundColor = .purple
ht += 50
arrTextFields.append(subview)
}
}
You need to enable user interation
for view in self.arrTextFields {
view.isUserInteractionEnabled = true
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(viewClicked)))
}
#objc func viewClicked(_ recognizer: UITapGestureRecognizer) {
print("tap")
}

Is there any easier way to view UIImageView programmatically?

I have 8 buttons and I want to display a picture every time I press the buttons.
What I wonder is, do I need to have 8 functions to display these images?
Or is there any easier ways?
Here is how I've done it, it works as it should, but I do not want to repeat the same things over and over again?
var imageView1:UIImageView!
var imageView2:UIImageView!
var imageView3:UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
showImage1()
showImage2()
showImage3()
tapGestureRecognizerFunc()
}
#objc func button1Tap() {
if self.imageView1.isHidden {
self.imageView1.isHidden = false
}else{
self.imageView1.isHidden = true
}
}
#objc func button2Tap() {
if self.imageView2.isHidden {
self.imageView2.isHidden = false
}else{
self.imageView2.isHidden = true
}
}
#objc func button3Tap() {
if self.imageView3.isHidden {
self.imageView3.isHidden = false
}else{
self.imageView3.isHidden = true
}
}
func showImage1() {
imageView1 = UIImageView(frame: CGRect(x: 271, y: 8, width: 29, height: 29))
imageView1.image = UIImage(named: "Done.png")
imageView1.contentMode = .scaleAspectFit
View1.addSubview(imageView1)
imageView1.isHidden = true
}
func showImage2() {
imageView2 = UIImageView(frame: CGRect(x: 271, y: 8, width: 29, height: 29))
imageView2.image = UIImage(named: "Done.png")
imageView2.contentMode = .scaleAspectFit
View2.addSubview(imageView2)
imageView2.isHidden = true
}
func showImage3() {
imageView2 = UIImageView(frame: CGRect(x: 271, y: 8, width: 29, height: 29))
imageView2.image = UIImage(named: "Done.png")
imageView2.contentMode = .scaleAspectFit
View3.addSubview(imageView2)
imageView2.isHidden = true
}
func tapGestureRecognizerFunc () {
let exercise1Tap = UITapGestureRecognizer(target: self, action: #selector(button1Tap))
exercise1Tap.numberOfTapsRequired = 2
View1.addGestureRecognizer(exercise1Tap)
let exercise2Tap = UITapGestureRecognizer(target: self, action: #selector(button2Tap))
exercise2Tap.numberOfTapsRequired = 2
View2.addGestureRecognizer(exercise2Tap)
let exercise3Tap = UITapGestureRecognizer(target: self, action: #selector(button3Tap))
exercise3Tap.numberOfTapsRequired = 2
View3.addGestureRecognizer(exercise3Tap)
}
yes i'm newbie
Since I don't know, where and how you create the Buttons it is difficult to answer.
The following is just a tip.
You should use an array of UIImageView
Your callback should use the Form buttonAction(sender : UIButton)
You could use a tag for the button to get the number of the corresponding button
For example:
class ViewController: UIViewController {
var imageviews : [UIImageView] = []
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...8 {
let imageview = UIImageView()
view.addSubview(imageview)
imageview.tag = i
imageviews.append(imageview)
let button = UIButton(frame: CGRect(x: 0, y: CGFloat(i)*50.0, width: 100, height: 30))
view.addSubview(button)
button.setTitle("Button \(i)", for: .normal)
button.setTitleColor(.black, for: .normal)
button.tag = i
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
}
}
#objc func buttonAction(sender : UIButton) {
let index = sender.tag
print("Button \(index) pressed")
imageviews[index].isHidden = !imageviews[index].isHidden
}
}

Updating UILabel with UISlider throwing "unresolved identifier" error for Sender call

The code below is the only code I am using. I have programmatically built a UISlider with a label that I want to update. I've written a function that should call the sender of the UISlider and update the label field to the value of the slider. But it keeps throwing the "unresolved identifier" error for the variable name of the label. Where do I place the function so it can access the label value? I've tried everything.
import UIKit
class ViewController: UIViewController {
override func viewDidLoad()
{
super.viewDidLoad()
let mySlider = UISlider(frame:CGRect(x: 60, y:550, width: 300, height: 20))
mySlider.minimumValue = 5
mySlider.maximumValue = 60
mySlider.isContinuous = true
mySlider.tintColor = .white
mySlider.addTarget(self, action: #selector(ViewController.sliderValueDidChange(_:)), for: .valueChanged)
let minuteLabel = UILabel(frame: CGRect(1500, 2000, 150, 1200))
minuteLabel.center = CGPoint(200, 350)
minuteLabel.textAlignment = .center
minuteLabel.font = UIFont(name: minuteLabel.font.fontName, size:250)
mySlider.addTarget(self, action: #selector(ViewController.sliderValueDidChange(_:)),for: .valueChanged)
minuteLabel.textColor = UIColor.white
minuteLabel.text = "\(mySlider.value)"
self.view.addSubview(minuteLabel)
self.view.addSubview(mySlider)
}
public func sliderValueDidChange(_sender: UISlider) {
minuteLabel.text = "\(_sender.value)"
}
}
It's because you create minuteLabel in viewDidLoad() but not assigning to any property inside your ViewController.
You can just create property minuteLabel inside class and assign your minuteLabel from viewDidLoad() to this.
class ViewController: UIViewController {
private var minuteLabel: UILabel?
override func viewDidLoad()
{
super.viewDidLoad()
let mySlider = UISlider(frame:CGRect(x: 60, y:550, width: 300, height: 20))
mySlider.minimumValue = 5
mySlider.maximumValue = 60
mySlider.isContinuous = true
mySlider.tintColor = .white
mySlider.addTarget(self, action: #selector(ViewController.sliderValueDidChange(_:)), for: .valueChanged)
let minuteLabel = UILabel(frame: CGRect(1500, 2000, 150, 1200))
minuteLabel.center = CGPoint(200, 350)
minuteLabel.textAlignment = .center
minuteLabel.font = UIFont(name: minuteLabel.font.fontName, size:250)
mySlider.addTarget(self, action: #selector(ViewController.sliderValueDidChange(_:)),for: .valueChanged)
minuteLabel.textColor = UIColor.white
minuteLabel.text = "\(mySlider.value)"
self.view.addSubview(minuteLabel)
self.view.addSubview(mySlider)
self.minuteLabel = minuteLabel // assign to class property
}
public func sliderValueDidChange(_sender: UISlider) {
minuteLabel?.text = "\(_sender.value)"
}
}