I realize this question has been asked numerous times before, but I can't quite get the solutions to work, even by just copying and pasting them, and suspect that most swift documentation spans the three versions since swift's release.
I'm attempting to do something as simple as storing a variable from a field input and not having much luck.
import UIKit
class ViewController: UIViewController {
#IBOutlet var userNumber: UILabel!
#IBOutlet var userField: UITextField!
#IBAction func userButton(_ sender: UIButton) {
let userInput = userField.text
//some action
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You should check whether you have set your textfield's delegate with respect to parent view controller.
Go to storyboard.
Select textfield.
Right click on it.
set delegate from textfield to view controller
Related
Im new to swift and I'm experimenting with classes and methods! I have been looking all over google and stackoverflow to find an answer! I have read multiple posts with the same problem but they still don't help me! I have written swift code for a bigger app but decided to write a small portion so I get the same idea. Im trying to update a UILabel's text with a method inside a class when a certain button is pressed. Im trying to change the text by MyLabel.text = "text" but its giving me the error of 'Instance member cannot be used on type "view controller"' Please help me find whats wrong with it and explain it! Thank you so much! Here is my code bellow:
class ViewController: UIViewController {
class Door {
var DoorLocked = false
func lockDoor() {
DoorLocked = true
MyLabel.text = "The door is locked!"
}
func unlockDoor() {
DoorLocked = false
MyLabel.text = "The door is unlocked!"
}
init() {
MyLabel.text = "This is a door!"
}
}
var DoorStatus = Door()
#IBOutlet weak var MyLabel: UILabel!
#IBAction func LockButton(sender: AnyObject) {
DoorStatus.lockDoor()
}
#IBAction func UnlockButton(sender: AnyObject) {
DoorStatus.unlockDoor()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
From a architectural point of view, I would argue that it does not make sense for the Door class to know of any labels on that specific ViewController. Further, the Swift language, does not allow you to access that label inside the nested class. Instead, consider doing something like:
class ViewController: UIViewController {
class Door {
var DoorLocked = false
func lockDoor() {
DoorLocked = true
}
func unlockDoor() {
DoorLocked = false
}
}
var DoorStatus = Door()
#IBOutlet weak var MyLabel: UILabel!
#IBAction func LockButton(sender: AnyObject) {
DoorStatus.lockDoor()
MyLabel.text = "The door is locked!"
}
#IBAction func UnlockButton(sender: AnyObject) {
DoorStatus.unlockDoor()
MyLabel.text = "The door is unlocked!"
}
override func viewDidLoad() {
super.viewDidLoad()
MyLabel.text = "This is a door!"
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The inner class Door doesn't know anything about MyLabel. Inner classes don't share variables with the class they're declared in, unlike other languages. It's pretty much like the Door class is declared at top level along-side ViewController. You need a good bit more background to separate a model & ViewController into separate classes and then make them communicate properly with a protocol/delegate pattern. Unless you're following a template for exactly how, first just do everything within ViewController. So declare your model variable doorLocked directly within ViewController, and update it along with changing the text of the label directly within the #IBAction.
Again caveat that this is just learning iOS & Swift at a basic level, then proper MVC design should come next.
Also, all variables should start with lower-case. Every time you start a variable with uppercase, it hurts the eyes because it looks like a class or other type rather than storage.
I have a very simple app so far. Two view controllers. I've set up a new .swift file for the second view. On each view I have a button that when pressed, changes a label to say "Pressed". Pretty simple.
On the first view controller everything works as expected. However, on the second view controller the app crashes when I press the button. I've set up IBOutlets and actions for all appropriate parts.
Does anyone have any insight?
code:
import UIKit
class PlayViewController: UIViewController {
#IBOutlet weak var newCardButton: UIButton!
#IBOutlet weak var labelTest: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func newCardButtonPressed(sender: UIButton) {
self.labelTest.text = "Pressed"
}
}
Screenshot:
Screenshot after crash- http://i.imgur.com/CHt8kA5.png
I think you should change the sender part like this.
#IBAction func newCardButtonPressed(sender: AnyObject) {
self.labelText.text = "Pressed"
}
If your connections are not set properly your app also crash. Delete them and reconnect it.From Utilities/connections inspector.
I have an experience where a user is rating a product, they do this by dragging sliders. Each slider has a related UILabel for the title and a UILabel for the value. I would like to avoid creating 12 functions, one for each slider and the associated label. I am new to development generally. I am guessing a class or an Array would be useful here, but am not sure how to use either. Here's the code that just updates the one value, and I know why that is, I'm just hoping to avoid declaring 12 variables for the value and 12 functions for each one.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var slider1: UISlider!
#IBOutlet weak var value1: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func sliderSlide(sender: UISlider) {
value1.text = round(sender.value*100).description
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Well,you can use Outlet Collection and 'tag',
Drag every label into a same Outlet Collection
Drag every Slider IBAction into a same function
Then set the tag of slider as the index of label in Outlet Collection.
For example,you first drag labelA to Collection,then the tag is 0
Then all the code
import UIKit
class ViewController: UIViewController {
#IBOutlet var labels: [UILabel]!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func sliderSlide(sender: UISlider) {
let index = sender.tag
let label = labels[index]
label.text = round(sender.value*100).description
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
You can connect more than one slider to the same function. That's the purpose of the sender argument. You can do a switch statement on the pointer in swift, or by a set tag of the slider if you prefer. If it's all updating the same label, why even care which slider is updating?
I can think of two ways of doing this. Make a custom view controller that looks exactly the same as the code you have. It will have the slider and label as subviews. Then you'd only have 12 container views on your storyboard (not the greatest).
The other way would be using IBOutletCollections. These are what they sound like, collections of IBOutlets. Assign each slider that you place on the storyboard a unique tag from 0-11 (this is done under the attributes inspector). The tag will act as an index for the values array. Make sure that when you add each label to the collection, you do it in the correct order (it does matter!). Using IBOutletCollections, your code would look like this:
class ViewController: UIViewController {
#IBOutlet weak var sliders: [UISlider]!
#IBOutlet weak var values: [UILabel]!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func sliderSlide(sender: UISlider) {
values[sender.tag].text = round(sender.value*100).description
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I'm programming a iOS app in Swift language and all I have to do is create a custom input for a textfield.
I created an additional View Controller with two buttons and what I want is this view controller (instead of the keyboard) to pop-up when I highlight my textfield.
Basically what I want is to create a small custom keyboard, but I just want it to be inside my app: I found lots of tutorials about creating custom keyboards, but it is not the same as having a simple View Controller that pops-up when text field is highlighted.
Can you suggest how to assign my view controller to textField.inputViewController in Swift?
Thanks
You can assign your own viewcontroller to inputViewcontroller:
Your viewController has to be a subclass of UIInputViewController for example:
class CustomInputViewController: UIInputViewController {
#IBOutlet var insertTextButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
self.inputView?.translatesAutoresizingMaskIntoConstraints = false
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func insertText(_ button: UIButton){
self.textDocumentProxy.insertText((button.titleLabel?.text)!);
}
}
Here with only one button insertTextButton which I design in the xib-file.
In your main view controller you need a subclass of your textfield (or textview):
class textfield: UITextField {
var _inputViewController : UIInputViewController?
override public var inputViewController: UIInputViewController?{
get { return _inputViewController }
set { _inputViewController = newValue }
}
}
which you assign to your textfield.
Now you can assign your own inputViewcontroller to your textfield, for example:
class ViewController: UIViewController {
private var customInputViewController = CustomInputViewController(nibName: "CustomInputViewController",
bundle: nil)
#IBOutlet var textField: textfield!
override func viewDidLoad() {
super.viewDidLoad()
self.textField.inputViewController = customInputViewController
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I used the xib-file with the name CustomInputViewController.xib to design the keyboard
As far as I know, you cannot use a view controller. You need to make your own view and assign it to the inputView field. Make sure the view has a delegate so it knows which field to use:
MyInputView keyboard = ...
field.inputView = keyboard
keyboard.delegate = field
Maybe this is a simple problem, but I spend some time try to solve it and so far I failed.
I want to show custom view with a few of button after I clicked a block of text. I try to add and remove this view form subview but it's doesn't work.
Can you give me some tips about my problem?
Thank you for your help.
my code
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var myTextField: UITextField!
#IBOutlet weak var simpleView: SimpleView!
override func viewDidLoad() {
super.viewDidLoad()
self.myTextField.delegate = self
self.simpleView.removeFromSuperview()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func textFieldDidBeginEditing(textField: UITextField!) {
println("works")
self.view.addSubview(simpleView)
}
func textFieldDidEndEditing(textField: UITextField!) {
println("works2")
}
}
You'd better set the hidden property of simpleView instead of removing and adding the view.
put a container view in your main view and set the visibility hidden. when you want to show the popup, set the visibility to visible and load the view inside the container. To get the popup
look and feel ,you can use a transformation to animate.