error passing data between ViewController - ios

I've a strange issue. I have a UITextField I can write inside and the text is displayed directly in UITextView. I'm using a UITabBarController to switch between the UIViewController.
I'm using that class to save data (wrote in TabBarController.swift):
public class ModelData {
var text = ""
var color:UIColor? = nil
}
That code to save the data (wrote in ViewController.swift):
override func viewDidDisappear(animated: Bool) {
let model = (self.tabBarController as TabBarViewController).model
model.color = textview.textColor
model.text = textview.text
}
And that code to give the data (wrote in SecondViewController.swift):
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
let model = (self.tabBarController as TabBarViewController).model
textview.textColor = model.color
textview.text = model.text
}
So, my problem is that: Because I use a UItextField where I can write inside I have disabled User Interaction in UITextView, but now I need to enable that options because I want scroll the UITextView. But now when I pass between the ViewController the data is not saved. (only the color is not saved)

For whatever reason, (it looks like a bug), the textColor property of UITextView returns nil when Selectable is unchecked in Interface Builder. It is not a problem if the selectable property is set to false in code. So a workaround is to leave Selectable checked in Interface Builder and set it to false in viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
// Set selectable to false here so that the user can't select the
// textview text, but User Interaction is still enabled to allow them
// to scroll it. This is a workaround for a problem in Interface
// Builder which causes the textColor property to return nil if Selectable
// is unchecked in Interface Builder.
textview.selectable = false
}

Related

iOS (swift) exit/dismiss preselect textView in share extension

when launching the iOS share extension the textView will by default already be selected / entered. (the keyboard will be visible and the textView will be in edit mode)
I don't want this to happen, how do I programatically exit the textView
override func viewDidLoad() {
self.textView.exit() // obviously doesn't work
}
I see tons of posts about how to exit when user press enter on the keyboard, I do not want to do it "when something delegate" I just want the textview to not be in edit mode when the extension is launched (on viewDidLoad).
I have also tried (as suggested in other post)
self.textView.endEditing(true)
which did not hide the keyboard or exit the textView
You can call textView.resignFirstResponder() in presentationAnimationDidFinish
class ShareViewController: SLComposeServiceViewController {
var textViewTintColor: UIColor?
override func viewDidLoad() {
super.viewDidLoad()
// hide cursor which appears during presentation animation
self.textViewTintColor = self.textView.tintColor
self.textView.tintColor = .clear
}
override func presentationAnimationDidFinish() {
super.presentationAnimationDidFinish()
guard let tintColor = self.textViewTintColor else { return }
self.textView.resignFirstResponder()
// reset cursor
self.textView.tintColor = tintColor
self.textViewTintColor = nil
}
}

Access TextField from another class or method without storyboard

Okay, this might be one of the most basic questions ever, but all answers I find use storyboard to declare an outlet for a label, textfield or whatever element that needs to be changed. I, however, don't use storyboards and write everything in code. Now I have a function setupViews, where I define a textfield:
let usernameInput = UITextField()
Now, I can perfectly set the text or placeholder or whatever inside this setupViews() class, but how can I access it outside? For example, if I have a function logIn(), I want to call usernameInput.text and use it in this function.
Someone who can point me in the right direction? Do I need to declare this textfield globally, in another file, or something else?
When I create my views in code I always associate a property with the view that has all those various display values.
I have not tested this code to see but hopefully the following will give you an idea.
import UIKit
struct {
var name: String
}
class CustomViewController : UIViewController {
// some struct which contains data for view
var customViewData : ViewDataInfo? {
didSet {
labelOnScreen.text = customViewData.name
}
}
var labelOnScreen: UILabel = {
let label = UILabel()
label.text = "Placeholder information..."
// stuff auto layout
label.translateAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
setupView()
}
private func setupView() {
view.addSubview(label)
// set your constraints here
}
}

How to add property to UIButton?

