I'm a newbie in swift and I'm trying to store a user input of type string into a text field.
I initialized an empty string and then assigned it to the text field when the button is pressed but it keeps printing that the string is nil whenever I input data to the text field.
Here is the code I have so far
import UIKit
import Photos
class ViewController: UIViewController {
#IBOutlet weak var link: UITextField!
var url = String()
#IBAction func buttonPressed(_ sender: UIButton) {
// Hide the keyboard when the button is pressed
self.link.resignFirstResponder()
link.text = url
print("The value of url is \(url)")
}
// Override function to hide the keyboard when the screen is touched
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
}
Any kind of help would be appreciated!
You keep getting that error because the assignment you're doing is wrong. You just need to change
link.text = url
to
url = link.text
This is because in the assignment operation, the left operand is the destination of the value you want to assign, in this case "url", and the right operand is the source of the value you want to assign, in this case link.text.
As a general rule of thumb, remember this.
destinationVariable = sourceVariable
Assignment Operator
The assignment operator (a = b) initializes or updates the value of a with the value of b:
let b = 10
var a = 5
a = b // a is now equal to 10
You need to change below mentioned line of code
link.text = url
to
url = link.text!
You are doing the reverse ways.
Change your code to
#IBAction func buttonPressed(_ sender: UIButton) {
// Hide the keyboard when the button is pressed
self.link.resignFirstResponder()
url = link.text
print("The value of url is \(url)")
}
Related
I'm trying to make an app that lets users input 4 numbers and display what cellular network is that number. Is there a way to automatically display the numbers in the label after the user inputs the numbers without clicking a button? I actually have a code that lets the user input the number but the user must click the enter button for it to display the result on the label. Is there a way for it to automatically display the result? By the way, I'm actually new to swift so I apologize. Here is the code:
import UIKit
import Firebase
class ViewController: UIViewController, FBSDKLoginButtonDelegate {
#IBOutlet weak var numField: UITextField!
#IBOutlet weak var answerField: UILabel!
#IBAction func enterButton(sender: AnyObject) {
matchNumber()
}
func matchNumber(){
let number: String = numField.text!
let numRef = Firebase(url: "https://npi2.firebaseio.com/num_details")
numRef.queryOrderedByKey().observeEventType(.ChildAdded, withBlock: { snapshot in
let network = snapshot.value as! String!
if snapshot.key == self.numField.text! {
self.answerField.text = network
}
else {
self.answerField.text = "Missing"
}
})
}
Add a target to your numField, something like this...
override func viewDidLoad() {
super.viewDidLoad()
self.numField.addTarget(self, action: "editingChanged:", forControlEvents: .EditingChanged)
}
This will trigger the editingChanged method every time a character changes in the numField.
func editingChanged(textField:UITextField) {
if let text = textField.text {
if text.characters.count == 4 {
matchNumber()
}
}
}
Finally we check if there is a string in the input and if it is 4 characters long before running the matchNumber method.
You could use the didSet method.
var numberstring = String() {
didSet {
yourlabel.text = numberstring
}
}
If you are using textfield to take input then you can use textfieldDidEndEditing delegate method.
I have a function that runs when a button is pressed.
Inside that function is another function.
I would like to pass the pressed button into the inner function so that I can change the text of the button depending on stuff in that inner function.
#IBAction func newItem(sender: AnyObject) {
let urlFetch:String = urlField.text!
self.service.createNewItem(urlFetch, I_WANT_BUTTON_HERE)
}
How do I pass the button into the function?
If it helps this is the function that I am passing it to:
func createNewItem(item_url: String, plus_button: UIButton) {
let dataDictionary = ["url" : item_url]
self.post("item/create", data: dataDictionary).responseJSON { (response) -> Void in
plus_button.titleLabel!.text = "success"
}
}
Later I will add an if statement that changes the text depending on what the response is.
The object passed into newItem method is actually the button you tapped so you can securely convert the type of parameter sender into UIButton like below:
#IBAction func newItem(sender: UIButton) {
...
self.service.createNewItem(urlFetch, sender)
}
There is also one thing though. Setting the text of titleLabel is not the right way of updating the title of button. You should be using setTitle:forState instead:
func createNewItem(item_url: String, plus_button: UIButton) {
...
plus_button.setTitle("success", forState: .Normal)
}
Instead of sending AnyObject as parameter in the newItem function, pass a UIButton.
#IBAction func newItem(sender: UIButton) {
let urlFetch:String = urlField.text!
self.service.createNewItem(urlFetch, sender)
}
Im making a basic registration form, and I'm getting multiple "Expected Expression in list of Expression Errors," as well as a couple expected separator errors. Ive tried fixing the errors myself, but I'm new at Swift, and wasn't able to fix it. Any help is appreciated.
import UIKit
class RegisterPageViewController: UIViewController {
#IBOutlet weak var userFullNameTextField: UITextField!
#IBOutlet weak var userEmailTextField: UITextField!
#IBOutlet weak var userPasswordTextField: UITextField!
#IBOutlet weak var userRepeatPasswordTextField: UITextField!
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 RegisterButtonTapped(sender: AnyObject) {
let userFullName = userFullNameTextField.text
let userEmail = userEmailTextField.text
let userPassword = userPasswordTextField.text
let userRepeatPassword = userRepeatPasswordTextField.text
}
// Check for empty fields
**//ERROR HERE EXPECTED DECLARATION**
if (((userFullName.isEmpty || userEmail.isEmpty || userPassword.isEmpty || userRepeatPassword.isEmpty))
{
// Display alert message
displayMyAlertMessage("All fields are required")
return;
}
// Check if passwords match
if(userPassword != userRepeatPassword)
{
// Display alert message
displayMyAlertMessage("Passwords do not match")
return;
}
func displayAlertMessage(userMessage:string)
{
var myAlert = UIAlertController(title:"Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.Alert);
}
}
// Store Data
// Display alert message with confirmation
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
Error 1: Non-closed parantheses
You're missing a closing paranthesis in the first if statement of the RegisterButtonTapped function:
if (((userFullName!.isEmpty || userEmail!.isEmpty
|| userPassword!.isEmpty || userRepeatPassword.isEmpty)) {
// Display alert message
displayMyAlertMessage("All fields are required")
return
}
Three left pranthesis ((( finished by only two right ones )). I this case, you really need no set of parantheses at all, but could save one set for readability:
if (userFullName!.isEmpty || userEmail!.isEmpty
|| userPassword!.isEmpty || userRepeatPassword.isEmpty) {
// Display alert message
displayMyAlertMessage("All fields are required")
return
}
Error 2: trying to include a function declaration within another function
(As pointed out by Duy Tran)
The function displayAlertMessage(...) is positioned within the function RegisterButtonTapped. Functions may only exists as methods directly in a class/structure etc (or as a global non-class owned function e.g. in a playground).
Hence, you should make sure the function displayAlertMessage(...) is placed outside the body of function RegisterButtonTapped.
General remarks
You should avoid "forced unwrappings" of optional variables. E.g. userFullName!.isEmpty will lead to a runtime exception in case the optional immutable userFullName has valuenil`. You should read up on optionals, optional binding, and so on.
Also note that you needn't put semi-colons ; after lines in Swift. However you won't get an error for doing so:
[swift-evolution] Proposal to remove semicolons
The function displayAlertMessage is placed within the IBAction body.
It should be placed outside your IBAction function.
I assure you that i have checked all the answers prior posting this question on Unwrapping an object, but this thing simply does not seem to work for me. I am simply trying to pass on a text value from my cell tapped to the Label on the next screen.
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if(segue.identifier == "detailViewSegue")
{
var DVC:DetailedViewController = segue.destinationViewController as DetailedViewController
let path:NSIndexPath = self.tableView.indexPathForSelectedRow()
var segueRecipeName:String = recipeMgr.RecipeName[path.row] as String
DVC.detailedRecipeLabel.text = segueRecipeName
}
}
The problem occurs at this line -
DVC.detailedRecipeLabel.text = segueRecipeName //Can't UnWrap Optional - None
I know I'm supposed to check the nil value of segueRecipeName before assigning. I do a print check on the console and it clearly is not null. The error occurs only when I'm assigning the value to the 2nd view controller class object. I'm sure this will help others learning Swift :)
DVC.detailedRecipeLabel is nil
Probably it's a IBOutlet that hasn't been loaded yet.
You should add a custom property to your DetailedViewController that will accept your text, save it and then you can assign it to the label in viewDidLoad.
Example:
class DetailedViewController ... {
...
var recipeName: NSString? = nil
...
override func viewDidLoad() -> () {
...
self.detailedRecipeLabel.text = self.recipeName
}
}
DVC.recipeName = segueRecipeName
I'm trying to make a simple app that counts the characters of a textfield, but when the user inputs the text, the function that converts the user-inputed string into a var and the function that counts the characters are executed at once. Here's the code:
import UIKit
class ViewController: UIViewController {
#IBOutlet var myTextField : UITextField
#IBOutlet var userTextField : UITextField
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
myTextField.text = fullConstant
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func modifyMyVariable(sender : AnyObject) {
myVariable = userTextField.text
}
#IBAction func clickMe(sender : AnyObject) {
countCharacters(&fullConstant)
println(fullConstant)
myTextField.text = fullConstant
}
}
And here's the "OtherFile.swift" where the functions are located:
import Foundation
var fullConstant = "Type something!"
var myVariable = ""
func modifyMyVariable() {
println()
}
func countCharacters(inout fullConstant: String) {
let FirstPart = "There are "
let LastPart = " characters"
var numberOfCharacters = countElements(myVariable)
switch numberOfCharacters {
case 0 :
fullConstant = "There isn't any character yet"
case 1 :
fullConstant = "There is just one character"
default :
fullConstant = FirstPart + String(numberOfCharacters) + LastPart
}
}
Both functions execute as soon the userTextField is edited, but if the user inputs one character, the countCharacters function takes the var myVariable before it's modified by the function modifyMyvariable, so it doesn't count the last character added.
To solve this, I've thought that I could call the function countCharacters from the function modifyMyVariable, so the variable myVariable has already changed when it counts the characters.
Change the following and see if it's then easier to fix your problem.
You should always only link each event to one IBAction. Your IBActions shouldn't be named after what you're trying to do in them; they should be named after the event that triggers them. For example, "modifyMyVariable" should be called "textEdited" or similar.
In that "textEdited" method, do all the work you need to do. If you need to call another function, call it from there instead of linking to two IBActions.
Put code in your "OtherFile" inside a
class OtherFile {
}
block, and hold an instance to that class as a variable in your view controller. You want to avoid declaring global functions outside of classes.
Not related, but name your constants using camelCase with first letter lower case, just like your variables. So FirstPart should be firstPart.
Avoid using 'inout' as much as possible. Each language has it's conventions; in ObjC and Swift, pass in values needed to do work, and return values that result from that work. So:
func countCharacters(text: String) -> (String)
Putting it all together, your 'modifyMyVariable' function (which should really be called 'textEdited') will look something like this:
myVariable = userTextField.text
let characterCount = self.myOtherFileInstance.countCharacters(myVariable)
myTextField.text = characterCount
and the other function (clickMe) should be deleted.