Using UIButton Text as Text Input - Swift - ios

Hello I have a profilelbl variable as below which is a uibutton. I want the text of the button to be an input in my database (parse). But I couldn't figured it out. I tried lots of things but still getting error:
#IBOutlet weak var profileLbl: UIButton!
var notification = PFObject(className: "notifications")
notification["actionReceiverName"] = profilelbl.text /*not working*/
/* also tried
notification["actionReceiverName"] = sender.profilelbl.text
notification["actionReceiverName"] = profilelbl.title */

you can do it easy like that
if let button = profilelbl as? UIButton {
if let title = button.titleForState(.Normal) {
println(title)
notification["actionReceiverName"] = title
}
}

Using UI objects to save/load data is a very bad idea. Using user-visible strings programmatically is an even worse idea. #ÖzgürErsil answered the question you asked, but the better answer to your question is "Don't do that. Ever."
Here are 2 examples where your approach will fail:
If 6 months later you want to change your UI and rename your button,
you won't remember that the button title is used in code and your
code will break. To that you would have to alter your database to
use a different string value.
If you decide to localize your app for foreign
languages, the button titles will come up in the local language, and
your code will break. There is no clean way to fix this problem,
since each local language would use a different version of the
button title.
It would be better to put unique tag numbers on your buttons, then look up text strings using the tags and pass those strings to your database.
Say you have button tags starting at 100.
You'd use code like this:
let buttonStrings = ["button1", "button2", "button3"]
let baseButtonTag = 100;
#IBAction func handleButton(sender: UIButton)
{
let tag = sender.tag
if tag >= baseButtonTag && tag < baseButtonTag + buttonStrings.count
{
let index = sender.tag - baseButtonTag
let buttonString = buttonStrings[index];
//Now use buttonString with your database as desired.
}
}

Related

Add data to a new line in UITextView every time button is pressed

I currently have a function that, when a button is pressed, takes a value that is determined from a UIStepper and adds it to a list of numbers. When I press the Add Tip button, it correctly displays the tip amount in the text view, but when I add a new value it replaces it rather than adding it underneath.
Here is the function:
#IBAction func addTipButton(_ sender: UIButton) {
let tipDollarCent = dollar + cent
sampleLog.text = "\(tipDollarCent)\n"
totalLabel.text = tipDollarCent
}
sampleLog is the Text View that needs to take a variable amount of lines of data, depending on how many time the user presses addTipButton
I am aware that my best course of action is probably to do an incremental loop, and I have tried implementing a separate addNewLine function, but tipDollarCent was out of scope and gave me an error.
I also initially tried adding sampleLog.text = "\(tipDollarCent)\n" += "\(tipDollarCent)\n" directly to the function.
I am hoping someone would be able to patiently and kindly explain to me what the best loop to use in this scenario would be, and how to properly implement it.
Here is a screenshot of my app so it is easier to see what I am trying to accomplish
If you want the textView text to append the newly created string, you can use the compound-assign operator for addition += to concatenate the what you previous had and grow it with a new string value.
var foo:String = "Foo"
let bar:String = "Bar"
foo += bar /* FooBar */ /* foo = foo + bar */
And for your comment on additions with doubles, the compound operator will also work with same-typed operands.
var pi:Double = 3.0
let fourteen:Double = 0.14
pi += fourteen /* 3.14 */ /* pi = pi + fourteen */

How to get Integer from button title

I have a Button labeled "3x3" now I want to create an Int variable with the value "3" in button click function.
I have tried
let newBoardSizeString = String.localizedStringWithFormat("\(sender.currentTitle?.characters.first)")
let newBoardSize = Int(newBoardSizeString)
The string i get is like this
"Optional(\"3\")"
and Int I get is
nil
I want only 3
This is an XY problem.
You ask: "How do I convert the first character of my button label to an Int."
The real answer is "Don't do that." It is a very bad idea to make the logic of your code depend on display information.
One simple solution is to use the tag property of your button and set the tag value to 3 in IB when you create the button:
let newBoardSize = sender.tag
Note that you either need to set your IBAction up with the sender as type UIButton (the better solution) or cast sender to the correct class in your IBAction.
Another approach is to set up outlets to your different buttons (e.g. threeButton and fourButton) and then in your IBAction, check which button is the sender and use a switch statement to figure out the appropriate value for each button:
func buttonTapped(sender: UIButton) {
switch sender {
case threeButton:
//Use the value 3
case fourButton
//Use the value 4
}
}
!
let newBoardSizeString = String.localizedStringWithFormat("\(sender.currentTitle?.characters.first!)")
let newBoardSizeString = String.localizedStringWithFormat("\(sender.currentTitle?.characters.first)")
if let unwrapped = Int(newBoardSizeString){
let newBoardSize = unwrapped
}
This works.
let newBoardSize = newBoardSizeString as! Int
Did you try ?
Int(newBoardSizeString)!
and make sure you are handling the nil before unwrapping the value.

Get the current text inside of a textfield for IOS custom keyboard