thanks for all help:)! fixed it using iboutlet collection and add properies on viewDidLoad
I'm trying to add properties to keyboard keys like layer.shadowColor or layer.shadowRadius.
I got an error
'Value of type '(UIButton)' -> () has no member 'layer'
how to fix this ?
this is my code keyboardViewController.swift
import UIKit
class KeyboardViewController: UIInputViewController {
var newKeyboardView: UIView!
#IBAction func keyPressed(sender: UIButton) {
}
#IBOutlet var nextKeyboardButton: UIButton!
override func updateViewConstraints() {
super.updateViewConstraints()
// Add custom view sizing constraints here
}
override func viewDidLoad() {
super.viewDidLoad()
loadInterface()
}
func loadInterface() {
// load the nib file
let keyboardNib = UINib(nibName: "newKeyboard", bundle: nil)
// instantiate the view
newKeyboardView = keyboardNib.instantiateWithOwner(self, options: nil)[0] as! UIView
// add the interface to the main view
view.addSubview(newKeyboardView)
// copy the background color
view.backgroundColor = newKeyboardView.backgroundColor
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated
}
override func textWillChange(textInput: UITextInput?) {
// The app is about to change the document's contents. Perform any preparation here.
}
override func textDidChange(textInput: UITextInput?) {
// The app has just changed the document's contents, the document context has been updated.
var textColor: UIColor
let proxy = self.textDocumentProxy
if proxy.keyboardAppearance == UIKeyboardAppearance.Dark {
textColor = UIColor.whiteColor()
} else {
textColor = UIColor.blackColor()
}
self.nextKeyboardButton.setTitleColor(textColor, forState: .Normal)
}
}
I think that in order to apply some style to the button, you need an outlet to this button.
Right now, from what I can understand, you are trying to apply styles to the button from the #IBAction to the sender, which is not the proper way to do it.
Try to make an outlet to the button in the view controller and then to apply the styles from within the viewDidLoad method.
I hope this is clear, but if you want a more specific answer you need to show us what you tried, for example pasting the code you have in the view controller
EDIT:
Based on the code you post, the keyboard is a Nib you instantiate from loadInterface(). I don't have a clear vision of the whole thing with only this piece of code, but it seems to me that you are trying to apply some styles to every key button of a keyboard view. Unfortunately this really depends on how the keyboard is implemented, can you provide some more details?
Anyway, from what I see I think you didn't write this code: probably you are following a tutorial or maintaining someone else's code. That's ok, but I suggest you to follow a an introduction course to iOS development with Swift, like the Udacity's one, which is fantastic IMHO (https://www.udacity.com/course/intro-to-ios-app-development-with-swift--ud585)
If you try to format your UIButton with QuartzCore framework, you'll need to import it first:
import QuartzCore
Then you will be able to access those members.
For example (latest swift3 code):
#IBAction func keyPressed(sender: UIButton) {
let button = sender as UIButton!
button?.backgroundColor = UIColor.red
button?.layer.shadowColor = UIColor.black.cgColor
button?.layer.shadowRadius = 1.0
button?.layer.cornerRadius = 4.0
}
In case you need to apply your styles sooner, try to consider to put this code into viewDidLoad or viewDidAppear methods:
self.nextKeyboardButton.backgroundColor = UIColor.red
self.nextKeyboardButton.layer.shadowColor = UIColor.black.cgColor
self.nextKeyboardButton.layer.shadowRadius = 1.0
self.nextKeyboardButton.layer.cornerRadius = 4.0
Seems like you're trying to "add property" not to a button, but rather to a closure which accepts a button as an argument.
Make it like this:
nextKeyboardButton.layer.shadowColor = UIColor.redColor.cgColor
nextKeyboardButton.layer.shadowRadius = 5.0

How do I activate an inputView using a UIButton in Swift?

