Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

How can I use a random number method to perform to actions at one button press?

Hello,

I am trying to make a function which will allow me to get a random number and use it to return two separate strings.

import Foundation

struct JokeBook {

    let jokeArray = [
        "Q: Why didn't the skeleton go skydiving?",
        "Q: Test"
    ]

    let answerArray = [
        "A: Because he didn't have the guts.",
        "A: Test"
    ]

    func randomNumber() -> Int {

        var unsignedArrayCount = UInt32(jokeArray.count)
        var unsignedRandomNumber = arc4random_uniform(unsignedArrayCount)
        var randomNumber = Int(unsignedRandomNumber)

        return randomNumber

    }

    func JokeNumber() -> String {

        var joke = jokeArray[randomNumber]//I get an error here because I don't have () but I don't want to run the whole randomNumber function again because it'll give me a different number and so a different string

        return joke
    }

    func AnswerNumber() -> String {

        var answer = answerArray[randomNumber]//Same error here.

        return answer
    }

Any help would be much appreciated

Cheers,

Liam

3 Answers

Have you learned about tuples yet?

I just completely removed the methods JokeNumber and AnswerNumber and made one method.

func getJokeWithAnswer() -> (joke: String, answer: String){
    var index = randomNumber()

    var joke = jokeArray[index]
    var answer = answerArray[index]

    return (joke, answer)
}

You can make calls to it like this now:

let jokeBook = JokeBook()
var test = jokeBook.getJokeWithAnswer()

//You now have access to these:
test.joke   //The Joke String
test.answer //The Answer String

Hello and thank you,

I don't believe I have learnt tuples but I would like to where did you learn about them?

The function you showed makes sense but how do you implement it for two separate labels in the ViewController. At the moment I have:

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var jokeLabel: UILabel!
    @IBOutlet weak var jokeButton: UIButton!
    @IBOutlet weak var answerLabel: UILabel!

    let jokeBook = JokeBook()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        jokeLabel.text = jokeBook.getJokeWithAnswer()//Error 1
        answerLabel.text = jokeBook.getJokeWithAnswer()//Error 1

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    @IBAction func showJoke() {
        jokeLabel.text = jokeBook.JokeNumber()//Error 2
        answerLabel.text = jokeBook.AnswerNumber()/Error 3

    }

}

Error 1 says '(joke: String, answer: String)' is not convertible to 'String' Error 2 and 3 are because I have not yet changed to the call you said I would use. So I have to labels one for the question and one for the answer that is why I have 2 arrays how can I make this work?

Thanks,

Liam

http://teamtreehouse.com/library/functions-and-optionals/parameters-and-tuples/tuples

TeamTreeHouse actually has a few episodes on tuples. The way I would implement the code would be this:

Note: I removed all the comments to avoid distracting from mine.

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var jokeLabel: UILabel!
    @IBOutlet weak var jokeButton: UIButton!
    @IBOutlet weak var answerLabel: UILabel!

    let jokeBook = JokeBook()

    //1. I made an instance of the jokeBook tuple containing two strings, named joke and answer.
    //It looked like this (joke: String, answer: String), so this means we can ask for the properties of our joke instance.
    let joke = jokeBook.getJokeWithAnswer()

    override func viewDidLoad() {
        super.viewDidLoad()

        jokeLabel.text = joke.joke      //2. I then loaded the joke from our tuple referencing the joke property.
        answerLabel.text = joke.answer  //3. After that I loaded the answer property from out tuple.

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }


    @IBAction func showJoke() {
        jokeLabel.text = joke.joke      //I then repeated what I did in the viewDidLoad() method because we're just pushing the properties to the label again.
        answerLabel.text = joke.answer 
    }

}

If you have any more questions at all ever, feel free to ask me at flyingturtle98@gmail.com

Thank you very much,

All I noticed with the code you have above is you missed a

()

in

let joke = jokeBook.getJokeWithAnswer()

it should be

let joke = jokeBook().getJokeWithAnswer()

Thank you again , Liam

Sure thing Liam! Hope to see you around Treehouse more!