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

Unexpected Error Array Increment

struct FactBook {
    let factarray = ["Hello World", "Hello MacOS", "Hello iOS"]
    var counter = 0

    func ramdomFact () -> String{

        return factarray[counter++];
    }
}

[code format edited by Mod]

The return statement throw up an error when implemented in a .swift file

5 Answers

Hi,

I don't like the structure of your code; there are probably prettier ways of doing this. However, I had a play and came up with the following, which does work:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var elementLabel: UILabel!
    var factBook: FactBook = FactBook()

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

    @IBAction func getNextElement(sender: AnyObject) {
// check if you've gone over the number of elements - this is hard-coded; poor! 
// should have a method to return the length of the private array and test against that 
        if(factBook.counter >= 3){
            factBook.counter = 0
        }
// call the method that just returns a string
        elementLabel.text = factBook.getNextFact()
        factBook.counter++
    }
}



// FactBook.swift
import Foundation

struct FactBook{
// create an array - should be done on the fly and have access to getter and setter methods too
    var factArray = ["Line one", "Line two", "Line three"]
    var counter: Int

    init(){
// make sure the Int is zeroed
        self.counter = 0
    }
// the sole functionality - counter testing is done elsewhere
    func getNextFact() -> String  {
        return factArray[counter]
    }
}

Yes Steve, even I had to pay around and got your and another solution (attached below) But, can you give me any reason why does my pervious code does not work:

//FactBook.swift
import Foundation
var counter = 0
struct FactBook {
    let factcollection = ["Hello World", "Hello Playground", "Hello iOS", "Hello Mac OS"]

    //var counter = 0

    func returnFact () -> String{

       return factcollection[counter++]
    }
}

But here in the above solution the issue becomes that counter is a global variable. Thus, any new instance new of FactBook will not have a independent copy of counter.

Your code structure is much better

Hi Supratik,

I edited the post to show the post more easily.

What are you trying to acheive here? What's the question?

I can help more from there.

Thanks,

Steve.

The struct defined here is for an simple App. It consists of a label and a button. When the button is pressed it changes the content of the label by calling the randomFact() method. Sample function call from View Controller: label.text = randomFact() The ViewContoller and the struct are in separate swift files.

The error of the return statement: 'Int' is not convertible to '@Ivalue UInt8'

OK - that makes sense. Is this a Treehouse exercise? I'd not expect to see factarray not in Camel Case.

Talk me through your code; let's see why this isn't doing what you expect it to.

First, though, what code are you given as a starter?

Steve.

class ViewController: UIViewController {

    @IBOutlet weak var FunFactLabel: UILabel! //Label I am outputting to 
    var factBook = FactBook() //struct in another swift file FunFacts.swift

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        FunFactLabel.text = factBook.ramdomFact() //member function call
    }

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

    @IBAction func showFunFact() {
     FunFactLabel.text = factBook.ramdomFact() //member function call

        }

    } 

There was actually a TreeHouse course based on the same idea but the conditions were slightly different. The course asked me to display a random string form a array of strings in a random manner. The random condition did work fine.

What I want to do is to sequentially go through the array and print the entire contents of the array to the label as I keep pressing the button.

But, view consists of a button and a label

One reason it will generate an error is that you are incrementing counter but not bounds checking it again the array.

So, the counter can reach a number that is greater than the number of elements in the array which will throw an exception. In my code, I test the value of counter and make sure it doesn't get higher than 2, as the hard-coded array has three elements. It would be better tested as if (counter >= factBook.factArray.count) so that the size of the array is taken into account.

I had a little play with this ... have a look at the following. This starts with an empty array and allows you to add to it. There's a warning to catch the error of trying to access the array when it is empty. (I'm using a deprecated class there, but it still works!)

import UIKit
import Foundation

class ViewController: UIViewController, UIAlertViewDelegate {

    @IBOutlet weak var elementLabel: UILabel!
    var factBook: FactBook = FactBook()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        // init the struct
        //var factBook: FactBook = FactBook()
    }

    @IBAction func addNewElement(sender: AnyObject) {
        factBook.addNewLine()
    }

    @IBAction func getNextElement(sender: AnyObject) {
        if(factBook.factArray.count == 0) {
            var anAlert: UIAlertView = UIAlertView(title: "Empty array", message: "There are no elements to show - add one first", delegate: self, cancelButtonTitle: "OK")
            anAlert.show()
            return
        }
        if(factBook.counter >= factBook.factArray.count){
            factBook.counter = 0
        }
        elementLabel.text = factBook.getNextFact()
        factBook.counter++
    }
}

// FactBook swift file
import Foundation

struct FactBook{
    var factArray: [String] = [] 
    var counter:Int

    init(){
        self.counter = 0
    }

    func getNextFact() -> String {
        return factArray[counter]
    }

    mutating func addNewLine(){
        var elements = factArray.count + 1
        factArray.append("Line \(elements)")
    }
}