I am developing a IOS custom keyboard. I was wondering if there was a way to fetch the current text inside of the text field and how it would work.
For example, we can use textDocumentProxy.hasText() to see if the textfield has text inside but I want to know the exact string that is inside the textfield.
The closest things would be textDocumentProxy.documentContextBeforeInput and textDocumentProxy.documentContextAfterInput. These will respect sentences and such, which means if the value is a paragraph, you will only get the current sentence. Users have been known to retrieve the entire string by repositioning the cursor multiple times until everything is retrieved.
Of course, you generally do not have to worry about this if the field expects a single value like a username, email, id number, etc. Combining the values of both before and after input contexts should suffice.
Sample Code
For the single phrase value, you would do:
let value = (textDocumentProxy.documentContextBeforeInput ?? "") + (textDocumentProxy.documentContextAfterInput ?? "")
For values that might contain sentence ending punctuation, it will be a little more complicated as you need to run it on a separate thread. Because of this, and the fact that you have to move the input cursor to get the full text, the cursor will visibly move. It is also unknown whether this will be accepted into the AppStore (after all, Apple probably did not add an easy way to get the full text on purpose in order to prevent official custom keyboards from invading a user's privacy).
Note: the below code is based off of this Stack Overflow answer except modified for Swift, removed unnecessary sleeps, uses strings with no custom categories, and uses a more efficient movement process.
func foo() {
dispatch_async(dispatch_queue_create("com.example.test", DISPATCH_QUEUE_SERIAL)) { () -> Void in
let string = self.fullDocumentContext()
}
}
func fullDocumentContext() {
let textDocumentProxy = self.textDocumentProxy
var before = textDocumentProxy.documentContextBeforeInput
var completePriorString = "";
// Grab everything before the cursor
while (before != nil && !before!.isEmpty) {
completePriorString = before! + completePriorString
let length = before!.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
textDocumentProxy.adjustTextPositionByCharacterOffset(-length)
NSThread.sleepForTimeInterval(0.01)
before = textDocumentProxy.documentContextBeforeInput
}
// Move the cursor back to the original position
self.textDocumentProxy.adjustTextPositionByCharacterOffset(completePriorString.characters.count)
NSThread.sleepForTimeInterval(0.01)
var after = textDocumentProxy.documentContextAfterInput
var completeAfterString = "";
// Grab everything after the cursor
while (after != nil && !after!.isEmpty) {
completeAfterString += after!
let length = after!.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
textDocumentProxy.adjustTextPositionByCharacterOffset(length)
NSThread.sleepForTimeInterval(0.01)
after = textDocumentProxy.documentContextAfterInput
}
// Go back to the original cursor position
self.textDocumentProxy.adjustTextPositionByCharacterOffset(-(completeAfterString.characters.count))
let completeString = completePriorString + completeAfterString
print(completeString)
return completeString
}

Passing a Swift variable from one IBAction to another [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
In my application I have a "Play" button which creates two random numbers and creates a string for those numbers, which is then used to fill in the two UIImage holders for cards (cards 0-10 which are set in a Array). Then the two random numbers are added together.
There is an input field where the user can input their guess and then hit "Submit". If their answer is correct it will flash "Correct". If the answer is wrong, it will flash Try Again. My question is how can I get the total variable passed to the Submit so I can successfully create my if else statements?
So here is the end code to the Play button Action which works perfectly
let total = firstRandomNumber + secondRandomNumber
Here is the code for the Submit button which is giving me an error
#IBAction func submit(sender: UIButton) {
correct.hidden = (true)
tryagain.hidden = (true)
let guess = Double(text.text!)
if guess = total {
correct.hidden = (false)
}
The error I'm getting is "undefined variable total"
So the variables are not going to be PASSED to Submit() because that's the function the button calls. The button can careless about your two variables. Instead you'll want to have two Global variables (in this case the two random numbers) and request them in Submit. These are variables that was created outside any functions and are set when they need to be set. So lets see how you'd do that with your code:
// Two random numbers (global)
var a: Int?
var b: Int?
func generateRandomNumber() {
a = // assign a to the number generator value
b = // same as above
}
func submit() { // your button call
if let userGuess = text.text { // do if let instead of ! it's safer
let total = a + b
if userGuess == total { // our check remember == is different from =
correctView.hidden = false
} else { // if it's wrong show this view
tryAgainView.hidden = false
}
}
}
Obviously there's a bunch missing but you can get the main idea. Let me know if these anything I can answer about this method.

How to get the current word being typed?

I am making a custom keyboard extension for iOS 8 and am unsuccessful at trying to reflect the current word being typed on a UILabel sitting on top of the keyboard (think autocorrect). So far the code I wrote reflects the sentence before the cursor and not as it's being written, but as the cursor is moved from one position to another. What I am trying to achieve is exactly like the first autocorrect box in the native keyboard. Would anyone mind telling me what I am doing wrong?
Code:
override func textWillChange(textInput: UITextInput) {
var tokens = (self.textDocumentProxy as! UITextDocumentProxy).documentContextBeforeInput .componentsSeparatedByString(" ") as NSArray
var lastWord = tokens.lastObject as! String
println(lastWord)
bannerView?.btn1.setTitle(lastWord, forState: .Normal)
}
I've tried setting a condition whereby if beforeCursor contained either a space/period/comma to set the button title as "" but that is not efficient in the long run as I need to obtain words in order to be able to make an autocorrect feature.
Edit:
I've figured out how to get the word before the cursor (updated the code above), but not how to update the label as each letter is being added. func textWillChange(textInput: UITextInput)isn't working out. It's not me it's her.
Thanks!
You should use the textDocumentProxy property of your UIInputViewController:
let proxy = self.textDocumentProxy as! UITextDocumentProxy
To get the word being typed, I would suggest something like this:
var lastWordTyped: String? {
if let documentContext = proxy.documentContextBeforeInput as NSString? {
let length = documentContext.length
if length > 0 && NSCharacterSet.letterCharacterSet().characterIsMember(documentContext.characterAtIndex(length - 1)) {
let components = documentContext.componentsSeparatedByCharactersInSet(NSCharacterSet.alphanumericCharacterSet().invertedSet) as! [String]
return components[components.endIndex - 1]
}
}
return nil
}

Resources