How to get Integer from button title - ios

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.

Related

Cannot subscript a value of type [uiButton] with an index of type 'UIButton' (Swift)

I have an array of UIButton radioController.buttonsArray = [ button1, button2, button3 ] and would like to set the default to the selected button by passing the selected button to a function radioController.defaultButton = radioController.buttonsArray[selectedButton]
I want to use a string (originally was an integer, but the position in the array kept changing with the design), so above this, I tried:
var selectedButton: UIButton = button1
switch currentSelection {
case "selection 1" : selectedButton = button1
case "selection 2" : selectedButton = button2
case "selection 3" : selectedButton = button3
default:
break
}
I first get the error message: Value of optional type '[UIButton]?' must be unwrapped to refer to member 'subscript' of wrapped base typ '[UIButton]'
but after "fixing" it ((with either ? or !) I get the message:
Cannot subscript a value of type [uiButton] with an index of type 'UIButton'
How do I declare selectedButton to do this? Or is there a better way?
You can only subscript arrays with Ints. If you want to find the index of a specific element in an array, you should use the firstIndex(of:) function on the array.
However, for your particular needs it seems there's no reason to access the array at all, since you already have access to the element you need.
You can just do radioController.defaultButton = selectedButton.

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
}

Using UIButton Text as Text Input - Swift

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.
}
}

Get an Int out of an UILabel Swift

I have the problem, to have a high amount of buttons which have a number as their label, so i thought i could take the label as an integer instead of creating an action for every button?!
#IBAction func NumberInput(sender: UIButton) {
var input:Int = sender.titleLabel as Int
}
If you want to do this, you can convert the string to an Int by using string.toInt() such as:
if let input = sender.titleLabel?.text?.toInt() {
// do something with input
} else {
// The label couldn't be parsed into an int
}
However, I'd suggest either using UIView.tag or subclassing UIButton and adding an Int property to it to accomplish this, in case you ever change the display of your labels.
You should make sure that the text exists
var input:Int = (sender.titleLabel.text! as NSString).integerValue
You can't convert a UILabel to an Int. I think you want this instead:
var input : Int? = sender.titleLabel.text?.toInt()
Another way to convert a label in swift:
let num = getIntFromLabel(labelView)
connect all your buttons to 1 IBAction. then create the following variable and the set/get methods based on how you will use it.
note: "something" is a UILabel. The variable I wrote below should help you do conversions easily and with cleaner syntax. "newValue" comes with all setter methods. It basically takes into account any value that could possibly used to set "num" to a new value.
var num : Int {
get {
return Int(something!)!
}
set {
something.text = Int(newValue)
}
}
For Swift 3, what you can do is to directly convert it from an String input to an integer, like this
Int(input.text!)
And then, if for any reason, if you wish to print it out or return is as a String again, you can do
String(Int(input.text!)!)
The exclamation mark shows that it is an optional.

Weird error in accessing the text of UIButton in swift

When I write a simple function such as this:
#IBAction func buttonTapped(theButton:UIButton) {
println(theButton.titleLabel.text);
}
It gives me an error: UILabel doesn't have a label called text.
However, when I change it to this:
#IBAction func buttonTapped(theButton:UIButton) {
println(theButton.titleLabel?.text);
}
It works fine, but it prints out something like this:
Optional("1");
What I am doing wrong? I am expecting a value of 1. But it is printing out Optional("1") and secondly, it is working fine when println(theButton.titleLabel?.text);
You can get directly from
let title = theButton.currentTitle!
Optional chaining makes the result optional, so you are printing optional value: https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/OptionalChaining.html
With optional binding you can print the value only if it exits.
if let text = theButton.titleLabel?.text {
println(text)
} else {
// text doesn't have value
}
#Kirsteins's answer shows how to obtain the button label text in a safe manner.
Remember that:
UIButton has a titleLabel, which is an optional UILabel.
UILabel has a text property, which is an optional String
so there are 2 optionals in the chain. You can use optional binding as in #Kirsteins's answer, or use forced unwrapping:
let text = theButton.titleLabel!.text!
which however I discourage using, because if any of the 2 is nil you'll have a runtime exception. But for completeness it's worth mentioning.
The buttons titleLabel property returns an optional UILabel, that means it's possible that the button doesn't have a titleLabel.
var titleLabel: UILabel? { get }
If you don't set a title to the button, then the button doesn't have a titleLabel property, the iOS framework adds the titleLabel only if the button has a title, I think this happens to reduce memory.
This is why you have to put the "?" (is called optional chaining you can read about it here http://bit.ly/1vrSOi1) in that line, but this usually get auto completed by Xcode itself.
Kirsteins answers it correctly but misses one small detail
if your object can be nil (optional) you need to check first if it exists to then access its value, like this:
if let text = theButton.titleLabel?.text {
println(text)
}
but you can also ignore the if and just call it like this:
let text : String = theButton.titleLabel?.text
// If theButton.titleLabel don't exists then text will be nil
this happen if the IBOutlet was declared with ? but if you declare with ! that means you know that it could be nil, but you never want it to be nil, for a IBOutlet i prefer this approach since if the IBOutlet is not connected then maybe something is worn with my code.
#IBOutlet var theButton : UIButton!
// and get text value as
theButton.titleLabel!.text
this will ensure theButton.titleLabel could be nil, but in this part of code it is required, hope this helps to understand the difference between optional (?) and optional required (!)

Resources