hello I was making a simple guess the number game and suddenly I come up with
Cannot invoke '<' with an argument list of type '(#lvalue UITextField!, #lvalue UInt32)
this is my whole script
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var guess: UITextField!
#IBOutlet weak var text: UILabel!
#IBAction func button(sender: AnyObject) {
if guess > random {
println(text = "your number was too high. Try again")
}
if guess < random {
println(text = "your number was too low. Try again")
}
}
var random = arc4random()%100
...
thanks
You have to convert the string contained in the guess text field into an integer, by using the toInt() method, which returns an optional though, in case the string is not convertible to a valid integer.
I would use optional binding to do the conversion and assign a valid value to a variable:
#IBAction func button(sender: AnyObject) {
if let guessInt = guess.text.toInt() {
if guessInt > random {
println("your number was too high. Try again")
}
if guessInt < random {
println("your number was too low. Try again")
}
}
}
However that change alone doesn't work because toInt returns a Int, whereas arc4random returns a UInt - since swift doesn't have implicit conversion between data types, an explicit conversion to Int is needed:
var random = Int(arc4random()%100)
you've defined "guess" as a UITextField, which is certainly not the same type as "random".
You need to tell the compiler how to convert that to an integer.
Something like:
let guessInteger = guess.text.toInt()
and then:
if guessInteger > random {
println("\(guess.text) was too high. Try again")
}
Related
I have a slider and I want to limit its value to range from 1 to 5. I have set the min and max values on both Interface Builder and in codes but am currently facing two main issues.
1) The value doesn't change (keeps saying value 1).
2) On top of that, I am also unable to adjust the value of the slider when VoiceOver accessibility mode is on. The value keeps reading it as 1, even though on the surface, it may be on value 3/4/5.
Here are some of my codes to implement the slider in Swift. I am not sure what is the problem here with this. Any help is appreciated!
#IBOutlet weak var busSlider: UISlider!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
busSlider.minimumValue = 1
busSlider.maximumValue = 5
}
override func viewDidAppear(animated: Bool) {
busSlider.accessibilityValue = NSNumberFormatter.localizedStringFromNumber(busSlider.value, numberStyle: NSNumberFormatterStyle.DecimalStyle)
busSlider.accessibilityLabel = NSLocalizedString("\(Int(busSlider.value))", comment: "")
}
override func accessibilityIncrement() {
busSlider.value++
busSlider.sendActionsForControlEvents(UIControlEvents.ValueChanged)
busSlider.accessibilityValue = NSNumberFormatter.localizedStringFromNumber(busSlider.value, numberStyle: NSNumberFormatterStyle.DecimalStyle)
busSlider.accessibilityLabel = NSLocalizedString("\(Int(busSlider.value))", comment: "")
}
override func accessibilityDecrement() {
busSlider.value--
busSlider.sendActionsForControlEvents(UIControlEvents.ValueChanged)
busSlider.accessibilityValue = NSNumberFormatter.localizedStringFromNumber(busSlider.value, numberStyle: NSNumberFormatterStyle.DecimalStyle)
busSlider.accessibilityLabel = NSLocalizedString("\(Int(busSlider.value))", comment: "")
}
*On the side note: I actually have 2 sliders on the same screen but belonging to different sections. The first slider reads the value in percentage (speak rate), and this slider needs to read the value in integer (number of stops).
I have this nice function that prints some info about a given method in a given type, here is a goplay
it does all i need except i can't find a way to get the method argument names,any idea to achieve that?
func AnalyzeMethod(instance interface {},methodName string){
m,ok := reflect.ValueOf(instance).Type().MethodByName(methodName)
if ok{
isVariadic := m.Type.IsVariadic()
var VariadicIndex int
var VariadicType reflect.Type
var FirstPositionalIndex int
var LastPositionalIndex int
var ArgsLength int = m.Type.NumIn()-1
//var []string ArgumentNames //can't find a way to get an ordered slice of names of every argument that the function takes
if ArgsLength>0{
FirstPositionalIndex = 1
}
if isVariadic{
VariadicIndex = ArgsLength
VariadicType = m.Type.In(VariadicIndex)
LastPositionalIndex = ArgsLength-1
} else {
VariadicIndex = -1
LastPositionalIndex = ArgsLength
}
fmt.Println("ArgsLength:",ArgsLength)
fmt.Println("FirstPositionalIndex:",FirstPositionalIndex)
fmt.Println("LastPositionalIndex:",LastPositionalIndex)
fmt.Println("Variadic:",isVariadic)
fmt.Println("VariadicIndex:",VariadicIndex)
fmt.Println("VariadicType:",VariadicType)
fmt.Println("ArgumentNames","How?")
}
}
The names of local variables (including function arguments) are just for the programmer; the compiler discards them when it generates code. There is no way to retrieve argument names as they are not available in the compiled code.
I am trying to randomly choose an enum value:
enum GeometryClassification {
case Circle
case Square
case Triangle
case GeometryClassificationMax
}
and the random selection:
let shapeGeometry = ( arc4random() % GeometryClassification.GeometryClassificationMax ) as GeometryClassification
but it fails.
I get errors like:
'GeometryClassification' is not convertible to 'UInt32'
How do I solve this?
In Swift there is actually a protocol for enums called CaseIterable that, if you add it to your enum, you can just reference all of the cases as a collection with .allCases as so:
enum GeometryClassification: CaseIterable {
case Circle
case Square
case Triangle
}
and then you can .allCases and then .randomElement() to get a random one
let randomGeometry = GeometryClassification.allCases.randomElement()!
The force unwrapping is required because there is a possibility of an enum having no cases and thus randomElement() would return nil.
Swift has gained new features since this answer was written that provide a much better solution — see "How to choose a random enumeration value" instead.
I'm not crazy about your last case there -- it seems like you're including .GeometryClassificationMax solely to enable random selection. You'll need to account for that extra case everywhere you use a switch statement, and it has no semantic value. Instead, a static method on the enum could determine the maximum value and return a random case, and would be much more understandable and maintainable.
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
private static let _count: GeometryClassification.RawValue = {
// find the maximum enum value
var maxValue: UInt32 = 0
while let _ = GeometryClassification(rawValue: maxValue) {
maxValue += 1
}
return maxValue
}()
static func randomGeometry() -> GeometryClassification {
// pick and return a new value
let rand = arc4random_uniform(_count)
return GeometryClassification(rawValue: rand)!
}
}
And you can now exhaust the enum in a switch statement:
switch GeometryClassification.randomGeometry() {
case .Circle:
println("Circle")
case .Square:
println("Square")
case .Triangle:
println("Triangle")
}
Since you're inside the enum class, having the random() method reference the highest value explicitly would eliminate having to count them every time:
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
static func random() -> GeometryClassification {
// Update as new enumerations are added
let maxValue = Triangle.rawValue
let rand = arc4random_uniform(maxValue+1)
return GeometryClassification(rawValue: rand)!
}
}
For Swift 5 there is "RandomNumberGenerator":
enum Weekday: CaseIterable {
case sunday, monday, tuesday, wednesday, thursday, friday, saturday
static func random<G: RandomNumberGenerator>(using generator: inout G) -> Weekday {
return Weekday.allCases.randomElement(using: &generator)!
}
static func random() -> Weekday {
var g = SystemRandomNumberGenerator()
return Weekday.random(using: &g)
}
}
You need to assign a raw type to your enum. If you use an integer type, then the enumeration case values will be auto-generated starting at 0:
enum GeometryClassification: UInt32 {
case Circle
case Square
case Triangle
case GeometryClassificationMax
}
Per Enumerations:
"Unlike C and Objective-C, Swift enumeration members are not assigned a default integer value when they are created."
Specifying the integer type lets it know to generate the values in the usual way.
Then you can generate the random value like this:
let randomEnum: GeometryClassification = GeometryClassification.fromRaw(arc4random_uniform(GeometryClassification.GeometryClassificationMax.toRaw()))!
This is a horribly ugly call, and all those fromRaw and toRaw calls are fairly inelegant, so I would really recommend generating a random UInt32 that is in the range you want first, then creating a GeometryClassification from that value:
GeometryClassification.fromRaw(someRandomUInt32)
You can put all the values into array and generate random,
extension GeometryClassification {
static func random() -> GeometryClassification {
let all: [GeometryClassification] = [.Circle,
.Square,
.Triangle,
.GeometryClassificationMax]
let randomIndex = Int(arc4random()) % all.count
return all[randomIndex]
}
}
The easiest thing to do is to create a global extension:
extension CaseIterable {
static func randomElement() -> AllCases.Element {
guard Self.allCases.count > 0 else {
fatalError("There must be at least one case in the enum")
}
return Self.allCases.randomElement()!
}
}
This way any enum which conforms to CaseIterable has the function automatically
Here's my Swift 1.2 take:
enum GeometryClassification : Int {
case Circle = 0
case Square = 1
case Triangle = 2
static func random() -> GeometryClassification {
let min = MutationType.Circle.rawValue
let max = MutationType.Triangle.rawValue
let rand = Int.random(min: min, max: max) // Uses ExSwift!
return self(rawValue: rand)!
}
}
I wrote a global extension using Andy's answer. Enjoy :)
extension CaseIterable {
static func random<G: RandomNumberGenerator>(using generator: inout G) -> Self.AllCases.Element {
return Self.allCases.randomElement(using: &generator)!
}
static func random() -> Self.AllCases.Element {
var g = SystemRandomNumberGenerator()
return Self.random(using: &g)
}
}
Just extend your enumeration to conform CaseIterable protocol and use like:
let state = YourEnum.random()
Go method receivers take a type along with a variable name for the type, example:
type MyFloat float64
func (x MyFloat) Abs() float64 {
if x < 0 {
return float64(-x)
}
return float64(x)
}
func main() {
f := MyFloat(-math.Sqrt2)
fmt.Println(f.Abs())
}
The receiver takes "x" along with the type receiving the method. What is the significance of the name 'x'. Since i am able to invoke the method on any instance of MyFloat ( not just on the one named as x ) why do i have to specify the x ? Since the receiver is a Type or a reference to a type why not simply take the type or the pointer alone like this
func (MyFloat) Abs() float64 {
if this < 0 {
return float64(-this)
}
return float64(this)
}
My assumption is instead of this in Java golang allows any name? Is that so ?
Your assumption is exact: the receiver has to be explicitly named in a method definition. It avoids any ambiguity. In your example, how could the Go compiler guess that x is the receiver?
Note that using "self" or "this" or "me" as the receiver name is considered as bad style in go. The name should be short - one letter is fine. See more information at https://code.google.com/p/go-wiki/wiki/CodeReviewComments#Receiver_Names
It's a design choice.
Java use this, Go-lang choose another mechanic.
In Go, it's legal to make the receiver a pointer or not.
Let's see:
func (t Type) Id() { return t }
func (t *Type) IdPointer() { return t }
What if Go use Java's design?
It will became:
func (Type) Id() { return this }
func (*Type) IdPointer() { return this }
Firstly, it is confused that what (*Type) is.
Secondly, this can also be a pointer or a value. Also confused.
But, anyway, you can design Go-lang like this.
It is a choice after all.
I think you are not using correctly you should use it in a struct.Where the receiver makes a reference to the struct's fields.
For example:
package main
import "fmt"
type Decimal struct {
first float64
}
func (x Decimal) out() float64 {
return x.first
}
func main() {
var start Decimal
start.first = 10.8
show := start.out()
fmt.Println(show)
}
I found what looks like an elegant solution to iterating over enums here: How to enumerate an enum with String type?
Next, I'm having trouble figuring out how to call this method. At face value, it doesn't look like it takes an argument, but when I try to call Card.createDeck() I get a compiler error telling me "error: missing argument for parameter #1 in call".
Please let me know what I'm doing wrong here? What am I supposed to pass to this method?
struct Card {
var rank: Rank
var suit: Suit
func simpleDescription() -> String {
return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
}
func createDeck() -> [Card] {
var deck = [Card]()
var n = 1
while let rank = Rank.fromRaw(n) {
var m = 1
while let suit = Suit.fromRaw(m) {
deck += Card(rank: rank, suit: suit)
m++
}
n++
}
return deck
}
}
createDeck() is a instance method. Doing Card.createDeck() is a call to a class method that doesn't exist.
class func - for class methods
Edit:
I misread that it was a struct, but the same logic applies.
static func - for static methods
You can not able to call it directly as you need instace of struct as it is not class function.So use
Card(rank:Rank.yourRank,suit:Suit.yourSuit).createDeck()
Actually to make struct you need rank and suit instance so first make them and than pass to Card constructor.By default struct have arguments as their properties.