I am attempting to have a UIDatePicker come up as a keyboard when the user hits a UIButton. I was able to get it to work with a textfield, but I don't like how the cursor is visible and the user could enter in any text if they had an external keyboard. Here is my code:
#IBAction func dateFieldStart(sender: UITextField) {
var datePickerStartView : UIDatePicker = UIDatePicker()
datePickerStartView.datePickerMode = UIDatePickerMode.Time
sender.inputView = datePickerStartView // error when sender is UIButton
}
I tried changing the sender to UIButton but it gave this error on the line that is marked above:
Cannot assign to 'inputView' in 'sender'
I have tried researching it and no one else seems to have had a problem with it. Anyone know how to trigger a UIDatePicker inputView using a UIButton or anything that might work better that the user cannot type into? Thanks!
This is years after the original question, but for anyone who may be looking for solution to this you can subclass UIButton and provide a getter and setter for the inputView property. Be sure to call becomeFirstResponder in the setter and override canBecomeFirstResponder. For example:
class MyButton: UIButton {
var myView: UIView? = UIView()
var toolBarView: UIView? = UIView()
override var inputView: UIView? {
get {
myView
}
set {
myView = newValue
becomeFirstResponder()
}
}
override var inputAccessoryView: UIView? {
get {
toolBarView
}
set {
toolBarView = newValue
}
}
override var canBecomeFirstResponder: Bool {
true
}
}
let tempInput = UITextField( frame:CGRect.zero )
tempInput.inputView = self.myPickerView // Your picker
self.view.addSubview( tempInput )
tempInput.becomeFirstResponder()
It's a good idea to keep a reference to tempInput so you can clean-up on close
I wanted to do the same thing, I ended up just overlaying a UITextField over the button and using the inputView of that instead.
Tip: set tintColor of the UITextField to UIColor.clearColor() to hide the cursor.
You can create a view for the picker off screen view and move it on screen when you need it. Here's another post on this.

Disabling user input for UITextfield in swift

pretty trivial question, I know. But I can not find anything online.
I need to disable the user from being able to edit the text inside of a text field. So that when the click on the text, a keyboard doesn't show up.
Any ideas?
A programmatic solution or if it is possible through storyboards would be great.
Try this:
Swift 2.0:
textField.userInteractionEnabled = false
Swift 3.0:
textField.isUserInteractionEnabled = false
Or in storyboard uncheck "User Interaction Enabled"
Another solution, declare your controller as UITextFieldDelegate, implement this call-back:
#IBOutlet weak var myTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
myTextField.delegate = self
}
func textFieldShouldBeginEditing(textField: UITextField) -> Bool {
if textField == myTextField {
return false; //do not show keyboard nor cursor
}
return true
}
In storyboard you have two choise:
set the control's 'enable' to false.
set the view's 'user interaction enable' false
The diffierence between these choise is:
the appearance of UITextfild to display in the screen.
First is set the control's enable. You can see the backgroud color is
changed.
Second is set the view's 'User interaction enable'. The backgroud color is NOT changed.
Within code:
textfield.enable = false
textfield.userInteractionEnabled = NO
Updated for Swift 3
textField.isEnabled = false
textfield.isUserInteractionEnabled = false
If you want to do it while keeping the user interaction on.
In my case I am using (or rather misusing) isFocused
self.myField.inputView = UIView()
This way it will focus but keyboard won't show up.
I like to do it like old times. You just use a custom UITextField Class like this one:
//
// ReadOnlyTextField.swift
// MediFormulas
//
// Created by Oscar Rodriguez on 6/21/17.
// Copyright © 2017 Nica Code. All rights reserved.
//
import UIKit
class ReadOnlyTextField: UITextField {
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
override init(frame: CGRect) {
super.init(frame: frame)
// Avoid keyboard to show up
self.inputView = UIView()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
// Avoid keyboard to show up
self.inputView = UIView()
}
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
// Avoid cut and paste option show up
if (action == #selector(self.cut(_:))) {
return false
} else if (action == #selector(self.paste(_:))) {
return false
}
return super.canPerformAction(action, withSender: sender)
}
}
In swift 5, I used following code to disable the textfield
override func viewDidLoad() {
super.viewDidLoad()
self.textfield.isEnabled = false
//e.g
self.design.isEnabled = false
}
Swift 4.2 / Xcode 10.1:
Just uncheck behavior Enabled in your storyboard -> attributes inspector.
you can use UILabel instead if you don't want the user to be able to modify anything in your UITextField
A programmatic solution would be to use enabled property:
yourTextField.enabled = false
A way to do it in a storyboard:
Uncheck the Enabled checkbox in the properties of your UITextField
textField.isUserInteractionEnabled = false

Resources